--- /dev/null
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0\r
+ DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1\r
+ DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2\r
+ DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3\r
+ DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4\r
+ DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5\r
+ DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6\r
+ DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7\r
+ DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8\r
+ DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9\r
+ DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10\r
+ DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11\r
+ DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12\r
+ DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13\r
+ DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14\r
+ DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15\r
+ DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16\r
+ DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17\r
+ DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18\r
+ DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19\r
+ DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20\r
+ DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21\r
+ DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22\r
+ DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23\r
+ DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24\r
+ DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25\r
+ DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26\r
+ DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27\r
+ DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28\r
+ DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29\r
+ DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30\r
+ DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; \r
+ DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; !\r
+ DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; "\r
+ DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; #\r
+ DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $\r
+ DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; %\r
+ DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; &\r
+ DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; '\r
+ DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; (\r
+ DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; )\r
+ DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; *\r
+ DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; +\r
+ DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; ,\r
+ DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; -\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; .\r
+ DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; /\r
+ DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0\r
+ DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1\r
+ DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2\r
+ DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3\r
+ DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4\r
+ DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5\r
+ DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6\r
+ DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7\r
+ DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8\r
+ DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9\r
+ DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; :\r
+ DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ;\r
+ DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; <\r
+ DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; =\r
+ DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; >\r
+ DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ?\r
+ DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A\r
+ DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B\r
+ DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C\r
+ DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F\r
+ DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G\r
+ DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H\r
+ DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I\r
+ DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J\r
+ DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K\r
+ DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L\r
+ DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M\r
+ DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O\r
+ DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P\r
+ DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q\r
+ DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R\r
+ DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S\r
+ DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T\r
+ DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U\r
+ DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V\r
+ DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W\r
+ DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X\r
+ DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y\r
+ DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z\r
+ DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [\r
+ DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \\r
+ DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ]\r
+ DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _\r
+ DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; `\r
+ DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b\r
+ DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c\r
+ DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d\r
+ DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e\r
+ DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h\r
+ DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i\r
+ DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j\r
+ DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k\r
+ DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l\r
+ DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m\r
+ DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n\r
+ DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o\r
+ DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q\r
+ DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r\r
+ DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s\r
+ DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t\r
+ DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u\r
+ DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v\r
+ DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w\r
+ DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x\r
+ DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y\r
+ DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z\r
+ DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; {\r
+ DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; |\r
+ DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; }\r
+ DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~\r
+ DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ; \7f\r
+ DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128\r
+ DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129\r
+ DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130\r
+ DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131\r
+ DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132\r
+ DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133\r
+ DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134\r
+ DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135\r
+ DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136\r
+ DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137\r
+ DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138\r
+ DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139\r
+ DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140\r
+ DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141\r
+ DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142\r
+ DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143\r
+ DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144\r
+ DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145\r
+ DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146\r
+ DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147\r
+ DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148\r
+ DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149\r
+ DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150\r
+ DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151\r
+ DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152\r
+ DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153\r
+ DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154\r
+ DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155\r
+ DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156\r
+ DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157\r
+ DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158\r
+ DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159\r
+ DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160\r
+ DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161\r
+ DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162\r
+ DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163\r
+ DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164\r
+ DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165\r
+ DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166\r
+ DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167\r
+ DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168\r
+ DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169\r
+ DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170\r
+ DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171\r
+ DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172\r
+ DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173\r
+ DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174\r
+ DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175\r
+ DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176\r
+ DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177\r
+ DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178\r
+ DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181\r
+ DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182\r
+ DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183\r
+ DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184\r
+ DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185\r
+ DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186\r
+ DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187\r
+ DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188\r
+ DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190\r
+ DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198\r
+ DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199\r
+ DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200\r
+ DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201\r
+ DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202\r
+ DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203\r
+ DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205\r
+ DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206\r
+ DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210\r
+ DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212\r
+ DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213\r
+ DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215\r
+ DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217\r
+ DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220\r
+ DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221\r
+ DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223\r
+ DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224\r
+ DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225\r
+ DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226\r
+ DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227\r
+ DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228\r
+ DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229\r
+ DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230\r
+ DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231\r
+ DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233\r
+ DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234\r
+ DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235\r
+ DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236\r
+ DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237\r
+ DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239\r
+ DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240\r
+ DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241\r
+ DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242\r
+ DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243\r
+ DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244\r
+ DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245\r
+ DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246\r
+ DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247\r
+ DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248\r
+ DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249\r
+ DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250\r
+ DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251\r
+ DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252\r
+ DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253\r
+ DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+ MXCC.OBJ \\r
+ MXCG.OBJ \\r
+ MXCL.OBJ \\r
+ MXCR.OBJ \\r
+ MXFB.OBJ \\r
+ MXFP.OBJ \\r
+ MXGC.OBJ \\r
+ MXGI.OBJ \\r
+ MXGM.OBJ \\r
+ MXGP.OBJ \\r
+ MXGV.OBJ \\r
+ MXHL.OBJ \\r
+ MXIT.OBJ \\r
+ MXLL.OBJ \\r
+ MXLN.OBJ \\r
+ MXOT.OBJ \\r
+ MXPB.OBJ \\r
+ MXPF.OBJ \\r
+ MXPG.OBJ \\r
+ MXPI.OBJ \\r
+ MXPN.OBJ \\r
+ MXPP.OBJ \\r
+ MXRA.OBJ \\r
+ MXRP.OBJ \\r
+ MXSA.OBJ \\r
+ MXSC.OBJ \\r
+ MXSI.OBJ \\r
+ MXSL.OBJ \\r
+ MXSM.OBJ \\r
+ MXSP.OBJ \\r
+ MXSS.OBJ \\r
+ MXTL.OBJ \\r
+ MXVS.OBJ \\r
+ MXWD.OBJ \\r
+ MXWM.OBJ \\r
+ MXWP.OBJ \\r
+ MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+ $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+JUMPS\r
+LOCALS\r
+\r
+TRUE EQU 1 ; Boolean constants\r
+FALSE EQU 0\r
+\r
+USE286 = FALSE ; TRUE enables 80286 instructions\r
+USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+ P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+ P386\r
+ USE286 = TRUE\r
+ENDIF\r
+\r
+MXVERSION EQU 0128h ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC EQU 3C2h ; Miscellaneous output\r
+TS EQU 3C4h ; Timing Sequencer index register\r
+GDC EQU 3CEh ; Graphics Data Controller index register\r
+CRTC EQU 3D4h ; CRTC index register\r
+STATUS EQU 3DAh ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET EQU 0\r
+OP_MOVE EQU 0 ; Same as OP_SET\r
+OP_AND EQU 1\r
+OP_OR EQU 2\r
+OP_XOR EQU 3\r
+OP_TRANS EQU 4\r
+OP_ADD EQU 5 ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU 4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.PUSH has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+ IFB <$reg> ;; Is argument blank?\r
+ EXITM ;; Yes, exit\r
+ ELSEIFIDNI <$reg>, <FLAGS> ;; Is argument the keyword "FLAGS"?\r
+ pushf ;; Yes, push flags\r
+ ELSE\r
+ push $reg ;; Push argument\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.POP has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+ IFNB <$reg> ;; Is argument non-blank?\r
+ IFIDNI <$reg>, <FLAGS> ;; Yes, is it the keyword "FLAGS"?\r
+ popf ;; Yes, pop flags\r
+ ELSE\r
+ pop $reg ;; Pop argument\r
+ ENDIF\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter MACRO localsize\r
+ IF USE286 EQ TRUE\r
+ enter localsize, 0\r
+ ELSE\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, localsize\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.leave MACRO argsize\r
+ IF USE286 EQ TRUE\r
+ leave\r
+ ELSE\r
+ mov sp, bp\r
+ pop bp\r
+ ENDIF\r
+ IFNB <argspace>\r
+ ret argsize\r
+ ELSE\r
+ ret\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shr MACRO arg, count\r
+ IF USE286 EQ TRUE\r
+ shr arg, count\r
+ ELSE\r
+ $temp = count\r
+ WHILE $temp GT 0\r
+ shr arg, 1\r
+ $temp = $temp-1\r
+ ENDM\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shl MACRO arg, count\r
+ IF USE286 EQ TRUE\r
+ shl arg, count\r
+ ELSE\r
+ $temp = count\r
+ WHILE $temp GT 0\r
+ shl arg, 1\r
+ $temp = $temp-1\r
+ ENDM\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.chk386 MACRO name, jump\r
+ IF USE386 EQ FALSE\r
+ .OUT "Warning: ", <name>, " needs a 386 or better to run!"\r
+ jmp @@jump\r
+ ENDIF\r
+ENDM\r
--- /dev/null
+/*\r
+ MODEX.H - C/C++ include file for the MODEX library\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_ // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT 0 // 80x25 text\r
+#define MX_320x175 1 // 320x175x256\r
+#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350 4 // 320x350x256\r
+#define MX_320x400 5 // 320x400x256, 2 pages\r
+#define MX_320x480 6 // 320x480x256, 1 page\r
+#define MX_360x175 7 // 360x175x256\r
+#define MX_360x200 8 // 360x200x256, 3 pages\r
+#define MX_360x240 9 // 360x240x256, 2 pages\r
+#define MX_360x350 10 // 360x350x256\r
+#define MX_360x400 11 // 360x400x256, 1 page\r
+#define MX_360x480 12 // 360x480x256, 1 page\r
+#define MX_400x600 13 // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN 0\r
+#define MX_FADEOUT 1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET 0 // No operator\r
+#define OP_AND 1 // And\r
+#define OP_OR 2 // Or\r
+#define OP_XOR 3 // Xor\r
+#define OP_TRANS 4 // Transparent\r
+#define OP_ADD 5 // Additive\r
+#define OP_MOVE 0 // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE unsigned char\r
+#define MXBOOL short int\r
+#define MXSINT short int\r
+#define MXUINT unsigned short int\r
+#define MXAPI far pascal\r
+#define MXPTR void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT MXAPI mxInit( void ); // Returns 0 if successful\r
+void MXAPI mxTerm( void );\r
+MXUINT MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void MXAPI mxChangeMode( MXUINT mode );\r
+void MXAPI mxSetMode( MXUINT mode );\r
+void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void MXAPI mxWriteMode( MXBYTE wm );\r
+void MXAPI mxSplitScreen( MXUINT line );\r
+void MXAPI mxStartAddress( MXUINT sa );\r
+void MXAPI mxStartLine( MXUINT sl );\r
+void MXAPI mxWaitDisplay( void );\r
+void MXAPI mxWaitRetrace( void );\r
+void MXAPI mxWritePlane( MXBYTE wp );\r
+void MXAPI mxReadPlane( MXBYTE rp );\r
+void MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL MXAPI mxGetClip( void );\r
+MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL MXAPI mxSetClip( MXBOOL );\r
+void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef MXBYTE\r
+#undef MXBOOL\r
+#undef MXSINT\r
+#undef MXUINT\r
+#undef MXPTR\r
+#undef MXAPI\r
+\r
+#endif // _MODEX_H_\r
--- /dev/null
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
--- /dev/null
+(*\r
+ Turbo Pascal interface to the MODEX library\r
+ Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+ (* Video modes *)\r
+ MX_TEXT = 0;\r
+ MX_320x175 = 1;\r
+ MX_320x200 = 2;\r
+ MX_320x240 = 3;\r
+ MX_320x350 = 4;\r
+ MX_320x400 = 5;\r
+ MX_320x480 = 6;\r
+ MX_360x175 = 7;\r
+ MX_360x200 = 8;\r
+ MX_360x240 = 9;\r
+ MX_360x350 = 10;\r
+ MX_360x400 = 11;\r
+ MX_360x480 = 12;\r
+ MX_400x600 = 13;\r
+\r
+ (* Fade effects *)\r
+ MX_FADEIN = 0;\r
+ MX_FADEOUT = 1;\r
+\r
+ (* Raster ops *)\r
+ OP_SET = 0;\r
+ OP_AND = 1;\r
+ OP_OR = 2;\r
+ OP_XOR = 3;\r
+ OP_TRANS = 4;\r
+ OP_ADD = 5;\r
+ OP_MOVE = 0; (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt; external;\r
+procedure mxChangeMode( Mode: word ); external;\r
+procedure mxCircle; external;\r
+procedure mxColorToGray; external;\r
+procedure mxFadePalette; external;\r
+procedure mxFillBox; external;\r
+procedure mxGammaCorrect; external;\r
+procedure mxGetAspect( var AspectX, AspectY: word ); external;\r
+function mxGetClipRegion; external;\r
+function mxGetClip: boolean; external;\r
+procedure mxGetImage; external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function mxGetPixel( X, Y: word ): byte; external;\r
+procedure mxGetScreenSize( var Width, Height: word ); external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external;\r
+function mxGetVersion: word; external;\r
+procedure mxGetVirtualScreen( var Width, Height: word ); external;\r
+procedure mxInit; external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external;\r
+procedure mxOutChar( X, Y: integer; C: char ); external;\r
+procedure mxOutText( X, Y: integer; S: pointer ); external;\r
+procedure mxPan( X, Y: word ); external;\r
+procedure mxPutImage; external;\r
+procedure mxPutPixel( X, Y: word; C: byte ); external;\r
+procedure mxPutTile; external;\r
+procedure mxReadPlane( Plane: byte ); external;\r
+procedure mxRotatePalette; external;\r
+procedure mxRowAddress( RowAddress: byte ); external;\r
+function mxSetClip( Clip: boolean ): boolean; external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external;\r
+procedure mxSetColor( Index, R, G, B: word ); external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word ); external;\r
+procedure mxSetMode( Mode: word ); external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word ); external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer ); external;\r
+procedure mxSetVirtualScreen( Width, Height: word ); external;\r
+procedure mxSplitScreen( Line: word ); external;\r
+procedure mxStartAddress( StartAddress: word ); external;\r
+procedure mxStartLine; external;\r
+procedure mxStretchImage; external;\r
+procedure mxTerm; external;\r
+procedure mxTransPutTile; external;\r
+procedure mxWaitDisplay; external;\r
+procedure mxWaitRetrace; external;\r
+procedure mxWriteMode( Mode: byte ); external;\r
+procedure mxWritePlane( Plane: byte ); external;\r
+\r
+procedure mxFillPoly; external;\r
+procedure mxGouraudPoly; external;\r
+procedure mxTexturePoly; external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+ Prints a Turbo Pascal string.\r
+ Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+ S := S + #0;\r
+ mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
--- /dev/null
+(*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ MAX_SPRITE = 100;\r
+type\r
+ (* Sprite structure *)\r
+ TSprite = record\r
+ X, Y : integer; (* Sprite coordinates *)\r
+ DX,DY: integer; (* Deltas for sprite movement *)\r
+ W, H : integer; (* Sprite width and height *)\r
+ Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *)\r
+ end;\r
+ (* RGB color structure *)\r
+ TRgb = record\r
+ R, G, B: byte;\r
+ end;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *)\r
+ Palette: array[ byte ] of TRgb; (* Palette *)\r
+ Page : word; (* Page offset *)\r
+ I : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X := Random( 320 ); (* Initialize position with random values *)\r
+ S.Y := Random( 240 );\r
+ S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+ S.DY := Random( 7 )-3;\r
+ S.W := 16; (* Size is fixed in this program *)\r
+ S.H := 16;\r
+ (* The image is a square with a hole inside *)\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); (* Get new position *)\r
+ Inc( S.Y, S.DY );\r
+ (* Check sprite position, change delta if needed *)\r
+ if( S.X > 320 ) then begin\r
+ S.X := 320;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.X < -16 ) then begin\r
+ S.X := -16;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.Y > 240 ) then begin\r
+ S.Y := 240;\r
+ S.DY := -S.DY;\r
+ end;\r
+ if( S.Y < -16 ) then begin\r
+ S.Y := -16;\r
+ S.DY := -S.DY;\r
+ end;\r
+ (* Draw the sprite, note the Page offset added to the *)\r
+ (* Y coordinate of the image *)\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+ (* Initialize library *)\r
+ mxInit;\r
+\r
+ (* Enter graphics mode *)\r
+ mxSetMode( MX_320x240 );\r
+\r
+ (* Print initialization message *)\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ (* Initialize sprites *)\r
+ for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+ (* Draw background *)\r
+ for I:=1 to 192 do begin\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ end;\r
+\r
+ (* Compute and set palette *)\r
+ for I:=1 to 192 do with Palette[I+63] do begin\r
+ R := 0;\r
+ G := 0;\r
+ B := 0;\r
+ if( I < 64 ) then\r
+ R := I shr 1+31\r
+ else if( I < 128 ) then\r
+ G := (I-64) shr 1+31\r
+ else\r
+ B := (I-128) shr 1+31;\r
+ end;\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ (* Main loop *)\r
+ Page := 240;\r
+ while( not KeyPressed ) do begin\r
+ (* Set clip region to current page *)\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ (* Restore background *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ (* Draw sprites *)\r
+ for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+ (* Print message *)\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ (* Flip page *)\r
+ mxStartLine( Page );\r
+ Page := 240-Page;\r
+ (* Animate palette *)\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO02 - Texture mapping and palette rotation\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+ LSIZE = 85;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of T2DPoint;\r
+ Width : word;\r
+ Data : array[ 1..64*64 ] of byte;\r
+ end;\r
+ TQuad = record\r
+ VtxCnt : word;\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+var\r
+ Vtx : array[ 0..7 ] of TPoint;\r
+ XVtx : array[ 0..7 ] of TPoint;\r
+ VVtx : array[ 0..7 ] of T2DPoint;\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Txts : array[ 0..5 ] of TTexture;\r
+ Nrm : array[ 0..5 ] of TPoint;\r
+ XNrm : array[ 0..5 ] of TPoint;\r
+ Page : word;\r
+ Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+ I: word;\r
+begin\r
+ mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+ MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+ mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+ (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+ with Txts[Idx] do begin\r
+ Desc[0].X := $80; Desc[0].Y := $80;\r
+ Desc[1].X := $80; Desc[1].Y := $3F80;\r
+ Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+ Desc[3].X := $3F80; Desc[3].Y := $80;\r
+ Width := 64;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Build vertexes for a cube *)\r
+ with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ for I:=0 to 7 do begin (* Make points 16:16 fixed *)\r
+ Vtx[I].X := Vtx[I].X*$10000;\r
+ Vtx[I].Y := Vtx[I].Y*$10000;\r
+ Vtx[I].Z := Vtx[I].Z*$10000;\r
+ end;\r
+ (* Build faces *)\r
+ with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+ with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+ with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+ with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+ with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+ with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+ for I:=0 to 5 do Face[I].Texture := I;\r
+ (* Build textures and palette *)\r
+ Randomize;\r
+ FillChar( Palette, SizeOf(Palette), 0 );\r
+ MakePlasmaPalette( Palette, PAL_RGB );\r
+ mxSetPalette( @Palette, 0, 193 );\r
+ for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *)\r
+ (* Draw cube: backface culling is straighforward in this case, so *)\r
+ (* it can be handled by the polygon filling procedure *)\r
+ for I:=0 to 5 do\r
+ mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *)\r
+ Page := 240-Page;\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 1000; (* Number of points *)\r
+ EDGE = 70; (* Length of cube edge *)\r
+ RADIUS = 90; (* Radius of sphere *)\r
+ WAITCOUNT = 192; (* Frames to wait for non-morphing shapes *)\r
+ MS = 32; (* Number of steps for morphing *)\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+ InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+ InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+ InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+ P3DPointArray = ^T3DPointArray;\r
+var\r
+ CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+ VVtx : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+ Page : word;\r
+ Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+ L: longint;\r
+begin\r
+ L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+ Toggle := A;\r
+ if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+ I: integer;\r
+begin\r
+ New( CubeVtx );\r
+ New( SphereVtx );\r
+ New( Vtx );\r
+ New( XVtx );\r
+ (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+ Randomize;\r
+ for I:=0 to MAXVTX-1 do begin\r
+ with CubeVtx^[I] do begin\r
+ (* Build cube *)\r
+ X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Z := Toggle( EDGE*$10000 );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ end;\r
+ with SphereVtx^[I] do begin\r
+ (* Build sphere *)\r
+Retry:\r
+ X := (longint(Random(2*RADIUS))-RADIUS);\r
+ Y := (longint(Random(2*RADIUS))-RADIUS);\r
+ if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+ Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+ end;\r
+ end;\r
+ (* Initialize morphing *)\r
+ Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+ Status := 0;\r
+ Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Fully unoptimized, slowest loop I could think of! *)\r
+ for I:=0 to MAXVTX-1 do begin\r
+ Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+ Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+ Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ C := #0;\r
+ repeat\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw points *)\r
+ for I:=0 to MAXVTX-1 do\r
+ mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ Page := 240-Page;\r
+ (* Morph *)\r
+ if( Odd(Status) ) then begin\r
+ Morph;\r
+ Inc( Morph1, Delta1 );\r
+ Inc( Morph2, Delta2 );\r
+ if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+ if( Status = 4 ) then Status := 0;\r
+ end\r
+ else begin\r
+ Dec( Count );\r
+ if( Count < 0 ) then begin\r
+ Inc( Status );\r
+ Count := WAITCOUNT;\r
+ Morph1 := InitMorph1[Status];\r
+ Morph2 := InitMorph2[Status];\r
+ Delta1 := InitDelta1[Status];\r
+ Delta2 := InitDelta2[Status];\r
+ end;\r
+ end;\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO04 - Multiple textures and triple buffering (3 pages)\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 256;\r
+ MAXCUB = 2;\r
+ MAXTXT = 2;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ TxtSunDial: array[ 0..7 ] of word = (\r
+ $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+ TxtSapphire : array[ 0..7 ] of word = (\r
+ $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+ TxtMarble: array[ 0..7 ] of word = (\r
+ $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of record X, Y: word end;\r
+ Width : word;\r
+ Data : pointer;\r
+ end;\r
+ TQuad = record\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+ TCube = record\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Base : integer;\r
+ end;\r
+var\r
+ Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+ VVtx : array[ 0..MAXVTX ] of T2DPoint;\r
+ Cube : array[ 0..MAXCUB ] of TCube;\r
+ ZList : array[ 0..MAXCUB ] of integer;\r
+ VtxCnt : word;\r
+ Txts : array[ 0..MAXTXT ] of TTexture;\r
+ Page : word;\r
+ Palette : array[ byte ] of record R, G, B: byte; end;\r
+ TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+ with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+ Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+ FaceIdx: array[ 0..23 ] of integer = (\r
+ 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+ I, VC: integer;\r
+begin\r
+ VC := VtxCnt;\r
+ C.Base := VC;\r
+ AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+ for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+ for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+ P: ^word;\r
+ I: integer;\r
+begin\r
+ P := @VtxData;\r
+ with Txts[Idx] do begin\r
+ for I:=0 to 3 do begin\r
+ Desc[I].X := P^; Inc( P );\r
+ Desc[I].Y := P^; Inc( P );\r
+ end;\r
+ Width := 129;\r
+ Data := TxtDat1;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+ V: integer;\r
+ F: file;\r
+ P: array[ 1..768 ] of byte;\r
+begin\r
+ (* Initialize objects *)\r
+ VtxCnt := 0;\r
+ MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *)\r
+ Cube[0].Face[0].Texture := 0;\r
+ V := VtxCnt;\r
+ MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+ tdSetTranslation( Trans );\r
+ tdSetRotation( 32, 32, 00 );\r
+ tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *)\r
+ for I:=V to V+7 do begin\r
+ Vtx[I].X := XVtx[I].X;\r
+ Vtx[I].Y := XVtx[I].Y;\r
+ Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+ end;\r
+ MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+ (* Load texture and palette *)\r
+ Assign( F, 'DEMO04.DAT' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, P, SizeOf(P) );\r
+ mxSetPalette( @P, 0, 256 );\r
+ GetMem( TxtDat1, 63*1024 );\r
+ BlockRead( F, TxtDat1^, 129*286 );\r
+ Close( F );\r
+ TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+ (* Init textures *)\r
+ MakeTexture( 0, TxtSundial );\r
+ MakeTexture( 1, TxtMarble );\r
+ MakeTexture( 2, TxtSapphire );\r
+ Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+ I, J, K: integer;\r
+ ZMax: array[ 0..MAXCUB ] of longint;\r
+ ZI: integer;\r
+ L: longint;\r
+begin\r
+ for I:=0 to MAXCUB do begin\r
+ L := XVtx[Cube[I].Base].Z;\r
+ for J:=1 to 7 do\r
+ if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+ ZMax[I] := L;\r
+ ZList[I] := I;\r
+ end;\r
+ for I:=0 to MAXCUB-1 do begin\r
+ ZI := I;\r
+ for J:=I+1 to MAXCUB do\r
+ if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+ if( ZI <> I ) then begin\r
+ K := ZList[I];\r
+ ZList[I] := ZList[ZI];\r
+ ZList[ZI] := K;\r
+ end;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I, J, K: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ AX := 0; AY := 0; AZ := 0;\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 600*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 1 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw objects *)\r
+ SortObjects;\r
+ for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+ for J:=0 to 5 do begin\r
+ K := Face[J].Texture;\r
+ mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+ end;\r
+ end;\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO05 - A Gouraud-shaded rotating torus\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+ MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *)\r
+ MAXVTX2 = 15; RADIUS2 = 30;\r
+ MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+ MAXFACE = MAXVTX;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *)\r
+ Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *)\r
+type\r
+ TQuad = record\r
+ QVtx : array[ 0..3 ] of integer;\r
+ end;\r
+var\r
+ Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *)\r
+ VVtx : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+ Face : array[ 0..MAXFACE ] of TQuad; (* Polys *)\r
+ Culled : array[ 0..MAXFACE ] of integer;\r
+ GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *)\r
+ VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *)\r
+ Page : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+ GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ R, N, X, Y, Z: real;\r
+ I, J, K, V: integer;\r
+begin\r
+ (* Build vertexes *)\r
+ for I:=0 to MAXVTX1 do begin\r
+ K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+ R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+ for J:=0 to MAXVTX2 do begin\r
+ V := I*(MAXVTX2+1)+J; (* Index of current vertex *)\r
+ (* Compute coordinates of current vertex *)\r
+ X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *)\r
+ Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+ Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+ Vtx[V].X := Round( X )*$10000; (* Save coordinates *)\r
+ Vtx[V].Y := Round( Y )*$10000;\r
+ Vtx[V].Z := Round( Z )*$10000;\r
+ (* Compute direction of Gouraud normal thru current vertex *)\r
+ X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+ Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+ N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *)\r
+ GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *)\r
+ GNrm[V].Y := Trunc( Y*$10000/N );\r
+ GNrm[V].Z := Trunc( Z*$10000/N );\r
+ end;\r
+ end;\r
+ (* Generate faces so that depth-sorting is not needed: there are still *)\r
+ (* some *very* little errors, but this is the best I could devise *)\r
+ J := 0;\r
+ K := 0;\r
+ for I:=0 to MAXFACE do with Face[I] do begin\r
+ QVtx[0] := GetVtx( J, K );\r
+ QVtx[1] := GetVtx( J, K+1 );\r
+ QVtx[2] := GetVtx( J+1, K+1 );\r
+ QVtx[3] := GetVtx( J+1, K );\r
+ Inc( K );\r
+ if( K > MAXVTX2 ) then begin\r
+ K := 0;\r
+ Inc( J );\r
+ end;\r
+ end;\r
+{$ifndef ALTPAL}\r
+ for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *)\r
+{$else}\r
+ for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+ for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetLight( Light );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+ tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *)\r
+ tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+ (* Backplane culling is not really needed here! *)\r
+ FillChar( Culled, SizeOf(Culled), 0 );\r
+ tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 3 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw polygons *)\r
+ for I:=0 to MAXFACE do with Face[I] do\r
+ if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO06 - Magnifying glass\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ R = 40; (* Lens radius *)\r
+ K : real = 1.8; (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+ TLine = array[ 0..319 ] of byte;\r
+ PLine = ^TLine;\r
+ TScreen = array[ 0..239 ] of PLine;\r
+var\r
+ VScreen: TScreen; (* Virtual screen *)\r
+ BallX : array[ 0..R, 0..R ] of integer;\r
+ BallY : array[ 0..R, 0..R ] of integer;\r
+ Sprite : array[ -R..R, -R..R ] of byte;\r
+ Page : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+ LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+ LR := Sqrt( X*X + Y*Y );\r
+ if( LR = 0 ) then Exit;\r
+ if( LR < R ) then begin\r
+ Z := Sqrt( R*R - LR*LR );\r
+ SinA := LR / R;\r
+ SinB := SinA / K;\r
+ TgB := SinB / Sqrt( 1-SinB*SinB );\r
+ Q := LR - TgB*Z;\r
+ X := Round( X * ( Q/LR ) );\r
+ Y := Round( Y * ( Q/LR ) );\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ F : file;\r
+ Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+ X, Y,\r
+ X2, Y2 : integer;\r
+begin\r
+ (* Load background image *)\r
+ Assign( F, 'demo06.dat' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, Palette, 768 );\r
+ mxSetPalette( @Palette, 0, 256 );\r
+ for Y:=0 to 239 do begin\r
+ New( VScreen[Y] );\r
+ BlockRead( F, VScreen[Y]^, 320 );\r
+ mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+ end;\r
+ Close( F );\r
+ (* Build lens *)\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ X2 := X;\r
+ Y2 := Y;\r
+ GetCoords( X2, Y2 );\r
+ BallX[X, Y] := X2;\r
+ BallY[X, Y] := Y2;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+ X, Y: integer;\r
+begin\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ end;\r
+ end;\r
+ (* Draw the sprite *)\r
+ mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+ Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*Delta;\r
+ end;\r
+end;\r
+\r
+var\r
+ X, Y, DX, DY: integer;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240;\r
+ X := R;\r
+ Y := R;\r
+ Randomize;\r
+ DX := Delta;\r
+ DY := Delta;\r
+\r
+ (* Main loop *)\r
+ repeat\r
+ (* Update video *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ PutLens( X, Y );\r
+ mxCircle( X, Page+Y, R, 0 );\r
+ (* Update lens coordinates *)\r
+ Inc( X, DX );\r
+ Check( X+R >= 319, X, DX, 319-R, -1 );\r
+ Check( X <= R, X, DX, R, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+ Check( Y <= R, Y, DY, R, +1 );\r
+ (* Flip pages: double buffering, avoid wait for display *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Wait for hidden page to show *)\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO07 - Hardware scrolling\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ (* Change this if scrolling seems jerky (this simple program does *)\r
+ (* not handle vertical retrace/display very well) *)\r
+ STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*(Random(3)+2);\r
+ end;\r
+end;\r
+\r
+var\r
+ I, X, Y, DX, DY: integer;\r
+begin\r
+ (* Initialize library and graphics mode *)\r
+ mxInit;\r
+ mxSetMode( MX_320x200 );\r
+ (* Set a 640x400 virtual screen *)\r
+ mxSetVirtualScreen( 640, 400 );\r
+ mxSetClip( TRUE );\r
+\r
+ X := 0;\r
+ Y := 0;\r
+ DX := 1;\r
+ DY := 1;\r
+\r
+ (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+ (* 320x200 windows, while smoothly panning virtual screen *)\r
+ while( not KeyPressed ) do begin\r
+ (* Points *)\r
+ mxSetClipRegion( 0, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxPutPixel( Random(320), Random(200), Random(16) );\r
+ (* Lines *)\r
+ mxSetClipRegion( 0, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+ (* Circles *)\r
+ mxSetClipRegion( 320, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+ (* Boxes *)\r
+ mxSetClipRegion( 320, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+ (* Pan *)\r
+ Inc( X, DX );\r
+ Check( X+320 >= 639, X, DX, 319, -1 );\r
+ Check( X < 0, X, DX, 0, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+ Check( Y < 0, Y, DY, 0, +1 );\r
+ mxPan( X, Y );\r
+ mxWaitRetrace;\r
+ end;\r
+\r
+ (* Shutdown *)\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT STRUC\r
+ X DD ?\r
+ Y DD ?\r
+ Z DD ?\r
+TPOINT ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT STRUC\r
+ IX DW ?\r
+ IY DW ?\r
+TIMAGEPOINT ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv MACRO arg\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul MACRO arg\r
+ imul arg\r
+ shrd eax, edx, 16\r
+ENDM\r
--- /dev/null
+unit Plasma;\r
+interface\r
+\r
+const\r
+ PAL_RGB = 0;\r
+ PAL_CLOUDS = 1;\r
+ PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+ Color: longint;\r
+begin\r
+ Color := Abs( XA-XB )+Abs( YA-YB );\r
+ Color := Random( Color shl 1 )-Color;\r
+ Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+ if( Color < 1 ) then Color := 1;\r
+ if( Color > 192 ) then Color := 192;\r
+ if( mxGetPixel( X, Y ) = 0 ) then\r
+ mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+ X, Y, Color: integer;\r
+begin\r
+ if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+ X := (X1+X2) shr 1;\r
+ Y := (Y1+Y2) shr 1;\r
+ NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+ NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+ NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+ NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+ Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+ mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+ mxPutPixel( X, Y, Color );\r
+ Divide( X1, Y1, X, Y );\r
+ Divide( X, Y1, X2, Y );\r
+ Divide( X, Y, X2, Y2 );\r
+ Divide( X1, Y, X, Y2 );\r
+ end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+ Dec( W );\r
+ Dec( H );\r
+ mxPutPixel( X, Y, C1 );\r
+ mxPutPixel( X, Y+H, C2 );\r
+ mxPutPixel( X+W, Y+H, C3 );\r
+ mxPutPixel( X+W, Y, C4 );\r
+ Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+ TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+ I: word;\r
+begin\r
+ FillChar( TPal(Palette)[1], 192*3, 0 );\r
+ case What of\r
+ PAL_CLOUDS:\r
+ for I:=1 to 192 do begin\r
+ TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].B := 63;\r
+ end;\r
+ PAL_LANDSCAPE:\r
+ begin\r
+ for I:=0 to 31 do begin\r
+ TPal(Palette)[I+1].R := I;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := I + I shr 1+15;\r
+ end;\r
+ for I:=32 to 63 do begin\r
+ TPal(Palette)[I+1].R := 0;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := 0;\r
+ end;\r
+ for I:=64 to 191 do begin\r
+ TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+ end;\r
+ end;\r
+ else\r
+ for I:=1 to 64 do begin\r
+ TPal(Palette)[I].G := I-1;\r
+ TPal(Palette)[I].B := 64-I;\r
+ TPal(Palette)[I+64].R := I-1;\r
+ TPal(Palette)[I+64].G := 64-I;\r
+ TPal(Palette)[I+128].B := I-1;\r
+ TPal(Palette)[I+128].R := 64-I;\r
+ end;\r
+ end;\r
+end;\r
+\r
+end.
\ No newline at end of file
--- /dev/null
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+ DEFVERT = 12; (* Vertex count *)\r
+ DEFREPL = 3; (* Repetition count *)\r
+ DEFQIXS = 2; (* Qixs *)\r
+ FADESPEED = 48;\r
+type\r
+ TPoint = record\r
+ X, Y : integer;\r
+ end;\r
+ TRGB = record\r
+ R, G, B: byte;\r
+ end;\r
+ TQix = record\r
+ Color: integer;\r
+ Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+ Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+ end;\r
+var\r
+ Page : integer;\r
+ MaxX,\r
+ MaxY : word;\r
+ Qix : array[ 0..DEFQIXS-1 ] of TQix;\r
+ Pal : array[ byte ] of TRGB;\r
+\r
+type\r
+ TReal = double;\r
+ TRPoint = record\r
+ X, Y: TReal;\r
+ end;\r
+ TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+ M: TMatrix;\r
+ G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+ C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=1 to Steps do begin\r
+ Pal[Idx+1].R := Pal[Idx].R + DR;\r
+ Pal[Idx+1].G := Pal[Idx].G + DG;\r
+ Pal[Idx+1].B := Pal[Idx].B + DB;\r
+ Inc( Idx );\r
+ end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+ with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+ with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+ BumpPal( 1, 0, 2, -2, 31 );\r
+ BumpPal( 32, 2, -2, 0, 31 );\r
+ BumpPal( 63, -2, 2, 2, 31 );\r
+ BumpPal( 94, 2, 0, -2, 31 );\r
+ BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+ for I:=0 to DEFVERT-1 do begin\r
+ Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+ Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+ Qix.Delta[I].X := Random(5)+1;\r
+ Qix.Delta[I].Y := Random(5)+1;\r
+ end;\r
+ Qix.Color := Color;\r
+\r
+ (* Initialize matrix (Catmull-Rom) *)\r
+ M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+ M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+ M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+ M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+ I, J: integer;\r
+ T, T2, T3: TReal;\r
+ X0, Y0, X, Y: TReal;\r
+ Delta: TReal;\r
+begin\r
+ (* Compute coefficients *)\r
+ for I:=0 to 3 do begin\r
+ C[I].X := 0;\r
+ for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+ C[I].Y := 0;\r
+ for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+ end;\r
+ X0 := C[3].X;\r
+ Y0 := C[3].Y;\r
+ Delta := 1 / N;\r
+ T := 0;\r
+ for I:=1 to N do begin\r
+ T := T + Delta;\r
+ T2 := T*T;\r
+ T3 := T*T2;\r
+ X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+ Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+ mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+ X0 := X;\r
+ Y0 := Y;\r
+ end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+ I, J: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do begin\r
+ mxBezier( Qix, I, Idx, 12 );\r
+ end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Inc( Vert[I,Idx].X, Delta[I].X );\r
+ if( Vert[I,Idx].X < 0 ) then begin\r
+ Vert[I,Idx].X := 0;\r
+ Delta[I].X := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].X > MaxX ) then begin\r
+ Vert[I,Idx].X := MaxX;\r
+ Delta[I].X := -Random( 5 )-1;\r
+ end;\r
+ Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+ if( Vert[I,Idx].Y < 0 ) then begin\r
+ Vert[I,Idx].Y := 0;\r
+ Delta[I].Y := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].Y > MaxY ) then begin\r
+ Vert[I,Idx].Y := MaxY;\r
+ Delta[I].Y := -Random( 5 )-1;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Vert[I,Dest].X := Vert[I,Src].X;\r
+ Vert[I,Dest].Y := Vert[I,Src].Y;\r
+ end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+ Q, Idx, I, J, P, Count: integer;\r
+begin\r
+ Count := 0;\r
+ P := DEFREPL-1;\r
+ I := 0;\r
+ J := 1;\r
+ repeat\r
+ mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Copy( Qix[Q], I, P );\r
+ Update( Qix[Q], I );\r
+ for Idx:=0 to DEFREPL-1 do begin\r
+ Plot( Qix[Q], Idx );\r
+ end;\r
+ end;\r
+ I := (I+1) mod DEFREPL;\r
+ J := (J+1) mod DEFREPL;\r
+ P := (P+1) mod DEFREPL;\r
+ Inc( Count );\r
+ mxStartLine( Page );\r
+ if( Count >= FADESPEED ) then begin\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Inc( Qix[Q].Color );\r
+ if( Qix[Q].Color > 156 ) then\r
+ Qix[Q].Color := 1;\r
+ end;\r
+ Count := 0;\r
+ end;\r
+ Page := 240-Page;\r
+ until( KeyPressed );\r
+end;\r
+\r
+var\r
+ I: integer;\r
+begin\r
+ Randomize;\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ mxGetScreenSize( MaxX, MaxY );\r
+ for I:=0 to DEFQIXS-1 do\r
+ Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+ InitPalette;\r
+ mxSetPalette( @Pal, 0, 157 );\r
+ Page := 240;\r
+ Dec( MaxX );\r
+ Dec( MaxY );\r
+ AnimateQix;\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin LABEL DWORD\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+tblCos LABEL DWORD\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
--- /dev/null
+COMMENT /\r
+ Fixed-point math functions and 3D transforms\r
+ Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC tdFixedMul\r
+PUBLIC tdGetNormal\r
+PUBLIC tdRotate\r
+PUBLIC tdGetSurfaceLight\r
+PUBLIC tdSetLight\r
+PUBLIC tdSetRotation\r
+PUBLIC tdSetTranslation\r
+PUBLIC tdTransform\r
+PUBLIC tdTransformToImage\r
+PUBLIC tdTransformLight\r
+PUBLIC tdBackPlaneCull\r
+PUBLIC tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA'\r
+ ASSUME ds:MATH_DATA\r
+\r
+INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table\r
+\r
+XRotation TPOINT <> ; 3x3 rotation matrix\r
+YRotation TPOINT <>\r
+ZRotation TPOINT <>\r
+\r
+Translation TPOINT <> ; Translation vector\r
+\r
+Light TPOINT <> ; Light vector\r
+AmbientLight DW 00 ; Ambient light\r
+\r
+XScale DD 10000h ; Scaling factor for X coordinate\r
+YScale DD 10000h ; Scaling factor for Y coordinate\r
+PerspectiveDistance DD 20000000h\r
+\r
+MATH_DATA ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective PROC PASCAL FAR\r
+ ARG Perspective:DWORD, \\r
+ ScaleX:DWORD, \\r
+ ScaleY:DWORD\r
+ USES ds\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov eax, [Perspective]\r
+ mov [PerspectiveDistance], eax\r
+ mov eax, [ScaleX]\r
+ mov [XScale], eax\r
+ mov eax, [ScaleY]\r
+ mov [YScale], eax\r
+\r
+ ret\r
+tdSetPerspective ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+; RX = X-axis rotation angle\r
+; RY = X-axis rotation angle\r
+; RZ = X-axis rotation angle\r
+; Output:\r
+; none\r
+;\r
+tdSetRotation PROC PASCAL FAR\r
+ ARG RX:WORD, \\r
+ RY:WORD, \\r
+ RZ:WORD\r
+ USES ds, si, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov bx, [RZ]\r
+ mov si, [RY]\r
+ mov di, [RX]\r
+ shl bx, 2\r
+ shl si, 2\r
+ shl di, 2\r
+\r
+ push ebp ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.Y], edx\r
+\r
+ mov eax, tblSin[si]\r
+ sar eax, 8 ; Convert fixed 8:24 to fixed 16:16\r
+ mov [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si] ; EDX:EAX = fixed 16:48\r
+ shrd eax, edx, 24 ; EAX = fixed 8:24\r
+ imul tblSin[di] ; EDX:EAX = fixed 16:48\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[di]\r
+ add eax, ebp\r
+ adc edx, ecx ; EDX:EAX = fixed 16:48\r
+ neg edx\r
+ mov [YRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblSin[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [YRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblSin[di]\r
+ mov [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [ZRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[di]\r
+ add eax, ebp\r
+ add edx, ecx\r
+ neg edx\r
+ mov [ZRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblCos[di]\r
+ mov [ZRotation.Z], edx\r
+\r
+ pop ebp ; Restore EBP\r
+\r
+ ret\r
+tdSetRotation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+; TV = pointer to translation vector\r
+; Output:\r
+; none\r
+;\r
+tdSetTranslation PROC PASCAL FAR\r
+ ARG TV:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [TV]\r
+ mov eax, es:[di].X\r
+ mov [Translation.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Translation.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Translation.Z], eax\r
+\r
+ ret\r
+tdSetTranslation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransform PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ LOCAL Adjust:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+ ALIGN DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ mov ebx, eax\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16)\r
+ mov es:[di].Z, eax\r
+; Get perspective factor\r
+ mov ebx, [PerspectiveDistance]\r
+ sub eax, ebx\r
+ neg eax ; EAX = PD - Z\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx ; EAX = fixed 16:16 result\r
+ mov [Adjust], eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.X]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Y]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdTransform ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TIMAGEPOINT\r
+; Count = number of entries to transform\r
+; DeltaX = translation distance for the X coordinate\r
+; DeltaY = translation distance for the Y coordinate\r
+; Output:\r
+; the maximum Z value\r
+;\r
+tdTransformToImage PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD\r
+ LOCAL Adjust:DWORD, \\r
+ Max:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+ mov [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+ mov eax, fs:[si].Z\r
+ cmp eax, [Max]\r
+ jle @@1\r
+ mov [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+ mov ax, WORD PTR fs:[si].X[2]\r
+ add ax, [DeltaX]\r
+ mov es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+ mov ax, WORD PTR fs:[si].Y[2]\r
+ add ax, [DeltaY]\r
+ mov es:[di].IY, ax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TIMAGEPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ mov eax, [Max]\r
+ shld edx, eax, 16\r
+ ret\r
+tdTransformToImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+; Light = pointer to light vector\r
+; Output:\r
+; none\r
+;\r
+tdSetLight PROC PASCAL FAR\r
+ ARG L:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [L]\r
+ mov eax, es:[di].X\r
+ mov [Light.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Light.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Light.Z], eax\r
+\r
+ ret\r
+tdSetLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+; Normals = pointer to an array of surface normals\r
+; Lights = pointer to an array of integer to be filled with\r
+; light intensity\r
+; Count = number of elements to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransformLight PROC PASCAL FAR\r
+ ARG Normals:DWORD, \\r
+ Lights:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov fs, ax\r
+ ASSUME fs:MATH_DATA\r
+\r
+ lds si, [Normals]\r
+ les di, [Lights]\r
+ ASSUME ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+ mov eax, ds:[si].Z\r
+ imul [Light.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, ds:[si].Y\r
+ imul [Light.Y]\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, ds:[si].X\r
+ imul [Light.X]\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = fixed 32:32 intensity\r
+ add dx, [AmbientLight]\r
+ test dx, dx\r
+ jg @@1\r
+ xor dx, dx ; Return 0 for no light\r
+@@1:\r
+ mov es:[di], dx\r
+ inc di\r
+ inc di\r
+ add si, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ASSUME fs:NOTHING\r
+ ret\r
+tdTransformLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+; Normal = pointer to TPOINT surface normal vector\r
+; Output:\r
+; AX = light intensity (>=0)\r
+; Notes:\r
+; the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight PROC PASCAL FAR\r
+ ARG Normal:DWORD\r
+ USES ds, esi, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [Normal]\r
+\r
+; Transform Z coordinate\r
+ mov eax, es:[di].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.Z]\r
+ shrd eax, edx, 16\r
+ mov esi, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, es:[di].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add esi, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, es:[di].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add eax, esi\r
+ shr eax, 16\r
+\r
+; Add ambient light\r
+ add ax, [AmbientLight]\r
+ test ax, ax\r
+ jge @@Exit\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ ret\r
+tdGetSurfaceLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdRotate PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdRotate ENDP\r
+\r
+tdFixedMul PROC PASCAL FAR\r
+ ARG F1:DWORD, \\r
+ F2:DWORD\r
+\r
+ mov eax, [F1]\r
+ imul [F2]\r
+ shr eax, 16\r
+\r
+ ret\r
+tdFixedMul ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+ push esi\r
+ push edi\r
+\r
+ add eax, eax\r
+ adc edx, 0\r
+ mov eax, edx ; Just discard the low bits\r
+\r
+ mov esi, eax\r
+ xor edi, edi\r
+ shld edi, esi, 16\r
+ shl esi, 16\r
+@@Loop:\r
+ mov ebx, eax\r
+ mul eax\r
+ add eax, esi\r
+ adc edx, edi\r
+ shrd eax, edx, 1\r
+ shr edx, 1\r
+ div ebx\r
+ cmp eax, ebx\r
+ jne @@Loop\r
+\r
+; Adjust EAX\r
+ shl eax, 8\r
+\r
+ pop edi\r
+ pop esi\r
+ ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+; Dest = pointer to TPOINT (vector) result\r
+; P1, P2, P3 = pointer to TPOINT points on surface\r
+; Output:\r
+; none\r
+; Notes:\r
+; the normal is given by the cross-product between (P3-P1) and\r
+; (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal PROC PASCAL FAR\r
+ ARG Dest:DWORD, \\r
+ P1:DWORD, \\r
+ P2:DWORD, \\r
+ P3:DWORD\r
+ LOCAL V1:TPOINT, \\r
+ V2:TPOINT, \\r
+ N:TPOINT\r
+ USES ds, si, es, di\r
+\r
+; Get vector V1\r
+ lds si, [P1]\r
+ les di, [P3]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V1.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V1.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V1.Z], eax\r
+\r
+; Get vector V2\r
+ les di, [P2]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V2.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V2.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+ mov eax, [V1.Z]\r
+ imul [V2.Y]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Y]\r
+ imul [V2.Z]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.X], eax\r
+\r
+ mov eax, [V1.X]\r
+ imul [V2.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Z]\r
+ imul [V2.X]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Y], eax\r
+\r
+ mov eax, [V1.Y]\r
+ imul [V2.X]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.X]\r
+ imul [V2.Y]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Z], eax\r
+\r
+; Get normal length\r
+ mov eax, [N.X]\r
+ imul eax\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [N.Y]\r
+ imul eax\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, [N.Z]\r
+ imul eax\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+ call subSqrt ; EAX = normal length\r
+ mov ebx, eax\r
+\r
+; Adjust vector and save it\r
+ les di, [Dest]\r
+ mov eax, [N.X]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].X, eax\r
+ mov eax, [N.Y]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Y, eax\r
+ mov eax, [N.Z]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Z, eax\r
+\r
+ ret\r
+tdGetNormal ENDP\r
+\r
+TPOLY STRUC\r
+ Vtx DW 4 DUP(?)\r
+TPOLY ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+; Poly = pointer to an array of TPOLY\r
+; Vertex = pointer to an array of TPOINT\r
+; Dest = pointer to an array of integer\r
+; Count = number of polygons to check\r
+; Step = size of TPOLY structure\r
+; Output:\r
+; if the n-th polygon is invisible the n-th entry of the\r
+; Dest array is set to -1, other entries are not modified\r
+; (so it's possible to use the Light array for Dest, because\r
+; the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+ ARG Step:WORD, \\r
+ Poly:DWORD, \\r
+ Vertex:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ds, WORD PTR Vertex[2]\r
+ les di, [Poly]\r
+ mov fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+ mov ax, es:[di].Vtx[2] ; Index of 2nd vertex\r
+ shl ax, 2\r
+ mov bx, ax\r
+ shl ax, 1\r
+ add bx, ax ; BX = index*SIZE TPOINT\r
+ add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex\r
+ mov ax, es:[di].Vtx[4] ; Index of 3rd vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex\r
+ mov ecx, ds:[si].X\r
+ sub ecx, ds:[bx].X ; ECX = V3.X-V2.X\r
+ mov edx, ds:[si].Y\r
+ sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y\r
+ mov ax, es:[di].Vtx[0] ; Index of 1st vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 1st vertex\r
+ mov eax, ds:[si].X\r
+ sub eax, ds:[bx].X ; EAX = V1.X-V2.X\r
+ mov esi, ds:[si].Y\r
+ sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y\r
+ imul edx\r
+ mov ebx, eax\r
+ xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+ mov eax, esi\r
+ imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ jl @@Next ; Polygon is visible\r
+ mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry\r
+ mov WORD PTR fs:[bx], -1 ; Remove polygon\r
+@@Next:\r
+ add WORD PTR [Dest], 2 ; Next entry for dest\r
+ add di, [Step] ; Next polygon\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT ENDS\r
+END\r
--- /dev/null
+typedef struct {\r
+ long x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT TVECTOR\r
+#define PPOINT PVECTOR\r
+\r
+#define VPTR void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+unit ThreeD;\r
+interface\r
+\r
+type\r
+ TVector = record\r
+ X, Y, Z : longint;\r
+ end;\r
+ TPoint = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight; external;\r
+procedure tdSetRotation( RX, RY, RZ: word ); external;\r
+procedure tdGetNormal; external;\r
+procedure tdSetTranslation( var TV: TVector ); external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate; external;\r
+function tdTransformToImage; external;\r
+procedure tdSetLight( var Light: TVector ); external;\r
+procedure tdSetPerspective; external;\r
+procedure tdTransformLight; external;\r
+function tdFixedMul( F1, F2: longint ): longint; external;\r
+procedure tdBackPlaneCull; external;\r
+{$L THREED}\r
+\r
+end.\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxBitBlt\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN subHorizontalLineInfo : NEAR\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+; SX, SY = source coordinates\r
+; Width = source width\r
+; Height = source height\r
+; DX, DY = destination coordinates\r
+; Output:\r
+; none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt PROC FAR\r
+ ARG DestY:WORD, \\r
+ DestX:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ SY:WORD, \\r
+ SX:WORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ SourceOffset:WORD, \\r
+ DestOffset:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ WritePlane:BYTE, \\r
+ LeftMask:BYTE, \\r
+ RightMask:BYTE = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Exit now if null width\r
+ cmp [Width], 0\r
+ je @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+ mov ax, [SX]\r
+ and al, 03h ; AL = source plane\r
+ mov dx, [DestX]\r
+ and dl, 03h ; DL = destination plane\r
+ mov bx, OFFSET subPlaneBlt\r
+ cmp al, dl ; Same source and destination plane?\r
+ jne @@BitBlt ; No, use slow procedure\r
+ mov bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+ call bx\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt PROC NEAR\r
+; Get horizontal line info and address of destination\r
+ mov bx, [DestX]\r
+ mov ax, [DestY]\r
+ mov cx, [Width]\r
+ call subHorizontalLineInfo\r
+ mov [LeftMask], al\r
+ mov [RightMask], ah\r
+ mov [Width], cx\r
+\r
+; Setup segments\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov es, ax\r
+\r
+; Get address of source pixel\r
+ mov ax, [SY]\r
+ mul [mx_BytesPerLine]\r
+ mov si, [SX]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+; Set write mode 1\r
+ mov dx, GDC\r
+ mov ax, 4105h\r
+ out dx, ax\r
+ cld\r
+\r
+; Move left block\r
+@@L0:\r
+ mov ah, [LeftMask]\r
+ or ah, ah\r
+ jz @@C0\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov ax, [mx_BytesPerLine]\r
+ dec ax\r
+ mov cx, [Height]\r
+ .push si, di\r
+@@L1:\r
+ movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec cx\r
+ jnz @@L1\r
+ .pop si, di\r
+ inc si\r
+ inc di\r
+\r
+; Move center block\r
+@@C0:\r
+ mov bx, [Width]\r
+ test bx, bx\r
+ jz @@R0\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Enable all planes\r
+ mov ax, [mx_BytesPerLine]\r
+ sub ax, bx\r
+ mov dx, [Height]\r
+ .push si, di\r
+@@C1:\r
+ mov cx, bx ; CX = image width\r
+ rep movsb ; Cannot use "movsw" here!\r
+ add si, ax ; Next scan line\r
+ add di, ax ; Next scan line\r
+ dec dx ; All lines processed?\r
+ jnz @@C1 ; No, continue\r
+ .pop si, di\r
+ add si, bx\r
+ add di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+ mov ah, [RightMask]\r
+ or ah, ah\r
+ jz @@Done\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov ax, [mx_BytesPerLine]\r
+ dec ax\r
+ mov cx, [Height]\r
+@@R1:\r
+ movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec cx\r
+ jnz @@R1\r
+\r
+@@Done:\r
+ mov dx, GDC\r
+ mov ax, 4005h\r
+ out dx, ax ; Restore write mode 0\r
+\r
+@@Exit:\r
+ ret\r
+subMoveBlt ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt PROC NEAR\r
+; Compute extra bytes and width count for each plane\r
+ mov cx, [Width]\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Get pixel addresses\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov es, ax\r
+ mov ax, [SY]\r
+ mul [mx_BytesPerLine]\r
+ mov si, [SX]\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax ; DS:SI points to source\r
+ mov [SourceOffset], si\r
+ mov ax, [DestY]\r
+ mul [mx_BytesPerLine]\r
+ mov di, [DestX]\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax ; ES:DI points to destination\r
+ mov [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+ mov ax, [SX]\r
+ and al, 03h\r
+ mov [ReadPlane], al\r
+ mov cx, [DestX]\r
+ and cl, 03h\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Ready to move now\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0\r
+ je @@Done\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov ax, [mx_BytesPerLine]\r
+ sub ax, ss:[bx] ; AX = extra bytes per line\r
+@@Loop:\r
+ mov cx, ss:[bx]\r
+ shr cx, 1\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ and [ReadPlane], 03h ; Should be faster on 386 using\r
+ jnz @@ReadPlaneOk ; BTR and ADC...\r
+ inc [SourceOffset]\r
+@@ReadPlaneOk:\r
+ rol [WritePlane], 1\r
+ adc [DestOffset], 0\r
+ mov si, [SourceOffset]\r
+ mov di, [DestOffset]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Done:\r
+ ret\r
+subPlaneBlt ENDP\r
+\r
+mxBitBlt ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCC.ASM - Fast clip line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC xsubClipLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+tblGroups LABEL WORD\r
+ DW 10, tbl00\r
+ DW 10, tbl10\r
+ DW 9, tbl20\r
+ DW -1, 0\r
+ DW 10, tbl40\r
+ DW 10, tbl50\r
+ DW 9, tbl60\r
+ DW -1, 0\r
+ DW 6, tbl80\r
+ DW 6, tbl90\r
+ DW 5, tblA0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+tbl00 DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A\r
+tbl10 DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A\r
+tbl20 DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29\r
+tbl40 DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A\r
+tbl50 DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A\r
+tbl60 DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69\r
+tbl80 DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86\r
+tbl90 DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96\r
+tblA0 DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5\r
+\r
+ccTT: clc\r
+ ret\r
+ccFF: stc\r
+ ret\r
+\r
+; Group 00 -------------------------------------------------\r
+;\r
+cc00:\r
+ clc\r
+ ret\r
+cc01:\r
+ jmp ClipQLeft\r
+cc02:\r
+ jmp ClipQRight\r
+cc04:\r
+ jmp ClipQTop\r
+cc05:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge ccTT\r
+ jmp ClipQTop\r
+cc06:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jge ccTT\r
+ jmp ClipQTop\r
+cc08:\r
+ jmp ClipQBottom\r
+cc09:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jle ccTT\r
+ jmp ClipQBottom\r
+cc0A:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jle ccTT\r
+ jmp ClipQBottom\r
+\r
+; Group 10 -------------------------------------------------\r
+;\r
+cc10FF:\r
+ stc\r
+ ret\r
+cc10TT:\r
+ clc\r
+ ret\r
+cc10:\r
+ jmp ClipPLeft\r
+cc12:\r
+ call ClipPLeft\r
+ jmp ClipQRight\r
+cc14:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc10FF\r
+ jmp ClipQTop\r
+cc16:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc10FF\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX2]\r
+ jle cc10TT\r
+ jmp ClipQRight\r
+cc18:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc10FF\r
+ jmp ClipQBottom\r
+cc1A:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc10FF\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX2]\r
+ jle cc10TT\r
+ jmp ClipQRight\r
+\r
+; Group 20 -------------------------------------------------\r
+;\r
+cc20TT:\r
+ clc\r
+ ret\r
+cc20FF:\r
+ stc\r
+ ret\r
+cc20:\r
+ jmp ClipPRight\r
+cc21:\r
+ call ClipPRight\r
+ jmp ClipQLeft\r
+cc24:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc20FF\r
+ jmp ClipQTop\r
+cc25:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc20FF\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX1]\r
+ jge cc20TT\r
+ jmp ClipQLeft\r
+cc28:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc20FF\r
+ jmp ClipQBottom\r
+cc29:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc20FF\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX1]\r
+ jge cc20TT\r
+ jmp ClipQLeft\r
+\r
+; Group 40 -------------------------------------------------\r
+;\r
+cc40TT:\r
+ clc\r
+ ret\r
+cc40FF:\r
+ stc\r
+ ret\r
+cc40:\r
+ jmp ClipPTop\r
+cc41:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jl cc40FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge cc40TT\r
+ jmp ClipQTop\r
+cc42:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jg cc40FF\r
+ jmp ClipQRight\r
+cc48:\r
+ call ClipPTop\r
+ jmp ClipQBottom\r
+cc49:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jl cc40FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jle cc40TT\r
+ jmp ClipQBottom\r
+cc4A:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jg cc40FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jle cc40TT\r
+ jmp ClipQBottom\r
+\r
+\r
+; Group 50 -------------------------------------------------\r
+;\r
+cc50TT:\r
+ clc\r
+ ret\r
+cc50FF:\r
+ stc\r
+ ret\r
+cc50:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc50TT\r
+ jmp ClipPTop\r
+cc52:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jl cc50FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jge cc50TT\r
+ jmp ClipPLeft\r
+cc58:\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX1]\r
+ jl cc50FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jge cc50TT\r
+ jmp ClipPLeft\r
+cc5A:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc50FF\r
+ call ClipQRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc50FF\r
+ cmp si, [mx_ClipY2]\r
+ jle cc50TT\r
+ jmp ClipQBottom\r
+\r
+; Group 60 -------------------------------------------------\r
+;\r
+cc60TT:\r
+ clc\r
+ ret\r
+cc60FF:\r
+ stc\r
+ ret\r
+cc60:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+cc61:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jl cc60FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jle cc60TT\r
+ jmp ClipPRight\r
+cc68:\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX2]\r
+ jg cc60FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+cc69:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jl cc60FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc60FF\r
+ cmp si, [mx_ClipY2]\r
+ jle cc69_1\r
+ call ClipQBottom\r
+cc69_1:\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+\r
+; Group 80 -------------------------------------------------\r
+;\r
+cc80TT:\r
+ clc\r
+ ret\r
+cc80FF:\r
+ stc\r
+ ret\r
+cc80:\r
+ jmp ClipPBottom\r
+cc81:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jl cc80FF\r
+ jmp ClipQLeft\r
+cc82:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jg cc80FF\r
+ jmp ClipQRight\r
+cc84:\r
+ call ClipPBottom\r
+ jmp ClipQTop\r
+cc85:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jl cc80FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge cc80FF\r
+ jmp ClipQTop\r
+cc86:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jg cc80FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jge cc80TT\r
+ jmp ClipQTop\r
+\r
+; Group 90 -------------------------------------------------\r
+;\r
+cc90TT:\r
+ clc\r
+ ret\r
+cc90FF:\r
+ stc\r
+ ret\r
+cc90:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc90TT\r
+ jmp ClipPBottom\r
+cc92:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jg cc90FF\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jge cc90TT\r
+ jmp ClipPLeft\r
+cc94:\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX1]\r
+ jl cc90FF\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc90TT\r
+ jmp ClipPBottom\r
+cc96:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc90FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jg cc90FF\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc96_1\r
+ call ClipPBottom\r
+cc96_1:\r
+ cmp si, [mx_ClipY1]\r
+ jge cc90TT\r
+ jmp ClipQTop\r
+\r
+; Group A0 -------------------------------------------------\r
+;\r
+ccA0TT:\r
+ clc\r
+ ret\r
+ccA0FF:\r
+ stc\r
+ ret\r
+ccA0:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+ccA1:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jg ccA0FF\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jle ccA0TT\r
+ jmp ClipPRight\r
+ccA4:\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX2]\r
+ jg ccA0FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+ccA5:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jg ccA0FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl ccA0FF\r
+ cmp si, [mx_ClipY1]\r
+ jge ccA5_1\r
+ call ClipQTop\r
+ccA5_1:\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX1\r
+ClipPLeft:\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov dx, [mx_ClipX1]\r
+ sub dx, di\r
+ imul dx\r
+ mov bp, cx\r
+ sub bp, di\r
+ idiv bp\r
+ add bx, ax\r
+ mov di, [mx_ClipX1]\r
+ clc\r
+ ret\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX2\r
+ClipPRight:\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov dx, [mx_ClipX2]\r
+ sub dx, di\r
+ imul dx\r
+ mov bp, cx\r
+ sub bp, di\r
+ idiv bp\r
+ add bx, ax\r
+ mov di, [mx_ClipX2]\r
+ clc\r
+ ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY2\r
+ClipPBottom:\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov dx, [mx_ClipY2]\r
+ sub dx, bx\r
+ imul dx\r
+ mov bp, si\r
+ sub bp, bx\r
+ idiv bp\r
+ add di, ax\r
+ mov bx, [mx_ClipY2]\r
+ clc\r
+ ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY1\r
+ClipPTop:\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov dx, [mx_ClipY1]\r
+ sub dx, bx\r
+ imul dx\r
+ mov bp, si\r
+ sub bp, bx\r
+ idiv bp\r
+ add di, ax\r
+ mov bx, [mx_ClipY1]\r
+ clc\r
+ ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQLeft:\r
+ mov ax, bx\r
+ sub ax, si\r
+ mov dx, [mx_ClipX1]\r
+ sub dx, cx\r
+ imul dx\r
+ mov bp, di\r
+ sub bp, cx\r
+ idiv bp\r
+ add si, ax\r
+ mov cx, [mx_ClipX1]\r
+ clc\r
+ ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQRight:\r
+ mov ax, bx\r
+ sub ax, si\r
+ mov dx, [mx_ClipX2]\r
+ sub dx, cx\r
+ imul dx\r
+ mov bp, di\r
+ sub bp, cx\r
+ idiv bp\r
+ add si, ax\r
+ mov cx, [mx_ClipX2]\r
+ clc\r
+ ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQBottom:\r
+ mov ax, di\r
+ sub ax, cx\r
+ mov dx, [mx_ClipY2]\r
+ sub dx, si\r
+ imul dx\r
+ mov bp, bx\r
+ sub bp, si\r
+ idiv bp\r
+ add cx, ax\r
+ mov si, [mx_ClipY2]\r
+ clc\r
+ ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQTop:\r
+ mov ax, di\r
+ sub ax, cx\r
+ mov dx, [mx_ClipY1]\r
+ sub dx, si\r
+ imul dx\r
+ mov bp, bx\r
+ sub bp, si\r
+ idiv bp\r
+ add cx, ax\r
+ mov si, [mx_ClipY1]\r
+ clc\r
+ ret\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was\r
+; supposed to be twice as fast as Cohen-Sutherland, but my\r
+; tests show only a very small increase in speed and a noticeable\r
+; increase of the program size! Maybe this is caused by the\r
+; slow speed of VGA cards, so probably a better test should\r
+; be performed with lines drawn in RAM.\r
+;\r
+; Input:\r
+; AX, BX = X1, Y1\r
+; CX, DX = X2, Y2\r
+; Output:\r
+; CF = set if line is full clipped\r
+; AX, BX = clipped X1, Y1\r
+; CX, DX = clipped X2, Y2\r
+; Note:\r
+; destroys SI, DI\r
+;\r
+xsubClipLine PROC NEAR\r
+ push bp\r
+ xor si, si ; SPY code\r
+\r
+ cmp dx, [mx_ClipY2]\r
+ jle @@1\r
+ or si, 08h\r
+ jmp @@2\r
+@@1:\r
+ cmp dx, [mx_ClipY1]\r
+ jge @@2\r
+ or si, 04h\r
+@@2:\r
+\r
+ cmp cx, [mx_ClipX2]\r
+ jle @@3\r
+ or si, 02h\r
+ jmp @@4\r
+@@3:\r
+ cmp cx, [mx_ClipX1]\r
+ jge @@4\r
+ or si, 01h\r
+@@4:\r
+\r
+ cmp bx, [mx_ClipY2]\r
+ jle @@5\r
+ or si, 80h\r
+ jmp @@6\r
+@@5:\r
+ cmp bx, [mx_ClipY1]\r
+ jge @@6\r
+ or si, 40h\r
+@@6:\r
+\r
+ cmp ax, [mx_ClipX2]\r
+ jle @@7\r
+ or si, 20h\r
+ jmp @@8\r
+@@7:\r
+ cmp ax, [mx_ClipX1]\r
+ jge @@8\r
+ or si, 10h\r
+@@8:\r
+\r
+ mov di, si\r
+ and di, 000Fh ; Index of procedure\r
+ and si, 00F0h\r
+ .shr si, 2 ; Index of group (times 4)\r
+ cmp di, cs:tblGroups[si] ; Is index within range?\r
+ jg @@Exit ; No, line is full clipped\r
+ mov si, cs:tblGroups[si+2] ; Get offset of group table\r
+ shl di, 1 ; We must index word elements\r
+ add si, di ; Make full offset\r
+ mov di, ax ; Move X1 to DI and free AX\r
+ mov si, cs:[si] ; Get subroutine address\r
+ xchg dx, si ; Move Y2 to SI and free DX\r
+ call dx ; Call the proper subroutine\r
+ mov ax, di ; Restore AX to X1\r
+ mov dx, si ; Restore DX to Y2\r
+ pop bp\r
+ ret\r
+\r
+@@Exit:\r
+ pop bp\r
+ stc\r
+ ret\r
+xsubClipLine ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCG.ASM - Color to gray conversion\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxColorToGray\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Converts RGB colors to gray shades.\r
+;\r
+; Input:\r
+; CPal = pointer to color palette\r
+; GPal = pointer to destination (gray) palette\r
+; Count = number of colors to convert\r
+; Output:\r
+; none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxColorToGray PROC FAR\r
+ ARG Count:WORD, \\r
+ DPal:DWORD, \\r
+ SPal:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov cx, [Count]\r
+ jcxz @@Exit\r
+ lds si, [SPal]\r
+ les di, [DPal]\r
+ cld\r
+; We use the standard formula\r
+; gray=(red*30 + green*59 + blue*11)/100\r
+; in the equivalent form\r
+; gray=(red*77 + green*151 + blue*28)/256\r
+; which doesn't need the last divide.\r
+ mov bx, 77 SHL 8 + 151\r
+@@Loop:\r
+ lodsb ; Red\r
+ mul bh\r
+ mov dx, ax\r
+ lodsb ; Green\r
+ mul bl\r
+ add dx, ax\r
+ lodsb ; Blue\r
+ mov ah, 28\r
+ mul ah\r
+ add ax, dx\r
+ mov al, ah\r
+ stosw ; Save new RGB\r
+ stosb\r
+ loop @@Loop\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxColorToGray ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCL.ASM - Bresenham circle\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxCircle\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a circle using the Bresenham algorithm.\r
+;\r
+; Input:\r
+; XC, YC = center coordinates\r
+; Radius = circle radius\r
+; Color = circle color\r
+; Output:\r
+; none\r
+; Note:\r
+; computes only points in the first octant, all other\r
+; points are obtained by symmetry.\r
+;\r
+mxCircle PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ Radius:WORD, \\r
+ YC:WORD, \\r
+ XC:WORD = ARG_SIZE\r
+ LOCAL Delta:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+\r
+ xor si, si ; X\r
+ mov di, [Radius] ; Y\r
+ mov ax, 3\r
+ sub ax, di\r
+ sub ax, di\r
+ mov [Delta], ax ; Delta = 3-R*2\r
+\r
+ mov ds, [mx_VideoSegment]\r
+\r
+@@Loop:\r
+ cmp si, di ;\r
+ jg @@Done ; Exit when X > Y\r
+; Draw points\r
+ mov ax, si\r
+ mov bx, di\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ neg ax\r
+ mov bx, di\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ mov bx, di\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ neg ax\r
+ mov bx, di\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ mov bx, si\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ neg ax\r
+ mov bx, si\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ mov bx, si\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ neg ax\r
+ mov bx, si\r
+ neg bx\r
+ call @@subPutPixel\r
+; Moves coordinates to next point\r
+ mov ax, [Delta]\r
+ test ax, ax\r
+ jl @@Next\r
+ mov ax, di\r
+ .shl ax, 2\r
+ sub ax, 4\r
+ sub [Delta], ax\r
+ dec di\r
+@@Next:\r
+ mov ax, si\r
+ .shl ax, 2\r
+ add ax, 6\r
+ add [Delta], ax\r
+ inc si\r
+ jmp @@Loop\r
+\r
+@@Done:\r
+ xor ax, ax\r
+ .pop ds, si, di\r
+ .leave ARG_SIZE\r
+\r
+;---------------------------------------\r
+; Put pixel function.\r
+; Input:\r
+; BX = X coordinate (relative to center)\r
+; AX = Y coordinate (relative to center)\r
+; DS = video segment\r
+@@subPutPixel:\r
+ add bx, [XC] ; Get absolute coordinates\r
+ add ax, [YC]\r
+\r
+ cmp bx, [mx_ClipX1] ; Clip pixel\r
+ jl @@subExit\r
+ cmp bx, [mx_ClipX2]\r
+ jg @@subExit\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@subExit\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@subExit\r
+\r
+ mul [mx_BytesPerLine] ; Get pixel offset\r
+ mov cx, bx ; Save X coordinate\r
+ .shr bx, 2\r
+ add bx, ax ; DS:BX = pixel offset\r
+\r
+ and cl, 3 ; Set write plane\r
+ mov ax, 0102h\r
+ shl ah, cl\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ mov al, [Color] ; Write pixel\r
+ mov ds:[bx], al\r
+\r
+@@subExit:\r
+ retn\r
+mxCircle ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCR.ASM - Clip functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetSysClipRegion\r
+PUBLIC mxGetClipRegion\r
+PUBLIC mxSetClipRegion\r
+PUBLIC mxSetClip\r
+PUBLIC mxGetClip\r
+\r
+PUBLIC subClipBox\r
+PUBLIC subClipImage\r
+\r
+PUBLIC mx_ClipX1\r
+PUBLIC mx_ClipY1\r
+PUBLIC mx_ClipX2\r
+PUBLIC mx_ClipY2\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_ClipX1 DW ? ; Clip coordinates\r
+mx_ClipY1 DW ?\r
+mx_ClipX2 DW ?\r
+mx_ClipY2 DW ?\r
+\r
+mx_SysClipX1 DW ? ; System clip coordinates\r
+mx_SysClipY1 DW ? ; (active when mx_ClipStatus is FALSE)\r
+mx_SysClipX2 DW ?\r
+mx_SysClipY2 DW ?\r
+\r
+mx_UserClipX1 DW ? ; User clip coordinates\r
+mx_UserClipY1 DW ? ; (active when mx_ClipStatus is TRUE)\r
+mx_UserClipX2 DW ?\r
+mx_UserClipY2 DW ?\r
+\r
+mx_ClipStatus DB ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Toggles clipping between user and system regions.\r
+;\r
+; Input:\r
+; ClipStatus = TRUE (FALSE) to enable (disable) clipping\r
+; Output:\r
+; AX = old clip status\r
+;\r
+mxSetClip PROC FAR\r
+ ARG ClipStatus:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [mx_UserClipX1]\r
+ mov bx, [mx_UserClipY1]\r
+ mov cx, [mx_UserClipX2]\r
+ mov dx, [mx_UserClipY2]\r
+ cmp [ClipStatus], TRUE\r
+ je @@Done\r
+ mov ax, [mx_SysClipX1]\r
+ mov bx, [mx_SysClipY1]\r
+ mov cx, [mx_SysClipX2]\r
+ mov dx, [mx_SysClipY2]\r
+@@Done:\r
+ mov [mx_ClipX1], ax\r
+ mov [mx_ClipY1], bx\r
+ mov [mx_ClipX2], cx\r
+ mov [mx_ClipY2], dx\r
+\r
+ mov al, [ClipStatus]\r
+ xchg al, [mx_ClipStatus]\r
+ xor ah, ah\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetClip ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current clipping status.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; TRUE (FALSE) if clipping enabled (disabled)\r
+;\r
+mxGetClip PROC FAR\r
+ ASSUME ds:NOTHING\r
+ mov al, [mx_ClipStatus]\r
+ xor ah, ah\r
+ ret\r
+mxGetClip ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the system clip region and disables user clipping.\r
+;\r
+; Input:\r
+; Width = width in pixels of clip region\r
+; Height = height in pixels of clip region\r
+; Output:\r
+; old clip status.\r
+;\r
+mxSetSysClipRegion PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ xor ax, ax ; Sys clip region always starts at (0,0)\r
+ mov [mx_SysClipX1], ax\r
+ mov [mx_SysClipY1], ax\r
+ mov ax, [Width]\r
+ dec ax\r
+ mov [mx_SysClipX2], ax\r
+ mov ax, [Height]\r
+ dec ax\r
+ mov [mx_SysClipY2], ax\r
+\r
+ IF USE286 EQ TRUE\r
+ push FALSE\r
+ ELSE\r
+ mov ax, FALSE\r
+ push ax\r
+ ENDIF\r
+ call mxSetClip\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetSysClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the clip region.\r
+;\r
+; Input:\r
+; X, Y = coordinates of top left corner of clip region\r
+; Width = width in pixels of clip region\r
+; Height = height in pixels of clip region\r
+; Output:\r
+; none (no checking on parameters)\r
+;\r
+mxSetClipRegion PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [X]\r
+ mov [mx_UserClipX1], ax\r
+ mov ax, [Y]\r
+ mov [mx_UserClipY1], ax\r
+ mov ax, [Width]\r
+ add ax, [X]\r
+ dec ax\r
+ mov [mx_UserClipX2], ax\r
+ mov ax, [Height]\r
+ add ax, [Y]\r
+ dec ax\r
+ mov [mx_UserClipY2], ax\r
+\r
+ mov al, [mx_ClipStatus]\r
+ cmp al, TRUE\r
+ jne @@Exit\r
+ push ax\r
+ call mxSetClip\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current user clip region.\r
+;\r
+; Input:\r
+; X, Y = pointers to integer coordinates of top left corner\r
+; Width = pointer to word width of clip region\r
+; Height = pointer to word height of clip region\r
+; Output:\r
+; AX = current clip status\r
+;\r
+mxGetClipRegion PROC FAR\r
+ ARG Height:DWORD, \\r
+ Width:DWORD, \\r
+ Y:DWORD, \\r
+ X:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push es, di\r
+\r
+ mov ax, [mx_UserClipX1]\r
+ les di, [X]\r
+ mov es:[di], ax\r
+ mov ax, [mx_UserClipY1]\r
+ les di, [Y]\r
+ mov es:[di], ax\r
+\r
+ mov ax, [mx_UserClipX2]\r
+ sub ax, [mx_UserClipX1]\r
+ inc ax\r
+ les di, [Width]\r
+ mov es:[di], ax\r
+ mov ax, [mx_UserClipY2]\r
+ sub ax, [mx_UserClipY1]\r
+ inc ax\r
+ les di, [Height]\r
+ mov es:[di], ax\r
+\r
+ mov al, [mx_ClipStatus]\r
+ xor ah, ah\r
+ .pop es, di\r
+ .leave ARG_SIZE\r
+mxGetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+; This function assumes that a "raw" image has to be clipped,\r
+; so it returns in SI the number of "raw" bytes to skip if\r
+; X, Y were clipped.\r
+;\r
+; Input:\r
+; BX, AX = X, Y coordinates of rectangle (signed)\r
+; CX = box width\r
+; DX = box height\r
+; Output:\r
+; CF = set if rectangle is full clipped\r
+; BX, AX = new X, Y coordinates of rectangle\r
+; CX, DX = clipped width and height\r
+; SI = number of bytes to skip before copying a buffer\r
+; DI destroyed\r
+;\r
+subClipImage PROC NEAR\r
+ ASSUME ds:NOTHING\r
+ xor si, si\r
+\r
+; Check clip height\r
+ mov di, [mx_ClipY1]\r
+ cmp ax, di\r
+ jge @@CheckBottom\r
+ sub di, ax ; Number of lines to clip\r
+ sub dx, di ; New box height\r
+ jle @@Exit\r
+ mov ax, di\r
+ mov di, dx ; Save box height into DI\r
+ mul cx ; DX:AX = number of bytes to skip\r
+ mov si, ax\r
+ mov dx, di ; Restore box height\r
+ mov ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+ mov di, [mx_ClipY2]\r
+ cmp ax, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, dx\r
+ sub di, ax\r
+ jge @@DoneHeight ; None, continue\r
+ add dx, di ; Clip lines\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+ mov di, [mx_ClipX1]\r
+ cmp bx, di\r
+ jge @@CheckRight\r
+ sub di, bx ; Number of columns to clip left\r
+ sub cx, di\r
+ jle @@Exit\r
+ add si, di ; Update skip count\r
+ mov bx, [mx_ClipX1]\r
+@@CheckRight:\r
+ mov di, [mx_ClipX2]\r
+ cmp bx, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, bx\r
+ sub di, cx\r
+ jge @@DoneWidth ; None, exit\r
+ add cx, di ; New box width\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+ clc\r
+ ret\r
+@@Exit:\r
+ stc\r
+ ret\r
+subClipImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+;\r
+; Input:\r
+; BX, AX = X, Y coordinates of rectangle (signed)\r
+; CX = box width\r
+; DX = box height\r
+; Output:\r
+; CF = set if rectangle is full clipped\r
+; BX, AX = new X, Y coordinates of rectangle\r
+; CX, DX = clipped width and height\r
+; DI destroyed\r
+;\r
+subClipBox PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+; Check clip height\r
+ mov di, [mx_ClipY1]\r
+ cmp ax, di\r
+ jge @@CheckBottom\r
+ sub di, ax ; Number of lines to clip\r
+ sub dx, di ; New box height\r
+ jle @@Exit\r
+ mov ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+ mov di, [mx_ClipY2]\r
+ cmp ax, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, dx\r
+ sub di, ax ; Clipped some point?\r
+ jge @@DoneHeight ; No, continue\r
+ add dx, di ; Clip lines (DI is negative)\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+ mov di, [mx_ClipX1]\r
+ cmp bx, di\r
+ jge @@CheckRight\r
+ sub di, bx ; Number of columns to clip left\r
+ sub cx, di\r
+ jle @@Exit\r
+ mov bx, [mx_ClipX1]\r
+@@CheckRight:\r
+ mov di, [mx_ClipX2]\r
+ cmp bx, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, bx\r
+ sub di, cx ; Clipped some point?\r
+ jge @@DoneWidth ; No, exit\r
+ add cx, di ; New box width (DI is negative)\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+ clc\r
+ ret\r
+@@Exit:\r
+ stc\r
+ ret\r
+subClipBox ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXEL.ASM - Mid-point ellipse\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxEllipse\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws an ellipse using the mid-point algorithm.\r
+;\r
+; Input:\r
+; XC, YC = center coordinates\r
+; A = horizontal radius\r
+; B = vertical radius\r
+; Color = ellipse color\r
+; Output:\r
+; none\r
+; Note:\r
+; computes only points in the first quadrant, all other\r
+; points are obtained by symmetry.\r
+;\r
+mxEllipse PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ B:WORD, \\r
+ A:WORD, \\r
+ YC:WORD, \\r
+ XC:WORD = ARG_SIZE\r
+ LOCAL A2:DWORD, \\r
+ B2:DWORD, \\r
+ CC:DWORD, \\r
+ DD:DWORD, \\r
+ X:DWORD, \\r
+ Y:DWORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+\r
+ .chk386 mxEllipse, @@Exit\r
+\r
+; Initialize variables\r
+ xor eax, eax\r
+ mov [X], ax ; X = 0\r
+ mov ax, [A]\r
+ mul eax ; EAX = A*A\r
+ mov [DD], eax ; DD = A*A\r
+ shl eax, 1\r
+ mov [CC], eax ; CC = 2*A*A\r
+ shl eax, 1\r
+ mov [A2], eax ; A2 = 4*A*A\r
+ movzx edx, [B]\r
+ mov [Y], edx\r
+ mul edx ; EAX = 4*A*A*B\r
+ sub [DD], eax ; DD = A*A - 4*A*A*B\r
+ movzx eax, [B]\r
+ mul eax ; EAX = B*B\r
+ shl eax, 2 ; EAX = 4*B*B\r
+ mov [B2], eax ; B2 = 4*B*B\r
+ add [CC], eax ; CC = 2*A*A + 4*B*B\r
+ add [D1], eax ; DD = A*A - 4*A*A*B + 4*B*B\r
+\r
+; Draw initial points\r
+ call subPlot4\r
+\r
+; First loop\r
+@@Loop1:\r
+ mov eax, [X] ; Check slope\r
+ mul [B2]\r
+ mov ecx, eax\r
+ mov eax, [Y]\r
+ mul [A2]\r
+ sub eax, ecx\r
+ sub eax, [CC] ; EAX = Y*A2 - X*B2 - CC\r
+ jle @@Done1 ; Crossed critical point, jump to next loop\r
+\r
+ mov ecx, [DD] ; Get error\r
+ test ecx, ecx ; Positive?\r
+ jl @@Draw1 ; No, use default step\r
+\r
+ mov eax, 1\r
+ sub eax, [Y]\r
+ mul [A2]\r
+ shl eax, 1\r
+ add ecx, eax ; Bump error\r
+ dec WORD PTR [Y] ; Decrement Y coordinate\r
+\r
+@@Draw1:\r
+ mov eax, [X]\r
+ shl eax, 1\r
+ add eax, 3\r
+ mul [B2]\r
+ add ecx, eax ; Bump error\r
+ mov [DD], ecx ; Save error\r
+ inc WORD PTR [X] ; Increment X coordinate\r
+\r
+ call subPlot4 ; Draw points\r
+ jmp @@Loop1\r
+@@Done1:\r
+\r
+; Initialize variables\r
+ shr [B2], 2\r
+ mov eax, [X]\r
+ mul eax\r
+ add [X]\r
+ shl eax, 2\r
+ inc eax\r
+ mul [B2]\r
+ mov [DD], eax\r
+ mov eax, [Y]\r
+ mul eax\r
+ add [Y]\r
+ dec eax\r
+ add [Y]\r
+ sub eax, [B2]\r
+ add [DD], eax\r
+ shl [B2], 3\r
+ inc WORD PTR [X]\r
+\r
+; Second loop\r
+@@Loop2:\r
+ cmp WORD PTR [Y], 0\r
+ ja @@Done2\r
+\r
+ mov ecx, [DD]\r
+ test ecx, ecx\r
+ jge @@Draw2\r
+\r
+ mov eax, [X]\r
+ inc eax\r
+ mul [B2]\r
+ add ecx, eax\r
+ inc WORD PTR [X]\r
+\r
+@@Draw2:\r
+ mov eax, [Y]\r
+ shl eax, 1\r
+ sub eax, 3\r
+ neg eax\r
+ imul [A2]\r
+ add ecx, eax\r
+ dec WORD PTR [Y]\r
+\r
+ call subPlot4\r
+ jmp @@Loop2\r
+@@Done2:\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxEllipse ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXFB.ASM - Fill box function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFillBox\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN subClipBox : NEAR\r
+EXTRN subHorizontalLineInfo : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Raster op functions. Raster op is limited to OP_MOVE,\r
+; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to\r
+; perform the selected logical functions on up to four\r
+; pixel at a time.\r
+;\r
+subRepFill PROC NEAR\r
+ mov ah, al\r
+ shr cx, 1\r
+ rep stosw\r
+ rcl cx, 1\r
+ rep stosb\r
+ ret\r
+subRepFill ENDP\r
+;\r
+subFill PROC NEAR\r
+@@Loop:\r
+ mov ds:[bx], al\r
+ add bx, dx\r
+ loop @@Loop\r
+ ret\r
+subFill ENDP\r
+;\r
+subRepMove PROC NEAR\r
+ mov si, di\r
+@@Loop:\r
+ mov ah, ds:[si] ; Dummy read to latch the data\r
+ mov ds:[si], al\r
+ inc si\r
+ loop @@Loop\r
+ ret\r
+subRepMove ENDP\r
+;\r
+subMove PROC NEAR\r
+@@Loop:\r
+ mov ah, ds:[bx] ; Dummy read to latch the data\r
+ mov ds:[bx], al\r
+ add bx, dx\r
+ loop @@Loop\r
+ ret\r
+subMove ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a rectangle with a specified color.\r
+;\r
+; Input:\r
+; X, Y = X, Y coordinates of rectangle\r
+; Width = width of rectangle\r
+; Height = height of rectangle\r
+; Color = fill color\r
+; Op = raster operator\r
+; Output:\r
+; none\r
+;\r
+; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR.\r
+;\r
+mxFillBox PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:BYTE:2, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL LeftMask:BYTE, \\r
+ RightMask:BYTE, \\r
+ FillFunction:WORD, \\r
+ RepFillFunction:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Clip rectangle\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipBox\r
+ jc @@Exit ; Full clipped\r
+\r
+ mov [Height], dx ; Save clipped height\r
+ call subHorizontalLineInfo ; Get additional info, init DI\r
+ mov [Width], cx\r
+ mov [LeftMask], al\r
+ mov [RightMask], ah\r
+\r
+; Initialize segments\r
+ mov ax, [mx_VideoSegment]\r
+ mov es, ax ; ES:DI points to pixel\r
+ mov ds, ax\r
+ cld ; Clear direction flag\r
+\r
+; Select fill functions\r
+ mov [FillFunction], OFFSET subFill\r
+ mov [RepFillFunction], OFFSET subRepFill\r
+ mov ax, [Op] ; Get raster op\r
+ cmp al, OP_XOR\r
+ ja @@1 ; Assume it's a fill\r
+ cmp al, OP_MOVE\r
+ je @@1\r
+ .shl al, 3\r
+ mov ah, al\r
+ mov al, 03h\r
+ mov dx, GDC\r
+ out dx, ax ; Set GDC logical function\r
+ mov [FillFunction], OFFSET subMove\r
+ mov [RepFillFunction], OFFSET subRepMove\r
+@@1:\r
+\r
+; Fill left block\r
+@@L0:\r
+ mov ah, [LeftMask]\r
+ or ah, ah\r
+ jz @@C0 ; Nothing to do, go to center block\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov dx, [mx_BytesPerLine]\r
+ mov cx, [Height]\r
+ mov bx, di\r
+ mov al, [Color]\r
+ call [FillFunction] ; Fill this column\r
+ inc di ; Update starting video offset\r
+\r
+; Fill center block\r
+@@C0:\r
+ mov cx, [Width]\r
+ jcxz @@R0 ; Nothing to do, go to right block\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Write to all planes\r
+ mov al, [Color]\r
+ mov bx, di\r
+ mov dx, [Height]\r
+ push di ; Save pixel address\r
+@@C1:\r
+ mov di, bx ; Update video offset\r
+ call [RepFillFunction] ; Fill current scan line\r
+ mov cx, [Width] ; Restore byte count\r
+ add bx, [mx_BytesPerLine] ; Bump to next scan line\r
+ dec dx ; Done all lines?\r
+ jnz @@C1 ; No, continue\r
+ pop di ; Restore pixel address\r
+ add di, [Width] ; Go to right block\r
+\r
+; Fill right block\r
+@@R0:\r
+ mov ah, [RightMask]\r
+ or ah, ah\r
+ jz @@Done ; Nothing to do, exit\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov dx, [mx_BytesPerLine]\r
+ mov cx, [Height]\r
+ mov bx, di\r
+ mov al, [Color]\r
+ call [FillFunction] ; Fill this column\r
+\r
+; Restore VGA registers\r
+@@Done:\r
+ mov dx, GDC\r
+ mov ax, 0003h\r
+ out dx, ax ; Set logical function to "move"\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxFillBox ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXFP.ASM - Fade palette function\r
+; Copyright (c) 1992-1994 ARTIS s.r.l.\r
+; Author: Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFadePalette\r
+\r
+MAXCOLOR EQU 256\r
+FADE_IN EQU 0\r
+FADE_OUT EQU 1\r
+\r
+; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
+; the delay between two consecutive passes (FADE_DELAY). Below are the\r
+; default values, used when no parameters are specified.\r
+;\r
+FADE_DELAY EQU 1 ; Vert. retraces between video updates\r
+FADE_SPEED EQU 48 ; Speed of effect (max 127)\r
+\r
+; Bit field record for fade commands\r
+;\r
+FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fades a VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to source/destination palette\r
+; Command = fading direction and optional parameters\r
+; Start = index of first color to fade\r
+; Count = number of color to fade\r
+; Red = destination red\r
+; Green = destination green\r
+; Blue = destination blue\r
+; Output:\r
+; none\r
+; Notes:\r
+; - about 1.5 Kbytes of stack space are needed for internal buffers;\r
+; - the Command argument usually is 0 to fade in and 1 to fade out,\r
+; however additional parameters may be specified. To set the effect\r
+; speed, i.e. the number of iterations needed to completely fade a\r
+; palette, shift the value one bit left and "or" it with the\r
+; direction bit (range is 0..127). To set the delay between two\r
+; consecutive passes, shift it eight bits left (range is 0..255).\r
+;\r
+mxFadePalette PROC FAR\r
+ ARG bBlue:WORD, \\r
+ bGreen:WORD, \\r
+ bRed:WORD, \\r
+ wCount:WORD, \\r
+ wStartIdx:WORD, \\r
+ wCommand:WORD, \\r
+ vfpPalette:DWORD = ARG_SIZE\r
+ LOCAL bSPalette:BYTE:MAXCOLOR*3, \\r
+ bDPalette:BYTE:MAXCOLOR*3, \\r
+ bLoopIndex:BYTE, \\r
+ bLoopStep:BYTE, \\r
+ bLoopCount:BYTE, \\r
+ wDelay:WORD, \\r
+ wSpeed:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push si, di, ds, es ; Save registers\r
+;\r
+; Check parameters and setup variables\r
+;\r
+@@GetDelay:\r
+ mov [wDelay], FADE_DELAY ; Set default delay\r
+ mov ax, [wCommand] ; Get command word\r
+ and ax, MASK fpDELAY ; Mask delay command\r
+ jz @@GetSpeed ; No command, get speed\r
+ IF USE286 EQ TRUE\r
+ shr ax, fpDELAY\r
+ ELSE\r
+ mov cl, fpDELAY ; Get size of delay field\r
+ shr ax, cl ; Right justify the field\r
+ ENDIF\r
+ mov [wDelay], ax ; Set new delay\r
+\r
+@@GetSpeed:\r
+ mov ax, [wCommand] ; Get command\r
+ and ax, MASK fpSPEED ; Mask speed\r
+ IF USE286 EQ TRUE\r
+ shr ax, fpSPEED\r
+ ELSE\r
+ mov cl, fpSPEED ; Get size of speed field\r
+ shr ax, cl ; Right justify the field\r
+ ENDIF\r
+ or ax, ax ; Any speed specified?\r
+ jnz @@SetVariables ; Yes, set variables\r
+ mov ax, FADE_SPEED ; Set default speed\r
+\r
+@@SetVariables:\r
+ mov [wSpeed], ax ; Set speed\r
+ inc ax ; Number of iterations\r
+ mov [bLoopCount], al ; Set loop count\r
+ mov [bLoopStep], 1 ; Assume we're fading in\r
+ mov [bLoopIndex], 0\r
+;\r
+; Check bounds for bad values\r
+;\r
+ mov ax, [wStartIdx] ; Get first index\r
+ cmp ax, MAXCOLOR ; Is in the valid range?\r
+ jae @@Exit ; No, exit\r
+ add ax, [wCount] ; Get last index\r
+ cmp ax, MAXCOLOR ; Is in the valid range?\r
+ jbe @@BoundsOk ; Yes, continue\r
+ mov ax, MAXCOLOR\r
+ sub ax, [wStartIdx]\r
+ mov [wCount], ax ; Set count to maximum value\r
+ or ax, ax\r
+ jz @@Exit ; Nothing to do, exit\r
+@@BoundsOk:\r
+;\r
+; Copy the source palette in a local array: if we fade in it's ready to\r
+; use, otherwise we'll overwrite it later\r
+;\r
+ mov cx, [wCount]\r
+ mov ax, cx\r
+ shl ax, 1\r
+ add cx, ax ; CX = wCount * 3\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [bSPalette] ; ES:DI points to local palette\r
+ mov ax, [wStartIdx]\r
+ mov si, ax\r
+ shl ax, 1\r
+ add ax, si\r
+ lds si, [vfpPalette] ; DS:SI points to user palette\r
+ add si, ax ; Skip unused entries\r
+ cld\r
+ shr cx, 1\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+;\r
+; Check direction\r
+;\r
+ test [wCommand], MASK fpDIRECTION ; Are we fading in?\r
+ jz @@Main ; Yes, ok to continue\r
+ mov ax, [wSpeed] ; Get speed\r
+ mov [bLoopIndex], al ; Exchange first and last index\r
+ mov [bLoopStep], -1 ; Move backward\r
+ mov ax, ss ; Overwrite our copy of\r
+ mov ds, ax ; user palette with the\r
+ mov es, ax ; current active palette\r
+ lea di, [bSPalette]\r
+ mov ax, [wStartIdx]\r
+ mov cx, [wCount]\r
+ call ReadPalette ; Read current palette\r
+;\r
+; Prepare variables and registers for fading\r
+;\r
+@@Main:\r
+ mov bh, BYTE PTR [bRed] ; Destination red\r
+ and bh, 00111111b ; Be sure it's a valid VGA value\r
+ mov bl, BYTE PTR [bGreen] ; Destination green\r
+ and bl, 00111111b ; Be sure it's a valid VGA value\r
+ mov dh, BYTE PTR [bBlue] ; Destination blue\r
+ and dh, 00111111b ; Be sure it's a valid VGA value\r
+ mov dl, [bLoopIndex] ; Loop index\r
+ mov ax, ss ; All tables are stored\r
+ mov ds, ax ; in the stack segment,\r
+ mov es, ax ; set DS and ES\r
+;\r
+; Main loop\r
+;\r
+@@Loop:\r
+ mov ax, [wCount] ; Store count in AX\r
+ mov cx, [wSpeed] ; Set maximum speed in CX\r
+ lea si, [bSPalette] ; DS:SI points to source palette\r
+ lea di, [bDPalette] ; ES:DI points to dest. palette\r
+ call RecalcPalette ; Build a faded palette\r
+\r
+ .push bx, dx ; Save registers we need\r
+ lea si, [bDPalette] ; DS:SI points to palette\r
+ mov ax, [wStartIdx] ; First index to write\r
+ mov bx, [wCount] ; Total entries to write\r
+ mov cx, [wDelay] ; Fade delay between updates\r
+ call WritePalette ; Write palette\r
+ .pop bx, dx ; Restore BX and DX\r
+\r
+ add dl, [bLoopStep] ; Change fade intensity\r
+ dec [bLoopCount] ; Done?\r
+ jnz @@Loop ; No, loop again\r
+\r
+@@Exit:\r
+ .pop si, di, ds, es ; Restore registers\r
+ .leave ARG_SIZE\r
+mxFadePalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Calculates a partially faded palette.\r
+;\r
+; Input:\r
+; AX = number of entries in palette\r
+; CX = maximum fade intensity (same as fade speed)\r
+; DS:SI = pointer to source palette\r
+; ES:DI = pointer to destination palette\r
+; BH = destination red\r
+; BL = destination green\r
+; DH = destination blue\r
+; DL = relative intensity of destination palette\r
+; Note:\r
+; it's important that a new palette can be calculated in less\r
+; than 1/70th of second. Fading to any RGB value requires use\r
+; of "imul" instructions: "idiv" may be replaced with faster\r
+; "sar", but only when the number of passes is a power of two,\r
+; thus reducing the range of selectable speeds.\r
+; In both cases an extimate of CPU cycles required by this\r
+; procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
+; CPU and a 256 color palette, so we keep "idiv" and hope\r
+; the target machine to be at least a 6 Mhz 80286 (that's not\r
+; asking too much...).\r
+;\r
+RecalcPalette PROC NEAR\r
+ cld\r
+ push bp ; Save BP\r
+ mov bp, ax ; Copy counter in BP\r
+@@Loop:\r
+ lodsb ; Red: read value\r
+ sub al, bh ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, bh ; Add destination value...\r
+ stosb ; ...and store it\r
+ lodsb ; Green: read value\r
+ sub al, bl ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, bl ; Add destination value...\r
+ stosb ; ...and store it\r
+ lodsb ; Blue: read value\r
+ sub al, dh ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, dh ; Add destination value...\r
+ stosb ; ...and store it\r
+ dec bp\r
+ jnz @@Loop\r
+ pop bp ; Restore BP\r
+ ret\r
+RecalcPalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Writes a 256 color palette.\r
+;\r
+; Input:\r
+; AX = index of first color to write\r
+; BX = number of colors to write (each color is an RGB triplet)\r
+; CX = number of vertical retraces to wait before writing to DACs\r
+; DS:SI = pointer to first entry of palette\r
+;\r
+WritePalette PROC NEAR\r
+ ASSUME ds:NOTHING\r
+ mov ah, al ; Save index\r
+ mov dx, 03DAh ; Input status register\r
+@@Delay1:\r
+ in al, dx\r
+ test al, 08h\r
+ jnz @@Delay1 ; Wait for display mode\r
+@@Delay2:\r
+ in al, dx\r
+ test al, 08h\r
+ jz @@Delay2 ; Wait for vertical retrace mode\r
+ loop @@Delay1 ; Repeat CX times\r
+@@Write:\r
+ mov cx, bx ; Get number of colors\r
+ mov dx, 03C8h ; PEL write address register\r
+ mov al, ah ; Restore index\r
+ out dx, al ; Select index of first color\r
+ inc dx ; PEL data register\r
+ cld ; Move forward\r
+ cli ; Disable interrupts\r
+@@Loop:\r
+ lodsb\r
+ out dx, al ; Red\r
+ lodsb\r
+ out dx, al ; Green\r
+ lodsb\r
+ out dx, al ; Blue\r
+ loop @@Loop ; Loop until done\r
+ sti ; Enable interrupts\r
+ ret\r
+WritePalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Reads the current palette.\r
+;\r
+; Input:\r
+; AX = index of first color to read\r
+; CX = number of colors\r
+; ES:DI = pointer to destination buffer\r
+;\r
+ReadPalette PROC NEAR\r
+ mov dx, 03C7h\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+ cld\r
+@@Loop:\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ loop @@Loop\r
+ ret\r
+ReadPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGC.ASM - Get color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetColor\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the selected DAC register.\r
+;\r
+; Input:\r
+; Index = color index (0-255)\r
+; R, G, B = byte pointers to red, green and blue\r
+; Output:\r
+; none\r
+;\r
+mxGetColor PROC FAR\r
+ ARG B:DWORD, \\r
+ G:DWORD, \\r
+ R:DWORD, \\r
+ Index:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [Index]\r
+ mov dx, 3C7h ; PEL read address register\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+\r
+ lds si, [R]\r
+ in al, dx\r
+ mov ds:[si], al\r
+ lds si, [G]\r
+ in al, dx\r
+ mov ds:[si], al\r
+ lds si, [B]\r
+ in al, dx\r
+ mov ds:[si], al\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetColor ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGI.ASM - Get image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies an image from screen to memory.\r
+;\r
+; Input:\r
+; Image = pointer to buffer for image\r
+; X, Y = coordinates of image on screen\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+;\r
+mxGetImage PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ ReadPlane:BYTE, \\r
+ Count:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov si, bx\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax\r
+ mov [PixelOffset], si\r
+ mov ds, [mx_VideoSegment] ; DS:SI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov di, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[di], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec di\r
+ dec di\r
+ jge @@PatchLoop\r
+\r
+; Get image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov es, WORD PTR Image[2] ; ES:DI will point to image\r
+ mov ah, [ReadPlane]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov di, WORD PTR Image[0]\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov si, [PixelOffset] ; DS:SI points to video memory\r
+@@Loop:\r
+ .push si, di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+@@MoveLoop:\r
+ movsb\r
+ add di, 3\r
+ dec cx\r
+ jnz @@MoveLoop\r
+ .pop si, di\r
+ add di, [Width] ; Go to next image line\r
+ add si, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc ah\r
+ test ah, 04h ; Plane wraparound?\r
+ jz @@PlaneOk ; No\r
+ inc [PixelOffset] ; Yes, bump video pointer\r
+ and ah, 03h\r
+@@PlaneOk:\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGetImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGM.ASM - Gamma correction\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGammaCorrect\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+mx_tblGamma LABEL BYTE\r
+ DB 00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34\r
+ DB 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46\r
+ DB 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55\r
+ DB 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Correct palette colors (gamma is 2.3).\r
+;\r
+; Input:\r
+; CPal = pointer to color palette\r
+; GPal = pointer to destination (gamma corrected) palette\r
+; Count = number of colors to convert\r
+; Output:\r
+; none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxGammaCorrect PROC FAR\r
+ ARG Count:WORD, \\r
+ DPal:DWORD, \\r
+ SPal:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov cx, [Count]\r
+ jcxz @@Exit ; Exit now if nothing to do\r
+ lds si, [SPal]\r
+ les di, [DPal]\r
+ mov bx, OFFSET mx_tblGamma ; Setup BX for XLAT instruction\r
+ cld\r
+ mov ax, cx ; AX = Count\r
+ add cx, cx ; CX = Count*2\r
+ add cx, ax ; CX = Count*3\r
+@@Loop:\r
+ lodsb\r
+ xlat mx_tblGamma\r
+ stosb\r
+ loop @@Loop\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGammaCorrect ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGP.ASM - Get palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetPalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to palette data (R,G,B)\r
+; Start = index of first color to get\r
+; Count = number of color to get\r
+; Output:\r
+; none\r
+;\r
+mxGetPalette PROC FAR\r
+ ARG Count:WORD, \\r
+ Start:WORD, \\r
+ Buffer:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push es, di\r
+\r
+ les di, [Buffer]\r
+ mov cx, [Count]\r
+ mov ax, [Start]\r
+ mov dx, 3C7h ; PEL read address register\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+ cld\r
+@@Loop:\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ loop @@Loop ; Loop until done\r
+\r
+ .pop es, di\r
+ .leave ARG_SIZE\r
+mxGetPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGV.ASM - Get version function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetVersion\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the library version.\r
+;\r
+mxGetVersion PROC FAR\r
+ mov ax, MXVERSION\r
+ ret\r
+mxGetVersion ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXHL.ASM - Horizontal line mask utility\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC subHorizontalLineInfo\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+tblLeftSize DW 00h, 03h, 02h, 01h\r
+tblLeftMask DB 00h, 0Eh, 0Ch, 08h\r
+tblRightMask DB 00h, 01h, 03h, 07h\r
+tblPatchMask DB 02h, 06h\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Prepares register for fast horizontal line drawing.\r
+;\r
+; Input:\r
+; BX, AX = X, Y address of left pixel\r
+; CX = line width\r
+; Output:\r
+; DI = left pixel offset in video memory\r
+; AL = left block write plane mask (0 = none)\r
+; AH = right block write plane mask (0 = none)\r
+; CX = center block width in 4-pixel blocks\r
+;\r
+subHorizontalLineInfo PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax ; Offset of left pixel\r
+\r
+ and bx, 03h\r
+ mov al, tblLeftMask[bx]\r
+ shl bx, 1\r
+ sub cx, tblLeftSize[bx]\r
+ jge @@1 ; Ok to continue\r
+\r
+; Special case: start and end in the middle of a 4-pixel block.\r
+; There are only three cases:\r
+; Pixels Left mask CX CX+2 Patch mask Result\r
+; 1) ..o. ..xx -1 1 .xx. ..x.\r
+; 2) .oo. .xxx -1 1 .xx. .xx.\r
+; 3) .o.. .xxx -2 0 .x.. .x..\r
+; All other cases are automatically handled with the standard masks.\r
+ mov bx, cx\r
+ inc bx\r
+ inc bx\r
+ and al, tblPatchMask[bx] ; Combine masks\r
+ xor ah, ah ; No right block\r
+ xor cx, cx ; No center block\r
+ jmp @@Exit\r
+\r
+@@1:\r
+ mov bx, cx\r
+ and bx, 03h\r
+ mov ah, tblRightMask[bx]\r
+ shr cx, 2\r
+\r
+@@Exit:\r
+ ret\r
+subHorizontalLineInfo ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxInit\r
+PUBLIC mxTerm\r
+\r
+PUBLIC mx_VideoSegment\r
+PUBLIC mx_CodeSegment\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW 0A000h\r
+mx_CodeSegment DW SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; AX = 0 on success\r
+;\r
+mxInit PROC FAR\r
+ LOCAL Result:WORD, \\r
+ VideoSeg:WORD, \\r
+ CStoDSalias:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov [Result], -1 ; Assume an error\r
+ mov [VideoSeg], 0A000h ; Real mode video segment\r
+ mov [CStoDSalias], cs ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+ mov ax, 1686h\r
+ int 2Fh\r
+ or ax, ax\r
+ jnz @@1 ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+ mov ax, 000Ah ; DMPI: create data alias\r
+ mov bx, cs\r
+ int 31h\r
+ jc @@Exit ; Exit if service failed\r
+ mov [CStoDSalias], ax ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+ mov ax, 0002h\r
+ mov bx, 0A000h ; Real mode segment of video\r
+ int 31h ; DPMI: get segment selector\r
+ jc @@Exit ; Exit if service failed\r
+ mov [VideoSeg], ax ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+ mov ds, [CStoDSalias]\r
+ ASSUME ds:MX_TEXT\r
+ mov [mx_CodeSegment], ds\r
+ mov ax, [VideoSeg]\r
+ mov [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+ mov [Result], 0\r
+\r
+@@Exit:\r
+ mov ax, [Result]\r
+ .pop ds, si, es, di\r
+ .leave\r
+mxInit ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; always 0.\r
+;\r
+mxTerm PROC FAR\r
+ ASSUME ds:NOTHING\r
+ xor ax, ax\r
+ ret\r
+mxTerm ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLL.ASM - Load latches\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxLoadLatches\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Loads the specified value into the VGA latches.\r
+;\r
+; Input:\r
+; BL = value to load into latches\r
+; Output:\r
+; none\r
+; Changes:\r
+; bit mask register to FFh;\r
+; function select register to "move";\r
+; write mode to 00h.\r
+; Note:\r
+; this is for internal use only.\r
+;\r
+mxLoadLatches PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+ .push ds, si\r
+ mov dx, GDC\r
+ mov ax, 0FF08h\r
+ out dx, ax ; Set bit mask to FFh\r
+ mov ax, 0003h\r
+ out dx, ax ; Set function to "move"\r
+ mov ax, 0005h\r
+ out dx, ax ; Set write mode\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov si, 0FFFFh\r
+ mov bh, 8 ; BH = write plane mask\r
+ mov cx, 3 ; CX = count = read plane\r
+; Saves old values and force BL into latches\r
+@@SetLoop:\r
+ mov dx, GDC\r
+ mov al, 04h\r
+ mov ah, cl\r
+ out dx, ax ; Select read plane\r
+ mov dx, TS\r
+ mov al, 02h\r
+ mov ah, bh\r
+ out dx, ax ; Select write plane\r
+ mov al, ds:[si]\r
+ push ax\r
+ mov ds:[si], bl\r
+ mov al, ds:[di] ; Force value into latch\r
+ shr bh, 1 ; Next write plane\r
+ loop @@SetLoop\r
+; Restore previous values\r
+ mov cx, 3\r
+ mov bh, 8\r
+ mov dx, TS\r
+@@ResetLoop:\r
+ mov al, 02h\r
+ mov ah, bh\r
+ out dx, ax ; Select write plane\r
+ pop ax\r
+ mov ds:[si], al\r
+ shr bh, 1 ; Next write plane\r
+ loop @@ResetLoop\r
+; Exit\r
+ .pop ds, si\r
+ ret\r
+mxLoadLatches ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+tblDrawFunc LABEL WORD\r
+ DW subWidthMove\r
+ DW subHeightMove\r
+ DW subWidthOp\r
+ DW subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+; X1, Y1 = start point\r
+; X2, Y2 = end point\r
+; Color = line color\r
+; Op = raster operator\r
+; Output:\r
+; none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD, \\r
+ Y2:WORD, \\r
+ X2:WORD, \\r
+ Y1:WORD, \\r
+ X1:WORD = ARG_SIZE\r
+ LOCAL Width:WORD, \\r
+ Height:WORD, \\r
+ ErrorAdd:WORD, \\r
+ ErrorSub:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD, \\r
+ P1:BYTE, \\r
+ P2:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [X1]\r
+ mov bx, [Y1]\r
+ mov cx, [X2]\r
+ mov dx, [Y2]\r
+ call subClipLine\r
+ jc @@Exit ; Line is full clipped\r
+\r
+; Get width\r
+ mov si, cx\r
+ xchg ax, si ; SI = X1, AX = X2\r
+ sub ax, si\r
+ jge @@1\r
+; Swap points, we want X1 < X2\r
+ xchg si, cx ; Swap X1 and X2\r
+ xchg bx, dx ; Swap Y1 and Y2\r
+ neg ax\r
+@@1:\r
+ mov [Width], ax\r
+\r
+; Get height\r
+ mov cx, [mx_BytesPerLine] ; We don't need X2 anymore\r
+ mov ax, dx\r
+ sub ax, bx\r
+ jge @@2\r
+ neg cx ; Move from bottom to top\r
+ neg ax ; Get absolute value of AX\r
+@@2:\r
+ mov [Height], ax\r
+ mov [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+ mov ax, bx\r
+ mul [mx_BytesPerLine]\r
+ mov cx, si ; CX = X1\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax ; SI = pixel offset\r
+ and cl, 03h\r
+ mov ax, 1102h\r
+ shl ah, cl\r
+ mov [WritePlane], ah\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+ xor bx, bx\r
+ mov al, BYTE PTR [Op]\r
+ cmp al, OP_MOVE\r
+ je @@3\r
+ and al, 03h\r
+ shl al, 1\r
+ shl al, 1\r
+ shl al, 1\r
+ mov ah, al\r
+ mov al, 03h\r
+ mov dx, GDC\r
+ out dx, ax ; Set logical function\r
+ inc bx\r
+ inc bx\r
+@@3:\r
+ mov ax, [Width]\r
+ mov cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+ cmp ax, cx\r
+ jae @@4\r
+ inc bx\r
+@@4:\r
+ shl bx, 1\r
+ call tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+ cmp BYTE PTR [Op], OP_MOVE\r
+ je @@Exit\r
+ mov ax, 0003h\r
+ mov dx, GDC\r
+ out dx, ax\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+; AX, BX = X1, Y1\r
+; CX, DX = X2, Y2\r
+; Output:\r
+; CF = set if line is full clipped\r
+; AX, BX = clipped X1, Y1\r
+; CX, DX = clipped X2, Y2\r
+; Note:\r
+; destroys SI, DI\r
+;\r
+subClipLine PROC NEAR\r
+ mov di, ax ; Copy X1 to DI and free AX\r
+ mov si, dx ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+ xor al, al\r
+@@P2X1: cmp cx, [mx_ClipX1]\r
+ jge @@P2X2\r
+ or al, 1\r
+@@P2X2: cmp cx, [mx_ClipX2]\r
+ jle @@P2Y1\r
+ or al, 2\r
+@@P2Y1: cmp si, [mx_ClipY1]\r
+ jge @@P2Y2\r
+ or al, 4\r
+@@P2Y2: cmp si, [mx_ClipY2]\r
+ jle @@P2XY\r
+ or al, 8\r
+@@P2XY: mov [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+ xor al, al\r
+@@P1X1: cmp di, [mx_ClipX1]\r
+ jge @@P1X2\r
+ or al, 1\r
+@@P1X2: cmp di, [mx_ClipX2]\r
+ jle @@P1Y1\r
+ or al, 2\r
+@@P1Y1: cmp bx, [mx_ClipY1]\r
+ jge @@P1Y2\r
+ or al, 4\r
+@@P1Y2: cmp bx, [mx_ClipY2]\r
+ jle @@P1XY\r
+ or al, 8\r
+@@P1XY: mov [P1], al\r
+; Check codes for trivial cases\r
+ mov ah, [P2]\r
+ test al, ah ; Is line invisible?\r
+ jnz @@FullClip ; Yes, exit\r
+ or ah, al ; Both points clipped?\r
+ jz @@Done ; Yes, exit\r
+; Calculate deltas\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov [DeltaX], ax\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov [DeltaY], ax\r
+ mov al, [P1] ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+ test al, al ; Is first point clipped?\r
+ jnz @@ClipX1 ; No, continue\r
+ xchg cx, di ; Swap points...\r
+ xchg bx, si\r
+ xchg al, [P2] ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+ test al, 1\r
+ jz @@ClipX2\r
+ mov ax, [mx_ClipX1]\r
+ sub ax, di\r
+ mov di, [mx_ClipX1]\r
+ jmp @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+ test al, 2\r
+ jz @@ClipY1\r
+ mov ax, [mx_ClipX2]\r
+ sub ax, di\r
+ mov di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+ imul [DeltaY]\r
+ idiv [DeltaX]\r
+ add bx, ax\r
+ mov al, 8\r
+ cmp bx, [mx_ClipY2]\r
+ jg @@CheckLoop\r
+ mov al, 4\r
+ cmp bx, [mx_ClipY1]\r
+ jl @@CheckLoop\r
+ xor al, al\r
+ jmp @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+ test al, 4\r
+ jz @@ClipY2\r
+ mov ax, [mx_ClipY1]\r
+ sub ax, bx\r
+ mov bx, [mx_ClipY1]\r
+ jmp @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+ mov ax, [mx_ClipY2]\r
+ sub ax, bx\r
+ mov bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+ imul [DeltaX]\r
+ idiv [DeltaY]\r
+ add di, ax\r
+ mov al, 1\r
+ cmp di, [mx_ClipX1]\r
+ jl @@CheckLoop\r
+ mov al, 2\r
+ cmp di, [mx_ClipX2]\r
+ jg @@CheckLoop\r
+ xor al, al\r
+@@CheckLoop:\r
+ mov ah, [P2]\r
+ test al, ah\r
+ jnz @@FullClip\r
+ or ah, al\r
+ jnz @@ClipLoop\r
+\r
+@@Done:\r
+ mov ax, di\r
+ mov dx, si\r
+ clc\r
+ ret\r
+@@FullClip:\r
+ stc\r
+ ret\r
+subClipLine ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove PROC NEAR\r
+ mov di, ax\r
+ neg di ; Initialize error term\r
+ shl cx, 1\r
+ mov [ErrorAdd], cx\r
+ mov cx, ax\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov al, 02h\r
+ mov ah, [WritePlane]\r
+ mov bl, BYTE PTR [Color]\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ rol ah, 1\r
+ adc si, 0\r
+ out dx, ax\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ add si, [DeltaY]\r
+ sub di, [ErrorSub]\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subWidthMove ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove PROC NEAR\r
+ mov di, cx\r
+ neg di ; Initialize error term\r
+ shl ax, 1\r
+ mov [ErrorAdd], ax\r
+ mov ax, cx\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov bl, BYTE PTR [Color]\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ add si, [DeltaY]\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ rol ah, 1 ; Next write plane\r
+ adc si, 0 ; Bump video offset if plane overflows\r
+ out dx, ax\r
+ sub di, [ErrorSub] ; Adjust error down\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subHeightMove ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp PROC NEAR\r
+ mov di, ax\r
+ neg di ; Initialize error term\r
+ shl cx, 1\r
+ mov [ErrorAdd], cx\r
+ mov cx, ax\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov al, 02h\r
+ mov ah, [WritePlane]\r
+ mov bl, BYTE PTR [Color]\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov bh, ds:[si] ; Latch data\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ rol ah, 1\r
+ adc si, 0\r
+ out dx, ax\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ add si, [DeltaY]\r
+ sub di, [ErrorSub]\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subWidthOp ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp PROC NEAR\r
+ mov di, cx\r
+ neg di ; Initialize error term\r
+ shl ax, 1\r
+ mov [ErrorAdd], ax\r
+ mov ax, cx\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov bl, BYTE PTR [Color]\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov bh, ds:[si]\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ add si, [DeltaY]\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ rol ah, 1 ; Next write plane\r
+ adc si, 0 ; Bump video offset if plane overflows\r
+ out dx, ax\r
+ sub di, [ErrorSub] ; Adjust error down\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subHeightOp ENDP\r
+\r
+mxLine ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxOutChar\r
+PUBLIC mxOutText\r
+PUBLIC mxSetFont\r
+PUBLIC mxSetTextColor\r
+PUBLIC mxGetTextStep\r
+PUBLIC mxSetTextStep\r
+\r
+MAX_WIDTH EQU 16 ; Must be <= 16\r
+MAX_HEIGHT EQU 32\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mxPutImage : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default LABEL\r
+ INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont LABEL WORD\r
+ DW fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth DW 8 ; Font width in pixels\r
+mx_FontHeight DW 8 ; Font height in pixels\r
+mx_FontCharSize DW 8 ; Size in bytes of a font character\r
+mx_FontColor DW 00FFh ; Color: foreground + background*256\r
+mx_FontOp DW OP_MOVE ; Raster op\r
+mx_DeltaX DW 8 ; Horizontal step\r
+mx_DeltaY DW 0 ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+; Font = pointer to font data\r
+; Width = width of font character in pixels\r
+; Height = height of font character in pixels\r
+; Output:\r
+; AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+; word is used to select one of the system fonts.\r
+;\r
+mxSetFont PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Font:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, WORD PTR Font[2] ; Get font segment\r
+ test ax, ax ; Null segment?\r
+ jnz @@UserFont ; No, install user font\r
+\r
+; Install system font\r
+ mov ax, WORD PTR Font[0] ; Get font number\r
+ cmp ax, MX_MAXSYSFONT ; Check range\r
+ jb @@SystemFont\r
+ xor ax, ax ; Out of range, use default font\r
+@@SystemFont:\r
+ shl ax, 1\r
+ shl ax, 1\r
+ mov bx, ax\r
+ mov ax, tbl_SystemFont[bx] ; Get font offset\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov WORD PTR mx_FontPtr[2], cs\r
+ mov al, BYTE PTR tbl_SystemFont[bx+2]\r
+ xor ah, ah\r
+ mov [mx_FontWidth], ax\r
+ mov [mx_DeltaX], ax\r
+ mov dl, BYTE PTR tbl_SystemFont[bx+3]\r
+ xor dh, dh\r
+ mov [mx_FontHeight], dx\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov [mx_DeltaX], ax\r
+ xor ax, ax\r
+ mov [mx_DeltaY], ax\r
+ jmp @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+ mov ax, -1 ; Assume an error\r
+ mov bx, [Width]\r
+ cmp bx, MAX_WIDTH\r
+ ja @@Exit ; Invalid character width\r
+ mov dx, [Height]\r
+ cmp dx, MAX_HEIGHT\r
+ ja @@Exit ; Invalid character height\r
+ mov [mx_FontWidth], bx\r
+ mov [mx_FontHeight], dx\r
+ mov ax, bx\r
+ add ax, 7\r
+ .shr ax, 3\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov ax, WORD PTR Font[0]\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov ax, WORD PTR Font[2]\r
+ mov WORD PTR mx_FontPtr[2], ax\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetFont ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+; Color = text color (foreground + background*256)\r
+; Op = raster op\r
+; Output:\r
+; none\r
+;\r
+mxSetTextColor PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [Color]\r
+ mov [mx_FontColor], ax\r
+ mov ax, [Op]\r
+ mov [mx_FontOp], ax\r
+\r
+ xor ax, ax\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetTextColor ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+; X, Y = video coordinates\r
+; C = character to print\r
+; Output:\r
+; none\r
+;\r
+mxOutChar PROC FAR\r
+ ARG C:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \\r
+ Count:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+ lds si, DWORD PTR [mx_FontPtr]\r
+ mov al, [C]\r
+ xor ah, ah\r
+ mul [mx_FontCharSize] ; Offset into font\r
+ add si, ax ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [Image]\r
+ mov dx, [mx_FontColor]\r
+ mov ax, [mx_FontHeight]\r
+ mov [Count], ax\r
+@@HeightLoop:\r
+ mov cx, [mx_FontWidth]\r
+ mov bh, ds:[si]\r
+ inc si ; Get a byte from font data\r
+ cmp cx, 8\r
+ jbe @@WidthLoop ; Ok for width <= 8\r
+ mov bl, ds:[si] ; Get another byte\r
+ inc si\r
+@@WidthLoop:\r
+ mov al, dl ; Assume foreground color\r
+ shl bx, 1 ; Is font bit set?\r
+ jc @@1 ; Yes, foreground is just great\r
+ mov al, dh ; Get background color\r
+@@1:\r
+ mov es:[di], al ; Put pixel into image\r
+ inc di\r
+ dec cx\r
+ jnz @@WidthLoop\r
+ dec [Count]\r
+ jnz @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+ lea ax, [Image]\r
+ push es\r
+ push ax ; Pointer to image\r
+ push [X]\r
+ push [Y] ; Image coordinates\r
+ push [mx_FontWidth]\r
+ push [mx_FontHeight] ; Image size\r
+ push [mx_FontOp] ; Raster op\r
+ call mxPutImage ; Write character\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxOutChar ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+; X, Y = text coordinates\r
+; S = pointer to ASCIIZ string\r
+; Output:\r
+; none\r
+;\r
+mxOutText PROC FAR\r
+ ARG S:DWORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [S]\r
+@@Loop:\r
+ mov al, ds:[si]\r
+ test al, al ; End of string?\r
+ jz @@Exit ; Yes, exit\r
+ inc si\r
+ push [X] ; Display character\r
+ push [Y]\r
+ push ax\r
+ call mxOutChar\r
+ mov ax, [mx_DeltaX]\r
+ add [X], ax ; Bump X coordinate\r
+ mov ax, [mx_DeltaY]\r
+ add [Y], ax ; Bump Y coordinate\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+ ret\r
+mxOutText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = horizontal distance in pixels\r
+; DeltaY = vertical distance in pixels\r
+; Output:\r
+; none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep PROC FAR\r
+ ARG DeltaY:WORD, \\r
+ DeltaX:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [DeltaX]\r
+ mov [mx_DeltaX], ax\r
+ mov ax, [DeltaY]\r
+ mov [mx_DeltaY], ax\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetTextStep ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = pointer to horizontal distance in pixels (integer)\r
+; DeltaY = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+; none\r
+;\r
+mxGetTextStep PROC FAR\r
+ ARG DeltaY:DWORD, \\r
+ DeltaX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [mx_DeltaX]\r
+ lds si, [DeltaX]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_DeltaY]\r
+ lds si, [DeltaY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetTextStep ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPB.ASM - Scan buffer for convex polygon fills\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mx_ScanBuffer\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+ALIGN 4\r
+\r
+mx_ScanBuffer LABEL\r
+ DW POLYSCANBUFSIZE DUP(?)\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFillPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT STRUC\r
+ X DW ?\r
+ Y DW ?\r
+TPOINT ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN STRUC\r
+ Y1 DW ?\r
+ Y2 DW ?\r
+TSCAN ENDS\r
+\r
+MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+EXTRN mx_ScanBuffer : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+;\r
+; Input:\r
+; DS:BX = pointer to start point (X1, Y1)\r
+; DS:SI = pointer to end point (X2, Y2)\r
+; ES:DI = pointer to edge buffer\r
+; Output:\r
+; ES:DI = updated pointer to edge buffer\r
+; Notes:\r
+; must preserve DS:SI.\r
+;\r
+subScan PROC NEAR\r
+ mov cx, ds:[si].X\r
+ sub cx, ds:[bx].X ; Get width\r
+ jg @@1\r
+ ret\r
+@@1:\r
+ push bp ; Save BP\r
+\r
+ mov ax, ds:[si].Y\r
+ mov bx, ds:[bx].Y\r
+ sub ax, bx ; Get height\r
+ jg @@T2B ; Scan top to bottom\r
+ jl @@B2T ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+ mov ax, bx\r
+@@V:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@V\r
+ jmp @@Exit\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@T2BLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@T2BLoop\r
+ jmp @@Exit\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+@@B2TLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@B2TLoop\r
+\r
+@@Exit:\r
+ pop bp ; Restore BP\r
+ ret\r
+subScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+;\r
+; Input:\r
+; Count = number of vertexes\r
+; Map = indexes of points and colors (integer)\r
+; Points = array of points (integer X, Y coordinates)\r
+; Color = base color\r
+; Output:\r
+; none\r
+; Notes:\r
+; vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxFillPoly PROC FAR\r
+ ARG Color:WORD, \\r
+ Points:DWORD, \\r
+ Map:DWORD, \\r
+ Count:WORD = ARG_SIZE\r
+ LOCAL WritePlane:BYTE:2, \\r
+ ScanOffsetT:WORD, \\r
+ ScanOffsetB:WORD, \\r
+ ScanCount:WORD, \\r
+ Holder:WORD, \\r
+ Height:WORD, \\r
+ MinIdxT:WORD, \\r
+ MinIdxB:WORD, \\r
+ MaxIdx:WORD, \\r
+ Width:WORD, \\r
+ BoxX1:WORD, \\r
+ BoxY1:WORD, \\r
+ BoxX2:WORD, \\r
+ BoxY2::WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+ mov cx, [Count]\r
+ cmp cx, 3\r
+ jb @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+ les di, [Map]\r
+ lds si, [Points] ; Pointer to vertex array\r
+ mov [BoxX1], 32767\r
+ mov [BoxX2], -32768\r
+ mov [BoxY1], 32767\r
+ mov [BoxY2], -32768\r
+\r
+ xor dx, dx\r
+@@MinMaxLoop:\r
+ mov bx, es:[di] ; Get index of vertex\r
+ .shl bx, 2 ; Get offset in point array\r
+ add bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+ mov ax, ds:[bx].X ; Get X coordinate\r
+ cmp ax, [BoxX1]\r
+ jge @@CheckMaxX\r
+ mov [BoxX1], ax\r
+ mov [MinIdxT], dx\r
+ mov [MinIdxB], dx\r
+@@CheckMaxX:\r
+ cmp ax, [BoxX2]\r
+ jle @@CheckMinY\r
+ mov [BoxX2], ax\r
+ mov [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+ mov ax, ds:[bx].Y\r
+ cmp ax, [BoxY1]\r
+ jge @@CheckMaxY\r
+ mov [BoxY1], ax\r
+@@CheckMaxY:\r
+ cmp ax, [BoxY2]\r
+ jle @@CheckDone\r
+ mov [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+ inc di ; Next map entry\r
+ inc dx\r
+ inc di\r
+ inc dx\r
+ dec cx\r
+ jnz @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+ mov ax, [BoxX2]\r
+ cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxX1]\r
+ cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get width\r
+ jle @@Exit ; Exit if not positive\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxY1]\r
+ cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get height\r
+ jle @@Exit ; Exit if not positive\r
+\r
+ dec [Count]\r
+ shl [Count], 1 ; We'll work with word offsets\r
+ mov es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+ mov ax, OFFSET mx_ScanBuffer\r
+ mov [ScanOffsetT], ax\r
+ mov si, [MinIdxT] ; Offset of bottom point index\r
+@@STLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of top point #1\r
+ dec si ; Next point\r
+ dec si\r
+ test si, si\r
+ jnl @@ST1\r
+ mov si, [Count]\r
+@@ST1:\r
+ mov [MinIdxT], si ; Save new index of top point\r
+ mov si, ds:[bx+si] ; Get index of top point #2\r
+ .shl di, 2 ; Convert indexes to offsets\r
+ .shl si, 2\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetT]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetT], di\r
+ mov si, [MinIdxT]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@STLoop ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+ mov ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+ mov [ScanOffsetB], ax\r
+ mov si, [MinIdxB] ; Offset of bottom point index\r
+@@SBLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of bottom point #1\r
+ inc si ; Next bottom point\r
+ inc si\r
+ cmp si, [Count]\r
+ jbe @@SB1\r
+ xor si, si\r
+@@SB1:\r
+ mov [MinIdxB], si ; Save new index of bottom point\r
+ mov si, ds:[bx+si] ; Get index of bottom point #2\r
+ .shl di, 2 ; Convert indexes to offsets\r
+ .shl si, 2\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetB]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetB], di\r
+ mov si, [MinIdxB]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@SBLoop ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+ mov si, OFFSET mx_ScanBuffer\r
+ mov ax, [BoxX1]\r
+ mov cx, [BoxX2]\r
+ sub cx, ax ; CX = bounding box width\r
+ mov bx, [mx_ClipX1]\r
+ sub bx, ax\r
+ jle @@ClipL1 ; No need to clip left\r
+ sub cx, bx ; Update width\r
+ add ax, bx ; BoxX1 = mx_ClipX1\r
+ mov [BoxX1], ax\r
+ .shl bx, 2 ; Warning!!! This is an hand-coded\r
+ add si, bx ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+ mov bx, ax\r
+ add bx, cx ; Last scan column\r
+ sub bx, [mx_ClipX2]\r
+ jle @@ClipL2 ; No need to clip right\r
+ sub cx, bx ; Clip right\r
+@@ClipL2:\r
+ test cx, cx ; Is clipped width positive?\r
+ jle @@Exit ; No, exit\r
+ mov [ScanCount], cx ; Save number of columns to draw\r
+ mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
+ mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+ mov ax, [BoxY1]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@ClipTB ; Need to clip top\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@ClipTB ; Need to clip bottom\r
+ jmp @@ClipYExit ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+ mov di, cx ; DI = scan count\r
+ inc di ; Increment count for pre-loop test\r
+ sub si, SIZE TSCAN\r
+@@ClipYLoop:\r
+ dec di ; Any column left?\r
+ jz @@ClipYExit ; No, exit\r
+ add si, SIZE TSCAN\r
+ mov ax, ds:[si].Y1 ; Y1\r
+ mov cx, ds:[si].Y2 ; Y2\r
+ mov dx, [mx_ClipY2]\r
+ cmp ax, dx ; Full clipped?\r
+ jg @@ClipYClip ; Yes, skip this column\r
+ cmp cx, dx ; Need to clip bottom?\r
+ jle @@ClipY1 ; No, continue\r
+; Clip bottom\r
+ mov ds:[si].Y2, dx\r
+ mov bx, cx\r
+ sub bx, dx ; Clip distance\r
+ sub cx, ax ; Height\r
+ jle @@ClipYClip\r
+ mov cx, ds:[si].Y2\r
+@@ClipY1:\r
+ mov dx, [mx_ClipY1]\r
+ cmp cx, dx ; Full top clipped?\r
+ jl @@ClipYClip ; Yes, skip\r
+ sub cx, ax ; Get height\r
+ jle @@ClipYClip ; Skip if not positive\r
+ cmp ax, dx ; Need to clip top?\r
+ jge @@ClipYLoop ; No, continue\r
+; Clip top\r
+ mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
+ sub dx, ax ; DX = number of pixels clipped\r
+ cmp cx, dx\r
+ ja @@ClipYLoop ; Not clipped, continue\r
+@@ClipYClip:\r
+ mov ds:[si].Y1, -1 ; Mark column as clipped\r
+ jmp @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+ mov es, [mx_VideoSegment]\r
+ mov si, [ScanOffsetT]\r
+ mov cl, BYTE PTR [BoxX1] ; Init write plane\r
+ and cl, 03h\r
+ mov al, 11h\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+ .shr [BoxX1], 2\r
+@@DrawLoop:\r
+ mov ax, ds:[si].Y1\r
+ test ax, ax ; Was column clipped?\r
+ js @@DrawNext ; Yes, skip\r
+ mov cx, ds:[si].Y2\r
+ sub cx, ax ; CX = height\r
+ jle @@DrawNext\r
+ mul [mx_BytesPerLine] ; Get pixel address\r
+ add ax, [BoxX1]\r
+ mov di, ax\r
+ mov ah, [WritePlane]\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax\r
+ mov ax, [Color]\r
+ mov dx, [mx_BytesPerLine]\r
+ shr cx, 1\r
+ jnc @@FillScan\r
+ mov es:[di], al\r
+ add di, dx\r
+ jcxz @@DrawNext\r
+@@FillScan:\r
+ mov es:[di], al\r
+ add di, dx\r
+ mov es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jnz @@FillScan\r
+@@DrawNext:\r
+ rol [WritePlane], 1\r
+ adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
+ add si, SIZE TSCAN\r
+ dec [ScanCount]\r
+ jnz @@DrawLoop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxFillPoly ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill with Gouraud shading\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGouraudPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT STRUC\r
+ X DW ?\r
+ Y DW ?\r
+TPOINT ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN STRUC\r
+ Y1 DW ?\r
+ E1 DB ?\r
+ C1 DB ?\r
+ Y2 DW ?\r
+ E2 DB ?\r
+ C2 DB ?\r
+TSCAN ENDS\r
+\r
+MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+EXTRN mx_ScanBuffer : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+; Also interpolates color for shading.\r
+;\r
+; Input:\r
+; DS:BX = pointer to start point (X1, Y1)\r
+; DS:SI = pointer to end point (X2, Y2)\r
+; ES:DI = pointer to edge buffer\r
+; DX = start color\r
+; AX = end color\r
+; Output:\r
+; ES:DI = updated pointer to edge buffer\r
+; Notes:\r
+; must preserve DS:SI.\r
+;\r
+subScan PROC NEAR\r
+ mov cx, ds:[si].X\r
+ sub cx, ds:[bx].X ; Get width\r
+ jg @@1\r
+ ret\r
+@@1:\r
+ push bp ; Save BP\r
+ push di ; Save scan info offset\r
+ push cx ; Save height\r
+ push ax ; Save colors\r
+ push dx\r
+\r
+ mov ax, ds:[si].Y\r
+ mov bx, ds:[bx].Y\r
+ sub ax, bx ; Get height\r
+ jg @@T2B ; Scan top to bottom\r
+ jl @@B2T ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+ mov ax, bx\r
+@@V:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@V\r
+ jmp @@GetColorInfo\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@T2BLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@T2BLoop\r
+ jmp @@GetColorInfo\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+@@B2TLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@B2TLoop\r
+\r
+; Now get the color info\r
+@@GetColorInfo:\r
+ pop bx ; Restore colors\r
+ pop ax\r
+ pop cx ; Height\r
+ pop di ; ES:DI -> scan info\r
+\r
+ sub ax, bx ; Get color range\r
+ jg @@CL2R\r
+ jl @@CR2L\r
+\r
+; Special case: same color\r
+ mov ah, bl\r
+ mov al, 80h\r
+@@CV:\r
+ mov WORD PTR es:[di].E1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@CV\r
+ jmp @@Exit\r
+\r
+; Scan left to right\r
+@@CL2R:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@CL2RLoop:\r
+ mov es:[di].C1, al\r
+ mov es:[di].E1, dh\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@CL2RLoop\r
+ jmp @@Exit\r
+\r
+; Scan right to left\r
+@@CR2L:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+\r
+@@CR2LLoop:\r
+ mov es:[di].C1, al\r
+ mov es:[di].E1, dh\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@CR2LLoop\r
+\r
+@@Exit:\r
+ pop bp\r
+ ret\r
+subScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a scan column.\r
+;\r
+; Input:\r
+; DS:SI = current TSCAN\r
+; ES:DI = address of top pixel\r
+; CX = number of pixels to write\r
+; DX = base color\r
+; Output:\r
+; none\r
+;\r
+subFillScan PROC NEAR\r
+ mov ax, WORD PTR ds:[si].E2\r
+ mov bx, WORD PTR ds:[si].E1\r
+ cmp ah, bh\r
+ jg @@L2R ; Color increases\r
+ jl @@R2L ; Color decreases\r
+\r
+; Special case: color doesn't change\r
+ add ax, dx\r
+ mov dx, [mx_BytesPerLine]\r
+@@V:\r
+ mov es:[di], ah\r
+ add di, dx\r
+ dec cx\r
+ jnz @@V\r
+ ret\r
+\r
+; Color increases\r
+@@L2R:\r
+ .push bp, si\r
+ mov si, bx\r
+ add si, dx ; Relocate color\r
+ sub ax, bx\r
+ xor dx, dx\r
+ div cx\r
+ mov bp, ax ; BP = color step, integer part\r
+ xor ax, ax\r
+ div cx\r
+ mov bx, ax ; BX = color step, fractional part\r
+ mov dx, 8000h\r
+ mov ax, [mx_BytesPerLine]\r
+ xchg si, ax\r
+@@L2RLoop:\r
+ mov es:[di], ah\r
+ add dx, bx\r
+ adc ax, bp\r
+ add di, si\r
+ dec cx\r
+ jnz @@L2RLoop\r
+ .pop bp, si\r
+ ret\r
+\r
+; Color decreases\r
+@@R2L:\r
+ .push bp, si\r
+ mov si, bx\r
+ add si, dx ; Relocate color\r
+ sub ax, bx\r
+ neg ax\r
+ xor dx, dx\r
+ div cx\r
+ mov bp, ax ; BP = color step, integer part\r
+ xor ax, ax\r
+ div cx\r
+ mov bx, ax ; BX = color step, fractional part\r
+ mov dx, 8000h\r
+ mov ax, [mx_BytesPerLine]\r
+ xchg si, ax\r
+@@R2LLoop:\r
+ mov es:[di], ah\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ add di, si\r
+ dec cx\r
+ jnz @@R2LLoop\r
+ .pop bp, si\r
+ ret\r
+subFillScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+; Interpolates pixel colors using the Gouraud algorithm.\r
+;\r
+; Input:\r
+; Count = number of vertexes\r
+; Map = indexes of points and colors (integer)\r
+; Points = array of points (integer X, Y coordinates)\r
+; Colors = array of colors (integer)\r
+; Color = base color\r
+; Output:\r
+; none\r
+; Notes:\r
+; vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxGouraudPoly PROC FAR\r
+ ARG Color:WORD, \\r
+ Colors:DWORD, \\r
+ Points:DWORD, \\r
+ Map:DWORD, \\r
+ Count:WORD = ARG_SIZE\r
+ LOCAL WritePlane:BYTE:2, \\r
+ ScanOffsetT:WORD, \\r
+ ScanOffsetB:WORD, \\r
+ ScanCount:WORD, \\r
+ Holder:WORD, \\r
+ Height:WORD, \\r
+ MinIdxT:WORD, \\r
+ MinIdxB:WORD, \\r
+ MaxIdx:WORD, \\r
+ Width:WORD, \\r
+ BoxX1:WORD, \\r
+ BoxY1:WORD, \\r
+ BoxX2:WORD, \\r
+ BoxY2::WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+ mov cx, [Count]\r
+ cmp cx, 3\r
+ jb @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+ les di, [Map]\r
+ lds si, [Points] ; Pointer to vertex array\r
+ mov [BoxX1], 32767\r
+ mov [BoxX2], -32768\r
+ mov [BoxY1], 32767\r
+ mov [BoxY2], -32768\r
+\r
+ xor dx, dx\r
+@@MinMaxLoop:\r
+ mov bx, es:[di] ; Get index of vertex\r
+ .shl bx, 2 ; Get offset in point array\r
+ add bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+ mov ax, ds:[bx].X ; Get X coordinate\r
+ cmp ax, [BoxX1]\r
+ jge @@CheckMaxX\r
+ mov [BoxX1], ax\r
+ mov [MinIdxT], dx\r
+ mov [MinIdxB], dx\r
+@@CheckMaxX:\r
+ cmp ax, [BoxX2]\r
+ jle @@CheckMinY\r
+ mov [BoxX2], ax\r
+ mov [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+ mov ax, ds:[bx].Y\r
+ cmp ax, [BoxY1]\r
+ jge @@CheckMaxY\r
+ mov [BoxY1], ax\r
+@@CheckMaxY:\r
+ cmp ax, [BoxY2]\r
+ jle @@CheckDone\r
+ mov [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+ inc di ; Next map entry\r
+ inc di\r
+ inc dx\r
+ inc dx\r
+ dec cx\r
+ jnz @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+ mov ax, [BoxX2]\r
+ cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxX1]\r
+ cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get width\r
+ jle @@Exit ; Exit if not positive\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxY1]\r
+ cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get height\r
+ jle @@Exit ; Exit if not positive\r
+\r
+ dec [Count]\r
+ shl [Count], 1 ; We'll work with word offsets\r
+ mov es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+ mov ax, OFFSET mx_ScanBuffer\r
+ mov [ScanOffsetT], ax\r
+ mov si, [MinIdxT] ; Offset of bottom point index\r
+@@STLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of top point #1\r
+ dec si ; Next point\r
+ dec si\r
+ test si, si\r
+ jnl @@ST1\r
+ mov si, [Count]\r
+@@ST1:\r
+ mov [MinIdxT], si ; Save new index of top point\r
+ mov si, ds:[bx+si] ; Get index of top point #2\r
+ lds bx, [Colors] ; Get pointer to color array\r
+ shl di, 1 ; Convert indexes to offsets\r
+ shl si, 1\r
+ mov ax, ds:[bx+si] ; Get colors\r
+ mov dx, ds:[bx+di]\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ shl si, 1\r
+ shl di, 1\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetT]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetT], di\r
+ mov si, [MinIdxT]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@STLoop ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+ mov ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+ mov [ScanOffsetB], ax\r
+ mov si, [MinIdxB] ; Offset of bottom point index\r
+@@SBLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of bottom point #1\r
+ inc si ; Next bottom point\r
+ inc si\r
+ cmp si, [Count]\r
+ jbe @@SB1\r
+ xor si, si\r
+@@SB1:\r
+ mov [MinIdxB], si ; Save new index of bottom point\r
+ mov si, ds:[bx+si] ; Get index of bottom point #2\r
+ lds bx, [Colors] ; Get pointer to color array\r
+ shl di, 1 ; Convert indexes to offsets\r
+ shl si, 1\r
+ mov ax, ds:[bx+si] ; Get colors\r
+ mov dx, ds:[bx+di]\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ shl si, 1\r
+ shl di, 1\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetB]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetB], di\r
+ mov si, [MinIdxB]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@SBLoop ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+ mov si, OFFSET mx_ScanBuffer\r
+ mov ax, [BoxX1]\r
+ mov cx, [BoxX2]\r
+ sub cx, ax ; CX = bounding box width\r
+ mov bx, [mx_ClipX1]\r
+ sub bx, ax\r
+ jle @@ClipL1 ; No need to clip left\r
+ sub cx, bx ; Update width\r
+ add ax, bx ; BoxX1 = mx_ClipX1\r
+ mov [BoxX1], ax\r
+ .shl bx, 3 ; Warning!!! This is an hand-coded\r
+ add si, bx ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+ mov bx, ax\r
+ add bx, cx ; Last scan column\r
+ sub bx, [mx_ClipX2]\r
+ jle @@ClipL2 ; No need to clip right\r
+ sub cx, bx ; Clip right\r
+@@ClipL2:\r
+ test cx, cx ; Is clipped width positive?\r
+ jle @@Exit ; No, exit\r
+ mov [ScanCount], cx ; Save number of columns to draw\r
+ mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
+ mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+ mov ax, [BoxY1]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@ClipTB ; Need to clip top\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@ClipTB ; Need to clip bottom\r
+ jmp @@ClipYExit ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+ mov di, cx ; DI = scan count\r
+ inc di ; Increment count for pre-loop test\r
+ sub si, SIZE TSCAN\r
+@@ClipYLoop:\r
+ dec di ; Any column left?\r
+ jz @@ClipYExit ; No, exit\r
+ add si, SIZE TSCAN\r
+ mov ax, ds:[si].Y1 ; Y1\r
+ mov cx, ds:[si].Y2 ; Y2\r
+ mov dx, [mx_ClipY2]\r
+ cmp ax, dx ; Full clipped?\r
+ jg @@ClipYClip ; Yes, skip this column\r
+ cmp cx, dx ; Need to clip bottom?\r
+ jle @@ClipY1 ; No, continue\r
+; Clip bottom, need to scale colors too\r
+ mov ds:[si].Y2, dx\r
+ mov bx, cx\r
+ sub bx, dx ; Clip distance\r
+ sub cx, ax ; Height\r
+ jle @@ClipYClip\r
+ mov ax, WORD PTR ds:[si].E1\r
+ sub ax, WORD PTR ds:[si].E2\r
+ imul bx\r
+ idiv cx\r
+ add WORD PTR ds:[si].E2, ax\r
+ mov ax, ds:[si].Y1 ; Restore AX and CX\r
+ mov cx, ds:[si].Y2\r
+@@ClipY1:\r
+ mov dx, [mx_ClipY1]\r
+ cmp cx, dx ; Full top clipped?\r
+ jl @@ClipYClip ; Yes, skip\r
+ sub cx, ax ; Get height\r
+ jle @@ClipYClip ; Skip if not positive\r
+ cmp ax, dx ; Need to clip top?\r
+ jge @@ClipYLoop ; No, continue\r
+; Clip top, need to scale colors too\r
+ mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
+ sub dx, ax ; DX = number of pixels clipped\r
+ cmp cx, dx\r
+ jbe @@ClipYClip ; Full clipped, skip\r
+ mov ax, WORD PTR ds:[si].E2\r
+ sub ax, WORD PTR ds:[si].E1 ; AX = color distance\r
+ imul dx\r
+ idiv cx\r
+ add WORD PTR ds:[si].E1, ax ; Update starting color\r
+ jmp @@ClipYLoop\r
+@@ClipYClip:\r
+ mov ds:[si].Y1, -1 ; Mark column as clipped\r
+ jmp @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+ mov es, [mx_VideoSegment]\r
+ mov si, [ScanOffsetT]\r
+ mov cl, BYTE PTR [BoxX1] ; Init write plane\r
+ and cl, 03h\r
+ mov al, 11h\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+ .shr [BoxX1], 2\r
+ mov ax, [Color] ; Make 8:8 fixed color\r
+ mov ah, al\r
+ xor al, al\r
+ mov [Color], ax\r
+@@DrawLoop:\r
+ mov ax, ds:[si].Y1\r
+ test ax, ax ; Was column clipped?\r
+ js @@DrawNext ; Yes, skip\r
+ mov cx, ds:[si].Y2\r
+ sub cx, ax ; CX = height\r
+ jle @@DrawNext\r
+ mul [mx_BytesPerLine] ; Get pixel address\r
+ add ax, [BoxX1]\r
+ mov di, ax\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax\r
+ mov dx, [Color]\r
+ call subFillScan\r
+@@DrawNext:\r
+ rol [WritePlane], 1\r
+ adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
+ add si, SIZE TSCAN\r
+ dec [ScanCount]\r
+ jnz @@DrawLoop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGouraudPoly ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove PROC NEAR\r
+ shr cx, 1 ; Make CX even\r
+ jc @@Odd ; Special case if odd byte\r
+@@Loop: movsb\r
+ add si, 3\r
+ movsb\r
+ add si, 3\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: movsb\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ and es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ and es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ or es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ or es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ xor es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ xor es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip: inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+ ret\r
+subAdd ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxPutImage PROC FAR\r
+ ARG Op:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+ mov cl, [ReadPlane]\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov si, WORD PTR Image[0]\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov di, [PixelOffset]\r
+@@Loop:\r
+ push si\r
+ push di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+ mov ah, [OpInfo] ; Transparent color for subTrans\r
+ call [MoveFunction]\r
+ pop di\r
+ pop si\r
+ add si, [Width] ; Go to next image line\r
+ add di, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ rol [WritePlane], 1\r
+ adc [PixelOffset], 0\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPan\r
+\r
+EXTRN mxWaitDisplay : FAR\r
+EXTRN mxStartAddress : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+; X, Y = new X, Y coordinates of view screen\r
+; Output:\r
+; none\r
+;\r
+mxPan PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov ax, [Y]\r
+ mul [mx_BytesPerLine]\r
+ mov dx, [X]\r
+ shr dx, 1\r
+ shr dx, 1\r
+ add ax, dx\r
+ push ax ; Push the start address\r
+ call mxWaitDisplay\r
+ call mxStartAddress\r
+\r
+ mov dx, 03DAh ; Set the pixel pan register\r
+ in al, dx\r
+ mov dx, 03C0h\r
+ mov al, 33h\r
+ out dx, al\r
+ mov al, BYTE PTR [X]\r
+ and al, 3\r
+ shl al, 1\r
+ out dx, al\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxPan ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPP.ASM - Get/put pixel functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetPixel\r
+PUBLIC mxPutPixel\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets a pixel.\r
+;\r
+; Input:\r
+; X, Y = pixel coordinates\r
+; Output:\r
+; pixel color\r
+;\r
+mxGetPixel PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ xor ax, ax\r
+ mov si, [X]\r
+ cmp si, [mx_ClipX1]\r
+ jl @@Exit\r
+ cmp si, [mx_ClipX2]\r
+ jg @@Exit\r
+ mov bx, [Y]\r
+ cmp bx, [mx_ClipY1]\r
+ jl @@Exit\r
+ cmp bx, [mx_ClipY2]\r
+ jg @@Exit\r
+\r
+ mov al, 04h ; Set read plane\r
+ mov ah, BYTE PTR [X]\r
+ and ah, 3\r
+ mov dx, GDC\r
+ out dx, ax\r
+\r
+ mov ds, [mx_VideoSegment]\r
+ mov ax, bx\r
+ mul [mx_BytesPerLine]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+ mov al, ds:[si] ; Get pixel value\r
+ xor ah, ah\r
+\r
+@@Exit:\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetPixel ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Puts a pixel of the specified color.\r
+;\r
+; Input:\r
+; X, Y = pixel coordinates\r
+; Color = pixel color\r
+; Output:\r
+; none\r
+;\r
+mxPutPixel PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov si, [X]\r
+ cmp si, [mx_ClipX1]\r
+ jl @@Exit\r
+ cmp si, [mx_ClipX2]\r
+ jg @@Exit\r
+ mov ax, [Y]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@Exit\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@Exit\r
+\r
+ mov ds, [mx_VideoSegment]\r
+ mul [mx_BytesPerLine]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+ mov cl, BYTE PTR [X] ; Set write plane\r
+ and cl, 3\r
+ mov ax, 0102h\r
+ shl ah, cl\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ mov al, [Color] ; Write pixel\r
+ mov ds:[si], al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxPutPixel ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXRA.ASM - Row address\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxRowAddress\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the row address register.\r
+;\r
+; Input:\r
+; RowAddress = row size in words\r
+; Output:\r
+; none\r
+;\r
+mxRowAddress PROC FAR\r
+ ARG RowAddress:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ mov dx, CRTC\r
+ mov al, 13h\r
+ mov ah, [RowAddress]\r
+ out dx, ax\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxRowAddress ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXRP.ASM - Rotate palette function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxRotatePalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates the palette of the specified number of colors.\r
+;\r
+; Input:\r
+; Palette = pointer to palette\r
+; Count = number of colors to rotate\r
+; Step = step size\r
+; Output:\r
+; none\r
+;\r
+; Note: if Step is positive palette is rotated left to right, otherwise\r
+; right to left.\r
+;\r
+mxRotatePalette PROC FAR\r
+ ARG Step:WORD, \\r
+ Count:WORD, \\r
+ Palette:DWORD = ARG_SIZE\r
+ LOCAL Holder:BYTE:768 = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov bx, [Count]\r
+ add bx, bx\r
+ add bx, [Count] ; BX = Count*3\r
+\r
+ lds si, [Palette] ; DS:SI -> palette\r
+ push ss\r
+ pop es\r
+ lea di, Holder ; ES:DI -> local space\r
+ cld\r
+\r
+ mov ax, [Step]\r
+ mov dx, ax\r
+ test ax, ax\r
+ jz @@Exit ; Nothing to do, exit\r
+ jl @@RightToLeft\r
+\r
+@@LeftToRight:\r
+ add ax, ax\r
+ add dx, ax ; DX = Step*3\r
+ sub bx, dx ; BX = (Count-Step)*3\r
+ add si, bx\r
+ push si\r
+ mov cx, dx\r
+ rep movsb\r
+ mov es, WORD PTR Palette[2]\r
+ mov di, si\r
+ dec di ; ES:DI -> last byte of palette\r
+ pop si\r
+ dec si\r
+ mov cx, bx\r
+ std\r
+ rep movsb\r
+ push ss\r
+ pop ds\r
+ lea si, Holder\r
+ les di, [Palette]\r
+ mov cx, dx\r
+ cld\r
+ rep movsb\r
+ jmp @@Exit\r
+\r
+@@RightToLeft:\r
+ add ax, ax\r
+ add dx, ax\r
+ neg dx ; DX = Step*3\r
+ sub bx, dx ; BX = (Count-Step)*3\r
+ mov cx, dx\r
+ rep movsb\r
+ les di, [Palette]\r
+ mov cx, bx\r
+ rep movsb\r
+ push ss\r
+ pop ds\r
+ lea si, Holder\r
+ mov cx, dx\r
+ rep movsb\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxRotatePalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSA.ASM - Start address function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStartAddress\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Modifies the starting address of video memory.\r
+;\r
+; Input:\r
+; StartAddr = new start address of video memory\r
+; Output:\r
+; none\r
+;\r
+mxStartAddress PROC FAR\r
+ ARG StartAddr:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov bx, [StartAddr]\r
+ mov dx, CRTC\r
+ mov al, 0Ch ; Linear Starting Address high\r
+ mov ah, bh\r
+ cli\r
+ out dx, ax\r
+ mov al, 0Dh ; Linear Starting Address low\r
+ mov ah, bl\r
+ out dx, ax\r
+ sti\r
+\r
+ .leave ARG_SIZE\r
+mxStartAddress ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSC.ASM - Set color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetColor\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the selected DAC register.\r
+;\r
+; Input:\r
+; Index = index of color to set\r
+; R, G, B = color components\r
+; Output:\r
+; none\r
+;\r
+mxSetColor PROC FAR\r
+ ARG B:BYTE:2, \\r
+ G:BYTE:2, \\r
+ R:BYTE:2, \\r
+ Index:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [Index]\r
+ mov dx, 3C8h ; PEL write address register\r
+ out dx, al\r
+ inc dx\r
+\r
+ mov al, [R]\r
+ out dx, al\r
+ mov al, [G]\r
+ out dx, al\r
+ mov al, [B]\r
+ out dx, al\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxSetColor ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Stretch image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStretchImage\r
+\r
+EXTRN subClipBox : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Stretches and copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; NewWidth = new width of image in pixels\r
+; NewHeight = new height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxStretchImage PROC FAR\r
+ ARG Op:WORD, \\r
+ NewHeight:WORD, \\r
+ NewWidth:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WidthStep:DWORD, \\r
+ HeightStep:DWORD, \\r
+ ImageLo:WORD, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Get width stretch factor\r
+ IF USE386 EQ TRUE\r
+ movzx edx, [Width]\r
+ xor eax, eax\r
+ movzx ebx, [NewWidth]\r
+ shl ebx, 16\r
+ idiv ebx\r
+ mov [WidthStep], eax\r
+ ELSE\r
+ xor dx, dx ; Width stretch factor\r
+ mov ax, [Width]\r
+ mov bx, [NewWidth]\r
+ div bx\r
+ mov WORD PTR WidthStep[2], ax\r
+ xor ax, ax\r
+ div bx\r
+ mov WORD PTR WidthStep[0], ax\r
+ ENDIF\r
+; Get height stretch factor\r
+ IF USE386 EQ TRUE\r
+ movzx edx, [Height]\r
+ xor eax, eax\r
+ movzx ebx, [NewHeight]\r
+ shl ebx, 16\r
+ idiv ebx\r
+ mov [HeightStep], eax\r
+ ELSE\r
+ xor dx, dx\r
+ mov ax, [Height]\r
+ mov bx, [NewHeight]\r
+ div bx\r
+ mov WORD PTR HeightStep[2], ax\r
+ xor ax, ax\r
+ div bx\r
+ mov WORD PTR HeightStep[0], ax\r
+ ENDIF\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [NewWidth]\r
+ mov dx, [NewHeight]\r
+ call subClipBox\r
+ jc @@Exit ; Full clipped\r
+ mov [NewWidth], cx\r
+ mov [NewHeight], dx\r
+ sub [X], bx\r
+ sub [Y], ax\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl ; Set read plane\r
+ mov cl, bl\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al ; Set write plane\r
+\r
+; Relocate image origin if previously clipped\r
+ mov ax, [Y]\r
+ test ax, ax\r
+ jz @@OriginYDone\r
+ IF USE386 EQ TRUE\r
+ shl eax, 16\r
+ imul [HeightStep]\r
+ mov ax, [Width]\r
+ mul dx\r
+ ELSE\r
+ mov bx, ax\r
+ mul WORD PTR HeightStep[0]\r
+ mov cx, dx\r
+ mov ax, bx\r
+ mul WORD PTR HeightStep[2]\r
+ add ax, cx\r
+ mul [Width]\r
+ ENDIF\r
+ add WORD PTR [Image], ax\r
+@@OriginYDone:\r
+ mov ax, [X]\r
+ test ax, ax\r
+ jz @@OriginXDone\r
+ IF USE386 EQ TRUE\r
+ shl eax, 16\r
+ imul [WidthStep]\r
+ add WORD PTR [Image], dx\r
+ ELSE\r
+ mov bx, ax\r
+ mul WORD PTR WidthStep[0]\r
+ mov cx, dx\r
+ mov ax, bx\r
+ mul WORD PTR WidthStep[2]\r
+ add ax, cx\r
+ add WORD PTR [Image], ax\r
+ ENDIF\r
+@@OriginXDone:\r
+ mov ax, WORD PTR HeightStep[2]\r
+ mul [Width]\r
+ mov WORD PTR HeightStep[2], ax\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ mov ds, WORD PTR Image[2]\r
+ xor ax, ax\r
+ mov [ImageLo], ax\r
+@@Loop:\r
+ mov si, WORD PTR Image[0] ; Get pointer to image\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov cx, [NewHeight]\r
+ mov di, [PixelOffset] ; ES:DI points to video memory\r
+ mov ah, [OpInfo] ; Additional raster op info\r
+ xor bx, bx\r
+ mov dx, [mx_BytesPerLine]\r
+ call [MoveFunction] ; Draw column\r
+ inc [ReadPlane] ; Next read plane\r
+ rol [WritePlane], 1 ; Next write plane\r
+ adc [PixelOffset], 0 ; Update video offset if needed\r
+ mov dx, WORD PTR WidthStep[0]\r
+ mov ax, WORD PTR WidthStep[2]\r
+ add [ImageLo], dx\r
+ adc WORD PTR Image[0], ax ; Next image column\r
+ dec [NewWidth]\r
+ jnz @@Loop ; Repeat for all columns\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions, on entry:\r
+; AH = additional raster op info (e.g. transparent color)\r
+; BX = 0,\r
+; CX = pixel count,\r
+; DX = mx_BytesPerLine.\r
+;\r
+subMove PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ mov es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ and es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ or es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ xor es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip:\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subAdd ENDP\r
+\r
+mxStretchImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Start line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStartLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes the video start address to the specified line.\r
+;\r
+; Input:\r
+; Line = new start line\r
+; Output:\r
+; none\r
+;\r
+mxStartLine PROC FAR\r
+ ARG Line:WORD = ARG_SIZE\r
+ .enter 0\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [Line] ; Get video offset\r
+ mul [mx_BytesPerLine]\r
+ xchg ax, bx ; Copy it into BX\r
+\r
+; Wait display\r
+ mov dx, STATUS\r
+@@1: in al, dx\r
+ test al, 08h\r
+ jnz @@1\r
+\r
+; Set starting address\r
+ mov dx, CRTC\r
+ mov al, 0Ch ; Linear Starting Address high\r
+ mov ah, bh\r
+ cli\r
+ out dx, ax\r
+ mov al, 0Dh ; Linear Starting Address low\r
+ mov ah, bl\r
+ out dx, ax\r
+ sti\r
+\r
+; Wait retrace\r
+ mov dx, STATUS\r
+@@2: in al,dx\r
+ test al, 08h\r
+ jz @@2\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxChangeMode\r
+PUBLIC mxGetAspect\r
+PUBLIC mxGetScreenSize\r
+PUBLIC mxSetMode\r
+\r
+PUBLIC mx_ScreenWidth\r
+PUBLIC mx_ScreenHeight\r
+PUBLIC mx_BytesPerLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mxSetSysClipRegion : FAR\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_ScreenWidth DW ? ; Current screen width\r
+mx_ScreenHeight DW ?\r
+mx_AspectX DW ? ; Aspect ratio for current mode\r
+mx_AspectY DW ?\r
+mx_BytesPerLine DW 0 ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine LABEL WORD ; CRTC\r
+ DW 04009h ; Cell height: 1 scan line\r
+ DW 00014h ; Double word mode off\r
+ DW 0E317h ; Byte mode on\r
+ DW 0\r
+TBL_DoubleLine LABEL WORD ; CRTC\r
+ DW 04109h ; Cell height: 2 scan lines\r
+ DW 00014h\r
+ DW 0E317h\r
+ DW 0\r
+TBL_Width320 LABEL WORD ; CRTC\r
+ DW 05F00h ; Horizontal total\r
+ DW 04F01h ; Horizontal displayed\r
+ DW 05002h ; Start horizontal blanking\r
+ DW 08203h ; End horizontal blanking\r
+ DW 05404h ; Start horizontal sync\r
+ DW 08005h ; End horizontal sync\r
+ DW 02813h ; Row address\r
+ DW 0\r
+TBL_Width360 LABEL WORD ; CRTC\r
+ DW 06B00h ; Horizontal total\r
+ DW 05901h ; Horizontal displayed\r
+ DW 05A02h ; Start horizontal blanking\r
+ DW 08E03h ; End horizontal blanking\r
+ DW 05E04h ; Start horizontal sync\r
+ DW 08A05h ; End horizontal sync\r
+ DW 02D13h ; Row address\r
+ DW 0\r
+TBL_Height175 LABEL WORD ; CRTC\r
+ DW 0BF06h ; Vertical total\r
+ DW 01F07h ; Overflow\r
+ DW 08310h ; Start vertical sync\r
+ DW 08511h ; End vertical sync\r
+ DW 05D12h ; Vertical displayed\r
+ DW 06315h ; Start vertical blanking\r
+ DW 0BA16h ; End vertical blanking\r
+ DW 0\r
+TBL_Height200 LABEL WORD ; CRTC\r
+ DW 0BF06h ; Vertical total\r
+ DW 01F07h ; Overflow\r
+ DW 09C10h ; Start vertical sync\r
+ DW 08E11h ; End vertical sync\r
+ DW 08F12h ; Vertical displayed\r
+ DW 09615h ; Start vertical blanking\r
+ DW 0B916h ; End vertical blanking\r
+ DW 0\r
+TBL_Height240 LABEL WORD ; CRTC\r
+ DW 00D06h ; Vertical total\r
+ DW 03E07h ; Overflow\r
+ DW 0EA10h ; Start vertical sync\r
+ DW 08C11h ; End vertical sync\r
+ DW 0DF12h ; Vertical displayed\r
+ DW 0E715h ; Start vertical blanking\r
+ DW 00616h ; End vertical blanking\r
+ DW 0\r
+TBL_Tweak400x600:\r
+ DW 07400h\r
+ DW 06301h\r
+ DW 06402h\r
+ DW 09703h\r
+ DW 06804h\r
+ DW 09505h\r
+ DW 08606h\r
+ DW 0F007h\r
+ DW 06009h\r
+ DW 0310Fh\r
+ DW 05B10h\r
+ DW 08D11h\r
+ DW 05712h\r
+ DW 03213h\r
+ DW 00014h\r
+ DW 06015h\r
+ DW 08016h\r
+ DW 0E317h\r
+ DW 0\r
+\r
+TBL_320x200:\r
+ DB 63h ; 400 scan lines, 25 MHz clock\r
+ DW 6, 5 ; Aspect: 6/5 = 1.2:1\r
+ DW 320, 200 ; Size\r
+ DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x240:\r
+ DB 0E3h ; 400 scan lines, 25 MHz clock\r
+ DW 1, 1 ; Aspect: 1/1 = 1:1\r
+ DW 320, 240 ; Size\r
+ DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x400:\r
+ DB 63h ; 480 scan lines, 25 MHz clock\r
+ DW 6, 10 ; Aspect: 6/10 = 0.6:1\r
+ DW 320, 400 ; Size\r
+ DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x480:\r
+ DB 0E3h ; 480 scan lines, 25 MHz clock\r
+ DW 1, 2 ; Aspect: 1/2 = 0.5:1\r
+ DW 320, 480 ; Size\r
+ DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+ DW 819 ; Max height\r
+TBL_360x200:\r
+ DB 067h ; 400 scan lines, 28 MHz clock\r
+ DW 27, 20 ; Aspect: 27/20 = 1.35:1\r
+ DW 360, 200 ; Size\r
+ DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x240:\r
+ DB 0E7h ; 480 scan lines, 28 MHz clock\r
+ DW 9, 8 ; Aspect: 9/8 = 1.125:1\r
+ DW 360, 240 ; Size\r
+ DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x400:\r
+ DB 067h ; 400 scan lines, 28 MHz clock\r
+ DW 27, 40 ; Aspect: 27/40 = 0.675:1\r
+ DW 360, 400 ; Size\r
+ DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x480:\r
+ DB 0E7h ; 480 scan lines, 28 MHz clock\r
+ DW 9, 16 ; Aspect: 9/16 = 0.5625:1\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_320x175:\r
+ DB 0A3h\r
+ DW 0, 0 ; Aspect:\r
+ DW 320, 175\r
+ DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+ DW 819\r
+TBL_320x350:\r
+ DB 0A3h\r
+ DW 0, 0 ; Aspect:\r
+ DW 320, 175\r
+ DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+ DW 819\r
+TBL_360x175:\r
+ DB 0A7h\r
+ DW 0, 0 ; Aspect:\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x350:\r
+ DB 0A7h\r
+ DW 0, 0 ; Aspect:\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_400x600:\r
+ DB 0E7h ; 28 MHz clock\r
+ DW 1, 2 ; Aspect: 1/2 = 0.5:1\r
+ DW 400, 600 ; Size\r
+ DW TBL_Tweak400x600, 0\r
+ DW 655 ; Max height\r
+\r
+TBL_Mode LABEL WORD\r
+ DW TBL_320x175\r
+ DW TBL_320x200\r
+ DW TBL_320x240\r
+ DW TBL_320x350\r
+ DW TBL_320x400\r
+ DW TBL_320x480\r
+ DW TBL_360x175\r
+ DW TBL_360x200\r
+ DW TBL_360x240\r
+ DW TBL_360x350\r
+ DW TBL_360x400\r
+ DW TBL_360x480\r
+ DW TBL_400x600\r
+\r
+MAXVMODE EQU ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText PROC NEAR\r
+ ASSUME ds:MX_TEXT\r
+ mov ax, 0003h\r
+ int 10h ; Call BIOS set mode\r
+\r
+ mov [mx_ScreenHeight], 0\r
+ mov [mx_BytesPerLine], 0\r
+ ret\r
+subText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+; Mode = mode to select (MX_???x???)\r
+; Output:\r
+; none\r
+;\r
+mxSetMode PROC FAR\r
+ ARG Mode:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov si, [Mode]\r
+ cmp si, MAXVMODE ; Is it a valid mode?\r
+ ja @@Exit ; No, exit\r
+ test si, si ; Text mode?\r
+ jnz @@Set ; No, handle it\r
+\r
+ call subText ; Back to text mode\r
+ jmp @@Exit ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+ dec si ; Skip text mode\r
+ shl si, 1\r
+ mov si, TBL_Mode[si]\r
+ cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+ push si ; Save SI\r
+ mov ax, 0013h\r
+ int 10h ; Use BIOS to set 320x200 linear mode\r
+ pop si ; Restore SI\r
+\r
+ mov dx, TS\r
+ mov ax, 0604h\r
+ out dx, ax ; Disable chain-4 mode\r
+ mov ax, 0100h\r
+ out dx, ax ; Reset\r
+ mov dx, MISC\r
+ lodsb\r
+ out dx, al ; New timing/size\r
+ mov dx, TS\r
+ mov ax, 0300h\r
+ out dx, ax ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ and al, 7Fh ; Clear write protect bit\r
+ out dx, al\r
+\r
+ lodsw ; Get X aspect\r
+ mov [mx_AspectX], ax\r
+ lodsw ; Get Y aspect\r
+ mov [mx_AspectY], ax\r
+ lodsw ; Get screen width\r
+ mov [mx_ScreenWidth], ax\r
+ shr ax, 1\r
+ shr ax, 1 ; Divide by four to get bytes per line\r
+ mov [mx_BytesPerLine], ax\r
+ lodsw ; Get screen height\r
+ mov [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+ mov bx, si\r
+ mov dx, CRTC\r
+@@TableLoop:\r
+ mov si, ds:[bx] ; DS:SI -> table of CRTC registers\r
+ inc bx\r
+ inc bx ; DS:BX -> offset of next table\r
+ test si, si ; Last table?\r
+ jz @@EndLoop ; Yes, exit loop\r
+@@Loop:\r
+ lodsw ; Get CRTC register index and value\r
+ test ax, ax ; End of table?\r
+ jz @@TableLoop ; Yes, go to next table\r
+ out dx, ax ; Set register AL to value AH\r
+ jmp @@Loop ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+ push [mx_ScreenWidth]\r
+ push WORD PTR ds:[bx]\r
+ call mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Enable all planes\r
+ mov es, [mx_VideoSegment]\r
+ xor di, di\r
+ mov cx, 8000h\r
+ xor ax, ax\r
+ rep stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ or al, 80h ; Set write protect bit\r
+ out dx, al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ mov ax, [mx_ScreenWidth]\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxSetMode ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+; Mode = mode to select (MX_???x???)\r
+; Output:\r
+; none\r
+; Notes:\r
+; this function assumes that mxSetMode and mxSetVirtualScreen\r
+; have been called first. View size is rearranged to match the\r
+; specified mode, but video memory is not cleared.\r
+; Differences from mxSetMode:\r
+; - video BIOS is not called to initialize graphics;\r
+; - row address register is not modified;\r
+; - video memory is not cleared;\r
+; - mx_BytesPerLine is not modified;\r
+; - system clip region is not modified.\r
+;\r
+mxChangeMode PROC FAR\r
+ ARG Mode:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov si, [Mode]\r
+ cmp si, MAXVMODE ; Is it a valid mode?\r
+ ja @@Exit ; No, exit\r
+ test si, si ; Text mode?\r
+ jz @@Exit ; Yes, exit\r
+\r
+ dec si ; Skip text mode\r
+ shl si, 1\r
+ mov si, TBL_Mode[si]\r
+ cld\r
+\r
+ mov dx, TS\r
+ mov ax, 0604h\r
+ out dx, ax ; Disable chain-4 mode\r
+ mov ax, 0100h\r
+ out dx, ax ; Reset\r
+ mov dx, MISC\r
+ lodsb\r
+ out dx, al ; New timing/size\r
+ mov dx, TS\r
+ mov ax, 0300h\r
+ out dx, ax ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ and al, 7Fh ; Clear write protect bit\r
+ out dx, al\r
+\r
+ lodsw ; Get X aspect\r
+ mov [mx_AspectX], ax\r
+ lodsw ; Get Y aspect\r
+ mov [mx_AspectY], ax\r
+ lodsw ; Get screen width\r
+ mov [mx_ScreenWidth], ax\r
+ lodsw ; Get screen height\r
+ mov [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+ mov bx, si\r
+ mov dx, CRTC\r
+@@TableLoop:\r
+ mov si, ds:[bx] ; DS:SI -> table of CRTC registers\r
+ inc bx\r
+ inc bx ; DS:BX -> offset of next table\r
+ test si, si ; Last table?\r
+ jz @@EndLoop ; Yes, exit loop\r
+@@Loop:\r
+ lodsw ; Get CRTC register index and value\r
+ test ax, ax ; End of table?\r
+ jz @@TableLoop ; Yes, go to next table\r
+ cmp al, 13h ; Row address register?\r
+ je @@Loop ; Yes, ignore it\r
+ out dx, ax ; Set register AL to value AH\r
+ jmp @@Loop ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ or al, 80h ; Set write protect bit\r
+ out dx, al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ mov ax, [mx_ScreenWidth]\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxChangeMode ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+; AspectX = pointer to aspect X\r
+; AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect PROC FAR\r
+ ARG AspectY:DWORD, \\r
+ AspectX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [AspectX]\r
+ mov ax, [mx_AspectX]\r
+ mov ds:[si], ax\r
+ lds si, [AspectY]\r
+ mov ax, [mx_AspectY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetAspect ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+; Width = pointer to screen width\r
+; Height = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+ ARG SizeY:DWORD, \\r
+ SizeX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [SizeX]\r
+ mov ax, [mx_ScreenWidth]\r
+ mov ds:[si], ax\r
+ lds si, [SizeY]\r
+ mov ax, [mx_ScreenHeight]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSP.ASM - Set palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetPalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to palette data (R,G,B)\r
+; Start = index of first color to set\r
+; Count = number of color to set\r
+; Output:\r
+; none\r
+;\r
+mxSetPalette PROC FAR\r
+ ARG Count:WORD, \\r
+ Start:WORD, \\r
+ Buffer:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ lds si, [Buffer]\r
+ mov cx, [Count]\r
+ mov ax, [Start]\r
+ mov dx, 3C8h ; PEL write address register\r
+ out dx, al\r
+ inc dx\r
+ cld\r
+ cli ; Disable interrupts\r
+@@Loop:\r
+ lodsb\r
+ out dx, al ; Red\r
+ lodsb\r
+ out dx, al ; Green\r
+ lodsb\r
+ out dx, al ; Blue\r
+ loop @@Loop ; Loop until done\r
+ sti ; Enable interrupts\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxSetPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSS.ASM - Split screen function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSplitScreen\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Splits the screen.\r
+;\r
+; Input:\r
+; Line = scan line at which screen has to be splitted\r
+; Output:\r
+; none\r
+;\r
+mxSplitScreen PROC FAR\r
+ ARG Line:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+; Modify the line compare value: bits 0-7 are in the Line Compare\r
+; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7)\r
+; and bit 9 is in the Maximum Row Address register (CRTC #9)\r
+ mov ax, [Line]\r
+ shl ax, 1 ; Adjust line for mode "X"\r
+ mov bh, ah\r
+ mov bl, ah\r
+ and bx, 0201h\r
+ mov cl, 4\r
+ shl bx, cl\r
+ shl bh, 1\r
+ mov dx, CRTC\r
+; Write bits 0-7 to line compare register\r
+ mov ah, al\r
+ mov al, 18h\r
+ out dx, ax\r
+; Write bit 8 to overflow register\r
+ mov al, 07h\r
+ out dx, al\r
+ inc dx\r
+ in al, dx\r
+ dec dx\r
+ mov ah, al\r
+ and ah, 11101111b\r
+ or ah, bl\r
+ mov al, 07h\r
+ out dx, ax\r
+; Write bit 9 to maximum row address register\r
+ mov al, 09h\r
+ out dx, al\r
+ inc dx\r
+ in al, dx\r
+ dec dx\r
+ mov ah, al\r
+ and ah, 10111111b\r
+ or ah, bh\r
+ mov al, 09h\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxSplitScreen ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutTile\r
+PUBLIC mxTransPutTile\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+ shr cx, 1 ; Move line\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutTile ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxTransPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+; Move one line\r
+ jcxz @@MoveLineDone\r
+@@MoveLineLoop:\r
+ mov al, ds:[si]\r
+ test al, al\r
+ jz @@MoveLineNext\r
+ mov es:[di], al\r
+@@MoveLineNext:\r
+ inc si\r
+ inc di\r
+ dec cx\r
+ jnz @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxTransPutTile ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXVS.ASM - Set/get virtual screen\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetVirtualScreen\r
+PUBLIC mxGetVirtualScreen\r
+\r
+EXTRN mxRowAddress : FAR\r
+EXTRN mxSetSysClipRegion : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_VirtualWidth DW ? ; Virtual screen size\r
+mx_VirtualHeight DW ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the virtual screen.\r
+;\r
+; Input:\r
+; Width = virtual screen width\r
+; Height = virtual screen height\r
+; Output:\r
+; 0 on success, else invalid parameters\r
+;\r
+mxSetVirtualScreen PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+\r
+; Set DS to code segment\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, 1 ; Assume an error\r
+ cmp [Width], 320 ; Check width\r
+ jb @@Exit\r
+ push ax ; Save return code\r
+ mov dx, 0004h\r
+ xor ax, ax ; DX:AX = 256K\r
+ div [Width] ; Max height in AX\r
+ cmp [Height], ax\r
+ pop ax ; Restore return code\r
+ ja @@Exit ; Exit if bad heigth\r
+\r
+ mov ax, [Width]\r
+ and ax, 0FFF8h ; Align to byte\r
+ mov [mx_VirtualWidth], ax\r
+ shr ax, 1\r
+ shr ax, 1\r
+ mov [mx_BytesPerLine], ax\r
+ shr ax, 1\r
+ push ax\r
+ call mxRowAddress ; Set row address\r
+ mov ax, [Height]\r
+ mov [mx_VirtualHeight], ax\r
+\r
+ push [Width]\r
+ push [Height]\r
+ call mxSetSysClipRegion\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetVirtualScreen ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current virtual screen size.\r
+;\r
+; Input:\r
+; Width = pointer to virtual screen width\r
+; Height = pointer to virtual screen height\r
+; Output:\r
+; none\r
+;\r
+mxGetVirtualScreen PROC FAR\r
+ ARG Height:DWORD, \\r
+ Width:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [mx_VirtualWidth]\r
+ lds si, [Width]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_VirtualHeight]\r
+ lds si, [Height]\r
+ mov ds:[si], ax\r
+\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetVirtualScreen ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWD.ASM - Wait display function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWaitDisplay\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for display start.\r
+;\r
+mxWaitDisplay PROC FAR\r
+ mov dx, STATUS\r
+@@1: in al, dx\r
+ test al, 08h\r
+ jnz @@1\r
+ ret\r
+mxWaitDisplay ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWM.ASM - Set write mode function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWriteMode\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write mode.\r
+;\r
+; Input:\r
+; Mode = write mode (0,1,2,3)\r
+; Output:\r
+; none\r
+;\r
+mxWriteMode PROC FAR\r
+ ARG Mode:BYTE:2 = ARG_SIZE\r
+ .enter 0\r
+\r
+ mov dx, GDC\r
+ mov ah, [Mode]\r
+ and ah, 00000011b\r
+ or ah, 01000000b\r
+ mov al, 05h\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxWriteMode ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWP.ASM - Set write/read plane functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWritePlane\r
+PUBLIC mxReadPlane\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write plane(s).\r
+;\r
+; Input:\r
+; Plane = write plane(s) to set (bit 0 enables plane 0,\r
+; bit 1 enables plane 1 and so on, different planes\r
+; may be selected at the same time)\r
+; Output:\r
+; none\r
+;\r
+mxWritePlane PROC FAR\r
+ ARG Plane:BYTE:2 = ARG_SIZE\r
+ .enter 0\r
+\r
+ mov ah, [Plane]\r
+ and ah, 00001111b ; Mask off unused bits\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxWritePlane ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the read plane.\r
+;\r
+; Input:\r
+; Plane = read plane to set (0,1,2,3)\r
+; Output:\r
+; none\r
+;\r
+mxReadPlane PROC FAR\r
+ ARG Plane:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ mov al, 04h\r
+ mov ah, [Plane]\r
+ and ah, 0000011b ; Mask off unused bits\r
+ mov dx, GDC\r
+ out dx, ax\r
+ .leave ARG_SIZE\r
+mxReadPlane ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWR.ASM - Wait vertical retrace function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWaitRetrace\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for vertical retrace start.\r
+;\r
+mxWaitRetrace PROC FAR\r
+ mov dx, STATUS\r
+@@1: in al,dx\r
+ test al, 08h\r
+ jz @@1\r
+ ret\r
+mxWaitRetrace ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0\r
+ DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1\r
+ DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2\r
+ DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3\r
+ DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4\r
+ DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5\r
+ DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6\r
+ DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7\r
+ DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8\r
+ DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9\r
+ DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10\r
+ DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11\r
+ DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12\r
+ DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13\r
+ DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14\r
+ DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15\r
+ DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16\r
+ DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17\r
+ DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18\r
+ DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19\r
+ DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20\r
+ DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21\r
+ DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22\r
+ DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23\r
+ DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24\r
+ DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25\r
+ DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26\r
+ DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27\r
+ DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28\r
+ DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29\r
+ DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30\r
+ DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; \r
+ DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; !\r
+ DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; "\r
+ DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; #\r
+ DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $\r
+ DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; %\r
+ DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; &\r
+ DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; '\r
+ DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; (\r
+ DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; )\r
+ DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; *\r
+ DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; +\r
+ DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; ,\r
+ DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; -\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; .\r
+ DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; /\r
+ DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0\r
+ DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1\r
+ DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2\r
+ DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3\r
+ DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4\r
+ DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5\r
+ DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6\r
+ DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7\r
+ DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8\r
+ DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9\r
+ DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; :\r
+ DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ;\r
+ DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; <\r
+ DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; =\r
+ DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; >\r
+ DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ?\r
+ DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A\r
+ DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B\r
+ DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C\r
+ DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F\r
+ DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G\r
+ DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H\r
+ DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I\r
+ DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J\r
+ DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K\r
+ DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L\r
+ DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M\r
+ DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O\r
+ DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P\r
+ DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q\r
+ DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R\r
+ DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S\r
+ DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T\r
+ DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U\r
+ DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V\r
+ DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W\r
+ DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X\r
+ DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y\r
+ DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z\r
+ DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [\r
+ DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \\r
+ DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ]\r
+ DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _\r
+ DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; `\r
+ DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b\r
+ DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c\r
+ DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d\r
+ DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e\r
+ DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h\r
+ DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i\r
+ DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j\r
+ DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k\r
+ DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l\r
+ DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m\r
+ DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n\r
+ DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o\r
+ DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q\r
+ DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r\r
+ DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s\r
+ DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t\r
+ DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u\r
+ DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v\r
+ DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w\r
+ DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x\r
+ DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y\r
+ DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z\r
+ DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; {\r
+ DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; |\r
+ DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; }\r
+ DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~\r
+ DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ; \7f\r
+ DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128\r
+ DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129\r
+ DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130\r
+ DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131\r
+ DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132\r
+ DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133\r
+ DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134\r
+ DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135\r
+ DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136\r
+ DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137\r
+ DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138\r
+ DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139\r
+ DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140\r
+ DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141\r
+ DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142\r
+ DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143\r
+ DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144\r
+ DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145\r
+ DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146\r
+ DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147\r
+ DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148\r
+ DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149\r
+ DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150\r
+ DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151\r
+ DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152\r
+ DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153\r
+ DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154\r
+ DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155\r
+ DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156\r
+ DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157\r
+ DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158\r
+ DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159\r
+ DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160\r
+ DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161\r
+ DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162\r
+ DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163\r
+ DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164\r
+ DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165\r
+ DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166\r
+ DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167\r
+ DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168\r
+ DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169\r
+ DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170\r
+ DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171\r
+ DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172\r
+ DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173\r
+ DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174\r
+ DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175\r
+ DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176\r
+ DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177\r
+ DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178\r
+ DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181\r
+ DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182\r
+ DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183\r
+ DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184\r
+ DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185\r
+ DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186\r
+ DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187\r
+ DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188\r
+ DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190\r
+ DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198\r
+ DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199\r
+ DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200\r
+ DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201\r
+ DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202\r
+ DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203\r
+ DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205\r
+ DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206\r
+ DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210\r
+ DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212\r
+ DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213\r
+ DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215\r
+ DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217\r
+ DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220\r
+ DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221\r
+ DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223\r
+ DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224\r
+ DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225\r
+ DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226\r
+ DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227\r
+ DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228\r
+ DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229\r
+ DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230\r
+ DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231\r
+ DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233\r
+ DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234\r
+ DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235\r
+ DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236\r
+ DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237\r
+ DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239\r
+ DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240\r
+ DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241\r
+ DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242\r
+ DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243\r
+ DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244\r
+ DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245\r
+ DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246\r
+ DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247\r
+ DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248\r
+ DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249\r
+ DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250\r
+ DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251\r
+ DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252\r
+ DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253\r
+ DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+ MXCC.OBJ \\r
+ MXCG.OBJ \\r
+ MXCL.OBJ \\r
+ MXCR.OBJ \\r
+ MXFB.OBJ \\r
+ MXFP.OBJ \\r
+ MXGC.OBJ \\r
+ MXGI.OBJ \\r
+ MXGM.OBJ \\r
+ MXGP.OBJ \\r
+ MXGV.OBJ \\r
+ MXHL.OBJ \\r
+ MXIT.OBJ \\r
+ MXLL.OBJ \\r
+ MXLN.OBJ \\r
+ MXOT.OBJ \\r
+ MXPB.OBJ \\r
+ MXPF.OBJ \\r
+ MXPG.OBJ \\r
+ MXPI.OBJ \\r
+ MXPN.OBJ \\r
+ MXPP.OBJ \\r
+ MXRA.OBJ \\r
+ MXRP.OBJ \\r
+ MXSA.OBJ \\r
+ MXSC.OBJ \\r
+ MXSI.OBJ \\r
+ MXSL.OBJ \\r
+ MXSM.OBJ \\r
+ MXSP.OBJ \\r
+ MXSS.OBJ \\r
+ MXTL.OBJ \\r
+ MXVS.OBJ \\r
+ MXWD.OBJ \\r
+ MXWM.OBJ \\r
+ MXWP.OBJ \\r
+ MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /zi\r
+#/p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+ $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+JUMPS\r
+LOCALS\r
+\r
+TRUE EQU 1 ; Boolean constants\r
+FALSE EQU 0\r
+\r
+USE286 = FALSE ; TRUE enables 80286 instructions\r
+USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+ P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+ P386\r
+ USE286 = TRUE\r
+ENDIF\r
+\r
+MXVERSION EQU 0128h ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC EQU 3C2h ; Miscellaneous output\r
+TS EQU 3C4h ; Timing Sequencer index register\r
+GDC EQU 3CEh ; Graphics Data Controller index register\r
+CRTC EQU 3D4h ; CRTC index register\r
+STATUS EQU 3DAh ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET EQU 0\r
+OP_MOVE EQU 0 ; Same as OP_SET\r
+OP_AND EQU 1\r
+OP_OR EQU 2\r
+OP_XOR EQU 3\r
+OP_TRANS EQU 4\r
+OP_ADD EQU 5 ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU 4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.PUSH has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+ IFB <$reg> ;; Is argument blank?\r
+ EXITM ;; Yes, exit\r
+ ELSEIFIDNI <$reg>, <FLAGS> ;; Is argument the keyword "FLAGS"?\r
+ pushf ;; Yes, push flags\r
+ ELSE\r
+ push $reg ;; Push argument\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.POP has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+ IFNB <$reg> ;; Is argument non-blank?\r
+ IFIDNI <$reg>, <FLAGS> ;; Yes, is it the keyword "FLAGS"?\r
+ popf ;; Yes, pop flags\r
+ ELSE\r
+ pop $reg ;; Pop argument\r
+ ENDIF\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter MACRO localsize\r
+ IF USE286 EQ TRUE\r
+ enter localsize, 0\r
+ ELSE\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, localsize\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.leave MACRO argsize\r
+ IF USE286 EQ TRUE\r
+ leave\r
+ ELSE\r
+ mov sp, bp\r
+ pop bp\r
+ ENDIF\r
+ IFNB <argspace>\r
+ ret argsize\r
+ ELSE\r
+ ret\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shr MACRO arg, count\r
+ IF USE286 EQ TRUE\r
+ shr arg, count\r
+ ELSE\r
+ $temp = count\r
+ WHILE $temp GT 0\r
+ shr arg, 1\r
+ $temp = $temp-1\r
+ ENDM\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shl MACRO arg, count\r
+ IF USE286 EQ TRUE\r
+ shl arg, count\r
+ ELSE\r
+ $temp = count\r
+ WHILE $temp GT 0\r
+ shl arg, 1\r
+ $temp = $temp-1\r
+ ENDM\r
+ ENDIF\r
+ENDM\r
--- /dev/null
+/*\r
+ MODEX.H - C/C++ include file for the MODEX library\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_ // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT 0 // 80x25 text\r
+#define MX_320x175 1 // 320x175x256\r
+#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350 4 // 320x350x256\r
+#define MX_320x400 5 // 320x400x256, 2 pages\r
+#define MX_320x480 6 // 320x480x256, 1 page\r
+#define MX_360x175 7 // 360x175x256\r
+#define MX_360x200 8 // 360x200x256, 3 pages\r
+#define MX_360x240 9 // 360x240x256, 2 pages\r
+#define MX_360x350 10 // 360x350x256\r
+#define MX_360x400 11 // 360x400x256, 1 page\r
+#define MX_360x480 12 // 360x480x256, 1 page\r
+#define MX_400x600 13 // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN 0\r
+#define MX_FADEOUT 1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET 0 // No operator\r
+#define OP_AND 1 // And\r
+#define OP_OR 2 // Or\r
+#define OP_XOR 3 // Xor\r
+#define OP_TRANS 4 // Transparent\r
+#define OP_ADD 5 // Additive\r
+#define OP_MOVE 0 // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE unsigned char\r
+#define MXBOOL short int\r
+#define MXSINT short int\r
+#define MXUINT unsigned short int\r
+#define MXAPI far pascal\r
+#define MXPTR void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT MXAPI mxInit( void ); // Returns 0 if successful\r
+void MXAPI mxTerm( void );\r
+MXUINT MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void MXAPI mxChangeMode( MXUINT mode );\r
+void MXAPI mxSetMode( MXUINT mode );\r
+void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void MXAPI mxWriteMode( MXBYTE wm );\r
+void MXAPI mxSplitScreen( MXUINT line );\r
+void MXAPI mxStartAddress( MXUINT sa );\r
+void MXAPI mxStartLine( MXUINT sl );\r
+void MXAPI mxWaitDisplay( void );\r
+void MXAPI mxWaitRetrace( void );\r
+void MXAPI mxWritePlane( MXBYTE wp );\r
+void MXAPI mxReadPlane( MXBYTE rp );\r
+void MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL MXAPI mxGetClip( void );\r
+MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL MXAPI mxSetClip( MXBOOL );\r
+void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef MXBYTE\r
+#undef MXBOOL\r
+#undef MXSINT\r
+#undef MXUINT\r
+#undef MXPTR\r
+#undef MXAPI\r
+\r
+#endif // _MODEX_H_\r
--- /dev/null
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
--- /dev/null
+(*\r
+ Turbo Pascal interface to the MODEX library\r
+ Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+ (* Video modes *)\r
+ MX_TEXT = 0;\r
+ MX_320x175 = 1;\r
+ MX_320x200 = 2;\r
+ MX_320x240 = 3;\r
+ MX_320x350 = 4;\r
+ MX_320x400 = 5;\r
+ MX_320x480 = 6;\r
+ MX_360x175 = 7;\r
+ MX_360x200 = 8;\r
+ MX_360x240 = 9;\r
+ MX_360x350 = 10;\r
+ MX_360x400 = 11;\r
+ MX_360x480 = 12;\r
+ MX_400x600 = 13;\r
+\r
+ (* Fade effects *)\r
+ MX_FADEIN = 0;\r
+ MX_FADEOUT = 1;\r
+\r
+ (* Raster ops *)\r
+ OP_SET = 0;\r
+ OP_AND = 1;\r
+ OP_OR = 2;\r
+ OP_XOR = 3;\r
+ OP_TRANS = 4;\r
+ OP_ADD = 5;\r
+ OP_MOVE = 0; (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt; external;\r
+procedure mxChangeMode( Mode: word ); external;\r
+procedure mxCircle; external;\r
+procedure mxColorToGray; external;\r
+procedure mxFadePalette; external;\r
+procedure mxFillBox; external;\r
+procedure mxGammaCorrect; external;\r
+procedure mxGetAspect( var AspectX, AspectY: word ); external;\r
+function mxGetClipRegion; external;\r
+function mxGetClip: boolean; external;\r
+procedure mxGetImage; external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function mxGetPixel( X, Y: word ): byte; external;\r
+procedure mxGetScreenSize( var Width, Height: word ); external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external;\r
+function mxGetVersion: word; external;\r
+procedure mxGetVirtualScreen( var Width, Height: word ); external;\r
+procedure mxInit; external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external;\r
+procedure mxOutChar( X, Y: integer; C: char ); external;\r
+procedure mxOutText( X, Y: integer; S: pointer ); external;\r
+procedure mxPan( X, Y: word ); external;\r
+procedure mxPutImage; external;\r
+procedure mxPutPixel( X, Y: word; C: byte ); external;\r
+procedure mxPutTile; external;\r
+procedure mxReadPlane( Plane: byte ); external;\r
+procedure mxRotatePalette; external;\r
+procedure mxRowAddress( RowAddress: byte ); external;\r
+function mxSetClip( Clip: boolean ): boolean; external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external;\r
+procedure mxSetColor( Index, R, G, B: word ); external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word ); external;\r
+procedure mxSetMode( Mode: word ); external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word ); external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer ); external;\r
+procedure mxSetVirtualScreen( Width, Height: word ); external;\r
+procedure mxSplitScreen( Line: word ); external;\r
+procedure mxStartAddress( StartAddress: word ); external;\r
+procedure mxStartLine; external;\r
+procedure mxStretchImage; external;\r
+procedure mxTerm; external;\r
+procedure mxTransPutTile; external;\r
+procedure mxWaitDisplay; external;\r
+procedure mxWaitRetrace; external;\r
+procedure mxWriteMode( Mode: byte ); external;\r
+procedure mxWritePlane( Plane: byte ); external;\r
+\r
+procedure mxFillPoly; external;\r
+procedure mxGouraudPoly; external;\r
+procedure mxTexturePoly; external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+ Prints a Turbo Pascal string.\r
+ Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+ S := S + #0;\r
+ mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
--- /dev/null
+(*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ MAX_SPRITE = 100;\r
+type\r
+ (* Sprite structure *)\r
+ TSprite = record\r
+ X, Y : integer; (* Sprite coordinates *)\r
+ DX,DY: integer; (* Deltas for sprite movement *)\r
+ W, H : integer; (* Sprite width and height *)\r
+ Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *)\r
+ end;\r
+ (* RGB color structure *)\r
+ TRgb = record\r
+ R, G, B: byte;\r
+ end;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *)\r
+ Palette: array[ byte ] of TRgb; (* Palette *)\r
+ Page : word; (* Page offset *)\r
+ I : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X := Random( 320 ); (* Initialize position with random values *)\r
+ S.Y := Random( 240 );\r
+ S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+ S.DY := Random( 7 )-3;\r
+ S.W := 16; (* Size is fixed in this program *)\r
+ S.H := 16;\r
+ (* The image is a square with a hole inside *)\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); (* Get new position *)\r
+ Inc( S.Y, S.DY );\r
+ (* Check sprite position, change delta if needed *)\r
+ if( S.X > 320 ) then begin\r
+ S.X := 320;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.X < -16 ) then begin\r
+ S.X := -16;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.Y > 240 ) then begin\r
+ S.Y := 240;\r
+ S.DY := -S.DY;\r
+ end;\r
+ if( S.Y < -16 ) then begin\r
+ S.Y := -16;\r
+ S.DY := -S.DY;\r
+ end;\r
+ (* Draw the sprite, note the Page offset added to the *)\r
+ (* Y coordinate of the image *)\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+ (* Initialize library *)\r
+ mxInit;\r
+\r
+ (* Enter graphics mode *)\r
+ mxSetMode( MX_320x240 );\r
+\r
+ (* Print initialization message *)\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ (* Initialize sprites *)\r
+ for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+ (* Draw background *)\r
+ for I:=1 to 192 do begin\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ end;\r
+\r
+ (* Compute and set palette *)\r
+ for I:=1 to 192 do with Palette[I+63] do begin\r
+ R := 0;\r
+ G := 0;\r
+ B := 0;\r
+ if( I < 64 ) then\r
+ R := I shr 1+31\r
+ else if( I < 128 ) then\r
+ G := (I-64) shr 1+31\r
+ else\r
+ B := (I-128) shr 1+31;\r
+ end;\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ (* Main loop *)\r
+ Page := 240;\r
+ while( not KeyPressed ) do begin\r
+ (* Set clip region to current page *)\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ (* Restore background *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ (* Draw sprites *)\r
+ for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+ (* Print message *)\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ (* Flip page *)\r
+ mxStartLine( Page );\r
+ Page := 240-Page;\r
+ (* Animate palette *)\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO02 - Texture mapping and palette rotation\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+ LSIZE = 85;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of T2DPoint;\r
+ Width : word;\r
+ Data : array[ 1..64*64 ] of byte;\r
+ end;\r
+ TQuad = record\r
+ VtxCnt : word;\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+var\r
+ Vtx : array[ 0..7 ] of TPoint;\r
+ XVtx : array[ 0..7 ] of TPoint;\r
+ VVtx : array[ 0..7 ] of T2DPoint;\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Txts : array[ 0..5 ] of TTexture;\r
+ Nrm : array[ 0..5 ] of TPoint;\r
+ XNrm : array[ 0..5 ] of TPoint;\r
+ Page : word;\r
+ Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+ I: word;\r
+begin\r
+ mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+ MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+ mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+ (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+ with Txts[Idx] do begin\r
+ Desc[0].X := $80; Desc[0].Y := $80;\r
+ Desc[1].X := $80; Desc[1].Y := $3F80;\r
+ Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+ Desc[3].X := $3F80; Desc[3].Y := $80;\r
+ Width := 64;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Build vertexes for a cube *)\r
+ with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ for I:=0 to 7 do begin (* Make points 16:16 fixed *)\r
+ Vtx[I].X := Vtx[I].X*$10000;\r
+ Vtx[I].Y := Vtx[I].Y*$10000;\r
+ Vtx[I].Z := Vtx[I].Z*$10000;\r
+ end;\r
+ (* Build faces *)\r
+ with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+ with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+ with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+ with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+ with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+ with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+ for I:=0 to 5 do Face[I].Texture := I;\r
+ (* Build textures and palette *)\r
+ Randomize;\r
+ FillChar( Palette, SizeOf(Palette), 0 );\r
+ MakePlasmaPalette( Palette, PAL_RGB );\r
+ mxSetPalette( @Palette, 0, 193 );\r
+ for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *)\r
+ (* Draw cube: backface culling is straighforward in this case, so *)\r
+ (* it can be handled by the polygon filling procedure *)\r
+ for I:=0 to 5 do\r
+ mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *)\r
+ Page := 240-Page;\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 1000; (* Number of points *)\r
+ EDGE = 70; (* Length of cube edge *)\r
+ RADIUS = 90; (* Radius of sphere *)\r
+ WAITCOUNT = 192; (* Frames to wait for non-morphing shapes *)\r
+ MS = 32; (* Number of steps for morphing *)\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+ InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+ InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+ InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+ P3DPointArray = ^T3DPointArray;\r
+var\r
+ CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+ VVtx : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+ Page : word;\r
+ Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+ L: longint;\r
+begin\r
+ L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+ Toggle := A;\r
+ if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+ I: integer;\r
+begin\r
+ New( CubeVtx );\r
+ New( SphereVtx );\r
+ New( Vtx );\r
+ New( XVtx );\r
+ (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+ Randomize;\r
+ for I:=0 to MAXVTX-1 do begin\r
+ with CubeVtx^[I] do begin\r
+ (* Build cube *)\r
+ X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Z := Toggle( EDGE*$10000 );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ end;\r
+ with SphereVtx^[I] do begin\r
+ (* Build sphere *)\r
+Retry:\r
+ X := (longint(Random(2*RADIUS))-RADIUS);\r
+ Y := (longint(Random(2*RADIUS))-RADIUS);\r
+ if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+ Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+ end;\r
+ end;\r
+ (* Initialize morphing *)\r
+ Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+ Status := 0;\r
+ Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Fully unoptimized, slowest loop I could think of! *)\r
+ for I:=0 to MAXVTX-1 do begin\r
+ Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+ Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+ Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ C := #0;\r
+ repeat\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw points *)\r
+ for I:=0 to MAXVTX-1 do\r
+ mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ Page := 240-Page;\r
+ (* Morph *)\r
+ if( Odd(Status) ) then begin\r
+ Morph;\r
+ Inc( Morph1, Delta1 );\r
+ Inc( Morph2, Delta2 );\r
+ if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+ if( Status = 4 ) then Status := 0;\r
+ end\r
+ else begin\r
+ Dec( Count );\r
+ if( Count < 0 ) then begin\r
+ Inc( Status );\r
+ Count := WAITCOUNT;\r
+ Morph1 := InitMorph1[Status];\r
+ Morph2 := InitMorph2[Status];\r
+ Delta1 := InitDelta1[Status];\r
+ Delta2 := InitDelta2[Status];\r
+ end;\r
+ end;\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO04 - Multiple textures and triple buffering (3 pages)\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 256;\r
+ MAXCUB = 2;\r
+ MAXTXT = 2;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ TxtSunDial: array[ 0..7 ] of word = (\r
+ $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+ TxtSapphire : array[ 0..7 ] of word = (\r
+ $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+ TxtMarble: array[ 0..7 ] of word = (\r
+ $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of record X, Y: word end;\r
+ Width : word;\r
+ Data : pointer;\r
+ end;\r
+ TQuad = record\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+ TCube = record\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Base : integer;\r
+ end;\r
+var\r
+ Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+ VVtx : array[ 0..MAXVTX ] of T2DPoint;\r
+ Cube : array[ 0..MAXCUB ] of TCube;\r
+ ZList : array[ 0..MAXCUB ] of integer;\r
+ VtxCnt : word;\r
+ Txts : array[ 0..MAXTXT ] of TTexture;\r
+ Page : word;\r
+ Palette : array[ byte ] of record R, G, B: byte; end;\r
+ TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+ with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+ Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+ FaceIdx: array[ 0..23 ] of integer = (\r
+ 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+ I, VC: integer;\r
+begin\r
+ VC := VtxCnt;\r
+ C.Base := VC;\r
+ AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+ for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+ for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+ P: ^word;\r
+ I: integer;\r
+begin\r
+ P := @VtxData;\r
+ with Txts[Idx] do begin\r
+ for I:=0 to 3 do begin\r
+ Desc[I].X := P^; Inc( P );\r
+ Desc[I].Y := P^; Inc( P );\r
+ end;\r
+ Width := 129;\r
+ Data := TxtDat1;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+ V: integer;\r
+ F: file;\r
+ P: array[ 1..768 ] of byte;\r
+begin\r
+ (* Initialize objects *)\r
+ VtxCnt := 0;\r
+ MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *)\r
+ Cube[0].Face[0].Texture := 0;\r
+ V := VtxCnt;\r
+ MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+ tdSetTranslation( Trans );\r
+ tdSetRotation( 32, 32, 00 );\r
+ tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *)\r
+ for I:=V to V+7 do begin\r
+ Vtx[I].X := XVtx[I].X;\r
+ Vtx[I].Y := XVtx[I].Y;\r
+ Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+ end;\r
+ MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+ (* Load texture and palette *)\r
+ Assign( F, 'DEMO04.DAT' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, P, SizeOf(P) );\r
+ mxSetPalette( @P, 0, 256 );\r
+ GetMem( TxtDat1, 63*1024 );\r
+ BlockRead( F, TxtDat1^, 129*286 );\r
+ Close( F );\r
+ TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+ (* Init textures *)\r
+ MakeTexture( 0, TxtSundial );\r
+ MakeTexture( 1, TxtMarble );\r
+ MakeTexture( 2, TxtSapphire );\r
+ Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+ I, J, K: integer;\r
+ ZMax: array[ 0..MAXCUB ] of longint;\r
+ ZI: integer;\r
+ L: longint;\r
+begin\r
+ for I:=0 to MAXCUB do begin\r
+ L := XVtx[Cube[I].Base].Z;\r
+ for J:=1 to 7 do\r
+ if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+ ZMax[I] := L;\r
+ ZList[I] := I;\r
+ end;\r
+ for I:=0 to MAXCUB-1 do begin\r
+ ZI := I;\r
+ for J:=I+1 to MAXCUB do\r
+ if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+ if( ZI <> I ) then begin\r
+ K := ZList[I];\r
+ ZList[I] := ZList[ZI];\r
+ ZList[ZI] := K;\r
+ end;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I, J, K: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ AX := 0; AY := 0; AZ := 0;\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 600*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 1 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw objects *)\r
+ SortObjects;\r
+ for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+ for J:=0 to 5 do begin\r
+ K := Face[J].Texture;\r
+ mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+ end;\r
+ end;\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO05 - A Gouraud-shaded rotating torus\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+ MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *)\r
+ MAXVTX2 = 15; RADIUS2 = 30;\r
+ MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+ MAXFACE = MAXVTX;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *)\r
+ Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *)\r
+type\r
+ TQuad = record\r
+ QVtx : array[ 0..3 ] of integer;\r
+ end;\r
+var\r
+ Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *)\r
+ VVtx : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+ Face : array[ 0..MAXFACE ] of TQuad; (* Polys *)\r
+ Culled : array[ 0..MAXFACE ] of integer;\r
+ GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *)\r
+ VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *)\r
+ Page : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+ GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ R, N, X, Y, Z: real;\r
+ I, J, K, V: integer;\r
+begin\r
+ (* Build vertexes *)\r
+ for I:=0 to MAXVTX1 do begin\r
+ K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+ R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+ for J:=0 to MAXVTX2 do begin\r
+ V := I*(MAXVTX2+1)+J; (* Index of current vertex *)\r
+ (* Compute coordinates of current vertex *)\r
+ X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *)\r
+ Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+ Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+ Vtx[V].X := Round( X )*$10000; (* Save coordinates *)\r
+ Vtx[V].Y := Round( Y )*$10000;\r
+ Vtx[V].Z := Round( Z )*$10000;\r
+ (* Compute direction of Gouraud normal thru current vertex *)\r
+ X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+ Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+ N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *)\r
+ GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *)\r
+ GNrm[V].Y := Trunc( Y*$10000/N );\r
+ GNrm[V].Z := Trunc( Z*$10000/N );\r
+ end;\r
+ end;\r
+ (* Generate faces so that depth-sorting is not needed: there are still *)\r
+ (* some *very* little errors, but this is the best I could devise *)\r
+ J := 0;\r
+ K := 0;\r
+ for I:=0 to MAXFACE do with Face[I] do begin\r
+ QVtx[0] := GetVtx( J, K );\r
+ QVtx[1] := GetVtx( J, K+1 );\r
+ QVtx[2] := GetVtx( J+1, K+1 );\r
+ QVtx[3] := GetVtx( J+1, K );\r
+ Inc( K );\r
+ if( K > MAXVTX2 ) then begin\r
+ K := 0;\r
+ Inc( J );\r
+ end;\r
+ end;\r
+{$ifndef ALTPAL}\r
+ for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *)\r
+{$else}\r
+ for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+ for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetLight( Light );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+ tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *)\r
+ tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+ (* Backplane culling is not really needed here! *)\r
+ FillChar( Culled, SizeOf(Culled), 0 );\r
+ tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 3 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw polygons *)\r
+ for I:=0 to MAXFACE do with Face[I] do\r
+ if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO06 - Magnifying glass\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ R = 40; (* Lens radius *)\r
+ K : real = 1.8; (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+ TLine = array[ 0..319 ] of byte;\r
+ PLine = ^TLine;\r
+ TScreen = array[ 0..239 ] of PLine;\r
+var\r
+ VScreen: TScreen; (* Virtual screen *)\r
+ BallX : array[ 0..R, 0..R ] of integer;\r
+ BallY : array[ 0..R, 0..R ] of integer;\r
+ Sprite : array[ -R..R, -R..R ] of byte;\r
+ Page : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+ LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+ LR := Sqrt( X*X + Y*Y );\r
+ if( LR = 0 ) then Exit;\r
+ if( LR < R ) then begin\r
+ Z := Sqrt( R*R - LR*LR );\r
+ SinA := LR / R;\r
+ SinB := SinA / K;\r
+ TgB := SinB / Sqrt( 1-SinB*SinB );\r
+ Q := LR - TgB*Z;\r
+ X := Round( X * ( Q/LR ) );\r
+ Y := Round( Y * ( Q/LR ) );\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ F : file;\r
+ Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+ X, Y,\r
+ X2, Y2 : integer;\r
+begin\r
+ (* Load background image *)\r
+ Assign( F, 'demo06.dat' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, Palette, 768 );\r
+ mxSetPalette( @Palette, 0, 256 );\r
+ for Y:=0 to 239 do begin\r
+ New( VScreen[Y] );\r
+ BlockRead( F, VScreen[Y]^, 320 );\r
+ mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+ end;\r
+ Close( F );\r
+ (* Build lens *)\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ X2 := X;\r
+ Y2 := Y;\r
+ GetCoords( X2, Y2 );\r
+ BallX[X, Y] := X2;\r
+ BallY[X, Y] := Y2;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+ X, Y: integer;\r
+begin\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ end;\r
+ end;\r
+ (* Draw the sprite *)\r
+ mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+ Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*Delta;\r
+ end;\r
+end;\r
+\r
+var\r
+ X, Y, DX, DY: integer;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240;\r
+ X := R;\r
+ Y := R;\r
+ Randomize;\r
+ DX := Delta;\r
+ DY := Delta;\r
+\r
+ (* Main loop *)\r
+ repeat\r
+ (* Update video *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ PutLens( X, Y );\r
+ mxCircle( X, Page+Y, R, 0 );\r
+ (* Update lens coordinates *)\r
+ Inc( X, DX );\r
+ Check( X+R >= 319, X, DX, 319-R, -1 );\r
+ Check( X <= R, X, DX, R, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+ Check( Y <= R, Y, DY, R, +1 );\r
+ (* Flip pages: double buffering, avoid wait for display *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Wait for hidden page to show *)\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO07 - Hardware scrolling\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ (* Change this if scrolling seems jerky (this simple program does *)\r
+ (* not handle vertical retrace/display very well) *)\r
+ STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*(Random(3)+2);\r
+ end;\r
+end;\r
+\r
+var\r
+ I, X, Y, DX, DY: integer;\r
+begin\r
+ (* Initialize library and graphics mode *)\r
+ mxInit;\r
+ mxSetMode( MX_320x200 );\r
+ (* Set a 640x400 virtual screen *)\r
+ mxSetVirtualScreen( 640, 400 );\r
+ mxSetClip( TRUE );\r
+\r
+ X := 0;\r
+ Y := 0;\r
+ DX := 1;\r
+ DY := 1;\r
+\r
+ (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+ (* 320x200 windows, while smoothly panning virtual screen *)\r
+ while( not KeyPressed ) do begin\r
+ (* Points *)\r
+ mxSetClipRegion( 0, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxPutPixel( Random(320), Random(200), Random(16) );\r
+ (* Lines *)\r
+ mxSetClipRegion( 0, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+ (* Circles *)\r
+ mxSetClipRegion( 320, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+ (* Boxes *)\r
+ mxSetClipRegion( 320, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+ (* Pan *)\r
+ Inc( X, DX );\r
+ Check( X+320 >= 639, X, DX, 319, -1 );\r
+ Check( X < 0, X, DX, 0, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+ Check( Y < 0, Y, DY, 0, +1 );\r
+ mxPan( X, Y );\r
+ mxWaitRetrace;\r
+ end;\r
+\r
+ (* Shutdown *)\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT STRUC\r
+ X DD ?\r
+ Y DD ?\r
+ Z DD ?\r
+TPOINT ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT STRUC\r
+ IX DW ?\r
+ IY DW ?\r
+TIMAGEPOINT ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv MACRO arg\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul MACRO arg\r
+ imul arg\r
+ shrd eax, edx, 16\r
+ENDM\r
--- /dev/null
+unit Plasma;\r
+interface\r
+\r
+const\r
+ PAL_RGB = 0;\r
+ PAL_CLOUDS = 1;\r
+ PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+ Color: longint;\r
+begin\r
+ Color := Abs( XA-XB )+Abs( YA-YB );\r
+ Color := Random( Color shl 1 )-Color;\r
+ Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+ if( Color < 1 ) then Color := 1;\r
+ if( Color > 192 ) then Color := 192;\r
+ if( mxGetPixel( X, Y ) = 0 ) then\r
+ mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+ X, Y, Color: integer;\r
+begin\r
+ if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+ X := (X1+X2) shr 1;\r
+ Y := (Y1+Y2) shr 1;\r
+ NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+ NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+ NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+ NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+ Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+ mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+ mxPutPixel( X, Y, Color );\r
+ Divide( X1, Y1, X, Y );\r
+ Divide( X, Y1, X2, Y );\r
+ Divide( X, Y, X2, Y2 );\r
+ Divide( X1, Y, X, Y2 );\r
+ end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+ Dec( W );\r
+ Dec( H );\r
+ mxPutPixel( X, Y, C1 );\r
+ mxPutPixel( X, Y+H, C2 );\r
+ mxPutPixel( X+W, Y+H, C3 );\r
+ mxPutPixel( X+W, Y, C4 );\r
+ Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+ TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+ I: word;\r
+begin\r
+ FillChar( TPal(Palette)[1], 192*3, 0 );\r
+ case What of\r
+ PAL_CLOUDS:\r
+ for I:=1 to 192 do begin\r
+ TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].B := 63;\r
+ end;\r
+ PAL_LANDSCAPE:\r
+ begin\r
+ for I:=0 to 31 do begin\r
+ TPal(Palette)[I+1].R := I;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := I + I shr 1+15;\r
+ end;\r
+ for I:=32 to 63 do begin\r
+ TPal(Palette)[I+1].R := 0;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := 0;\r
+ end;\r
+ for I:=64 to 191 do begin\r
+ TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+ end;\r
+ end;\r
+ else\r
+ for I:=1 to 64 do begin\r
+ TPal(Palette)[I].G := I-1;\r
+ TPal(Palette)[I].B := 64-I;\r
+ TPal(Palette)[I+64].R := I-1;\r
+ TPal(Palette)[I+64].G := 64-I;\r
+ TPal(Palette)[I+128].B := I-1;\r
+ TPal(Palette)[I+128].R := 64-I;\r
+ end;\r
+ end;\r
+end;\r
+\r
+end.
\ No newline at end of file
--- /dev/null
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+ DEFVERT = 12; (* Vertex count *)\r
+ DEFREPL = 3; (* Repetition count *)\r
+ DEFQIXS = 2; (* Qixs *)\r
+ FADESPEED = 48;\r
+type\r
+ TPoint = record\r
+ X, Y : integer;\r
+ end;\r
+ TRGB = record\r
+ R, G, B: byte;\r
+ end;\r
+ TQix = record\r
+ Color: integer;\r
+ Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+ Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+ end;\r
+var\r
+ Page : integer;\r
+ MaxX,\r
+ MaxY : word;\r
+ Qix : array[ 0..DEFQIXS-1 ] of TQix;\r
+ Pal : array[ byte ] of TRGB;\r
+\r
+type\r
+ TReal = double;\r
+ TRPoint = record\r
+ X, Y: TReal;\r
+ end;\r
+ TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+ M: TMatrix;\r
+ G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+ C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=1 to Steps do begin\r
+ Pal[Idx+1].R := Pal[Idx].R + DR;\r
+ Pal[Idx+1].G := Pal[Idx].G + DG;\r
+ Pal[Idx+1].B := Pal[Idx].B + DB;\r
+ Inc( Idx );\r
+ end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+ with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+ with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+ BumpPal( 1, 0, 2, -2, 31 );\r
+ BumpPal( 32, 2, -2, 0, 31 );\r
+ BumpPal( 63, -2, 2, 2, 31 );\r
+ BumpPal( 94, 2, 0, -2, 31 );\r
+ BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+ for I:=0 to DEFVERT-1 do begin\r
+ Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+ Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+ Qix.Delta[I].X := Random(5)+1;\r
+ Qix.Delta[I].Y := Random(5)+1;\r
+ end;\r
+ Qix.Color := Color;\r
+\r
+ (* Initialize matrix (Catmull-Rom) *)\r
+ M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+ M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+ M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+ M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+ I, J: integer;\r
+ T, T2, T3: TReal;\r
+ X0, Y0, X, Y: TReal;\r
+ Delta: TReal;\r
+begin\r
+ (* Compute coefficients *)\r
+ for I:=0 to 3 do begin\r
+ C[I].X := 0;\r
+ for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+ C[I].Y := 0;\r
+ for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+ end;\r
+ X0 := C[3].X;\r
+ Y0 := C[3].Y;\r
+ Delta := 1 / N;\r
+ T := 0;\r
+ for I:=1 to N do begin\r
+ T := T + Delta;\r
+ T2 := T*T;\r
+ T3 := T*T2;\r
+ X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+ Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+ mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+ X0 := X;\r
+ Y0 := Y;\r
+ end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+ I, J: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do begin\r
+ mxBezier( Qix, I, Idx, 12 );\r
+ end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Inc( Vert[I,Idx].X, Delta[I].X );\r
+ if( Vert[I,Idx].X < 0 ) then begin\r
+ Vert[I,Idx].X := 0;\r
+ Delta[I].X := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].X > MaxX ) then begin\r
+ Vert[I,Idx].X := MaxX;\r
+ Delta[I].X := -Random( 5 )-1;\r
+ end;\r
+ Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+ if( Vert[I,Idx].Y < 0 ) then begin\r
+ Vert[I,Idx].Y := 0;\r
+ Delta[I].Y := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].Y > MaxY ) then begin\r
+ Vert[I,Idx].Y := MaxY;\r
+ Delta[I].Y := -Random( 5 )-1;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Vert[I,Dest].X := Vert[I,Src].X;\r
+ Vert[I,Dest].Y := Vert[I,Src].Y;\r
+ end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+ Q, Idx, I, J, P, Count: integer;\r
+begin\r
+ Count := 0;\r
+ P := DEFREPL-1;\r
+ I := 0;\r
+ J := 1;\r
+ repeat\r
+ mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Copy( Qix[Q], I, P );\r
+ Update( Qix[Q], I );\r
+ for Idx:=0 to DEFREPL-1 do begin\r
+ Plot( Qix[Q], Idx );\r
+ end;\r
+ end;\r
+ I := (I+1) mod DEFREPL;\r
+ J := (J+1) mod DEFREPL;\r
+ P := (P+1) mod DEFREPL;\r
+ Inc( Count );\r
+ mxStartLine( Page );\r
+ if( Count >= FADESPEED ) then begin\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Inc( Qix[Q].Color );\r
+ if( Qix[Q].Color > 156 ) then\r
+ Qix[Q].Color := 1;\r
+ end;\r
+ Count := 0;\r
+ end;\r
+ Page := 240-Page;\r
+ until( KeyPressed );\r
+end;\r
+\r
+var\r
+ I: integer;\r
+begin\r
+ Randomize;\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ mxGetScreenSize( MaxX, MaxY );\r
+ for I:=0 to DEFQIXS-1 do\r
+ Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+ InitPalette;\r
+ mxSetPalette( @Pal, 0, 157 );\r
+ Page := 240;\r
+ Dec( MaxX );\r
+ Dec( MaxY );\r
+ AnimateQix;\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin LABEL DWORD\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+tblCos LABEL DWORD\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
--- /dev/null
+COMMENT /\r
+ Fixed-point math functions and 3D transforms\r
+ Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC tdFixedMul\r
+PUBLIC tdGetNormal\r
+PUBLIC tdRotate\r
+PUBLIC tdGetSurfaceLight\r
+PUBLIC tdSetLight\r
+PUBLIC tdSetRotation\r
+PUBLIC tdSetTranslation\r
+PUBLIC tdTransform\r
+PUBLIC tdTransformToImage\r
+PUBLIC tdTransformLight\r
+PUBLIC tdBackPlaneCull\r
+PUBLIC tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA'\r
+ ASSUME ds:MATH_DATA\r
+\r
+INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table\r
+\r
+XRotation TPOINT <> ; 3x3 rotation matrix\r
+YRotation TPOINT <>\r
+ZRotation TPOINT <>\r
+\r
+Translation TPOINT <> ; Translation vector\r
+\r
+Light TPOINT <> ; Light vector\r
+AmbientLight DW 00 ; Ambient light\r
+\r
+XScale DD 10000h ; Scaling factor for X coordinate\r
+YScale DD 10000h ; Scaling factor for Y coordinate\r
+PerspectiveDistance DD 20000000h\r
+\r
+MATH_DATA ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective PROC PASCAL FAR\r
+ ARG Perspective:DWORD, \\r
+ ScaleX:DWORD, \\r
+ ScaleY:DWORD\r
+ USES ds\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov eax, [Perspective]\r
+ mov [PerspectiveDistance], eax\r
+ mov eax, [ScaleX]\r
+ mov [XScale], eax\r
+ mov eax, [ScaleY]\r
+ mov [YScale], eax\r
+\r
+ ret\r
+tdSetPerspective ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+; RX = X-axis rotation angle\r
+; RY = X-axis rotation angle\r
+; RZ = X-axis rotation angle\r
+; Output:\r
+; none\r
+;\r
+tdSetRotation PROC PASCAL FAR\r
+ ARG RX:WORD, \\r
+ RY:WORD, \\r
+ RZ:WORD\r
+ USES ds, si, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov bx, [RZ]\r
+ mov si, [RY]\r
+ mov di, [RX]\r
+ shl bx, 2\r
+ shl si, 2\r
+ shl di, 2\r
+\r
+ push ebp ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.Y], edx\r
+\r
+ mov eax, tblSin[si]\r
+ sar eax, 8 ; Convert fixed 8:24 to fixed 16:16\r
+ mov [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si] ; EDX:EAX = fixed 16:48\r
+ shrd eax, edx, 24 ; EAX = fixed 8:24\r
+ imul tblSin[di] ; EDX:EAX = fixed 16:48\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[di]\r
+ add eax, ebp\r
+ adc edx, ecx ; EDX:EAX = fixed 16:48\r
+ neg edx\r
+ mov [YRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblSin[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [YRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblSin[di]\r
+ mov [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [ZRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[di]\r
+ add eax, ebp\r
+ add edx, ecx\r
+ neg edx\r
+ mov [ZRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblCos[di]\r
+ mov [ZRotation.Z], edx\r
+\r
+ pop ebp ; Restore EBP\r
+\r
+ ret\r
+tdSetRotation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+; TV = pointer to translation vector\r
+; Output:\r
+; none\r
+;\r
+tdSetTranslation PROC PASCAL FAR\r
+ ARG TV:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [TV]\r
+ mov eax, es:[di].X\r
+ mov [Translation.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Translation.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Translation.Z], eax\r
+\r
+ ret\r
+tdSetTranslation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransform PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ LOCAL Adjust:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+ ALIGN DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ mov ebx, eax\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16)\r
+ mov es:[di].Z, eax\r
+; Get perspective factor\r
+ mov ebx, [PerspectiveDistance]\r
+ sub eax, ebx\r
+ neg eax ; EAX = PD - Z\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx ; EAX = fixed 16:16 result\r
+ mov [Adjust], eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.X]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Y]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdTransform ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TIMAGEPOINT\r
+; Count = number of entries to transform\r
+; DeltaX = translation distance for the X coordinate\r
+; DeltaY = translation distance for the Y coordinate\r
+; Output:\r
+; the maximum Z value\r
+;\r
+tdTransformToImage PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD\r
+ LOCAL Adjust:DWORD, \\r
+ Max:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+ mov [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+ mov eax, fs:[si].Z\r
+ cmp eax, [Max]\r
+ jle @@1\r
+ mov [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+ mov ax, WORD PTR fs:[si].X[2]\r
+ add ax, [DeltaX]\r
+ mov es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+ mov ax, WORD PTR fs:[si].Y[2]\r
+ add ax, [DeltaY]\r
+ mov es:[di].IY, ax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TIMAGEPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ mov eax, [Max]\r
+ shld edx, eax, 16\r
+ ret\r
+tdTransformToImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+; Light = pointer to light vector\r
+; Output:\r
+; none\r
+;\r
+tdSetLight PROC PASCAL FAR\r
+ ARG L:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [L]\r
+ mov eax, es:[di].X\r
+ mov [Light.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Light.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Light.Z], eax\r
+\r
+ ret\r
+tdSetLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+; Normals = pointer to an array of surface normals\r
+; Lights = pointer to an array of integer to be filled with\r
+; light intensity\r
+; Count = number of elements to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransformLight PROC PASCAL FAR\r
+ ARG Normals:DWORD, \\r
+ Lights:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov fs, ax\r
+ ASSUME fs:MATH_DATA\r
+\r
+ lds si, [Normals]\r
+ les di, [Lights]\r
+ ASSUME ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+ mov eax, ds:[si].Z\r
+ imul [Light.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, ds:[si].Y\r
+ imul [Light.Y]\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, ds:[si].X\r
+ imul [Light.X]\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = fixed 32:32 intensity\r
+ add dx, [AmbientLight]\r
+ test dx, dx\r
+ jg @@1\r
+ xor dx, dx ; Return 0 for no light\r
+@@1:\r
+ mov es:[di], dx\r
+ inc di\r
+ inc di\r
+ add si, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ASSUME fs:NOTHING\r
+ ret\r
+tdTransformLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+; Normal = pointer to TPOINT surface normal vector\r
+; Output:\r
+; AX = light intensity (>=0)\r
+; Notes:\r
+; the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight PROC PASCAL FAR\r
+ ARG Normal:DWORD\r
+ USES ds, esi, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [Normal]\r
+\r
+; Transform Z coordinate\r
+ mov eax, es:[di].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.Z]\r
+ shrd eax, edx, 16\r
+ mov esi, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, es:[di].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add esi, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, es:[di].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add eax, esi\r
+ shr eax, 16\r
+\r
+; Add ambient light\r
+ add ax, [AmbientLight]\r
+ test ax, ax\r
+ jge @@Exit\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ ret\r
+tdGetSurfaceLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdRotate PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdRotate ENDP\r
+\r
+tdFixedMul PROC PASCAL FAR\r
+ ARG F1:DWORD, \\r
+ F2:DWORD\r
+\r
+ mov eax, [F1]\r
+ imul [F2]\r
+ shr eax, 16\r
+\r
+ ret\r
+tdFixedMul ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+ push esi\r
+ push edi\r
+\r
+ add eax, eax\r
+ adc edx, 0\r
+ mov eax, edx ; Just discard the low bits\r
+\r
+ mov esi, eax\r
+ xor edi, edi\r
+ shld edi, esi, 16\r
+ shl esi, 16\r
+@@Loop:\r
+ mov ebx, eax\r
+ mul eax\r
+ add eax, esi\r
+ adc edx, edi\r
+ shrd eax, edx, 1\r
+ shr edx, 1\r
+ div ebx\r
+ cmp eax, ebx\r
+ jne @@Loop\r
+\r
+; Adjust EAX\r
+ shl eax, 8\r
+\r
+ pop edi\r
+ pop esi\r
+ ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+; Dest = pointer to TPOINT (vector) result\r
+; P1, P2, P3 = pointer to TPOINT points on surface\r
+; Output:\r
+; none\r
+; Notes:\r
+; the normal is given by the cross-product between (P3-P1) and\r
+; (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal PROC PASCAL FAR\r
+ ARG Dest:DWORD, \\r
+ P1:DWORD, \\r
+ P2:DWORD, \\r
+ P3:DWORD\r
+ LOCAL V1:TPOINT, \\r
+ V2:TPOINT, \\r
+ N:TPOINT\r
+ USES ds, si, es, di\r
+\r
+; Get vector V1\r
+ lds si, [P1]\r
+ les di, [P3]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V1.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V1.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V1.Z], eax\r
+\r
+; Get vector V2\r
+ les di, [P2]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V2.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V2.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+ mov eax, [V1.Z]\r
+ imul [V2.Y]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Y]\r
+ imul [V2.Z]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.X], eax\r
+\r
+ mov eax, [V1.X]\r
+ imul [V2.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Z]\r
+ imul [V2.X]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Y], eax\r
+\r
+ mov eax, [V1.Y]\r
+ imul [V2.X]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.X]\r
+ imul [V2.Y]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Z], eax\r
+\r
+; Get normal length\r
+ mov eax, [N.X]\r
+ imul eax\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [N.Y]\r
+ imul eax\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, [N.Z]\r
+ imul eax\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+ call subSqrt ; EAX = normal length\r
+ mov ebx, eax\r
+\r
+; Adjust vector and save it\r
+ les di, [Dest]\r
+ mov eax, [N.X]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].X, eax\r
+ mov eax, [N.Y]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Y, eax\r
+ mov eax, [N.Z]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Z, eax\r
+\r
+ ret\r
+tdGetNormal ENDP\r
+\r
+TPOLY STRUC\r
+ Vtx DW 4 DUP(?)\r
+TPOLY ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+; Poly = pointer to an array of TPOLY\r
+; Vertex = pointer to an array of TPOINT\r
+; Dest = pointer to an array of integer\r
+; Count = number of polygons to check\r
+; Step = size of TPOLY structure\r
+; Output:\r
+; if the n-th polygon is invisible the n-th entry of the\r
+; Dest array is set to -1, other entries are not modified\r
+; (so it's possible to use the Light array for Dest, because\r
+; the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+ ARG Step:WORD, \\r
+ Poly:DWORD, \\r
+ Vertex:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ds, WORD PTR Vertex[2]\r
+ les di, [Poly]\r
+ mov fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+ mov ax, es:[di].Vtx[2] ; Index of 2nd vertex\r
+ shl ax, 2\r
+ mov bx, ax\r
+ shl ax, 1\r
+ add bx, ax ; BX = index*SIZE TPOINT\r
+ add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex\r
+ mov ax, es:[di].Vtx[4] ; Index of 3rd vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex\r
+ mov ecx, ds:[si].X\r
+ sub ecx, ds:[bx].X ; ECX = V3.X-V2.X\r
+ mov edx, ds:[si].Y\r
+ sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y\r
+ mov ax, es:[di].Vtx[0] ; Index of 1st vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 1st vertex\r
+ mov eax, ds:[si].X\r
+ sub eax, ds:[bx].X ; EAX = V1.X-V2.X\r
+ mov esi, ds:[si].Y\r
+ sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y\r
+ imul edx\r
+ mov ebx, eax\r
+ xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+ mov eax, esi\r
+ imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ jl @@Next ; Polygon is visible\r
+ mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry\r
+ mov WORD PTR fs:[bx], -1 ; Remove polygon\r
+@@Next:\r
+ add WORD PTR [Dest], 2 ; Next entry for dest\r
+ add di, [Step] ; Next polygon\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT ENDS\r
+END\r
--- /dev/null
+typedef struct {\r
+ long x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT TVECTOR\r
+#define PPOINT PVECTOR\r
+\r
+#define VPTR void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+unit ThreeD;\r
+interface\r
+\r
+type\r
+ TVector = record\r
+ X, Y, Z : longint;\r
+ end;\r
+ TPoint = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight; external;\r
+procedure tdSetRotation( RX, RY, RZ: word ); external;\r
+procedure tdGetNormal; external;\r
+procedure tdSetTranslation( var TV: TVector ); external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate; external;\r
+function tdTransformToImage; external;\r
+procedure tdSetLight( var Light: TVector ); external;\r
+procedure tdSetPerspective; external;\r
+procedure tdTransformLight; external;\r
+function tdFixedMul( F1, F2: longint ): longint; external;\r
+procedure tdBackPlaneCull; external;\r
+{$L THREED}\r
+\r
+end.\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxBitBlt\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN subHorizontalLineInfo : NEAR\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+; SX, SY = source coordinates\r
+; Width = source width\r
+; Height = source height\r
+; DX, DY = destination coordinates\r
+; Output:\r
+; none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt PROC FAR\r
+ ARG DestY:WORD, \\r
+ DestX:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ SY:WORD, \\r
+ SX:WORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ SourceOffset:WORD, \\r
+ DestOffset:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ WritePlane:BYTE, \\r
+ LeftMask:BYTE, \\r
+ RightMask:BYTE = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Exit now if null width\r
+ cmp [Width], 0\r
+ je @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+ mov ax, [SX]\r
+ and al, 03h ; AL = source plane\r
+ mov dx, [DestX]\r
+ and dl, 03h ; DL = destination plane\r
+ mov bx, OFFSET subPlaneBlt\r
+ cmp al, dl ; Same source and destination plane?\r
+ jne @@BitBlt ; No, use slow procedure\r
+ mov bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+ call bx\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt PROC NEAR\r
+; Get horizontal line info and address of destination\r
+ mov bx, [DestX]\r
+ mov ax, [DestY]\r
+ mov cx, [Width]\r
+ call subHorizontalLineInfo\r
+ mov [LeftMask], al\r
+ mov [RightMask], ah\r
+ mov [Width], cx\r
+\r
+; Setup segments\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov es, ax\r
+\r
+; Get address of source pixel\r
+ mov ax, [SY]\r
+ mul [mx_BytesPerLine]\r
+ mov si, [SX]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+; Set write mode 1\r
+ mov dx, GDC\r
+ mov ax, 4105h\r
+ out dx, ax\r
+ cld\r
+\r
+; Move left block\r
+@@L0:\r
+ mov ah, [LeftMask]\r
+ or ah, ah\r
+ jz @@C0\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov ax, [mx_BytesPerLine]\r
+ dec ax\r
+ mov cx, [Height]\r
+ .push si, di\r
+@@L1:\r
+ movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec cx\r
+ jnz @@L1\r
+ .pop si, di\r
+ inc si\r
+ inc di\r
+\r
+; Move center block\r
+@@C0:\r
+ mov bx, [Width]\r
+ test bx, bx\r
+ jz @@R0\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Enable all planes\r
+ mov ax, [mx_BytesPerLine]\r
+ sub ax, bx\r
+ mov dx, [Height]\r
+ .push si, di\r
+@@C1:\r
+ mov cx, bx ; CX = image width\r
+ rep movsb ; Cannot use "movsw" here!\r
+ add si, ax ; Next scan line\r
+ add di, ax ; Next scan line\r
+ dec dx ; All lines processed?\r
+ jnz @@C1 ; No, continue\r
+ .pop si, di\r
+ add si, bx\r
+ add di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+ mov ah, [RightMask]\r
+ or ah, ah\r
+ jz @@Done\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov ax, [mx_BytesPerLine]\r
+ dec ax\r
+ mov cx, [Height]\r
+@@R1:\r
+ movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec cx\r
+ jnz @@R1\r
+\r
+@@Done:\r
+ mov dx, GDC\r
+ mov ax, 4005h\r
+ out dx, ax ; Restore write mode 0\r
+\r
+@@Exit:\r
+ ret\r
+subMoveBlt ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt PROC NEAR\r
+; Compute extra bytes and width count for each plane\r
+ mov cx, [Width]\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Get pixel addresses\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov es, ax\r
+ mov ax, [SY]\r
+ mul [mx_BytesPerLine]\r
+ mov si, [SX]\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax ; DS:SI points to source\r
+ mov [SourceOffset], si\r
+ mov ax, [DestY]\r
+ mul [mx_BytesPerLine]\r
+ mov di, [DestX]\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax ; ES:DI points to destination\r
+ mov [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+ mov ax, [SX]\r
+ and al, 03h\r
+ mov [ReadPlane], al\r
+ mov cx, [DestX]\r
+ and cl, 03h\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Ready to move now\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0\r
+ je @@Done\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov ax, [mx_BytesPerLine]\r
+ sub ax, ss:[bx] ; AX = extra bytes per line\r
+@@Loop:\r
+ mov cx, ss:[bx]\r
+ shr cx, 1\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ and [ReadPlane], 03h ; Should be faster on 386 using\r
+ jnz @@ReadPlaneOk ; BTR and ADC...\r
+ inc [SourceOffset]\r
+@@ReadPlaneOk:\r
+ rol [WritePlane], 1\r
+ adc [DestOffset], 0\r
+ mov si, [SourceOffset]\r
+ mov di, [DestOffset]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Done:\r
+ ret\r
+subPlaneBlt ENDP\r
+\r
+mxBitBlt ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCC.ASM - Fast clip line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC xsubClipLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+tblGroups LABEL WORD\r
+ DW 10, tbl00\r
+ DW 10, tbl10\r
+ DW 9, tbl20\r
+ DW -1, 0\r
+ DW 10, tbl40\r
+ DW 10, tbl50\r
+ DW 9, tbl60\r
+ DW -1, 0\r
+ DW 6, tbl80\r
+ DW 6, tbl90\r
+ DW 5, tblA0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+tbl00 DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A\r
+tbl10 DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A\r
+tbl20 DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29\r
+tbl40 DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A\r
+tbl50 DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A\r
+tbl60 DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69\r
+tbl80 DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86\r
+tbl90 DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96\r
+tblA0 DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5\r
+\r
+ccTT: clc\r
+ ret\r
+ccFF: stc\r
+ ret\r
+\r
+; Group 00 -------------------------------------------------\r
+;\r
+cc00:\r
+ clc\r
+ ret\r
+cc01:\r
+ jmp ClipQLeft\r
+cc02:\r
+ jmp ClipQRight\r
+cc04:\r
+ jmp ClipQTop\r
+cc05:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge ccTT\r
+ jmp ClipQTop\r
+cc06:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jge ccTT\r
+ jmp ClipQTop\r
+cc08:\r
+ jmp ClipQBottom\r
+cc09:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jle ccTT\r
+ jmp ClipQBottom\r
+cc0A:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jle ccTT\r
+ jmp ClipQBottom\r
+\r
+; Group 10 -------------------------------------------------\r
+;\r
+cc10FF:\r
+ stc\r
+ ret\r
+cc10TT:\r
+ clc\r
+ ret\r
+cc10:\r
+ jmp ClipPLeft\r
+cc12:\r
+ call ClipPLeft\r
+ jmp ClipQRight\r
+cc14:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc10FF\r
+ jmp ClipQTop\r
+cc16:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc10FF\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX2]\r
+ jle cc10TT\r
+ jmp ClipQRight\r
+cc18:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc10FF\r
+ jmp ClipQBottom\r
+cc1A:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc10FF\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX2]\r
+ jle cc10TT\r
+ jmp ClipQRight\r
+\r
+; Group 20 -------------------------------------------------\r
+;\r
+cc20TT:\r
+ clc\r
+ ret\r
+cc20FF:\r
+ stc\r
+ ret\r
+cc20:\r
+ jmp ClipPRight\r
+cc21:\r
+ call ClipPRight\r
+ jmp ClipQLeft\r
+cc24:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc20FF\r
+ jmp ClipQTop\r
+cc25:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc20FF\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX1]\r
+ jge cc20TT\r
+ jmp ClipQLeft\r
+cc28:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc20FF\r
+ jmp ClipQBottom\r
+cc29:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc20FF\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX1]\r
+ jge cc20TT\r
+ jmp ClipQLeft\r
+\r
+; Group 40 -------------------------------------------------\r
+;\r
+cc40TT:\r
+ clc\r
+ ret\r
+cc40FF:\r
+ stc\r
+ ret\r
+cc40:\r
+ jmp ClipPTop\r
+cc41:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jl cc40FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge cc40TT\r
+ jmp ClipQTop\r
+cc42:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jg cc40FF\r
+ jmp ClipQRight\r
+cc48:\r
+ call ClipPTop\r
+ jmp ClipQBottom\r
+cc49:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jl cc40FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jle cc40TT\r
+ jmp ClipQBottom\r
+cc4A:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jg cc40FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jle cc40TT\r
+ jmp ClipQBottom\r
+\r
+\r
+; Group 50 -------------------------------------------------\r
+;\r
+cc50TT:\r
+ clc\r
+ ret\r
+cc50FF:\r
+ stc\r
+ ret\r
+cc50:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc50TT\r
+ jmp ClipPTop\r
+cc52:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jl cc50FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jge cc50TT\r
+ jmp ClipPLeft\r
+cc58:\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX1]\r
+ jl cc50FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jge cc50TT\r
+ jmp ClipPLeft\r
+cc5A:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc50FF\r
+ call ClipQRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc50FF\r
+ cmp si, [mx_ClipY2]\r
+ jle cc50TT\r
+ jmp ClipQBottom\r
+\r
+; Group 60 -------------------------------------------------\r
+;\r
+cc60TT:\r
+ clc\r
+ ret\r
+cc60FF:\r
+ stc\r
+ ret\r
+cc60:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+cc61:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jl cc60FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jle cc60TT\r
+ jmp ClipPRight\r
+cc68:\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX2]\r
+ jg cc60FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+cc69:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jl cc60FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc60FF\r
+ cmp si, [mx_ClipY2]\r
+ jle cc69_1\r
+ call ClipQBottom\r
+cc69_1:\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+\r
+; Group 80 -------------------------------------------------\r
+;\r
+cc80TT:\r
+ clc\r
+ ret\r
+cc80FF:\r
+ stc\r
+ ret\r
+cc80:\r
+ jmp ClipPBottom\r
+cc81:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jl cc80FF\r
+ jmp ClipQLeft\r
+cc82:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jg cc80FF\r
+ jmp ClipQRight\r
+cc84:\r
+ call ClipPBottom\r
+ jmp ClipQTop\r
+cc85:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jl cc80FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge cc80FF\r
+ jmp ClipQTop\r
+cc86:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jg cc80FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jge cc80TT\r
+ jmp ClipQTop\r
+\r
+; Group 90 -------------------------------------------------\r
+;\r
+cc90TT:\r
+ clc\r
+ ret\r
+cc90FF:\r
+ stc\r
+ ret\r
+cc90:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc90TT\r
+ jmp ClipPBottom\r
+cc92:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jg cc90FF\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jge cc90TT\r
+ jmp ClipPLeft\r
+cc94:\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX1]\r
+ jl cc90FF\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc90TT\r
+ jmp ClipPBottom\r
+cc96:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc90FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jg cc90FF\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc96_1\r
+ call ClipPBottom\r
+cc96_1:\r
+ cmp si, [mx_ClipY1]\r
+ jge cc90TT\r
+ jmp ClipQTop\r
+\r
+; Group A0 -------------------------------------------------\r
+;\r
+ccA0TT:\r
+ clc\r
+ ret\r
+ccA0FF:\r
+ stc\r
+ ret\r
+ccA0:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+ccA1:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jg ccA0FF\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jle ccA0TT\r
+ jmp ClipPRight\r
+ccA4:\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX2]\r
+ jg ccA0FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+ccA5:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jg ccA0FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl ccA0FF\r
+ cmp si, [mx_ClipY1]\r
+ jge ccA5_1\r
+ call ClipQTop\r
+ccA5_1:\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX1\r
+ClipPLeft:\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov dx, [mx_ClipX1]\r
+ sub dx, di\r
+ imul dx\r
+ mov bp, cx\r
+ sub bp, di\r
+ idiv bp\r
+ add bx, ax\r
+ mov di, [mx_ClipX1]\r
+ clc\r
+ ret\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX2\r
+ClipPRight:\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov dx, [mx_ClipX2]\r
+ sub dx, di\r
+ imul dx\r
+ mov bp, cx\r
+ sub bp, di\r
+ idiv bp\r
+ add bx, ax\r
+ mov di, [mx_ClipX2]\r
+ clc\r
+ ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY2\r
+ClipPBottom:\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov dx, [mx_ClipY2]\r
+ sub dx, bx\r
+ imul dx\r
+ mov bp, si\r
+ sub bp, bx\r
+ idiv bp\r
+ add di, ax\r
+ mov bx, [mx_ClipY2]\r
+ clc\r
+ ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY1\r
+ClipPTop:\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov dx, [mx_ClipY1]\r
+ sub dx, bx\r
+ imul dx\r
+ mov bp, si\r
+ sub bp, bx\r
+ idiv bp\r
+ add di, ax\r
+ mov bx, [mx_ClipY1]\r
+ clc\r
+ ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQLeft:\r
+ mov ax, bx\r
+ sub ax, si\r
+ mov dx, [mx_ClipX1]\r
+ sub dx, cx\r
+ imul dx\r
+ mov bp, di\r
+ sub bp, cx\r
+ idiv bp\r
+ add si, ax\r
+ mov cx, [mx_ClipX1]\r
+ clc\r
+ ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQRight:\r
+ mov ax, bx\r
+ sub ax, si\r
+ mov dx, [mx_ClipX2]\r
+ sub dx, cx\r
+ imul dx\r
+ mov bp, di\r
+ sub bp, cx\r
+ idiv bp\r
+ add si, ax\r
+ mov cx, [mx_ClipX2]\r
+ clc\r
+ ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQBottom:\r
+ mov ax, di\r
+ sub ax, cx\r
+ mov dx, [mx_ClipY2]\r
+ sub dx, si\r
+ imul dx\r
+ mov bp, bx\r
+ sub bp, si\r
+ idiv bp\r
+ add cx, ax\r
+ mov si, [mx_ClipY2]\r
+ clc\r
+ ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQTop:\r
+ mov ax, di\r
+ sub ax, cx\r
+ mov dx, [mx_ClipY1]\r
+ sub dx, si\r
+ imul dx\r
+ mov bp, bx\r
+ sub bp, si\r
+ idiv bp\r
+ add cx, ax\r
+ mov si, [mx_ClipY1]\r
+ clc\r
+ ret\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was\r
+; supposed to be twice as fast as Cohen-Sutherland, but my\r
+; tests show only a very small increase in speed and a noticeable\r
+; increase of the program size! Maybe this is caused by the\r
+; slow speed of VGA cards, so probably a better test should\r
+; be performed with lines drawn in RAM.\r
+;\r
+; Input:\r
+; AX, BX = X1, Y1\r
+; CX, DX = X2, Y2\r
+; Output:\r
+; CF = set if line is full clipped\r
+; AX, BX = clipped X1, Y1\r
+; CX, DX = clipped X2, Y2\r
+; Note:\r
+; destroys SI, DI\r
+;\r
+xsubClipLine PROC NEAR\r
+ push bp\r
+ xor si, si ; SPY code\r
+\r
+ cmp dx, [mx_ClipY2]\r
+ jle @@1\r
+ or si, 08h\r
+ jmp @@2\r
+@@1:\r
+ cmp dx, [mx_ClipY1]\r
+ jge @@2\r
+ or si, 04h\r
+@@2:\r
+\r
+ cmp cx, [mx_ClipX2]\r
+ jle @@3\r
+ or si, 02h\r
+ jmp @@4\r
+@@3:\r
+ cmp cx, [mx_ClipX1]\r
+ jge @@4\r
+ or si, 01h\r
+@@4:\r
+\r
+ cmp bx, [mx_ClipY2]\r
+ jle @@5\r
+ or si, 80h\r
+ jmp @@6\r
+@@5:\r
+ cmp bx, [mx_ClipY1]\r
+ jge @@6\r
+ or si, 40h\r
+@@6:\r
+\r
+ cmp ax, [mx_ClipX2]\r
+ jle @@7\r
+ or si, 20h\r
+ jmp @@8\r
+@@7:\r
+ cmp ax, [mx_ClipX1]\r
+ jge @@8\r
+ or si, 10h\r
+@@8:\r
+\r
+ mov di, si\r
+ and di, 000Fh ; Index of procedure\r
+ and si, 00F0h\r
+ .shr si, 2 ; Index of group (times 4)\r
+ cmp di, cs:tblGroups[si] ; Is index within range?\r
+ jg @@Exit ; No, line is full clipped\r
+ mov si, cs:tblGroups[si+2] ; Get offset of group table\r
+ shl di, 1 ; We must index word elements\r
+ add si, di ; Make full offset\r
+ mov di, ax ; Move X1 to DI and free AX\r
+ mov si, cs:[si] ; Get subroutine address\r
+ xchg dx, si ; Move Y2 to SI and free DX\r
+ call dx ; Call the proper subroutine\r
+ mov ax, di ; Restore AX to X1\r
+ mov dx, si ; Restore DX to Y2\r
+ pop bp\r
+ ret\r
+\r
+@@Exit:\r
+ pop bp\r
+ stc\r
+ ret\r
+xsubClipLine ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCG.ASM - Color to gray conversion\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxColorToGray\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Converts RGB colors to gray shades.\r
+;\r
+; Input:\r
+; CPal = pointer to color palette\r
+; GPal = pointer to destination (gray) palette\r
+; Count = number of colors to convert\r
+; Output:\r
+; none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxColorToGray PROC FAR\r
+ ARG Count:WORD, \\r
+ DPal:DWORD, \\r
+ SPal:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov cx, [Count]\r
+ jcxz @@Exit\r
+ lds si, [SPal]\r
+ les di, [DPal]\r
+ cld\r
+; We use the standard formula\r
+; gray=(red*30 + green*59 + blue*11)/100\r
+; in the equivalent form\r
+; gray=(red*77 + green*151 + blue*28)/256\r
+; which doesn't need the last divide.\r
+ mov bx, 77 SHL 8 + 151\r
+@@Loop:\r
+ lodsb ; Red\r
+ mul bh\r
+ mov dx, ax\r
+ lodsb ; Green\r
+ mul bl\r
+ add dx, ax\r
+ lodsb ; Blue\r
+ mov ah, 28\r
+ mul ah\r
+ add ax, dx\r
+ mov al, ah\r
+ stosw ; Save new RGB\r
+ stosb\r
+ loop @@Loop\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxColorToGray ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCL.ASM - Bresenham circle\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxCircle\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a circle using the Bresenham algorithm.\r
+;\r
+; Input:\r
+; XC, YC = center coordinates\r
+; Radius = circle radius\r
+; Color = circle color\r
+; Output:\r
+; none\r
+; Note:\r
+; computes only points in the first octant, all other\r
+; points are obtained by symmetry.\r
+;\r
+mxCircle PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ Radius:WORD, \\r
+ YC:WORD, \\r
+ XC:WORD = ARG_SIZE\r
+ LOCAL Delta:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+\r
+ xor si, si ; X\r
+ mov di, [Radius] ; Y\r
+ mov ax, 3\r
+ sub ax, di\r
+ sub ax, di\r
+ mov [Delta], ax ; Delta = 3-R*2\r
+\r
+ mov ds, [mx_VideoSegment]\r
+\r
+@@Loop:\r
+ cmp si, di ;\r
+ jg @@Done ; Exit when X > Y\r
+; Draw points\r
+ mov ax, si\r
+ mov bx, di\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ neg ax\r
+ mov bx, di\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ mov bx, di\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ neg ax\r
+ mov bx, di\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ mov bx, si\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ neg ax\r
+ mov bx, si\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ mov bx, si\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ neg ax\r
+ mov bx, si\r
+ neg bx\r
+ call @@subPutPixel\r
+; Moves coordinates to next point\r
+ mov ax, [Delta]\r
+ test ax, ax\r
+ jl @@Next\r
+ mov ax, di\r
+ .shl ax, 2\r
+ sub ax, 4\r
+ sub [Delta], ax\r
+ dec di\r
+@@Next:\r
+ mov ax, si\r
+ .shl ax, 2\r
+ add ax, 6\r
+ add [Delta], ax\r
+ inc si\r
+ jmp @@Loop\r
+\r
+@@Done:\r
+ xor ax, ax\r
+ .pop ds, si, di\r
+ .leave ARG_SIZE\r
+\r
+;---------------------------------------\r
+; Put pixel function.\r
+; Input:\r
+; BX = X coordinate (relative to center)\r
+; AX = Y coordinate (relative to center)\r
+; DS = video segment\r
+@@subPutPixel:\r
+ add bx, [XC] ; Get absolute coordinates\r
+ add ax, [YC]\r
+\r
+ cmp bx, [mx_ClipX1] ; Clip pixel\r
+ jl @@subExit\r
+ cmp bx, [mx_ClipX2]\r
+ jg @@subExit\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@subExit\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@subExit\r
+\r
+ mul [mx_BytesPerLine] ; Get pixel offset\r
+ mov cx, bx ; Save X coordinate\r
+ .shr bx, 2\r
+ add bx, ax ; DS:BX = pixel offset\r
+\r
+ and cl, 3 ; Set write plane\r
+ mov ax, 0102h\r
+ shl ah, cl\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ mov al, [Color] ; Write pixel\r
+ mov ds:[bx], al\r
+\r
+@@subExit:\r
+ retn\r
+mxCircle ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCR.ASM - Clip functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetSysClipRegion\r
+PUBLIC mxGetClipRegion\r
+PUBLIC mxSetClipRegion\r
+PUBLIC mxSetClip\r
+PUBLIC mxGetClip\r
+\r
+PUBLIC subClipBox\r
+PUBLIC subClipImage\r
+\r
+PUBLIC mx_ClipX1\r
+PUBLIC mx_ClipY1\r
+PUBLIC mx_ClipX2\r
+PUBLIC mx_ClipY2\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_ClipX1 DW ? ; Clip coordinates\r
+mx_ClipY1 DW ?\r
+mx_ClipX2 DW ?\r
+mx_ClipY2 DW ?\r
+\r
+mx_SysClipX1 DW ? ; System clip coordinates\r
+mx_SysClipY1 DW ? ; (active when mx_ClipStatus is FALSE)\r
+mx_SysClipX2 DW ?\r
+mx_SysClipY2 DW ?\r
+\r
+mx_UserClipX1 DW ? ; User clip coordinates\r
+mx_UserClipY1 DW ? ; (active when mx_ClipStatus is TRUE)\r
+mx_UserClipX2 DW ?\r
+mx_UserClipY2 DW ?\r
+\r
+mx_ClipStatus DB ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Toggles clipping between user and system regions.\r
+;\r
+; Input:\r
+; ClipStatus = TRUE (FALSE) to enable (disable) clipping\r
+; Output:\r
+; AX = old clip status\r
+;\r
+mxSetClip PROC FAR\r
+ ARG ClipStatus:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [mx_UserClipX1]\r
+ mov bx, [mx_UserClipY1]\r
+ mov cx, [mx_UserClipX2]\r
+ mov dx, [mx_UserClipY2]\r
+ cmp [ClipStatus], TRUE\r
+ je @@Done\r
+ mov ax, [mx_SysClipX1]\r
+ mov bx, [mx_SysClipY1]\r
+ mov cx, [mx_SysClipX2]\r
+ mov dx, [mx_SysClipY2]\r
+@@Done:\r
+ mov [mx_ClipX1], ax\r
+ mov [mx_ClipY1], bx\r
+ mov [mx_ClipX2], cx\r
+ mov [mx_ClipY2], dx\r
+\r
+ mov al, [ClipStatus]\r
+ xchg al, [mx_ClipStatus]\r
+ xor ah, ah\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetClip ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current clipping status.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; TRUE (FALSE) if clipping enabled (disabled)\r
+;\r
+mxGetClip PROC FAR\r
+ ASSUME ds:NOTHING\r
+ mov al, [mx_ClipStatus]\r
+ xor ah, ah\r
+ ret\r
+mxGetClip ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the system clip region and disables user clipping.\r
+;\r
+; Input:\r
+; Width = width in pixels of clip region\r
+; Height = height in pixels of clip region\r
+; Output:\r
+; old clip status.\r
+;\r
+mxSetSysClipRegion PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ xor ax, ax ; Sys clip region always starts at (0,0)\r
+ mov [mx_SysClipX1], ax\r
+ mov [mx_SysClipY1], ax\r
+ mov ax, [Width]\r
+ dec ax\r
+ mov [mx_SysClipX2], ax\r
+ mov ax, [Height]\r
+ dec ax\r
+ mov [mx_SysClipY2], ax\r
+\r
+ IF USE286 EQ TRUE\r
+ push FALSE\r
+ ELSE\r
+ mov ax, FALSE\r
+ push ax\r
+ ENDIF\r
+ call mxSetClip\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetSysClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the clip region.\r
+;\r
+; Input:\r
+; X, Y = coordinates of top left corner of clip region\r
+; Width = width in pixels of clip region\r
+; Height = height in pixels of clip region\r
+; Output:\r
+; none (no checking on parameters)\r
+;\r
+mxSetClipRegion PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [X]\r
+ mov [mx_UserClipX1], ax\r
+ mov ax, [Y]\r
+ mov [mx_UserClipY1], ax\r
+ mov ax, [Width]\r
+ add ax, [X]\r
+ dec ax\r
+ mov [mx_UserClipX2], ax\r
+ mov ax, [Height]\r
+ add ax, [Y]\r
+ dec ax\r
+ mov [mx_UserClipY2], ax\r
+\r
+ mov al, [mx_ClipStatus]\r
+ cmp al, TRUE\r
+ jne @@Exit\r
+ push ax\r
+ call mxSetClip\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current user clip region.\r
+;\r
+; Input:\r
+; X, Y = pointers to integer coordinates of top left corner\r
+; Width = pointer to word width of clip region\r
+; Height = pointer to word height of clip region\r
+; Output:\r
+; AX = current clip status\r
+;\r
+mxGetClipRegion PROC FAR\r
+ ARG Height:DWORD, \\r
+ Width:DWORD, \\r
+ Y:DWORD, \\r
+ X:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push es, di\r
+\r
+ mov ax, [mx_UserClipX1]\r
+ les di, [X]\r
+ mov es:[di], ax\r
+ mov ax, [mx_UserClipY1]\r
+ les di, [Y]\r
+ mov es:[di], ax\r
+\r
+ mov ax, [mx_UserClipX2]\r
+ sub ax, [mx_UserClipX1]\r
+ inc ax\r
+ les di, [Width]\r
+ mov es:[di], ax\r
+ mov ax, [mx_UserClipY2]\r
+ sub ax, [mx_UserClipY1]\r
+ inc ax\r
+ les di, [Height]\r
+ mov es:[di], ax\r
+\r
+ mov al, [mx_ClipStatus]\r
+ xor ah, ah\r
+ .pop es, di\r
+ .leave ARG_SIZE\r
+mxGetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+; This function assumes that a "raw" image has to be clipped,\r
+; so it returns in SI the number of "raw" bytes to skip if\r
+; X, Y were clipped.\r
+;\r
+; Input:\r
+; BX, AX = X, Y coordinates of rectangle (signed)\r
+; CX = box width\r
+; DX = box height\r
+; Output:\r
+; CF = set if rectangle is full clipped\r
+; BX, AX = new X, Y coordinates of rectangle\r
+; CX, DX = clipped width and height\r
+; SI = number of bytes to skip before copying a buffer\r
+; DI destroyed\r
+;\r
+subClipImage PROC NEAR\r
+ ASSUME ds:NOTHING\r
+ xor si, si\r
+\r
+; Check clip height\r
+ mov di, [mx_ClipY1]\r
+ cmp ax, di\r
+ jge @@CheckBottom\r
+ sub di, ax ; Number of lines to clip\r
+ sub dx, di ; New box height\r
+ jle @@Exit\r
+ mov ax, di\r
+ mov di, dx ; Save box height into DI\r
+ mul cx ; DX:AX = number of bytes to skip\r
+ mov si, ax\r
+ mov dx, di ; Restore box height\r
+ mov ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+ mov di, [mx_ClipY2]\r
+ cmp ax, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, dx\r
+ sub di, ax\r
+ jge @@DoneHeight ; None, continue\r
+ add dx, di ; Clip lines\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+ mov di, [mx_ClipX1]\r
+ cmp bx, di\r
+ jge @@CheckRight\r
+ sub di, bx ; Number of columns to clip left\r
+ sub cx, di\r
+ jle @@Exit\r
+ add si, di ; Update skip count\r
+ mov bx, [mx_ClipX1]\r
+@@CheckRight:\r
+ mov di, [mx_ClipX2]\r
+ cmp bx, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, bx\r
+ sub di, cx\r
+ jge @@DoneWidth ; None, exit\r
+ add cx, di ; New box width\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+ clc\r
+ ret\r
+@@Exit:\r
+ stc\r
+ ret\r
+subClipImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+;\r
+; Input:\r
+; BX, AX = X, Y coordinates of rectangle (signed)\r
+; CX = box width\r
+; DX = box height\r
+; Output:\r
+; CF = set if rectangle is full clipped\r
+; BX, AX = new X, Y coordinates of rectangle\r
+; CX, DX = clipped width and height\r
+; DI destroyed\r
+;\r
+subClipBox PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+; Check clip height\r
+ mov di, [mx_ClipY1]\r
+ cmp ax, di\r
+ jge @@CheckBottom\r
+ sub di, ax ; Number of lines to clip\r
+ sub dx, di ; New box height\r
+ jle @@Exit\r
+ mov ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+ mov di, [mx_ClipY2]\r
+ cmp ax, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, dx\r
+ sub di, ax ; Clipped some point?\r
+ jge @@DoneHeight ; No, continue\r
+ add dx, di ; Clip lines (DI is negative)\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+ mov di, [mx_ClipX1]\r
+ cmp bx, di\r
+ jge @@CheckRight\r
+ sub di, bx ; Number of columns to clip left\r
+ sub cx, di\r
+ jle @@Exit\r
+ mov bx, [mx_ClipX1]\r
+@@CheckRight:\r
+ mov di, [mx_ClipX2]\r
+ cmp bx, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, bx\r
+ sub di, cx ; Clipped some point?\r
+ jge @@DoneWidth ; No, exit\r
+ add cx, di ; New box width (DI is negative)\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+ clc\r
+ ret\r
+@@Exit:\r
+ stc\r
+ ret\r
+subClipBox ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXEL.ASM - Mid-point ellipse\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxEllipse\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws an ellipse using the mid-point algorithm.\r
+;\r
+; Input:\r
+; XC, YC = center coordinates\r
+; A = horizontal radius\r
+; B = vertical radius\r
+; Color = ellipse color\r
+; Output:\r
+; none\r
+; Note:\r
+; computes only points in the first quadrant, all other\r
+; points are obtained by symmetry.\r
+;\r
+mxEllipse PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ B:WORD, \\r
+ A:WORD, \\r
+ YC:WORD, \\r
+ XC:WORD = ARG_SIZE\r
+ LOCAL A2:DWORD, \\r
+ B2:DWORD, \\r
+ CC:DWORD, \\r
+ DD:DWORD, \\r
+ X:DWORD, \\r
+ Y:DWORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+\r
+ .chk386 mxEllipse, @@Exit\r
+\r
+; Initialize variables\r
+ xor eax, eax\r
+ mov [X], ax ; X = 0\r
+ mov ax, [A]\r
+ mul eax ; EAX = A*A\r
+ mov [DD], eax ; DD = A*A\r
+ shl eax, 1\r
+ mov [CC], eax ; CC = 2*A*A\r
+ shl eax, 1\r
+ mov [A2], eax ; A2 = 4*A*A\r
+ movzx edx, [B]\r
+ mov [Y], edx\r
+ mul edx ; EAX = 4*A*A*B\r
+ sub [DD], eax ; DD = A*A - 4*A*A*B\r
+ movzx eax, [B]\r
+ mul eax ; EAX = B*B\r
+ shl eax, 2 ; EAX = 4*B*B\r
+ mov [B2], eax ; B2 = 4*B*B\r
+ add [CC], eax ; CC = 2*A*A + 4*B*B\r
+ add [D1], eax ; DD = A*A - 4*A*A*B + 4*B*B\r
+\r
+; Draw initial points\r
+ call subPlot4\r
+\r
+; First loop\r
+@@Loop1:\r
+ mov eax, [X] ; Check slope\r
+ mul [B2]\r
+ mov ecx, eax\r
+ mov eax, [Y]\r
+ mul [A2]\r
+ sub eax, ecx\r
+ sub eax, [CC] ; EAX = Y*A2 - X*B2 - CC\r
+ jle @@Done1 ; Crossed critical point, jump to next loop\r
+\r
+ mov ecx, [DD] ; Get error\r
+ test ecx, ecx ; Positive?\r
+ jl @@Draw1 ; No, use default step\r
+\r
+ mov eax, 1\r
+ sub eax, [Y]\r
+ mul [A2]\r
+ shl eax, 1\r
+ add ecx, eax ; Bump error\r
+ dec WORD PTR [Y] ; Decrement Y coordinate\r
+\r
+@@Draw1:\r
+ mov eax, [X]\r
+ shl eax, 1\r
+ add eax, 3\r
+ mul [B2]\r
+ add ecx, eax ; Bump error\r
+ mov [DD], ecx ; Save error\r
+ inc WORD PTR [X] ; Increment X coordinate\r
+\r
+ call subPlot4 ; Draw points\r
+ jmp @@Loop1\r
+@@Done1:\r
+\r
+; Initialize variables\r
+ shr [B2], 2\r
+ mov eax, [X]\r
+ mul eax\r
+ add [X]\r
+ shl eax, 2\r
+ inc eax\r
+ mul [B2]\r
+ mov [DD], eax\r
+ mov eax, [Y]\r
+ mul eax\r
+ add [Y]\r
+ dec eax\r
+ add [Y]\r
+ sub eax, [B2]\r
+ add [DD], eax\r
+ shl [B2], 3\r
+ inc WORD PTR [X]\r
+\r
+; Second loop\r
+@@Loop2:\r
+ cmp WORD PTR [Y], 0\r
+ ja @@Done2\r
+\r
+ mov ecx, [DD]\r
+ test ecx, ecx\r
+ jge @@Draw2\r
+\r
+ mov eax, [X]\r
+ inc eax\r
+ mul [B2]\r
+ add ecx, eax\r
+ inc WORD PTR [X]\r
+\r
+@@Draw2:\r
+ mov eax, [Y]\r
+ shl eax, 1\r
+ sub eax, 3\r
+ neg eax\r
+ imul [A2]\r
+ add ecx, eax\r
+ dec WORD PTR [Y]\r
+\r
+ call subPlot4\r
+ jmp @@Loop2\r
+@@Done2:\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxEllipse ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXFB.ASM - Fill box function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFillBox\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN subClipBox : NEAR\r
+EXTRN subHorizontalLineInfo : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Raster op functions. Raster op is limited to OP_MOVE,\r
+; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to\r
+; perform the selected logical functions on up to four\r
+; pixel at a time.\r
+;\r
+subRepFill PROC NEAR\r
+ mov ah, al\r
+ shr cx, 1\r
+ rep stosw\r
+ rcl cx, 1\r
+ rep stosb\r
+ ret\r
+subRepFill ENDP\r
+;\r
+subFill PROC NEAR\r
+@@Loop:\r
+ mov ds:[bx], al\r
+ add bx, dx\r
+ loop @@Loop\r
+ ret\r
+subFill ENDP\r
+;\r
+subRepMove PROC NEAR\r
+ mov si, di\r
+@@Loop:\r
+ mov ah, ds:[si] ; Dummy read to latch the data\r
+ mov ds:[si], al\r
+ inc si\r
+ loop @@Loop\r
+ ret\r
+subRepMove ENDP\r
+;\r
+subMove PROC NEAR\r
+@@Loop:\r
+ mov ah, ds:[bx] ; Dummy read to latch the data\r
+ mov ds:[bx], al\r
+ add bx, dx\r
+ loop @@Loop\r
+ ret\r
+subMove ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a rectangle with a specified color.\r
+;\r
+; Input:\r
+; X, Y = X, Y coordinates of rectangle\r
+; Width = width of rectangle\r
+; Height = height of rectangle\r
+; Color = fill color\r
+; Op = raster operator\r
+; Output:\r
+; none\r
+;\r
+; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR.\r
+;\r
+mxFillBox PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:BYTE:2, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL LeftMask:BYTE, \\r
+ RightMask:BYTE, \\r
+ FillFunction:WORD, \\r
+ RepFillFunction:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Clip rectangle\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipBox\r
+ jc @@Exit ; Full clipped\r
+\r
+ mov [Height], dx ; Save clipped height\r
+ call subHorizontalLineInfo ; Get additional info, init DI\r
+ mov [Width], cx\r
+ mov [LeftMask], al\r
+ mov [RightMask], ah\r
+\r
+; Initialize segments\r
+ mov ax, [mx_VideoSegment]\r
+ mov es, ax ; ES:DI points to pixel\r
+ mov ds, ax\r
+ cld ; Clear direction flag\r
+\r
+; Select fill functions\r
+ mov [FillFunction], OFFSET subFill\r
+ mov [RepFillFunction], OFFSET subRepFill\r
+ mov ax, [Op] ; Get raster op\r
+ cmp al, OP_XOR\r
+ ja @@1 ; Assume it's a fill\r
+ cmp al, OP_MOVE\r
+ je @@1\r
+ .shl al, 3\r
+ mov ah, al\r
+ mov al, 03h\r
+ mov dx, GDC\r
+ out dx, ax ; Set GDC logical function\r
+ mov [FillFunction], OFFSET subMove\r
+ mov [RepFillFunction], OFFSET subRepMove\r
+@@1:\r
+\r
+; Fill left block\r
+@@L0:\r
+ mov ah, [LeftMask]\r
+ or ah, ah\r
+ jz @@C0 ; Nothing to do, go to center block\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov dx, [mx_BytesPerLine]\r
+ mov cx, [Height]\r
+ mov bx, di\r
+ mov al, [Color]\r
+ call [FillFunction] ; Fill this column\r
+ inc di ; Update starting video offset\r
+\r
+; Fill center block\r
+@@C0:\r
+ mov cx, [Width]\r
+ jcxz @@R0 ; Nothing to do, go to right block\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Write to all planes\r
+ mov al, [Color]\r
+ mov bx, di\r
+ mov dx, [Height]\r
+ push di ; Save pixel address\r
+@@C1:\r
+ mov di, bx ; Update video offset\r
+ call [RepFillFunction] ; Fill current scan line\r
+ mov cx, [Width] ; Restore byte count\r
+ add bx, [mx_BytesPerLine] ; Bump to next scan line\r
+ dec dx ; Done all lines?\r
+ jnz @@C1 ; No, continue\r
+ pop di ; Restore pixel address\r
+ add di, [Width] ; Go to right block\r
+\r
+; Fill right block\r
+@@R0:\r
+ mov ah, [RightMask]\r
+ or ah, ah\r
+ jz @@Done ; Nothing to do, exit\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov dx, [mx_BytesPerLine]\r
+ mov cx, [Height]\r
+ mov bx, di\r
+ mov al, [Color]\r
+ call [FillFunction] ; Fill this column\r
+\r
+; Restore VGA registers\r
+@@Done:\r
+ mov dx, GDC\r
+ mov ax, 0003h\r
+ out dx, ax ; Set logical function to "move"\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxFillBox ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXFP.ASM - Fade palette function\r
+; Copyright (c) 1992-1994 ARTIS s.r.l.\r
+; Author: Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFadePalette\r
+\r
+MAXCOLOR EQU 256\r
+FADE_IN EQU 0\r
+FADE_OUT EQU 1\r
+\r
+; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
+; the delay between two consecutive passes (FADE_DELAY). Below are the\r
+; default values, used when no parameters are specified.\r
+;\r
+FADE_DELAY EQU 1 ; Vert. retraces between video updates\r
+FADE_SPEED EQU 48 ; Speed of effect (max 127)\r
+\r
+; Bit field record for fade commands\r
+;\r
+FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fades a VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to source/destination palette\r
+; Command = fading direction and optional parameters\r
+; Start = index of first color to fade\r
+; Count = number of color to fade\r
+; Red = destination red\r
+; Green = destination green\r
+; Blue = destination blue\r
+; Output:\r
+; none\r
+; Notes:\r
+; - about 1.5 Kbytes of stack space are needed for internal buffers;\r
+; - the Command argument usually is 0 to fade in and 1 to fade out,\r
+; however additional parameters may be specified. To set the effect\r
+; speed, i.e. the number of iterations needed to completely fade a\r
+; palette, shift the value one bit left and "or" it with the\r
+; direction bit (range is 0..127). To set the delay between two\r
+; consecutive passes, shift it eight bits left (range is 0..255).\r
+;\r
+mxFadePalette PROC FAR\r
+ ARG bBlue:WORD, \\r
+ bGreen:WORD, \\r
+ bRed:WORD, \\r
+ wCount:WORD, \\r
+ wStartIdx:WORD, \\r
+ wCommand:WORD, \\r
+ vfpPalette:DWORD = ARG_SIZE\r
+ LOCAL bSPalette:BYTE:MAXCOLOR*3, \\r
+ bDPalette:BYTE:MAXCOLOR*3, \\r
+ bLoopIndex:BYTE, \\r
+ bLoopStep:BYTE, \\r
+ bLoopCount:BYTE, \\r
+ wDelay:WORD, \\r
+ wSpeed:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push si, di, ds, es ; Save registers\r
+;\r
+; Check parameters and setup variables\r
+;\r
+@@GetDelay:\r
+ mov [wDelay], FADE_DELAY ; Set default delay\r
+ mov ax, [wCommand] ; Get command word\r
+ and ax, MASK fpDELAY ; Mask delay command\r
+ jz @@GetSpeed ; No command, get speed\r
+ IF USE286 EQ TRUE\r
+ shr ax, fpDELAY\r
+ ELSE\r
+ mov cl, fpDELAY ; Get size of delay field\r
+ shr ax, cl ; Right justify the field\r
+ ENDIF\r
+ mov [wDelay], ax ; Set new delay\r
+\r
+@@GetSpeed:\r
+ mov ax, [wCommand] ; Get command\r
+ and ax, MASK fpSPEED ; Mask speed\r
+ IF USE286 EQ TRUE\r
+ shr ax, fpSPEED\r
+ ELSE\r
+ mov cl, fpSPEED ; Get size of speed field\r
+ shr ax, cl ; Right justify the field\r
+ ENDIF\r
+ or ax, ax ; Any speed specified?\r
+ jnz @@SetVariables ; Yes, set variables\r
+ mov ax, FADE_SPEED ; Set default speed\r
+\r
+@@SetVariables:\r
+ mov [wSpeed], ax ; Set speed\r
+ inc ax ; Number of iterations\r
+ mov [bLoopCount], al ; Set loop count\r
+ mov [bLoopStep], 1 ; Assume we're fading in\r
+ mov [bLoopIndex], 0\r
+;\r
+; Check bounds for bad values\r
+;\r
+ mov ax, [wStartIdx] ; Get first index\r
+ cmp ax, MAXCOLOR ; Is in the valid range?\r
+ jae @@Exit ; No, exit\r
+ add ax, [wCount] ; Get last index\r
+ cmp ax, MAXCOLOR ; Is in the valid range?\r
+ jbe @@BoundsOk ; Yes, continue\r
+ mov ax, MAXCOLOR\r
+ sub ax, [wStartIdx]\r
+ mov [wCount], ax ; Set count to maximum value\r
+ or ax, ax\r
+ jz @@Exit ; Nothing to do, exit\r
+@@BoundsOk:\r
+;\r
+; Copy the source palette in a local array: if we fade in it's ready to\r
+; use, otherwise we'll overwrite it later\r
+;\r
+ mov cx, [wCount]\r
+ mov ax, cx\r
+ shl ax, 1\r
+ add cx, ax ; CX = wCount * 3\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [bSPalette] ; ES:DI points to local palette\r
+ mov ax, [wStartIdx]\r
+ mov si, ax\r
+ shl ax, 1\r
+ add ax, si\r
+ lds si, [vfpPalette] ; DS:SI points to user palette\r
+ add si, ax ; Skip unused entries\r
+ cld\r
+ shr cx, 1\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+;\r
+; Check direction\r
+;\r
+ test [wCommand], MASK fpDIRECTION ; Are we fading in?\r
+ jz @@Main ; Yes, ok to continue\r
+ mov ax, [wSpeed] ; Get speed\r
+ mov [bLoopIndex], al ; Exchange first and last index\r
+ mov [bLoopStep], -1 ; Move backward\r
+ mov ax, ss ; Overwrite our copy of\r
+ mov ds, ax ; user palette with the\r
+ mov es, ax ; current active palette\r
+ lea di, [bSPalette]\r
+ mov ax, [wStartIdx]\r
+ mov cx, [wCount]\r
+ call ReadPalette ; Read current palette\r
+;\r
+; Prepare variables and registers for fading\r
+;\r
+@@Main:\r
+ mov bh, BYTE PTR [bRed] ; Destination red\r
+ and bh, 00111111b ; Be sure it's a valid VGA value\r
+ mov bl, BYTE PTR [bGreen] ; Destination green\r
+ and bl, 00111111b ; Be sure it's a valid VGA value\r
+ mov dh, BYTE PTR [bBlue] ; Destination blue\r
+ and dh, 00111111b ; Be sure it's a valid VGA value\r
+ mov dl, [bLoopIndex] ; Loop index\r
+ mov ax, ss ; All tables are stored\r
+ mov ds, ax ; in the stack segment,\r
+ mov es, ax ; set DS and ES\r
+;\r
+; Main loop\r
+;\r
+@@Loop:\r
+ mov ax, [wCount] ; Store count in AX\r
+ mov cx, [wSpeed] ; Set maximum speed in CX\r
+ lea si, [bSPalette] ; DS:SI points to source palette\r
+ lea di, [bDPalette] ; ES:DI points to dest. palette\r
+ call RecalcPalette ; Build a faded palette\r
+\r
+ .push bx, dx ; Save registers we need\r
+ lea si, [bDPalette] ; DS:SI points to palette\r
+ mov ax, [wStartIdx] ; First index to write\r
+ mov bx, [wCount] ; Total entries to write\r
+ mov cx, [wDelay] ; Fade delay between updates\r
+ call WritePalette ; Write palette\r
+ .pop bx, dx ; Restore BX and DX\r
+\r
+ add dl, [bLoopStep] ; Change fade intensity\r
+ dec [bLoopCount] ; Done?\r
+ jnz @@Loop ; No, loop again\r
+\r
+@@Exit:\r
+ .pop si, di, ds, es ; Restore registers\r
+ .leave ARG_SIZE\r
+mxFadePalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Calculates a partially faded palette.\r
+;\r
+; Input:\r
+; AX = number of entries in palette\r
+; CX = maximum fade intensity (same as fade speed)\r
+; DS:SI = pointer to source palette\r
+; ES:DI = pointer to destination palette\r
+; BH = destination red\r
+; BL = destination green\r
+; DH = destination blue\r
+; DL = relative intensity of destination palette\r
+; Note:\r
+; it's important that a new palette can be calculated in less\r
+; than 1/70th of second. Fading to any RGB value requires use\r
+; of "imul" instructions: "idiv" may be replaced with faster\r
+; "sar", but only when the number of passes is a power of two,\r
+; thus reducing the range of selectable speeds.\r
+; In both cases an extimate of CPU cycles required by this\r
+; procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
+; CPU and a 256 color palette, so we keep "idiv" and hope\r
+; the target machine to be at least a 6 Mhz 80286 (that's not\r
+; asking too much...).\r
+;\r
+RecalcPalette PROC NEAR\r
+ cld\r
+ push bp ; Save BP\r
+ mov bp, ax ; Copy counter in BP\r
+@@Loop:\r
+ lodsb ; Red: read value\r
+ sub al, bh ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, bh ; Add destination value...\r
+ stosb ; ...and store it\r
+ lodsb ; Green: read value\r
+ sub al, bl ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, bl ; Add destination value...\r
+ stosb ; ...and store it\r
+ lodsb ; Blue: read value\r
+ sub al, dh ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, dh ; Add destination value...\r
+ stosb ; ...and store it\r
+ dec bp\r
+ jnz @@Loop\r
+ pop bp ; Restore BP\r
+ ret\r
+RecalcPalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Writes a 256 color palette.\r
+;\r
+; Input:\r
+; AX = index of first color to write\r
+; BX = number of colors to write (each color is an RGB triplet)\r
+; CX = number of vertical retraces to wait before writing to DACs\r
+; DS:SI = pointer to first entry of palette\r
+;\r
+WritePalette PROC NEAR\r
+ ASSUME ds:NOTHING\r
+ mov ah, al ; Save index\r
+ mov dx, 03DAh ; Input status register\r
+@@Delay1:\r
+ in al, dx\r
+ test al, 08h\r
+ jnz @@Delay1 ; Wait for display mode\r
+@@Delay2:\r
+ in al, dx\r
+ test al, 08h\r
+ jz @@Delay2 ; Wait for vertical retrace mode\r
+ loop @@Delay1 ; Repeat CX times\r
+@@Write:\r
+ mov cx, bx ; Get number of colors\r
+ mov dx, 03C8h ; PEL write address register\r
+ mov al, ah ; Restore index\r
+ out dx, al ; Select index of first color\r
+ inc dx ; PEL data register\r
+ cld ; Move forward\r
+ cli ; Disable interrupts\r
+@@Loop:\r
+ lodsb\r
+ out dx, al ; Red\r
+ lodsb\r
+ out dx, al ; Green\r
+ lodsb\r
+ out dx, al ; Blue\r
+ loop @@Loop ; Loop until done\r
+ sti ; Enable interrupts\r
+ ret\r
+WritePalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Reads the current palette.\r
+;\r
+; Input:\r
+; AX = index of first color to read\r
+; CX = number of colors\r
+; ES:DI = pointer to destination buffer\r
+;\r
+ReadPalette PROC NEAR\r
+ mov dx, 03C7h\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+ cld\r
+@@Loop:\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ loop @@Loop\r
+ ret\r
+ReadPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGC.ASM - Get color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetColor\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the selected DAC register.\r
+;\r
+; Input:\r
+; Index = color index (0-255)\r
+; R, G, B = byte pointers to red, green and blue\r
+; Output:\r
+; none\r
+;\r
+mxGetColor PROC FAR\r
+ ARG B:DWORD, \\r
+ G:DWORD, \\r
+ R:DWORD, \\r
+ Index:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [Index]\r
+ mov dx, 3C7h ; PEL read address register\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+\r
+ lds si, [R]\r
+ in al, dx\r
+ mov ds:[si], al\r
+ lds si, [G]\r
+ in al, dx\r
+ mov ds:[si], al\r
+ lds si, [B]\r
+ in al, dx\r
+ mov ds:[si], al\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetColor ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGI.ASM - Get image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies an image from screen to memory.\r
+;\r
+; Input:\r
+; Image = pointer to buffer for image\r
+; X, Y = coordinates of image on screen\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+;\r
+mxGetImage PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ ReadPlane:BYTE, \\r
+ Count:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov si, bx\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax\r
+ mov [PixelOffset], si\r
+ mov ds, [mx_VideoSegment] ; DS:SI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov di, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[di], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec di\r
+ dec di\r
+ jge @@PatchLoop\r
+\r
+; Get image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov es, WORD PTR Image[2] ; ES:DI will point to image\r
+ mov ah, [ReadPlane]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov di, WORD PTR Image[0]\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov si, [PixelOffset] ; DS:SI points to video memory\r
+@@Loop:\r
+ .push si, di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+@@MoveLoop:\r
+ movsb\r
+ add di, 3\r
+ dec cx\r
+ jnz @@MoveLoop\r
+ .pop si, di\r
+ add di, [Width] ; Go to next image line\r
+ add si, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc ah\r
+ test ah, 04h ; Plane wraparound?\r
+ jz @@PlaneOk ; No\r
+ inc [PixelOffset] ; Yes, bump video pointer\r
+ and ah, 03h\r
+@@PlaneOk:\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGetImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGM.ASM - Gamma correction\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGammaCorrect\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+mx_tblGamma LABEL BYTE\r
+ DB 00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34\r
+ DB 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46\r
+ DB 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55\r
+ DB 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Correct palette colors (gamma is 2.3).\r
+;\r
+; Input:\r
+; CPal = pointer to color palette\r
+; GPal = pointer to destination (gamma corrected) palette\r
+; Count = number of colors to convert\r
+; Output:\r
+; none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxGammaCorrect PROC FAR\r
+ ARG Count:WORD, \\r
+ DPal:DWORD, \\r
+ SPal:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov cx, [Count]\r
+ jcxz @@Exit ; Exit now if nothing to do\r
+ lds si, [SPal]\r
+ les di, [DPal]\r
+ mov bx, OFFSET mx_tblGamma ; Setup BX for XLAT instruction\r
+ cld\r
+ mov ax, cx ; AX = Count\r
+ add cx, cx ; CX = Count*2\r
+ add cx, ax ; CX = Count*3\r
+@@Loop:\r
+ lodsb\r
+ xlat mx_tblGamma\r
+ stosb\r
+ loop @@Loop\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGammaCorrect ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGP.ASM - Get palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetPalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to palette data (R,G,B)\r
+; Start = index of first color to get\r
+; Count = number of color to get\r
+; Output:\r
+; none\r
+;\r
+mxGetPalette PROC FAR\r
+ ARG Count:WORD, \\r
+ Start:WORD, \\r
+ Buffer:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push es, di\r
+\r
+ les di, [Buffer]\r
+ mov cx, [Count]\r
+ mov ax, [Start]\r
+ mov dx, 3C7h ; PEL read address register\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+ cld\r
+@@Loop:\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ loop @@Loop ; Loop until done\r
+\r
+ .pop es, di\r
+ .leave ARG_SIZE\r
+mxGetPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGV.ASM - Get version function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetVersion\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the library version.\r
+;\r
+mxGetVersion PROC FAR\r
+ mov ax, MXVERSION\r
+ ret\r
+mxGetVersion ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXHL.ASM - Horizontal line mask utility\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC subHorizontalLineInfo\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+tblLeftSize DW 00h, 03h, 02h, 01h\r
+tblLeftMask DB 00h, 0Eh, 0Ch, 08h\r
+tblRightMask DB 00h, 01h, 03h, 07h\r
+tblPatchMask DB 02h, 06h\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Prepares register for fast horizontal line drawing.\r
+;\r
+; Input:\r
+; BX, AX = X, Y address of left pixel\r
+; CX = line width\r
+; Output:\r
+; DI = left pixel offset in video memory\r
+; AL = left block write plane mask (0 = none)\r
+; AH = right block write plane mask (0 = none)\r
+; CX = center block width in 4-pixel blocks\r
+;\r
+subHorizontalLineInfo PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax ; Offset of left pixel\r
+\r
+ and bx, 03h\r
+ mov al, tblLeftMask[bx]\r
+ shl bx, 1\r
+ sub cx, tblLeftSize[bx]\r
+ jge @@1 ; Ok to continue\r
+\r
+; Special case: start and end in the middle of a 4-pixel block.\r
+; There are only three cases:\r
+; Pixels Left mask CX CX+2 Patch mask Result\r
+; 1) ..o. ..xx -1 1 .xx. ..x.\r
+; 2) .oo. .xxx -1 1 .xx. .xx.\r
+; 3) .o.. .xxx -2 0 .x.. .x..\r
+; All other cases are automatically handled with the standard masks.\r
+ mov bx, cx\r
+ inc bx\r
+ inc bx\r
+ and al, tblPatchMask[bx] ; Combine masks\r
+ xor ah, ah ; No right block\r
+ xor cx, cx ; No center block\r
+ jmp @@Exit\r
+\r
+@@1:\r
+ mov bx, cx\r
+ and bx, 03h\r
+ mov ah, tblRightMask[bx]\r
+ shr cx, 2\r
+\r
+@@Exit:\r
+ ret\r
+subHorizontalLineInfo ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxInit\r
+PUBLIC mxTerm\r
+\r
+PUBLIC mx_VideoSegment\r
+PUBLIC mx_CodeSegment\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW 0A000h\r
+mx_CodeSegment DW SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; AX = 0 on success\r
+;\r
+mxInit PROC FAR\r
+ LOCAL Result:WORD, \\r
+ VideoSeg:WORD, \\r
+ CStoDSalias:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov [Result], -1 ; Assume an error\r
+ mov [VideoSeg], 0A000h ; Real mode video segment\r
+ mov [CStoDSalias], cs ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+ mov ax, 1686h\r
+ int 2Fh\r
+ or ax, ax\r
+ jnz @@1 ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+ mov ax, 000Ah ; DMPI: create data alias\r
+ mov bx, cs\r
+ int 31h\r
+ jc @@Exit ; Exit if service failed\r
+ mov [CStoDSalias], ax ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+ mov ax, 0002h\r
+ mov bx, 0A000h ; Real mode segment of video\r
+ int 31h ; DPMI: get segment selector\r
+ jc @@Exit ; Exit if service failed\r
+ mov [VideoSeg], ax ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+ mov ds, [CStoDSalias]\r
+ ASSUME ds:MX_TEXT\r
+ mov [mx_CodeSegment], ds\r
+ mov ax, [VideoSeg]\r
+ mov [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+ mov [Result], 0\r
+\r
+@@Exit:\r
+ mov ax, [Result]\r
+ .pop ds, si, es, di\r
+ .leave\r
+mxInit ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; always 0.\r
+;\r
+mxTerm PROC FAR\r
+ ASSUME ds:NOTHING\r
+ xor ax, ax\r
+ ret\r
+mxTerm ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLL.ASM - Load latches\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxLoadLatches\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Loads the specified value into the VGA latches.\r
+;\r
+; Input:\r
+; BL = value to load into latches\r
+; Output:\r
+; none\r
+; Changes:\r
+; bit mask register to FFh;\r
+; function select register to "move";\r
+; write mode to 00h.\r
+; Note:\r
+; this is for internal use only.\r
+;\r
+mxLoadLatches PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+ .push ds, si\r
+ mov dx, GDC\r
+ mov ax, 0FF08h\r
+ out dx, ax ; Set bit mask to FFh\r
+ mov ax, 0003h\r
+ out dx, ax ; Set function to "move"\r
+ mov ax, 0005h\r
+ out dx, ax ; Set write mode\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov si, 0FFFFh\r
+ mov bh, 8 ; BH = write plane mask\r
+ mov cx, 3 ; CX = count = read plane\r
+; Saves old values and force BL into latches\r
+@@SetLoop:\r
+ mov dx, GDC\r
+ mov al, 04h\r
+ mov ah, cl\r
+ out dx, ax ; Select read plane\r
+ mov dx, TS\r
+ mov al, 02h\r
+ mov ah, bh\r
+ out dx, ax ; Select write plane\r
+ mov al, ds:[si]\r
+ push ax\r
+ mov ds:[si], bl\r
+ mov al, ds:[di] ; Force value into latch\r
+ shr bh, 1 ; Next write plane\r
+ loop @@SetLoop\r
+; Restore previous values\r
+ mov cx, 3\r
+ mov bh, 8\r
+ mov dx, TS\r
+@@ResetLoop:\r
+ mov al, 02h\r
+ mov ah, bh\r
+ out dx, ax ; Select write plane\r
+ pop ax\r
+ mov ds:[si], al\r
+ shr bh, 1 ; Next write plane\r
+ loop @@ResetLoop\r
+; Exit\r
+ .pop ds, si\r
+ ret\r
+mxLoadLatches ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+tblDrawFunc LABEL WORD\r
+ DW subWidthMove\r
+ DW subHeightMove\r
+ DW subWidthOp\r
+ DW subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+; X1, Y1 = start point\r
+; X2, Y2 = end point\r
+; Color = line color\r
+; Op = raster operator\r
+; Output:\r
+; none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD, \\r
+ Y2:WORD, \\r
+ X2:WORD, \\r
+ Y1:WORD, \\r
+ X1:WORD = ARG_SIZE\r
+ LOCAL Width:WORD, \\r
+ Height:WORD, \\r
+ ErrorAdd:WORD, \\r
+ ErrorSub:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD, \\r
+ P1:BYTE, \\r
+ P2:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [X1]\r
+ mov bx, [Y1]\r
+ mov cx, [X2]\r
+ mov dx, [Y2]\r
+ call subClipLine\r
+ jc @@Exit ; Line is full clipped\r
+\r
+; Get width\r
+ mov si, cx\r
+ xchg ax, si ; SI = X1, AX = X2\r
+ sub ax, si\r
+ jge @@1\r
+; Swap points, we want X1 < X2\r
+ xchg si, cx ; Swap X1 and X2\r
+ xchg bx, dx ; Swap Y1 and Y2\r
+ neg ax\r
+@@1:\r
+ mov [Width], ax\r
+\r
+; Get height\r
+ mov cx, [mx_BytesPerLine] ; We don't need X2 anymore\r
+ mov ax, dx\r
+ sub ax, bx\r
+ jge @@2\r
+ neg cx ; Move from bottom to top\r
+ neg ax ; Get absolute value of AX\r
+@@2:\r
+ mov [Height], ax\r
+ mov [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+ mov ax, bx\r
+ mul [mx_BytesPerLine]\r
+ mov cx, si ; CX = X1\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax ; SI = pixel offset\r
+ and cl, 03h\r
+ mov ax, 1102h\r
+ shl ah, cl\r
+ mov [WritePlane], ah\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+ xor bx, bx\r
+ mov al, BYTE PTR [Op]\r
+ cmp al, OP_MOVE\r
+ je @@3\r
+ and al, 03h\r
+ shl al, 1\r
+ shl al, 1\r
+ shl al, 1\r
+ mov ah, al\r
+ mov al, 03h\r
+ mov dx, GDC\r
+ out dx, ax ; Set logical function\r
+ inc bx\r
+ inc bx\r
+@@3:\r
+ mov ax, [Width]\r
+ mov cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+ cmp ax, cx\r
+ jae @@4\r
+ inc bx\r
+@@4:\r
+ shl bx, 1\r
+ call tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+ cmp BYTE PTR [Op], OP_MOVE\r
+ je @@Exit\r
+ mov ax, 0003h\r
+ mov dx, GDC\r
+ out dx, ax\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+; AX, BX = X1, Y1\r
+; CX, DX = X2, Y2\r
+; Output:\r
+; CF = set if line is full clipped\r
+; AX, BX = clipped X1, Y1\r
+; CX, DX = clipped X2, Y2\r
+; Note:\r
+; destroys SI, DI\r
+;\r
+subClipLine PROC NEAR\r
+ mov di, ax ; Copy X1 to DI and free AX\r
+ mov si, dx ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+ xor al, al\r
+@@P2X1: cmp cx, [mx_ClipX1]\r
+ jge @@P2X2\r
+ or al, 1\r
+@@P2X2: cmp cx, [mx_ClipX2]\r
+ jle @@P2Y1\r
+ or al, 2\r
+@@P2Y1: cmp si, [mx_ClipY1]\r
+ jge @@P2Y2\r
+ or al, 4\r
+@@P2Y2: cmp si, [mx_ClipY2]\r
+ jle @@P2XY\r
+ or al, 8\r
+@@P2XY: mov [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+ xor al, al\r
+@@P1X1: cmp di, [mx_ClipX1]\r
+ jge @@P1X2\r
+ or al, 1\r
+@@P1X2: cmp di, [mx_ClipX2]\r
+ jle @@P1Y1\r
+ or al, 2\r
+@@P1Y1: cmp bx, [mx_ClipY1]\r
+ jge @@P1Y2\r
+ or al, 4\r
+@@P1Y2: cmp bx, [mx_ClipY2]\r
+ jle @@P1XY\r
+ or al, 8\r
+@@P1XY: mov [P1], al\r
+; Check codes for trivial cases\r
+ mov ah, [P2]\r
+ test al, ah ; Is line invisible?\r
+ jnz @@FullClip ; Yes, exit\r
+ or ah, al ; Both points clipped?\r
+ jz @@Done ; Yes, exit\r
+; Calculate deltas\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov [DeltaX], ax\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov [DeltaY], ax\r
+ mov al, [P1] ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+ test al, al ; Is first point clipped?\r
+ jnz @@ClipX1 ; No, continue\r
+ xchg cx, di ; Swap points...\r
+ xchg bx, si\r
+ xchg al, [P2] ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+ test al, 1\r
+ jz @@ClipX2\r
+ mov ax, [mx_ClipX1]\r
+ sub ax, di\r
+ mov di, [mx_ClipX1]\r
+ jmp @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+ test al, 2\r
+ jz @@ClipY1\r
+ mov ax, [mx_ClipX2]\r
+ sub ax, di\r
+ mov di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+ imul [DeltaY]\r
+ idiv [DeltaX]\r
+ add bx, ax\r
+ mov al, 8\r
+ cmp bx, [mx_ClipY2]\r
+ jg @@CheckLoop\r
+ mov al, 4\r
+ cmp bx, [mx_ClipY1]\r
+ jl @@CheckLoop\r
+ xor al, al\r
+ jmp @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+ test al, 4\r
+ jz @@ClipY2\r
+ mov ax, [mx_ClipY1]\r
+ sub ax, bx\r
+ mov bx, [mx_ClipY1]\r
+ jmp @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+ mov ax, [mx_ClipY2]\r
+ sub ax, bx\r
+ mov bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+ imul [DeltaX]\r
+ idiv [DeltaY]\r
+ add di, ax\r
+ mov al, 1\r
+ cmp di, [mx_ClipX1]\r
+ jl @@CheckLoop\r
+ mov al, 2\r
+ cmp di, [mx_ClipX2]\r
+ jg @@CheckLoop\r
+ xor al, al\r
+@@CheckLoop:\r
+ mov ah, [P2]\r
+ test al, ah\r
+ jnz @@FullClip\r
+ or ah, al\r
+ jnz @@ClipLoop\r
+\r
+@@Done:\r
+ mov ax, di\r
+ mov dx, si\r
+ clc\r
+ ret\r
+@@FullClip:\r
+ stc\r
+ ret\r
+subClipLine ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove PROC NEAR\r
+ mov di, ax\r
+ neg di ; Initialize error term\r
+ shl cx, 1\r
+ mov [ErrorAdd], cx\r
+ mov cx, ax\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov al, 02h\r
+ mov ah, [WritePlane]\r
+ mov bl, BYTE PTR [Color]\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ rol ah, 1\r
+ adc si, 0\r
+ out dx, ax\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ add si, [DeltaY]\r
+ sub di, [ErrorSub]\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subWidthMove ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove PROC NEAR\r
+ mov di, cx\r
+ neg di ; Initialize error term\r
+ shl ax, 1\r
+ mov [ErrorAdd], ax\r
+ mov ax, cx\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov bl, BYTE PTR [Color]\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ add si, [DeltaY]\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ rol ah, 1 ; Next write plane\r
+ adc si, 0 ; Bump video offset if plane overflows\r
+ out dx, ax\r
+ sub di, [ErrorSub] ; Adjust error down\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subHeightMove ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp PROC NEAR\r
+ mov di, ax\r
+ neg di ; Initialize error term\r
+ shl cx, 1\r
+ mov [ErrorAdd], cx\r
+ mov cx, ax\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov al, 02h\r
+ mov ah, [WritePlane]\r
+ mov bl, BYTE PTR [Color]\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov bh, ds:[si] ; Latch data\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ rol ah, 1\r
+ adc si, 0\r
+ out dx, ax\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ add si, [DeltaY]\r
+ sub di, [ErrorSub]\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subWidthOp ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp PROC NEAR\r
+ mov di, cx\r
+ neg di ; Initialize error term\r
+ shl ax, 1\r
+ mov [ErrorAdd], ax\r
+ mov ax, cx\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov bl, BYTE PTR [Color]\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov bh, ds:[si]\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ add si, [DeltaY]\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ rol ah, 1 ; Next write plane\r
+ adc si, 0 ; Bump video offset if plane overflows\r
+ out dx, ax\r
+ sub di, [ErrorSub] ; Adjust error down\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subHeightOp ENDP\r
+\r
+mxLine ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxOutChar\r
+PUBLIC mxOutText\r
+PUBLIC mxSetFont\r
+PUBLIC mxSetTextColor\r
+PUBLIC mxGetTextStep\r
+PUBLIC mxSetTextStep\r
+\r
+MAX_WIDTH EQU 16 ; Must be <= 16\r
+MAX_HEIGHT EQU 32\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mxPutImage : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default LABEL\r
+ INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont LABEL WORD\r
+ DW fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth DW 8 ; Font width in pixels\r
+mx_FontHeight DW 8 ; Font height in pixels\r
+mx_FontCharSize DW 8 ; Size in bytes of a font character\r
+mx_FontColor DW 00FFh ; Color: foreground + background*256\r
+mx_FontOp DW OP_MOVE ; Raster op\r
+mx_DeltaX DW 8 ; Horizontal step\r
+mx_DeltaY DW 0 ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+; Font = pointer to font data\r
+; Width = width of font character in pixels\r
+; Height = height of font character in pixels\r
+; Output:\r
+; AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+; word is used to select one of the system fonts.\r
+;\r
+mxSetFont PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Font:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, WORD PTR Font[2] ; Get font segment\r
+ test ax, ax ; Null segment?\r
+ jnz @@UserFont ; No, install user font\r
+\r
+; Install system font\r
+ mov ax, WORD PTR Font[0] ; Get font number\r
+ cmp ax, MX_MAXSYSFONT ; Check range\r
+ jb @@SystemFont\r
+ xor ax, ax ; Out of range, use default font\r
+@@SystemFont:\r
+ shl ax, 1\r
+ shl ax, 1\r
+ mov bx, ax\r
+ mov ax, tbl_SystemFont[bx] ; Get font offset\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov WORD PTR mx_FontPtr[2], cs\r
+ mov al, BYTE PTR tbl_SystemFont[bx+2]\r
+ xor ah, ah\r
+ mov [mx_FontWidth], ax\r
+ mov [mx_DeltaX], ax\r
+ mov dl, BYTE PTR tbl_SystemFont[bx+3]\r
+ xor dh, dh\r
+ mov [mx_FontHeight], dx\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov [mx_DeltaX], ax\r
+ xor ax, ax\r
+ mov [mx_DeltaY], ax\r
+ jmp @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+ mov ax, -1 ; Assume an error\r
+ mov bx, [Width]\r
+ cmp bx, MAX_WIDTH\r
+ ja @@Exit ; Invalid character width\r
+ mov dx, [Height]\r
+ cmp dx, MAX_HEIGHT\r
+ ja @@Exit ; Invalid character height\r
+ mov [mx_FontWidth], bx\r
+ mov [mx_FontHeight], dx\r
+ mov ax, bx\r
+ add ax, 7\r
+ .shr ax, 3\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov ax, WORD PTR Font[0]\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov ax, WORD PTR Font[2]\r
+ mov WORD PTR mx_FontPtr[2], ax\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetFont ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+; Color = text color (foreground + background*256)\r
+; Op = raster op\r
+; Output:\r
+; none\r
+;\r
+mxSetTextColor PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [Color]\r
+ mov [mx_FontColor], ax\r
+ mov ax, [Op]\r
+ mov [mx_FontOp], ax\r
+\r
+ xor ax, ax\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetTextColor ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+; X, Y = video coordinates\r
+; C = character to print\r
+; Output:\r
+; none\r
+;\r
+mxOutChar PROC FAR\r
+ ARG C:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \\r
+ Count:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+ lds si, DWORD PTR [mx_FontPtr]\r
+ mov al, [C]\r
+ xor ah, ah\r
+ mul [mx_FontCharSize] ; Offset into font\r
+ add si, ax ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [Image]\r
+ mov dx, [mx_FontColor]\r
+ mov ax, [mx_FontHeight]\r
+ mov [Count], ax\r
+@@HeightLoop:\r
+ mov cx, [mx_FontWidth]\r
+ mov bh, ds:[si]\r
+ inc si ; Get a byte from font data\r
+ cmp cx, 8\r
+ jbe @@WidthLoop ; Ok for width <= 8\r
+ mov bl, ds:[si] ; Get another byte\r
+ inc si\r
+@@WidthLoop:\r
+ mov al, dl ; Assume foreground color\r
+ shl bx, 1 ; Is font bit set?\r
+ jc @@1 ; Yes, foreground is just great\r
+ mov al, dh ; Get background color\r
+@@1:\r
+ mov es:[di], al ; Put pixel into image\r
+ inc di\r
+ dec cx\r
+ jnz @@WidthLoop\r
+ dec [Count]\r
+ jnz @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+ lea ax, [Image]\r
+ push es\r
+ push ax ; Pointer to image\r
+ push [X]\r
+ push [Y] ; Image coordinates\r
+ push [mx_FontWidth]\r
+ push [mx_FontHeight] ; Image size\r
+ push [mx_FontOp] ; Raster op\r
+ call mxPutImage ; Write character\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxOutChar ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+; X, Y = text coordinates\r
+; S = pointer to ASCIIZ string\r
+; Output:\r
+; none\r
+;\r
+mxOutText PROC FAR\r
+ ARG S:DWORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [S]\r
+@@Loop:\r
+ mov al, ds:[si]\r
+ test al, al ; End of string?\r
+ jz @@Exit ; Yes, exit\r
+ inc si\r
+ push [X] ; Display character\r
+ push [Y]\r
+ push ax\r
+ call mxOutChar\r
+ mov ax, [mx_DeltaX]\r
+ add [X], ax ; Bump X coordinate\r
+ mov ax, [mx_DeltaY]\r
+ add [Y], ax ; Bump Y coordinate\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+ ret\r
+mxOutText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = horizontal distance in pixels\r
+; DeltaY = vertical distance in pixels\r
+; Output:\r
+; none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep PROC FAR\r
+ ARG DeltaY:WORD, \\r
+ DeltaX:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [DeltaX]\r
+ mov [mx_DeltaX], ax\r
+ mov ax, [DeltaY]\r
+ mov [mx_DeltaY], ax\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetTextStep ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = pointer to horizontal distance in pixels (integer)\r
+; DeltaY = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+; none\r
+;\r
+mxGetTextStep PROC FAR\r
+ ARG DeltaY:DWORD, \\r
+ DeltaX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [mx_DeltaX]\r
+ lds si, [DeltaX]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_DeltaY]\r
+ lds si, [DeltaY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetTextStep ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPB.ASM - Scan buffer for convex polygon fills\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mx_ScanBuffer\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+ALIGN 4\r
+\r
+mx_ScanBuffer LABEL\r
+ DW POLYSCANBUFSIZE DUP(?)\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFillPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT STRUC\r
+ X DW ?\r
+ Y DW ?\r
+TPOINT ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN STRUC\r
+ Y1 DW ?\r
+ Y2 DW ?\r
+TSCAN ENDS\r
+\r
+MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+EXTRN mx_ScanBuffer : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+;\r
+; Input:\r
+; DS:BX = pointer to start point (X1, Y1)\r
+; DS:SI = pointer to end point (X2, Y2)\r
+; ES:DI = pointer to edge buffer\r
+; Output:\r
+; ES:DI = updated pointer to edge buffer\r
+; Notes:\r
+; must preserve DS:SI.\r
+;\r
+subScan PROC NEAR\r
+ mov cx, ds:[si].X\r
+ sub cx, ds:[bx].X ; Get width\r
+ jg @@1\r
+ ret\r
+@@1:\r
+ push bp ; Save BP\r
+\r
+ mov ax, ds:[si].Y\r
+ mov bx, ds:[bx].Y\r
+ sub ax, bx ; Get height\r
+ jg @@T2B ; Scan top to bottom\r
+ jl @@B2T ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+ mov ax, bx\r
+@@V:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@V\r
+ jmp @@Exit\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@T2BLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@T2BLoop\r
+ jmp @@Exit\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+@@B2TLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@B2TLoop\r
+\r
+@@Exit:\r
+ pop bp ; Restore BP\r
+ ret\r
+subScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+;\r
+; Input:\r
+; Count = number of vertexes\r
+; Map = indexes of points and colors (integer)\r
+; Points = array of points (integer X, Y coordinates)\r
+; Color = base color\r
+; Output:\r
+; none\r
+; Notes:\r
+; vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxFillPoly PROC FAR\r
+ ARG Color:WORD, \\r
+ Points:DWORD, \\r
+ Map:DWORD, \\r
+ Count:WORD = ARG_SIZE\r
+ LOCAL WritePlane:BYTE:2, \\r
+ ScanOffsetT:WORD, \\r
+ ScanOffsetB:WORD, \\r
+ ScanCount:WORD, \\r
+ Holder:WORD, \\r
+ Height:WORD, \\r
+ MinIdxT:WORD, \\r
+ MinIdxB:WORD, \\r
+ MaxIdx:WORD, \\r
+ Width:WORD, \\r
+ BoxX1:WORD, \\r
+ BoxY1:WORD, \\r
+ BoxX2:WORD, \\r
+ BoxY2::WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+ mov cx, [Count]\r
+ cmp cx, 3\r
+ jb @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+ les di, [Map]\r
+ lds si, [Points] ; Pointer to vertex array\r
+ mov [BoxX1], 32767\r
+ mov [BoxX2], -32768\r
+ mov [BoxY1], 32767\r
+ mov [BoxY2], -32768\r
+\r
+ xor dx, dx\r
+@@MinMaxLoop:\r
+ mov bx, es:[di] ; Get index of vertex\r
+ .shl bx, 2 ; Get offset in point array\r
+ add bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+ mov ax, ds:[bx].X ; Get X coordinate\r
+ cmp ax, [BoxX1]\r
+ jge @@CheckMaxX\r
+ mov [BoxX1], ax\r
+ mov [MinIdxT], dx\r
+ mov [MinIdxB], dx\r
+@@CheckMaxX:\r
+ cmp ax, [BoxX2]\r
+ jle @@CheckMinY\r
+ mov [BoxX2], ax\r
+ mov [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+ mov ax, ds:[bx].Y\r
+ cmp ax, [BoxY1]\r
+ jge @@CheckMaxY\r
+ mov [BoxY1], ax\r
+@@CheckMaxY:\r
+ cmp ax, [BoxY2]\r
+ jle @@CheckDone\r
+ mov [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+ inc di ; Next map entry\r
+ inc dx\r
+ inc di\r
+ inc dx\r
+ dec cx\r
+ jnz @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+ mov ax, [BoxX2]\r
+ cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxX1]\r
+ cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get width\r
+ jle @@Exit ; Exit if not positive\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxY1]\r
+ cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get height\r
+ jle @@Exit ; Exit if not positive\r
+\r
+ dec [Count]\r
+ shl [Count], 1 ; We'll work with word offsets\r
+ mov es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+ mov ax, OFFSET mx_ScanBuffer\r
+ mov [ScanOffsetT], ax\r
+ mov si, [MinIdxT] ; Offset of bottom point index\r
+@@STLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of top point #1\r
+ dec si ; Next point\r
+ dec si\r
+ test si, si\r
+ jnl @@ST1\r
+ mov si, [Count]\r
+@@ST1:\r
+ mov [MinIdxT], si ; Save new index of top point\r
+ mov si, ds:[bx+si] ; Get index of top point #2\r
+ .shl di, 2 ; Convert indexes to offsets\r
+ .shl si, 2\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetT]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetT], di\r
+ mov si, [MinIdxT]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@STLoop ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+ mov ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+ mov [ScanOffsetB], ax\r
+ mov si, [MinIdxB] ; Offset of bottom point index\r
+@@SBLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of bottom point #1\r
+ inc si ; Next bottom point\r
+ inc si\r
+ cmp si, [Count]\r
+ jbe @@SB1\r
+ xor si, si\r
+@@SB1:\r
+ mov [MinIdxB], si ; Save new index of bottom point\r
+ mov si, ds:[bx+si] ; Get index of bottom point #2\r
+ .shl di, 2 ; Convert indexes to offsets\r
+ .shl si, 2\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetB]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetB], di\r
+ mov si, [MinIdxB]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@SBLoop ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+ mov si, OFFSET mx_ScanBuffer\r
+ mov ax, [BoxX1]\r
+ mov cx, [BoxX2]\r
+ sub cx, ax ; CX = bounding box width\r
+ mov bx, [mx_ClipX1]\r
+ sub bx, ax\r
+ jle @@ClipL1 ; No need to clip left\r
+ sub cx, bx ; Update width\r
+ add ax, bx ; BoxX1 = mx_ClipX1\r
+ mov [BoxX1], ax\r
+ .shl bx, 2 ; Warning!!! This is an hand-coded\r
+ add si, bx ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+ mov bx, ax\r
+ add bx, cx ; Last scan column\r
+ sub bx, [mx_ClipX2]\r
+ jle @@ClipL2 ; No need to clip right\r
+ sub cx, bx ; Clip right\r
+@@ClipL2:\r
+ test cx, cx ; Is clipped width positive?\r
+ jle @@Exit ; No, exit\r
+ mov [ScanCount], cx ; Save number of columns to draw\r
+ mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
+ mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+ mov ax, [BoxY1]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@ClipTB ; Need to clip top\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@ClipTB ; Need to clip bottom\r
+ jmp @@ClipYExit ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+ mov di, cx ; DI = scan count\r
+ inc di ; Increment count for pre-loop test\r
+ sub si, SIZE TSCAN\r
+@@ClipYLoop:\r
+ dec di ; Any column left?\r
+ jz @@ClipYExit ; No, exit\r
+ add si, SIZE TSCAN\r
+ mov ax, ds:[si].Y1 ; Y1\r
+ mov cx, ds:[si].Y2 ; Y2\r
+ mov dx, [mx_ClipY2]\r
+ cmp ax, dx ; Full clipped?\r
+ jg @@ClipYClip ; Yes, skip this column\r
+ cmp cx, dx ; Need to clip bottom?\r
+ jle @@ClipY1 ; No, continue\r
+; Clip bottom\r
+ mov ds:[si].Y2, dx\r
+ mov bx, cx\r
+ sub bx, dx ; Clip distance\r
+ sub cx, ax ; Height\r
+ jle @@ClipYClip\r
+ mov cx, ds:[si].Y2\r
+@@ClipY1:\r
+ mov dx, [mx_ClipY1]\r
+ cmp cx, dx ; Full top clipped?\r
+ jl @@ClipYClip ; Yes, skip\r
+ sub cx, ax ; Get height\r
+ jle @@ClipYClip ; Skip if not positive\r
+ cmp ax, dx ; Need to clip top?\r
+ jge @@ClipYLoop ; No, continue\r
+; Clip top\r
+ mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
+ sub dx, ax ; DX = number of pixels clipped\r
+ cmp cx, dx\r
+ ja @@ClipYLoop ; Not clipped, continue\r
+@@ClipYClip:\r
+ mov ds:[si].Y1, -1 ; Mark column as clipped\r
+ jmp @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+ mov es, [mx_VideoSegment]\r
+ mov si, [ScanOffsetT]\r
+ mov cl, BYTE PTR [BoxX1] ; Init write plane\r
+ and cl, 03h\r
+ mov al, 11h\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+ .shr [BoxX1], 2\r
+@@DrawLoop:\r
+ mov ax, ds:[si].Y1\r
+ test ax, ax ; Was column clipped?\r
+ js @@DrawNext ; Yes, skip\r
+ mov cx, ds:[si].Y2\r
+ sub cx, ax ; CX = height\r
+ jle @@DrawNext\r
+ mul [mx_BytesPerLine] ; Get pixel address\r
+ add ax, [BoxX1]\r
+ mov di, ax\r
+ mov ah, [WritePlane]\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax\r
+ mov ax, [Color]\r
+ mov dx, [mx_BytesPerLine]\r
+ shr cx, 1\r
+ jnc @@FillScan\r
+ mov es:[di], al\r
+ add di, dx\r
+ jcxz @@DrawNext\r
+@@FillScan:\r
+ mov es:[di], al\r
+ add di, dx\r
+ mov es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jnz @@FillScan\r
+@@DrawNext:\r
+ rol [WritePlane], 1\r
+ adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
+ add si, SIZE TSCAN\r
+ dec [ScanCount]\r
+ jnz @@DrawLoop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxFillPoly ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill with Gouraud shading\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGouraudPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT STRUC\r
+ X DW ?\r
+ Y DW ?\r
+TPOINT ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN STRUC\r
+ Y1 DW ?\r
+ E1 DB ?\r
+ C1 DB ?\r
+ Y2 DW ?\r
+ E2 DB ?\r
+ C2 DB ?\r
+TSCAN ENDS\r
+\r
+MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+EXTRN mx_ScanBuffer : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+; Also interpolates color for shading.\r
+;\r
+; Input:\r
+; DS:BX = pointer to start point (X1, Y1)\r
+; DS:SI = pointer to end point (X2, Y2)\r
+; ES:DI = pointer to edge buffer\r
+; DX = start color\r
+; AX = end color\r
+; Output:\r
+; ES:DI = updated pointer to edge buffer\r
+; Notes:\r
+; must preserve DS:SI.\r
+;\r
+subScan PROC NEAR\r
+ mov cx, ds:[si].X\r
+ sub cx, ds:[bx].X ; Get width\r
+ jg @@1\r
+ ret\r
+@@1:\r
+ push bp ; Save BP\r
+ push di ; Save scan info offset\r
+ push cx ; Save height\r
+ push ax ; Save colors\r
+ push dx\r
+\r
+ mov ax, ds:[si].Y\r
+ mov bx, ds:[bx].Y\r
+ sub ax, bx ; Get height\r
+ jg @@T2B ; Scan top to bottom\r
+ jl @@B2T ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+ mov ax, bx\r
+@@V:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@V\r
+ jmp @@GetColorInfo\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@T2BLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@T2BLoop\r
+ jmp @@GetColorInfo\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+@@B2TLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@B2TLoop\r
+\r
+; Now get the color info\r
+@@GetColorInfo:\r
+ pop bx ; Restore colors\r
+ pop ax\r
+ pop cx ; Height\r
+ pop di ; ES:DI -> scan info\r
+\r
+ sub ax, bx ; Get color range\r
+ jg @@CL2R\r
+ jl @@CR2L\r
+\r
+; Special case: same color\r
+ mov ah, bl\r
+ mov al, 80h\r
+@@CV:\r
+ mov WORD PTR es:[di].E1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@CV\r
+ jmp @@Exit\r
+\r
+; Scan left to right\r
+@@CL2R:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@CL2RLoop:\r
+ mov es:[di].C1, al\r
+ mov es:[di].E1, dh\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@CL2RLoop\r
+ jmp @@Exit\r
+\r
+; Scan right to left\r
+@@CR2L:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+\r
+@@CR2LLoop:\r
+ mov es:[di].C1, al\r
+ mov es:[di].E1, dh\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@CR2LLoop\r
+\r
+@@Exit:\r
+ pop bp\r
+ ret\r
+subScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a scan column.\r
+;\r
+; Input:\r
+; DS:SI = current TSCAN\r
+; ES:DI = address of top pixel\r
+; CX = number of pixels to write\r
+; DX = base color\r
+; Output:\r
+; none\r
+;\r
+subFillScan PROC NEAR\r
+ mov ax, WORD PTR ds:[si].E2\r
+ mov bx, WORD PTR ds:[si].E1\r
+ cmp ah, bh\r
+ jg @@L2R ; Color increases\r
+ jl @@R2L ; Color decreases\r
+\r
+; Special case: color doesn't change\r
+ add ax, dx\r
+ mov dx, [mx_BytesPerLine]\r
+@@V:\r
+ mov es:[di], ah\r
+ add di, dx\r
+ dec cx\r
+ jnz @@V\r
+ ret\r
+\r
+; Color increases\r
+@@L2R:\r
+ .push bp, si\r
+ mov si, bx\r
+ add si, dx ; Relocate color\r
+ sub ax, bx\r
+ xor dx, dx\r
+ div cx\r
+ mov bp, ax ; BP = color step, integer part\r
+ xor ax, ax\r
+ div cx\r
+ mov bx, ax ; BX = color step, fractional part\r
+ mov dx, 8000h\r
+ mov ax, [mx_BytesPerLine]\r
+ xchg si, ax\r
+@@L2RLoop:\r
+ mov es:[di], ah\r
+ add dx, bx\r
+ adc ax, bp\r
+ add di, si\r
+ dec cx\r
+ jnz @@L2RLoop\r
+ .pop bp, si\r
+ ret\r
+\r
+; Color decreases\r
+@@R2L:\r
+ .push bp, si\r
+ mov si, bx\r
+ add si, dx ; Relocate color\r
+ sub ax, bx\r
+ neg ax\r
+ xor dx, dx\r
+ div cx\r
+ mov bp, ax ; BP = color step, integer part\r
+ xor ax, ax\r
+ div cx\r
+ mov bx, ax ; BX = color step, fractional part\r
+ mov dx, 8000h\r
+ mov ax, [mx_BytesPerLine]\r
+ xchg si, ax\r
+@@R2LLoop:\r
+ mov es:[di], ah\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ add di, si\r
+ dec cx\r
+ jnz @@R2LLoop\r
+ .pop bp, si\r
+ ret\r
+subFillScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+; Interpolates pixel colors using the Gouraud algorithm.\r
+;\r
+; Input:\r
+; Count = number of vertexes\r
+; Map = indexes of points and colors (integer)\r
+; Points = array of points (integer X, Y coordinates)\r
+; Colors = array of colors (integer)\r
+; Color = base color\r
+; Output:\r
+; none\r
+; Notes:\r
+; vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxGouraudPoly PROC FAR\r
+ ARG Color:WORD, \\r
+ Colors:DWORD, \\r
+ Points:DWORD, \\r
+ Map:DWORD, \\r
+ Count:WORD = ARG_SIZE\r
+ LOCAL WritePlane:BYTE:2, \\r
+ ScanOffsetT:WORD, \\r
+ ScanOffsetB:WORD, \\r
+ ScanCount:WORD, \\r
+ Holder:WORD, \\r
+ Height:WORD, \\r
+ MinIdxT:WORD, \\r
+ MinIdxB:WORD, \\r
+ MaxIdx:WORD, \\r
+ Width:WORD, \\r
+ BoxX1:WORD, \\r
+ BoxY1:WORD, \\r
+ BoxX2:WORD, \\r
+ BoxY2::WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+ mov cx, [Count]\r
+ cmp cx, 3\r
+ jb @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+ les di, [Map]\r
+ lds si, [Points] ; Pointer to vertex array\r
+ mov [BoxX1], 32767\r
+ mov [BoxX2], -32768\r
+ mov [BoxY1], 32767\r
+ mov [BoxY2], -32768\r
+\r
+ xor dx, dx\r
+@@MinMaxLoop:\r
+ mov bx, es:[di] ; Get index of vertex\r
+ .shl bx, 2 ; Get offset in point array\r
+ add bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+ mov ax, ds:[bx].X ; Get X coordinate\r
+ cmp ax, [BoxX1]\r
+ jge @@CheckMaxX\r
+ mov [BoxX1], ax\r
+ mov [MinIdxT], dx\r
+ mov [MinIdxB], dx\r
+@@CheckMaxX:\r
+ cmp ax, [BoxX2]\r
+ jle @@CheckMinY\r
+ mov [BoxX2], ax\r
+ mov [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+ mov ax, ds:[bx].Y\r
+ cmp ax, [BoxY1]\r
+ jge @@CheckMaxY\r
+ mov [BoxY1], ax\r
+@@CheckMaxY:\r
+ cmp ax, [BoxY2]\r
+ jle @@CheckDone\r
+ mov [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+ inc di ; Next map entry\r
+ inc di\r
+ inc dx\r
+ inc dx\r
+ dec cx\r
+ jnz @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+ mov ax, [BoxX2]\r
+ cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxX1]\r
+ cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get width\r
+ jle @@Exit ; Exit if not positive\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxY1]\r
+ cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get height\r
+ jle @@Exit ; Exit if not positive\r
+\r
+ dec [Count]\r
+ shl [Count], 1 ; We'll work with word offsets\r
+ mov es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+ mov ax, OFFSET mx_ScanBuffer\r
+ mov [ScanOffsetT], ax\r
+ mov si, [MinIdxT] ; Offset of bottom point index\r
+@@STLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of top point #1\r
+ dec si ; Next point\r
+ dec si\r
+ test si, si\r
+ jnl @@ST1\r
+ mov si, [Count]\r
+@@ST1:\r
+ mov [MinIdxT], si ; Save new index of top point\r
+ mov si, ds:[bx+si] ; Get index of top point #2\r
+ lds bx, [Colors] ; Get pointer to color array\r
+ shl di, 1 ; Convert indexes to offsets\r
+ shl si, 1\r
+ mov ax, ds:[bx+si] ; Get colors\r
+ mov dx, ds:[bx+di]\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ shl si, 1\r
+ shl di, 1\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetT]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetT], di\r
+ mov si, [MinIdxT]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@STLoop ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+ mov ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+ mov [ScanOffsetB], ax\r
+ mov si, [MinIdxB] ; Offset of bottom point index\r
+@@SBLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of bottom point #1\r
+ inc si ; Next bottom point\r
+ inc si\r
+ cmp si, [Count]\r
+ jbe @@SB1\r
+ xor si, si\r
+@@SB1:\r
+ mov [MinIdxB], si ; Save new index of bottom point\r
+ mov si, ds:[bx+si] ; Get index of bottom point #2\r
+ lds bx, [Colors] ; Get pointer to color array\r
+ shl di, 1 ; Convert indexes to offsets\r
+ shl si, 1\r
+ mov ax, ds:[bx+si] ; Get colors\r
+ mov dx, ds:[bx+di]\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ shl si, 1\r
+ shl di, 1\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetB]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetB], di\r
+ mov si, [MinIdxB]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@SBLoop ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+ mov si, OFFSET mx_ScanBuffer\r
+ mov ax, [BoxX1]\r
+ mov cx, [BoxX2]\r
+ sub cx, ax ; CX = bounding box width\r
+ mov bx, [mx_ClipX1]\r
+ sub bx, ax\r
+ jle @@ClipL1 ; No need to clip left\r
+ sub cx, bx ; Update width\r
+ add ax, bx ; BoxX1 = mx_ClipX1\r
+ mov [BoxX1], ax\r
+ .shl bx, 3 ; Warning!!! This is an hand-coded\r
+ add si, bx ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+ mov bx, ax\r
+ add bx, cx ; Last scan column\r
+ sub bx, [mx_ClipX2]\r
+ jle @@ClipL2 ; No need to clip right\r
+ sub cx, bx ; Clip right\r
+@@ClipL2:\r
+ test cx, cx ; Is clipped width positive?\r
+ jle @@Exit ; No, exit\r
+ mov [ScanCount], cx ; Save number of columns to draw\r
+ mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
+ mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+ mov ax, [BoxY1]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@ClipTB ; Need to clip top\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@ClipTB ; Need to clip bottom\r
+ jmp @@ClipYExit ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+ mov di, cx ; DI = scan count\r
+ inc di ; Increment count for pre-loop test\r
+ sub si, SIZE TSCAN\r
+@@ClipYLoop:\r
+ dec di ; Any column left?\r
+ jz @@ClipYExit ; No, exit\r
+ add si, SIZE TSCAN\r
+ mov ax, ds:[si].Y1 ; Y1\r
+ mov cx, ds:[si].Y2 ; Y2\r
+ mov dx, [mx_ClipY2]\r
+ cmp ax, dx ; Full clipped?\r
+ jg @@ClipYClip ; Yes, skip this column\r
+ cmp cx, dx ; Need to clip bottom?\r
+ jle @@ClipY1 ; No, continue\r
+; Clip bottom, need to scale colors too\r
+ mov ds:[si].Y2, dx\r
+ mov bx, cx\r
+ sub bx, dx ; Clip distance\r
+ sub cx, ax ; Height\r
+ jle @@ClipYClip\r
+ mov ax, WORD PTR ds:[si].E1\r
+ sub ax, WORD PTR ds:[si].E2\r
+ imul bx\r
+ idiv cx\r
+ add WORD PTR ds:[si].E2, ax\r
+ mov ax, ds:[si].Y1 ; Restore AX and CX\r
+ mov cx, ds:[si].Y2\r
+@@ClipY1:\r
+ mov dx, [mx_ClipY1]\r
+ cmp cx, dx ; Full top clipped?\r
+ jl @@ClipYClip ; Yes, skip\r
+ sub cx, ax ; Get height\r
+ jle @@ClipYClip ; Skip if not positive\r
+ cmp ax, dx ; Need to clip top?\r
+ jge @@ClipYLoop ; No, continue\r
+; Clip top, need to scale colors too\r
+ mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
+ sub dx, ax ; DX = number of pixels clipped\r
+ cmp cx, dx\r
+ jbe @@ClipYClip ; Full clipped, skip\r
+ mov ax, WORD PTR ds:[si].E2\r
+ sub ax, WORD PTR ds:[si].E1 ; AX = color distance\r
+ imul dx\r
+ idiv cx\r
+ add WORD PTR ds:[si].E1, ax ; Update starting color\r
+ jmp @@ClipYLoop\r
+@@ClipYClip:\r
+ mov ds:[si].Y1, -1 ; Mark column as clipped\r
+ jmp @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+ mov es, [mx_VideoSegment]\r
+ mov si, [ScanOffsetT]\r
+ mov cl, BYTE PTR [BoxX1] ; Init write plane\r
+ and cl, 03h\r
+ mov al, 11h\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+ .shr [BoxX1], 2\r
+ mov ax, [Color] ; Make 8:8 fixed color\r
+ mov ah, al\r
+ xor al, al\r
+ mov [Color], ax\r
+@@DrawLoop:\r
+ mov ax, ds:[si].Y1\r
+ test ax, ax ; Was column clipped?\r
+ js @@DrawNext ; Yes, skip\r
+ mov cx, ds:[si].Y2\r
+ sub cx, ax ; CX = height\r
+ jle @@DrawNext\r
+ mul [mx_BytesPerLine] ; Get pixel address\r
+ add ax, [BoxX1]\r
+ mov di, ax\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax\r
+ mov dx, [Color]\r
+ call subFillScan\r
+@@DrawNext:\r
+ rol [WritePlane], 1\r
+ adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
+ add si, SIZE TSCAN\r
+ dec [ScanCount]\r
+ jnz @@DrawLoop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGouraudPoly ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove PROC NEAR\r
+ shr cx, 1 ; Make CX even\r
+ jc @@Odd ; Special case if odd byte\r
+@@Loop: movsb\r
+ add si, 3\r
+ movsb\r
+ add si, 3\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: movsb\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ and es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ and es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ or es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ or es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ xor es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ xor es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip: inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+ ret\r
+subAdd ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxPutImage PROC FAR\r
+ ARG Op:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+ mov cl, [ReadPlane]\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov si, WORD PTR Image[0]\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov di, [PixelOffset]\r
+@@Loop:\r
+ push si\r
+ push di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+ mov ah, [OpInfo] ; Transparent color for subTrans\r
+ call [MoveFunction]\r
+ pop di\r
+ pop si\r
+ add si, [Width] ; Go to next image line\r
+ add di, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ rol [WritePlane], 1\r
+ adc [PixelOffset], 0\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPan\r
+\r
+EXTRN mxWaitDisplay : FAR\r
+EXTRN mxStartAddress : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+; X, Y = new X, Y coordinates of view screen\r
+; Output:\r
+; none\r
+;\r
+mxPan PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov ax, [Y]\r
+ mul [mx_BytesPerLine]\r
+ mov dx, [X]\r
+ shr dx, 1\r
+ shr dx, 1\r
+ add ax, dx\r
+ push ax ; Push the start address\r
+ call mxWaitDisplay\r
+ call mxStartAddress\r
+\r
+ mov dx, 03DAh ; Set the pixel pan register\r
+ in al, dx\r
+ mov dx, 03C0h\r
+ mov al, 33h\r
+ out dx, al\r
+ mov al, BYTE PTR [X]\r
+ and al, 3\r
+ shl al, 1\r
+ out dx, al\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxPan ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPP.ASM - Get/put pixel functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetPixel\r
+PUBLIC mxPutPixel\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets a pixel.\r
+;\r
+; Input:\r
+; X, Y = pixel coordinates\r
+; Output:\r
+; pixel color\r
+;\r
+mxGetPixel PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ xor ax, ax\r
+ mov si, [X]\r
+ cmp si, [mx_ClipX1]\r
+ jl @@Exit\r
+ cmp si, [mx_ClipX2]\r
+ jg @@Exit\r
+ mov bx, [Y]\r
+ cmp bx, [mx_ClipY1]\r
+ jl @@Exit\r
+ cmp bx, [mx_ClipY2]\r
+ jg @@Exit\r
+\r
+ mov al, 04h ; Set read plane\r
+ mov ah, BYTE PTR [X]\r
+ and ah, 3\r
+ mov dx, GDC\r
+ out dx, ax\r
+\r
+ mov ds, [mx_VideoSegment]\r
+ mov ax, bx\r
+ mul [mx_BytesPerLine]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+ mov al, ds:[si] ; Get pixel value\r
+ xor ah, ah\r
+\r
+@@Exit:\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetPixel ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Puts a pixel of the specified color.\r
+;\r
+; Input:\r
+; X, Y = pixel coordinates\r
+; Color = pixel color\r
+; Output:\r
+; none\r
+;\r
+mxPutPixel PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov si, [X]\r
+ cmp si, [mx_ClipX1]\r
+ jl @@Exit\r
+ cmp si, [mx_ClipX2]\r
+ jg @@Exit\r
+ mov ax, [Y]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@Exit\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@Exit\r
+\r
+ mov ds, [mx_VideoSegment]\r
+ mul [mx_BytesPerLine]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+ mov cl, BYTE PTR [X] ; Set write plane\r
+ and cl, 3\r
+ mov ax, 0102h\r
+ shl ah, cl\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ mov al, [Color] ; Write pixel\r
+ mov ds:[si], al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxPutPixel ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXRA.ASM - Row address\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxRowAddress\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the row address register.\r
+;\r
+; Input:\r
+; RowAddress = row size in words\r
+; Output:\r
+; none\r
+;\r
+mxRowAddress PROC FAR\r
+ ARG RowAddress:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ mov dx, CRTC\r
+ mov al, 13h\r
+ mov ah, [RowAddress]\r
+ out dx, ax\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxRowAddress ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXRP.ASM - Rotate palette function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxRotatePalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates the palette of the specified number of colors.\r
+;\r
+; Input:\r
+; Palette = pointer to palette\r
+; Count = number of colors to rotate\r
+; Step = step size\r
+; Output:\r
+; none\r
+;\r
+; Note: if Step is positive palette is rotated left to right, otherwise\r
+; right to left.\r
+;\r
+mxRotatePalette PROC FAR\r
+ ARG Step:WORD, \\r
+ Count:WORD, \\r
+ Palette:DWORD = ARG_SIZE\r
+ LOCAL Holder:BYTE:768 = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov bx, [Count]\r
+ add bx, bx\r
+ add bx, [Count] ; BX = Count*3\r
+\r
+ lds si, [Palette] ; DS:SI -> palette\r
+ push ss\r
+ pop es\r
+ lea di, Holder ; ES:DI -> local space\r
+ cld\r
+\r
+ mov ax, [Step]\r
+ mov dx, ax\r
+ test ax, ax\r
+ jz @@Exit ; Nothing to do, exit\r
+ jl @@RightToLeft\r
+\r
+@@LeftToRight:\r
+ add ax, ax\r
+ add dx, ax ; DX = Step*3\r
+ sub bx, dx ; BX = (Count-Step)*3\r
+ add si, bx\r
+ push si\r
+ mov cx, dx\r
+ rep movsb\r
+ mov es, WORD PTR Palette[2]\r
+ mov di, si\r
+ dec di ; ES:DI -> last byte of palette\r
+ pop si\r
+ dec si\r
+ mov cx, bx\r
+ std\r
+ rep movsb\r
+ push ss\r
+ pop ds\r
+ lea si, Holder\r
+ les di, [Palette]\r
+ mov cx, dx\r
+ cld\r
+ rep movsb\r
+ jmp @@Exit\r
+\r
+@@RightToLeft:\r
+ add ax, ax\r
+ add dx, ax\r
+ neg dx ; DX = Step*3\r
+ sub bx, dx ; BX = (Count-Step)*3\r
+ mov cx, dx\r
+ rep movsb\r
+ les di, [Palette]\r
+ mov cx, bx\r
+ rep movsb\r
+ push ss\r
+ pop ds\r
+ lea si, Holder\r
+ mov cx, dx\r
+ rep movsb\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxRotatePalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSA.ASM - Start address function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStartAddress\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Modifies the starting address of video memory.\r
+;\r
+; Input:\r
+; StartAddr = new start address of video memory\r
+; Output:\r
+; none\r
+;\r
+mxStartAddress PROC FAR\r
+ ARG StartAddr:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov bx, [StartAddr]\r
+ mov dx, CRTC\r
+ mov al, 0Ch ; Linear Starting Address high\r
+ mov ah, bh\r
+ cli\r
+ out dx, ax\r
+ mov al, 0Dh ; Linear Starting Address low\r
+ mov ah, bl\r
+ out dx, ax\r
+ sti\r
+\r
+ .leave ARG_SIZE\r
+mxStartAddress ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSC.ASM - Set color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetColor\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the selected DAC register.\r
+;\r
+; Input:\r
+; Index = index of color to set\r
+; R, G, B = color components\r
+; Output:\r
+; none\r
+;\r
+mxSetColor PROC FAR\r
+ ARG B:BYTE:2, \\r
+ G:BYTE:2, \\r
+ R:BYTE:2, \\r
+ Index:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [Index]\r
+ mov dx, 3C8h ; PEL write address register\r
+ out dx, al\r
+ inc dx\r
+\r
+ mov al, [R]\r
+ out dx, al\r
+ mov al, [G]\r
+ out dx, al\r
+ mov al, [B]\r
+ out dx, al\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxSetColor ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Stretch image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStretchImage\r
+\r
+EXTRN subClipBox : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Stretches and copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; NewWidth = new width of image in pixels\r
+; NewHeight = new height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxStretchImage PROC FAR\r
+ ARG Op:WORD, \\r
+ NewHeight:WORD, \\r
+ NewWidth:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WidthStep:DWORD, \\r
+ HeightStep:DWORD, \\r
+ ImageLo:WORD, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Get width stretch factor\r
+ IF USE386 EQ TRUE\r
+ movzx edx, [Width]\r
+ xor eax, eax\r
+ movzx ebx, [NewWidth]\r
+ shl ebx, 16\r
+ idiv ebx\r
+ mov [WidthStep], eax\r
+ ELSE\r
+ xor dx, dx ; Width stretch factor\r
+ mov ax, [Width]\r
+ mov bx, [NewWidth]\r
+ div bx\r
+ mov WORD PTR WidthStep[2], ax\r
+ xor ax, ax\r
+ div bx\r
+ mov WORD PTR WidthStep[0], ax\r
+ ENDIF\r
+; Get height stretch factor\r
+ IF USE386 EQ TRUE\r
+ movzx edx, [Height]\r
+ xor eax, eax\r
+ movzx ebx, [NewHeight]\r
+ shl ebx, 16\r
+ idiv ebx\r
+ mov [HeightStep], eax\r
+ ELSE\r
+ xor dx, dx\r
+ mov ax, [Height]\r
+ mov bx, [NewHeight]\r
+ div bx\r
+ mov WORD PTR HeightStep[2], ax\r
+ xor ax, ax\r
+ div bx\r
+ mov WORD PTR HeightStep[0], ax\r
+ ENDIF\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [NewWidth]\r
+ mov dx, [NewHeight]\r
+ call subClipBox\r
+ jc @@Exit ; Full clipped\r
+ mov [NewWidth], cx\r
+ mov [NewHeight], dx\r
+ sub [X], bx\r
+ sub [Y], ax\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl ; Set read plane\r
+ mov cl, bl\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al ; Set write plane\r
+\r
+; Relocate image origin if previously clipped\r
+ mov ax, [Y]\r
+ test ax, ax\r
+ jz @@OriginYDone\r
+ IF USE386 EQ TRUE\r
+ shl eax, 16\r
+ imul [HeightStep]\r
+ mov ax, [Width]\r
+ mul dx\r
+ ELSE\r
+ mov bx, ax\r
+ mul WORD PTR HeightStep[0]\r
+ mov cx, dx\r
+ mov ax, bx\r
+ mul WORD PTR HeightStep[2]\r
+ add ax, cx\r
+ mul [Width]\r
+ ENDIF\r
+ add WORD PTR [Image], ax\r
+@@OriginYDone:\r
+ mov ax, [X]\r
+ test ax, ax\r
+ jz @@OriginXDone\r
+ IF USE386 EQ TRUE\r
+ shl eax, 16\r
+ imul [WidthStep]\r
+ add WORD PTR [Image], dx\r
+ ELSE\r
+ mov bx, ax\r
+ mul WORD PTR WidthStep[0]\r
+ mov cx, dx\r
+ mov ax, bx\r
+ mul WORD PTR WidthStep[2]\r
+ add ax, cx\r
+ add WORD PTR [Image], ax\r
+ ENDIF\r
+@@OriginXDone:\r
+ mov ax, WORD PTR HeightStep[2]\r
+ mul [Width]\r
+ mov WORD PTR HeightStep[2], ax\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ mov ds, WORD PTR Image[2]\r
+ xor ax, ax\r
+ mov [ImageLo], ax\r
+@@Loop:\r
+ mov si, WORD PTR Image[0] ; Get pointer to image\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov cx, [NewHeight]\r
+ mov di, [PixelOffset] ; ES:DI points to video memory\r
+ mov ah, [OpInfo] ; Additional raster op info\r
+ xor bx, bx\r
+ mov dx, [mx_BytesPerLine]\r
+ call [MoveFunction] ; Draw column\r
+ inc [ReadPlane] ; Next read plane\r
+ rol [WritePlane], 1 ; Next write plane\r
+ adc [PixelOffset], 0 ; Update video offset if needed\r
+ mov dx, WORD PTR WidthStep[0]\r
+ mov ax, WORD PTR WidthStep[2]\r
+ add [ImageLo], dx\r
+ adc WORD PTR Image[0], ax ; Next image column\r
+ dec [NewWidth]\r
+ jnz @@Loop ; Repeat for all columns\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions, on entry:\r
+; AH = additional raster op info (e.g. transparent color)\r
+; BX = 0,\r
+; CX = pixel count,\r
+; DX = mx_BytesPerLine.\r
+;\r
+subMove PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ mov es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ and es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ or es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ xor es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip:\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subAdd ENDP\r
+\r
+mxStretchImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Start line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStartLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes the video start address to the specified line.\r
+;\r
+; Input:\r
+; Line = new start line\r
+; Output:\r
+; none\r
+;\r
+mxStartLine PROC FAR\r
+ ARG Line:WORD = ARG_SIZE\r
+ .enter 0\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [Line] ; Get video offset\r
+ mul [mx_BytesPerLine]\r
+ xchg ax, bx ; Copy it into BX\r
+\r
+; Wait display\r
+ mov dx, STATUS\r
+@@1: in al, dx\r
+ test al, 08h\r
+ jnz @@1\r
+\r
+; Set starting address\r
+ mov dx, CRTC\r
+ mov al, 0Ch ; Linear Starting Address high\r
+ mov ah, bh\r
+ cli\r
+ out dx, ax\r
+ mov al, 0Dh ; Linear Starting Address low\r
+ mov ah, bl\r
+ out dx, ax\r
+ sti\r
+\r
+; Wait retrace\r
+ mov dx, STATUS\r
+@@2: in al,dx\r
+ test al, 08h\r
+ jz @@2\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxChangeMode\r
+PUBLIC mxGetAspect\r
+PUBLIC mxGetScreenSize\r
+PUBLIC mxSetMode\r
+\r
+PUBLIC mx_ScreenWidth\r
+PUBLIC mx_ScreenHeight\r
+PUBLIC mx_BytesPerLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mxSetSysClipRegion : FAR\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_ScreenWidth DW ? ; Current screen width\r
+mx_ScreenHeight DW ?\r
+mx_AspectX DW ? ; Aspect ratio for current mode\r
+mx_AspectY DW ?\r
+mx_BytesPerLine DW 0 ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine LABEL WORD ; CRTC\r
+ DW 04009h ; Cell height: 1 scan line\r
+ DW 00014h ; Double word mode off\r
+ DW 0E317h ; Byte mode on\r
+ DW 0\r
+TBL_DoubleLine LABEL WORD ; CRTC\r
+ DW 04109h ; Cell height: 2 scan lines\r
+ DW 00014h\r
+ DW 0E317h\r
+ DW 0\r
+TBL_Width320 LABEL WORD ; CRTC\r
+ DW 05F00h ; Horizontal total\r
+ DW 04F01h ; Horizontal displayed\r
+ DW 05002h ; Start horizontal blanking\r
+ DW 08203h ; End horizontal blanking\r
+ DW 05404h ; Start horizontal sync\r
+ DW 08005h ; End horizontal sync\r
+ DW 02813h ; Row address\r
+ DW 0\r
+TBL_Width360 LABEL WORD ; CRTC\r
+ DW 06B00h ; Horizontal total\r
+ DW 05901h ; Horizontal displayed\r
+ DW 05A02h ; Start horizontal blanking\r
+ DW 08E03h ; End horizontal blanking\r
+ DW 05E04h ; Start horizontal sync\r
+ DW 08A05h ; End horizontal sync\r
+ DW 02D13h ; Row address\r
+ DW 0\r
+TBL_Height175 LABEL WORD ; CRTC\r
+ DW 0BF06h ; Vertical total\r
+ DW 01F07h ; Overflow\r
+ DW 08310h ; Start vertical sync\r
+ DW 08511h ; End vertical sync\r
+ DW 05D12h ; Vertical displayed\r
+ DW 06315h ; Start vertical blanking\r
+ DW 0BA16h ; End vertical blanking\r
+ DW 0\r
+TBL_Height200 LABEL WORD ; CRTC\r
+ DW 0BF06h ; Vertical total\r
+ DW 01F07h ; Overflow\r
+ DW 09C10h ; Start vertical sync\r
+ DW 08E11h ; End vertical sync\r
+ DW 08F12h ; Vertical displayed\r
+ DW 09615h ; Start vertical blanking\r
+ DW 0B916h ; End vertical blanking\r
+ DW 0\r
+TBL_Height240 LABEL WORD ; CRTC\r
+ DW 00D06h ; Vertical total\r
+ DW 03E07h ; Overflow\r
+ DW 0EA10h ; Start vertical sync\r
+ DW 08C11h ; End vertical sync\r
+ DW 0DF12h ; Vertical displayed\r
+ DW 0E715h ; Start vertical blanking\r
+ DW 00616h ; End vertical blanking\r
+ DW 0\r
+TBL_Tweak400x600:\r
+ DW 07400h\r
+ DW 06301h\r
+ DW 06402h\r
+ DW 09703h\r
+ DW 06804h\r
+ DW 09505h\r
+ DW 08606h\r
+ DW 0F007h\r
+ DW 06009h\r
+ DW 0310Fh\r
+ DW 05B10h\r
+ DW 08D11h\r
+ DW 05712h\r
+ DW 03213h\r
+ DW 00014h\r
+ DW 06015h\r
+ DW 08016h\r
+ DW 0E317h\r
+ DW 0\r
+\r
+TBL_320x200:\r
+ DB 63h ; 400 scan lines, 25 MHz clock\r
+ DW 6, 5 ; Aspect: 6/5 = 1.2:1\r
+ DW 320, 200 ; Size\r
+ DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x240:\r
+ DB 0E3h ; 400 scan lines, 25 MHz clock\r
+ DW 1, 1 ; Aspect: 1/1 = 1:1\r
+ DW 320, 240 ; Size\r
+ DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x400:\r
+ DB 63h ; 480 scan lines, 25 MHz clock\r
+ DW 6, 10 ; Aspect: 6/10 = 0.6:1\r
+ DW 320, 400 ; Size\r
+ DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x480:\r
+ DB 0E3h ; 480 scan lines, 25 MHz clock\r
+ DW 1, 2 ; Aspect: 1/2 = 0.5:1\r
+ DW 320, 480 ; Size\r
+ DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+ DW 819 ; Max height\r
+TBL_360x200:\r
+ DB 067h ; 400 scan lines, 28 MHz clock\r
+ DW 27, 20 ; Aspect: 27/20 = 1.35:1\r
+ DW 360, 200 ; Size\r
+ DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x240:\r
+ DB 0E7h ; 480 scan lines, 28 MHz clock\r
+ DW 9, 8 ; Aspect: 9/8 = 1.125:1\r
+ DW 360, 240 ; Size\r
+ DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x400:\r
+ DB 067h ; 400 scan lines, 28 MHz clock\r
+ DW 27, 40 ; Aspect: 27/40 = 0.675:1\r
+ DW 360, 400 ; Size\r
+ DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x480:\r
+ DB 0E7h ; 480 scan lines, 28 MHz clock\r
+ DW 9, 16 ; Aspect: 9/16 = 0.5625:1\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_320x175:\r
+ DB 0A3h\r
+ DW 0, 0 ; Aspect:\r
+ DW 320, 175\r
+ DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+ DW 819\r
+TBL_320x350:\r
+ DB 0A3h\r
+ DW 0, 0 ; Aspect:\r
+ DW 320, 175\r
+ DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+ DW 819\r
+TBL_360x175:\r
+ DB 0A7h\r
+ DW 0, 0 ; Aspect:\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x350:\r
+ DB 0A7h\r
+ DW 0, 0 ; Aspect:\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_400x600:\r
+ DB 0E7h ; 28 MHz clock\r
+ DW 1, 2 ; Aspect: 1/2 = 0.5:1\r
+ DW 400, 600 ; Size\r
+ DW TBL_Tweak400x600, 0\r
+ DW 655 ; Max height\r
+\r
+TBL_Mode LABEL WORD\r
+ DW TBL_320x175\r
+ DW TBL_320x200\r
+ DW TBL_320x240\r
+ DW TBL_320x350\r
+ DW TBL_320x400\r
+ DW TBL_320x480\r
+ DW TBL_360x175\r
+ DW TBL_360x200\r
+ DW TBL_360x240\r
+ DW TBL_360x350\r
+ DW TBL_360x400\r
+ DW TBL_360x480\r
+ DW TBL_400x600\r
+\r
+MAXVMODE EQU ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText PROC NEAR\r
+ ASSUME ds:MX_TEXT\r
+ mov ax, 0003h\r
+ int 10h ; Call BIOS set mode\r
+\r
+ mov [mx_ScreenHeight], 0\r
+ mov [mx_BytesPerLine], 0\r
+ ret\r
+subText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+; Mode = mode to select (MX_???x???)\r
+; Output:\r
+; none\r
+;\r
+mxSetMode PROC FAR\r
+ ARG Mode:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov si, [Mode]\r
+ cmp si, MAXVMODE ; Is it a valid mode?\r
+ ja @@Exit ; No, exit\r
+ test si, si ; Text mode?\r
+ jnz @@Set ; No, handle it\r
+\r
+ call subText ; Back to text mode\r
+ jmp @@Exit ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+ dec si ; Skip text mode\r
+ shl si, 1\r
+ mov si, TBL_Mode[si]\r
+ cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+ push si ; Save SI\r
+ mov ax, 0013h\r
+ int 10h ; Use BIOS to set 320x200 linear mode\r
+ pop si ; Restore SI\r
+\r
+ mov dx, TS\r
+ mov ax, 0604h\r
+ out dx, ax ; Disable chain-4 mode\r
+ mov ax, 0100h\r
+ out dx, ax ; Reset\r
+ mov dx, MISC\r
+ lodsb\r
+ out dx, al ; New timing/size\r
+ mov dx, TS\r
+ mov ax, 0300h\r
+ out dx, ax ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ and al, 7Fh ; Clear write protect bit\r
+ out dx, al\r
+\r
+ lodsw ; Get X aspect\r
+ mov [mx_AspectX], ax\r
+ lodsw ; Get Y aspect\r
+ mov [mx_AspectY], ax\r
+ lodsw ; Get screen width\r
+ mov [mx_ScreenWidth], ax\r
+ shr ax, 1\r
+ shr ax, 1 ; Divide by four to get bytes per line\r
+ mov [mx_BytesPerLine], ax\r
+ lodsw ; Get screen height\r
+ mov [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+ mov bx, si\r
+ mov dx, CRTC\r
+@@TableLoop:\r
+ mov si, ds:[bx] ; DS:SI -> table of CRTC registers\r
+ inc bx\r
+ inc bx ; DS:BX -> offset of next table\r
+ test si, si ; Last table?\r
+ jz @@EndLoop ; Yes, exit loop\r
+@@Loop:\r
+ lodsw ; Get CRTC register index and value\r
+ test ax, ax ; End of table?\r
+ jz @@TableLoop ; Yes, go to next table\r
+ out dx, ax ; Set register AL to value AH\r
+ jmp @@Loop ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+ push [mx_ScreenWidth]\r
+ push WORD PTR ds:[bx]\r
+ call mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Enable all planes\r
+ mov es, [mx_VideoSegment]\r
+ xor di, di\r
+ mov cx, 8000h\r
+ xor ax, ax\r
+ rep stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ or al, 80h ; Set write protect bit\r
+ out dx, al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ mov ax, [mx_ScreenWidth]\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxSetMode ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+; Mode = mode to select (MX_???x???)\r
+; Output:\r
+; none\r
+; Notes:\r
+; this function assumes that mxSetMode and mxSetVirtualScreen\r
+; have been called first. View size is rearranged to match the\r
+; specified mode, but video memory is not cleared.\r
+; Differences from mxSetMode:\r
+; - video BIOS is not called to initialize graphics;\r
+; - row address register is not modified;\r
+; - video memory is not cleared;\r
+; - mx_BytesPerLine is not modified;\r
+; - system clip region is not modified.\r
+;\r
+mxChangeMode PROC FAR\r
+ ARG Mode:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov si, [Mode]\r
+ cmp si, MAXVMODE ; Is it a valid mode?\r
+ ja @@Exit ; No, exit\r
+ test si, si ; Text mode?\r
+ jz @@Exit ; Yes, exit\r
+\r
+ dec si ; Skip text mode\r
+ shl si, 1\r
+ mov si, TBL_Mode[si]\r
+ cld\r
+\r
+ mov dx, TS\r
+ mov ax, 0604h\r
+ out dx, ax ; Disable chain-4 mode\r
+ mov ax, 0100h\r
+ out dx, ax ; Reset\r
+ mov dx, MISC\r
+ lodsb\r
+ out dx, al ; New timing/size\r
+ mov dx, TS\r
+ mov ax, 0300h\r
+ out dx, ax ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ and al, 7Fh ; Clear write protect bit\r
+ out dx, al\r
+\r
+ lodsw ; Get X aspect\r
+ mov [mx_AspectX], ax\r
+ lodsw ; Get Y aspect\r
+ mov [mx_AspectY], ax\r
+ lodsw ; Get screen width\r
+ mov [mx_ScreenWidth], ax\r
+ lodsw ; Get screen height\r
+ mov [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+ mov bx, si\r
+ mov dx, CRTC\r
+@@TableLoop:\r
+ mov si, ds:[bx] ; DS:SI -> table of CRTC registers\r
+ inc bx\r
+ inc bx ; DS:BX -> offset of next table\r
+ test si, si ; Last table?\r
+ jz @@EndLoop ; Yes, exit loop\r
+@@Loop:\r
+ lodsw ; Get CRTC register index and value\r
+ test ax, ax ; End of table?\r
+ jz @@TableLoop ; Yes, go to next table\r
+ cmp al, 13h ; Row address register?\r
+ je @@Loop ; Yes, ignore it\r
+ out dx, ax ; Set register AL to value AH\r
+ jmp @@Loop ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ or al, 80h ; Set write protect bit\r
+ out dx, al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ mov ax, [mx_ScreenWidth]\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxChangeMode ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+; AspectX = pointer to aspect X\r
+; AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect PROC FAR\r
+ ARG AspectY:DWORD, \\r
+ AspectX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [AspectX]\r
+ mov ax, [mx_AspectX]\r
+ mov ds:[si], ax\r
+ lds si, [AspectY]\r
+ mov ax, [mx_AspectY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetAspect ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+; Width = pointer to screen width\r
+; Height = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+ ARG SizeY:DWORD, \\r
+ SizeX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [SizeX]\r
+ mov ax, [mx_ScreenWidth]\r
+ mov ds:[si], ax\r
+ lds si, [SizeY]\r
+ mov ax, [mx_ScreenHeight]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSP.ASM - Set palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetPalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to palette data (R,G,B)\r
+; Start = index of first color to set\r
+; Count = number of color to set\r
+; Output:\r
+; none\r
+;\r
+mxSetPalette PROC FAR\r
+ ARG Count:WORD, \\r
+ Start:WORD, \\r
+ Buffer:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ lds si, [Buffer]\r
+ mov cx, [Count]\r
+ mov ax, [Start]\r
+ mov dx, 3C8h ; PEL write address register\r
+ out dx, al\r
+ inc dx\r
+ cld\r
+ cli ; Disable interrupts\r
+@@Loop:\r
+ lodsb\r
+ out dx, al ; Red\r
+ lodsb\r
+ out dx, al ; Green\r
+ lodsb\r
+ out dx, al ; Blue\r
+ loop @@Loop ; Loop until done\r
+ sti ; Enable interrupts\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxSetPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSS.ASM - Split screen function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSplitScreen\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Splits the screen.\r
+;\r
+; Input:\r
+; Line = scan line at which screen has to be splitted\r
+; Output:\r
+; none\r
+;\r
+mxSplitScreen PROC FAR\r
+ ARG Line:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+; Modify the line compare value: bits 0-7 are in the Line Compare\r
+; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7)\r
+; and bit 9 is in the Maximum Row Address register (CRTC #9)\r
+ mov ax, [Line]\r
+ shl ax, 1 ; Adjust line for mode "X"\r
+ mov bh, ah\r
+ mov bl, ah\r
+ and bx, 0201h\r
+ mov cl, 4\r
+ shl bx, cl\r
+ shl bh, 1\r
+ mov dx, CRTC\r
+; Write bits 0-7 to line compare register\r
+ mov ah, al\r
+ mov al, 18h\r
+ out dx, ax\r
+; Write bit 8 to overflow register\r
+ mov al, 07h\r
+ out dx, al\r
+ inc dx\r
+ in al, dx\r
+ dec dx\r
+ mov ah, al\r
+ and ah, 11101111b\r
+ or ah, bl\r
+ mov al, 07h\r
+ out dx, ax\r
+; Write bit 9 to maximum row address register\r
+ mov al, 09h\r
+ out dx, al\r
+ inc dx\r
+ in al, dx\r
+ dec dx\r
+ mov ah, al\r
+ and ah, 10111111b\r
+ or ah, bh\r
+ mov al, 09h\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxSplitScreen ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutTile\r
+PUBLIC mxTransPutTile\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+ shr cx, 1 ; Move line\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutTile ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxTransPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+; Move one line\r
+ jcxz @@MoveLineDone\r
+@@MoveLineLoop:\r
+ mov al, ds:[si]\r
+ test al, al\r
+ jz @@MoveLineNext\r
+ mov es:[di], al\r
+@@MoveLineNext:\r
+ inc si\r
+ inc di\r
+ dec cx\r
+ jnz @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxTransPutTile ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXVS.ASM - Set/get virtual screen\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetVirtualScreen\r
+PUBLIC mxGetVirtualScreen\r
+\r
+EXTRN mxRowAddress : FAR\r
+EXTRN mxSetSysClipRegion : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_VirtualWidth DW ? ; Virtual screen size\r
+mx_VirtualHeight DW ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the virtual screen.\r
+;\r
+; Input:\r
+; Width = virtual screen width\r
+; Height = virtual screen height\r
+; Output:\r
+; 0 on success, else invalid parameters\r
+;\r
+mxSetVirtualScreen PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+\r
+; Set DS to code segment\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, 1 ; Assume an error\r
+ cmp [Width], 320 ; Check width\r
+ jb @@Exit\r
+ push ax ; Save return code\r
+ mov dx, 0004h\r
+ xor ax, ax ; DX:AX = 256K\r
+ div [Width] ; Max height in AX\r
+ cmp [Height], ax\r
+ pop ax ; Restore return code\r
+ ja @@Exit ; Exit if bad heigth\r
+\r
+ mov ax, [Width]\r
+ and ax, 0FFF8h ; Align to byte\r
+ mov [mx_VirtualWidth], ax\r
+ shr ax, 1\r
+ shr ax, 1\r
+ mov [mx_BytesPerLine], ax\r
+ shr ax, 1\r
+ push ax\r
+ call mxRowAddress ; Set row address\r
+ mov ax, [Height]\r
+ mov [mx_VirtualHeight], ax\r
+\r
+ push [Width]\r
+ push [Height]\r
+ call mxSetSysClipRegion\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetVirtualScreen ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current virtual screen size.\r
+;\r
+; Input:\r
+; Width = pointer to virtual screen width\r
+; Height = pointer to virtual screen height\r
+; Output:\r
+; none\r
+;\r
+mxGetVirtualScreen PROC FAR\r
+ ARG Height:DWORD, \\r
+ Width:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [mx_VirtualWidth]\r
+ lds si, [Width]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_VirtualHeight]\r
+ lds si, [Height]\r
+ mov ds:[si], ax\r
+\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetVirtualScreen ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWD.ASM - Wait display function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWaitDisplay\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for display start.\r
+;\r
+mxWaitDisplay PROC FAR\r
+ mov dx, STATUS\r
+@@1: in al, dx\r
+ test al, 08h\r
+ jnz @@1\r
+ ret\r
+mxWaitDisplay ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWM.ASM - Set write mode function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWriteMode\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write mode.\r
+;\r
+; Input:\r
+; Mode = write mode (0,1,2,3)\r
+; Output:\r
+; none\r
+;\r
+mxWriteMode PROC FAR\r
+ ARG Mode:BYTE:2 = ARG_SIZE\r
+ .enter 0\r
+\r
+ mov dx, GDC\r
+ mov ah, [Mode]\r
+ and ah, 00000011b\r
+ or ah, 01000000b\r
+ mov al, 05h\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxWriteMode ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWP.ASM - Set write/read plane functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWritePlane\r
+PUBLIC mxReadPlane\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write plane(s).\r
+;\r
+; Input:\r
+; Plane = write plane(s) to set (bit 0 enables plane 0,\r
+; bit 1 enables plane 1 and so on, different planes\r
+; may be selected at the same time)\r
+; Output:\r
+; none\r
+;\r
+mxWritePlane PROC FAR\r
+ ARG Plane:BYTE:2 = ARG_SIZE\r
+ .enter 0\r
+\r
+ mov ah, [Plane]\r
+ and ah, 00001111b ; Mask off unused bits\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxWritePlane ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the read plane.\r
+;\r
+; Input:\r
+; Plane = read plane to set (0,1,2,3)\r
+; Output:\r
+; none\r
+;\r
+mxReadPlane PROC FAR\r
+ ARG Plane:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ mov al, 04h\r
+ mov ah, [Plane]\r
+ and ah, 0000011b ; Mask off unused bits\r
+ mov dx, GDC\r
+ out dx, ax\r
+ .leave ARG_SIZE\r
+mxReadPlane ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWR.ASM - Wait vertical retrace function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWaitRetrace\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for vertical retrace start.\r
+;\r
+mxWaitRetrace PROC FAR\r
+ mov dx, STATUS\r
+@@1: in al,dx\r
+ test al, 08h\r
+ jz @@1\r
+ ret\r
+mxWaitRetrace ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
xfill.$(OBJ) : xfill.asm# xfill.inc xlib.inc model.inc\r
$(CC) -c $(CFLAGS) xfill.asm# xfill.inc xlib.inc model.inc\r
\r
+xbezier.$(OBJ): xbezier.asm\r
+ $(CC) -c $(CFLAGS) xbezier.asm\r
+\r
#\r
#other~\r
#\r
-/*;IFDEF s\r
+IFDEF s\r
; DISPLAY "XLIB04 Small Model"\r
-; .model small\r
-;ELSE\r
-; IFDEF c\r
+ .model small\r
+ELSE\r
+ IFDEF c\r
; DISPLAY "XLIB04 Compact Model"\r
-; .model compact\r
-; ELSE\r
-; IFDEF l\r
+ .model compact\r
+ ELSE\r
+ IFDEF l\r
; DISPLAY "XLIB04 Large Model"\r
-; .model large\r
-; ELSE\r
+ .model large\r
+ ELSE\r
+ IFDEF h\r
+ .model huge\r
+ ELSE\r
; DISPLAY "WARNING: Model was not defined at the command line."\r
; DISPLAY " Using default small model ie /ds "\r
; DISPLAY " Include in TASM commandline either /ds, /dc or /dl"\r
-;; .model small\r
-; ENDIF\r
-; ENDIF\r
-;ENDIF\r
-*/\r
+ .model small\r
+ ENDIF\r
+ ENDIF\r
+ENDIF\r
\r
$\r
\r
-LOCALS\r
+.LOCALS\r
.8086\r
\r
include model.inc\r
\r
;\r
\r
-;.LOCALS\r
+;.global\r
;.8086\r
\r
; First lets find out what memory model to use\r
-\r
-include model.inc\r
+;.model huge\r
+;include model.inc\r
\r
\r
AC_INDEX equ 03c0h ;Attribute controller index register\r
global _VsyncPaletteStart :word\r
global _VsyncPaletteCount :word\r
global _VsyncPaletteBuffer :byte\r
-\r
-\r
mov dx,[_ScrnLogicalByteWidth]\r
mul dx\r
pop dx\r
- shr bx,2\r
+ shr bx,1\r
+ shr bx,1\r
add bx,ax\r
- add bx,[PgOffs]\r
+ add bx,[bp+14]\r
and cl,3\r
endm\r
\r
;\r
\r
_x_line proc\r
-ARG x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word\r
+;ARG x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word\r
LOCAL vertincr:word,incr1:word,incr2:word,routine:word=LocalStk\r
push bp ; Set up stack frame\r
mov bp,sp\r
; check for vertical line\r
\r
mov si,[_ScrnLogicalByteWidth]\r
- mov cx,[x2]\r
- sub cx,[x1]\r
+ mov cx,[bp+8]\r
+ sub cx,[bp+4]\r
jz VertLine\r
\r
; force x1 < x2\r
\r
neg cx\r
\r
- mov bx,[x2]\r
- xchg bx,[x1]\r
- mov [x2],bx\r
+ mov bx,[bp+8]\r
+ xchg bx,[bp+4]\r
+ mov [bp+8],bx\r
\r
- mov bx,[y2]\r
- xchg bx,[y1]\r
- mov [y2],bx\r
+ mov bx,[bp+10]\r
+ xchg bx,[bp+6]\r
+ mov [bp+10],bx\r
\r
; calc dy = abs(y2 - y1)\r
\r
L01:\r
- mov bx,[y2]\r
- sub bx,[y1]\r
+ mov bx,[bp+10]\r
+ sub bx,[bp+6]\r
jnz short skip\r
jmp HorizLine\r
skip: jns L03\r
; calc first pixel address\r
\r
push cx\r
- mov ax,[y1]\r
- mov bx,[x1]\r
+ mov ax,[bp+6]\r
+ mov bx,[bp+4]\r
ModeXAddr\r
mov di,bx\r
mov al,1\r
shl al,cl\r
mov ah,al ; duplicate nybble\r
- shl al,4\r
+ shl al,1\r
+ shl al,1\r
+ shl al,1\r
+ shl al,1\r
add ah,al\r
mov bl,ah\r
pop cx\r
; routine for verticle lines\r
\r
VertLine:\r
- mov ax,[y1]\r
- mov bx,[y2]\r
+ mov ax,[bp+6]\r
+ mov bx,[bp+10]\r
mov cx,bx\r
sub cx,ax\r
jge L31\r
\r
L31:\r
inc cx\r
- mov bx,[x1]\r
+ mov bx,[bp+4]\r
push cx\r
ModeXAddr\r
\r
mov al,MAP_MASK\r
out dx,ax\r
pop cx\r
- mov ax, word ptr [Color]\r
+ mov ax, word ptr [bp+12]\r
\r
; draw the line\r
\r
HorizLine:\r
push ds\r
\r
- mov ax,[y1]\r
- mov bx,[x1]\r
+ mov ax,[bp+6]\r
+ mov bx,[bp+4]\r
ModeXAddr\r
\r
mov di,bx ; set dl = first byte mask\r
mov dl,00fh\r
shl dl,cl\r
\r
- mov cx,[x2] ; set dh = last byte mask\r
+ mov cx,[bp+8] ; set dh = last byte mask\r
and cl,3\r
mov dh,00eh\r
shl dh,cl\r
\r
; determine byte offset of first and last pixel in line\r
\r
- mov ax,[x2]\r
- mov bx,[x1]\r
+ mov ax,[bp+8]\r
+ mov bx,[bp+4]\r
\r
- shr ax,2 ; set ax = last byte column\r
- shr bx,2 ; set bx = first byte column\r
+ shr ax,1 ; set ax = last byte column\r
+ shr bx,1 ; set bx = first byte column\r
+ shr ax,1 ; set ax = last byte column\r
+ shr bx,1 ; set bx = first byte column\r
mov cx,ax ; cx = ax - bx\r
sub cx,bx\r
\r
mov ax,dx ; mov end byte masks to ax\r
mov dx,SC_INDEX ; setup dx for VGA outs\r
- mov bx, [Color]\r
+ mov bx, [bp+12]\r
\r
; set pixels in leftmost byte of line\r
\r
\r
LoSlopeLine:\r
mov al,MAP_MASK\r
- mov bh,byte ptr [Color]\r
+ mov bh,byte ptr [bp+12]\r
L10:\r
mov ah,bl\r
\r
mov al,MAP_MASK\r
L21: out dx,ax\r
push ax\r
- mov ax,[Color]\r
+ mov ax,[bp+12]\r
mov es:[di],al\r
pop ax\r
add di,bx\r
_x_line endp\r
\r
end\r
-\1a
\ No newline at end of file
; and tripple buffering - Tore Jahn Bastiansen\r
; (toreba@ifi.uio.no) for the\r
;-----------------------------------------------------------------------\r
-\r
-\r
include xlib.inc\r
include xmain.inc\r
\r
\r
- .data\r
+ _DATA SEGMENT WORD PUBLIC USE16 'DATA'\r
+;.data\r
\r
\r
; Mode X CRTC register tweaks for various resolutions\r
\r
\r
-LABEL X256Y200 word\r
+X256Y200 LABEL word\r
db 0e3h ; dot clock\r
db 8 ; Number of CRTC Registers to update\r
dw 05f00h ; horz total\r
dw 200\r
\r
\r
-LABEL X256Y240 word\r
+X256Y240 label word\r
db 0e3h ; dot clock\r
db 16 ; Number of CRTC Registers to update\r
dw 05f00h ; horz total\r
dw 376\r
dw 282\r
\r
-LABEL X256Y400 word\r
+X256Y400 label word\r
db 0e3h ; dot clock\r
db 8 ; Number of CRTC Registers to update\r
dw 05f00h ; horz total\r
dw 400\r
\r
\r
-LABEL X256Y480 word\r
+X256Y480 label word\r
db 0e3h ; dot clock\r
db 16 ; Number of CRTC Registers to update\r
dw 05f00h ; horz total\r
\r
DoubleScanFlag db ? ; Flag to indicate double scanned mode\r
\r
+_DATA ENDS\r
+\r
+\r
.code\r
\r
;-------------------------------------------------------------------------\r
mov ax,bx ; no - set logical width = physical\r
\r
@@ValidLogicalWidth:\r
- shr ax,3\r
+ shr ax,1\r
+ shr ax,1\r
+ shr ax,1\r
out dx,al\r
\r
; The EXACT logical pixel width may not have been possible since\r
mov [_RightClip],ax ; Set default Right clip column\r
; screen\r
sub ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position\r
- shl ax,2 ; of physical screen in virtual\r
+ shl ax,1 ; of physical screen in virtual\r
+ shl ax,1 ; of physical screen in virtual\r
mov [_MaxScrollX],ax ; screen in pixels\r
mov ax,bx ; set ax to byte width of virt scrn\r
- shl ax,2 ; convert to pixels\r
+ shl ax,1 ; convert to pixels\r
+ shl ax,1 ; convert to pixels\r
mov [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width\r
mov cx,ax ; save ax (return value)\r
\r
; parts adapted from M. Abrash code.\r
;------------------------------------------------------------------------\r
_x_set_mode proc\r
- ARG mode:word,logicalscrwidth:word\r
+ ;;arg mode:word,logicalscrwidth:word\r
push bp ;preserve caller's stack frame\r
mov bp,sp\r
\r
mov cx,PARAM_COUNT\r
rep stosb\r
\r
- mov cx,[mode]\r
+ mov cx,[BP+4]\r
cmp cx,LAST_X_MODE ; have we selected a valid mode\r
jle @@ValidMode ; Yes !\r
\r
mov [_SplitScrnScanLine],ax ; No splitscrn ==\r
; splitscrn=PhysicalscrnHeight\r
mov bx,ax ; Copy width for later use\r
- shr ax,2 ; Convert to byte width\r
+ shr ax,1 ; Convert to byte width\r
+ shr ax,1 ; Convert to byte width\r
mov [_ScrnPhysicalByteWidth],ax ; Store for later use\r
lodsw ; Load Screen Phys. Height\r
mov [_ScrnPhysicalHeight],ax ; Store for later use\r
\r
; Mode X is set, now set the required logical page width.\r
\r
- mov cx,[logicalscrwidth]\r
+ mov cx,[BP+6]\r
\r
call SetLogicalScrWidth\r
\r
; Written by Themie Gouthas\r
;----------------------------------------------------------------------\r
_x_select_default_plane proc\r
-ARG Plane:byte\r
+ ;arg Plane:byte\r
push bp\r
mov bp,sp ; set up stack frame\r
- mov cl,byte ptr [Plane]\r
+ mov cl,byte ptr [bp+4]\r
\r
; SELECT WRITE PLANE\r
and cl,011b ;CL = plane\r
;----------------------------------------------------------------------\r
\r
_x_set_splitscreen proc\r
- ARG Line:word\r
+ ;arg Line:word\r
push bp\r
mov bp,sp ; set up stack frame\r
push si\r
mov [_PhysicalStartPixelX],ax ; offset within virtual screen\r
mov [_PhysicalStartY],ax\r
mov [_SplitScrnActive],TRUE\r
- mov ax,[Line]\r
+ mov ax,[bp+4]\r
jns @@NotNeg ; Check that Split Scrn start scan line is +ve\r
\r
mov ax,0 ; Since -ve set to 0\r
\r
mov ah,bh\r
and ah,1\r
- shl ah,4\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
out dx,al ; screen scan line,\r
inc dx ; So using readability of VGA registers\r
dec dx\r
mov ah,bh\r
and ah,2\r
- ror ah,3\r
+ ror ah,1\r
+ ror ah,1\r
+ ror ah,1\r
mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
out dx,al ; Bit 9 of split screen scan line\r
inc dx ; As we did before, update the apropriate\r
\r
mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height\r
cmp ax,[_BottomClip]\r
- jle @@BottomClipOK ; Adjust Clip Rectangle if necessary\r
+ jle @@BottomClipOK2 ; Adjust Clip Rectangle if necessary\r
mov [_BottomClip],ax\r
-@@BottomClipOK:\r
+@@BottomClipOK2:\r
sub ax,[_SplitScrnScanLine] ; Update the maximum Y position of\r
mov [_MaxScrollY],ax ; Physical screen in logical screen\r
\r
;------------------------------------------------------------------------\r
\r
_x_page_flip proc\r
- ARG x:word,y:word\r
+ ;arg x:word,y:word\r
push bp ;preserve caller's stack frame\r
mov bp,sp ;point to local stack frame\r
push si\r
\r
- mov si,[x]\r
+ mov si,[bp+4]\r
mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment\r
- mov cx,[y]\r
+ mov cx,[bp+6]\r
mul cx ; for Y\r
cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ?\r
je @@DoubleBuffer\r
; Parts addapted from M. Abrash code published in DDJ Mag.\r
;------------------------------------------------------------------------\r
_x_set_start_addr proc\r
- ARG x:word,y:word\r
+ ;arg x:word,y:word\r
push bp\r
mov bp,sp\r
push si\r
\r
- mov si,[x]\r
+ mov si,[bp+4]\r
mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment\r
- mov cx,[y] ; for Y\r
+ mov cx,[bp+6] ; for Y\r
mul cx\r
cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ?\r
je @@PageResolution\r
\r
@@AddColumn:\r
mov cx,si\r
- shr cx,2\r
+ shr cx,1\r
+ shr cx,1\r
mov [_PhysicalStartByteX],cx\r
add ax,cx ; add the column offset for X\r
mov bh,al ; setup CRTC start addr regs and\r
cmp [_SplitScrnActive],TRUE\r
je @@SplitScreenEnabled\r
\r
-@@error:\r
+@@error0:\r
mov [_ErrorValue],ERROR\r
pop bp\r
ret\r
\r
@@SplitScreenEnabled:\r
cmp [_CurrXMode],4 ; Do nothing for Modes > 2\r
- jg @@error\r
+ jg @@error0\r
mov bx,[_ScrnPhysicalHeight]\r
\r
mov ax,[_ScrnLogicalHeight]\r
mov [_SplitScrnVisibleHeight],ax\r
\r
or [DoubleScanFlag],0\r
- jz @@NotDoubleScanned\r
+ jz @@NotDoubleScanned0\r
shl bx,1\r
dec bx\r
-@@NotDoubleScanned:\r
+@@NotDoubleScanned0:\r
;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes\r
;shl bx,cl\r
\r
\r
mov ah,bh\r
and ah,1\r
- shl ah,4\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
out dx,al ; screen scan line,\r
inc dx ; So using readability of VGA registers\r
dec dx\r
mov ah,bh\r
and ah,2\r
- ror ah,3\r
+ ror ah,1\r
+ ror ah,1\r
+ ror ah,1\r
mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
out dx,al ; Bit 9 of split screen scan line\r
inc dx ; As we did before, update the apropriate\r
out dx,al\r
sti ; Registers are set, so interrupts are safe\r
\r
-@@done:\r
+@@done0:\r
\r
mov [_ErrorValue],OK\r
pop bp\r
mov bp,sp\r
\r
cmp [_SplitScrnActive],TRUE\r
- je @@SplitScreenEnabled\r
+ je @@SplitScreenEnabled0\r
\r
-@@error:\r
+@@error1:\r
mov [_ErrorValue],ERROR\r
pop bp\r
ret\r
\r
-@@SplitScreenEnabled:\r
+@@SplitScreenEnabled0:\r
cmp [_CurrXMode],4 ; Do nothing for Modes > 2\r
- jg @@error\r
+ jg @@error1\r
\r
mov bx,[_SplitScrnScanLine]\r
mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
mov [_SplitScrnVisibleHeight],ax\r
\r
or [DoubleScanFlag],0\r
- jz @@NotDoubleScanned\r
+ jz @@NotDoubleScanned1\r
shl bx,1\r
dec bx\r
-@@NotDoubleScanned:\r
+@@NotDoubleScanned1:\r
;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes\r
;shl bx,cl\r
WaitVsyncStart ; wait for vertical retrace\r
\r
mov ah,bh\r
and ah,1\r
- shl ah,4\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
out dx,al ; screen scan line,\r
inc dx ; So using readability of VGA registers\r
dec dx\r
mov ah,bh\r
and ah,2\r
- ror ah,3\r
+ ror ah,1\r
+ ror ah,1\r
+ ror ah,1\r
mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
out dx,al ; Bit 9 of split screen scan line\r
inc dx ; As we did before, update the apropriate\r
out dx,al\r
sti ; Registers are set, so interrupts are safe\r
\r
-@@Done:\r
+@@Done1:\r
mov [_ErrorValue],0\r
pop bp\r
ret\r
\r
\r
_x_adjust_splitscreen proc\r
- ARG ScanLine\r
+ ;arg ScanLine\r
push bp\r
mov bp,sp\r
\r
cmp [_SplitScrnActive],TRUE\r
- je @@SplitScreenEnabled\r
+ je @@SplitScreenEnabled1\r
\r
-@@error:\r
+@@error2:\r
mov [_ErrorValue],ERROR\r
pop bp\r
ret\r
\r
-@@SplitScreenEnabled:\r
+@@SplitScreenEnabled1:\r
cmp [_CurrXMode],4 ; Do nothing for Modes > 2\r
- jg @@error\r
- mov bx,[ScanLine] ; Is the required starting scan line\r
+ jg @@error2\r
+ mov bx,[bp+4] ; Is the required starting scan line\r
cmp bx,[_SplitScrnScanLine] ; valid ?\r
- js @@Done ; No - Then do nothing\r
+ js @@Done2 ; No - Then do nothing\r
\r
@@ValidScanLine:\r
\r
mov [_SplitScrnVisibleHeight],ax\r
\r
or [DoubleScanFlag],0\r
- jz @@NotDoubleScanned\r
+ jz @@NotDoubleScanned2\r
shl bx,1\r
dec bx\r
-@@NotDoubleScanned:\r
+@@NotDoubleScanned2:\r
;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes\r
;shl bx,cl\r
\r
\r
mov ah,bh\r
and ah,1\r
- shl ah,4\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
+ shl ah,1\r
mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
out dx,al ; screen scan line,\r
inc dx ; So using readability of VGA registers\r
dec dx\r
mov ah,bh\r
and ah,2\r
- ror ah,3\r
+ ror ah,1\r
+ ror ah,1\r
+ ror ah,1\r
mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
out dx,al ; Bit 9 of split screen scan line\r
inc dx ; As we did before, update the apropriate\r
or al,ah\r
out dx,al\r
sti ; Registers are set, so interrupts are safe\r
-@@Done:\r
+@@Done2:\r
mov [_ErrorValue],OK\r
pop bp\r
ret\r
\r
\r
_x_set_doublebuffer proc\r
- ARG PageHeight:word\r
+ ;arg PageHeight:word\r
push bp\r
mov bp,sp\r
\r
mov ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to\r
shr ax,1 ; _ScrnLogicalHeight / 2\r
\r
- mov bx,[PageHeight] ; Is the require D.B. Page Height\r
+ mov bx,[bp+4] ; Is the require D.B. Page Height\r
cmp ax,bx ; > the Maximum D.B. Page Height ?\r
\r
js @@InvalidHeight ; no - jump\r
mov [_ScrnLogicalHeight],ax ; Update logical screen height to\r
; reflect the height of a D.B. page\r
cmp ax,[_BottomClip]\r
- jle @@BottomClipOK ; Adjust Clip Rectangle if necessary\r
+ jle @@BottomClipOK0 ; Adjust Clip Rectangle if necessary\r
mov [_BottomClip],ax\r
-@@BottomClipOK:\r
+@@BottomClipOK0:\r
push ax\r
mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second\r
mov cx,ax ; D.B. Page in video ram\r
;------------------------------------------------------------------------\r
\r
_x_set_tripplebuffer proc\r
- ARG PageHeight:word\r
+ ;arg PageHeight:word\r
push bp\r
mov bp,sp\r
\r
cmp [_DoubleBufferActive],0\r
- jne @@Error\r
+ jne @@Error3\r
cmp [_TrippleBufferActive],0\r
- je @@OkToContinue\r
-@@Error:\r
+ je @@OkToContinue3\r
+@@Error3:\r
mov [_ErrorValue],ERROR\r
pop bp\r
ret\r
\r
-@@OkToContinue:\r
+@@OkToContinue3:\r
mov [_VisiblePageIdx],0 ; Set visible Page to 0\r
mov ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to\r
mov bx,3\r
xor dx,dx\r
idiv bx ; _ScrnLogicalHeight / 3\r
\r
- mov bx,[PageHeight] ; Is the require T.B. Page Height\r
+ mov bx,[bp+4] ; Is the require T.B. Page Height\r
cmp ax,bx ; > the Maximum T.B. Page Height ?\r
\r
- js @@InvalidHeight ; no - jump\r
+ js @@InvalidHeight0 ; no - jump\r
mov ax,bx ; yes - Set the T.B. Page height to\r
; to the maximum allowed.\r
\r
-@@InvalidHeight:\r
+@@InvalidHeight0:\r
mov [_ScrnLogicalHeight],ax ; Update logical screen height to\r
; reflect the height of a T.B. page\r
cmp ax,[_BottomClip]\r
- jle @@BottomClipOK ; Adjust Clip Rectangle if necessary\r
+ jle @@BottomClipOK1 ; Adjust Clip Rectangle if necessary\r
mov [_BottomClip],ax\r
-@@BottomClipOK:\r
+@@BottomClipOK1:\r
push ax\r
mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second\r
mov cx,ax ; D.B. Page in video ram\r
;------------------------------------------------------------------------\r
\r
_x_set_cliprect proc\r
-ARG left:word,top:word,right:word,bottom:word\r
+;arg left:word,top:word,right:word,bottom:word\r
push bp\r
mov bp,sp\r
- mov ax,[left]\r
- mov bx,[right]\r
+ mov ax,[bp+4]\r
+ mov bx,[bp+8]\r
cmp bx,ax\r
jns @@CorrectXOrder\r
xchg bx,ax\r
@@CorrectXOrder:\r
mov [_LeftClip],ax\r
mov [_RightClip],bx\r
- mov ax,[top]\r
- mov bx,[bottom]\r
+ mov ax,[bp+6]\r
+ mov bx,[bp+10]\r
cmp bx,ax\r
jns @@CorrectYOrder\r
xchg bx,ax\r
_x_wait_vsync endp\r
\r
\r
- end\r
+end\r
global _x_show_splitscreen :proc\r
global _x_adjust_splitscreen :proc\r
global _x_set_doublebuffer :proc\r
- global _x_set_tripplebuffer :proc\r
+ global _x_set_tripplebuffer :proc\r
global _x_set_cliprect :proc\r
- global _x_wait_vsync :proc
\ No newline at end of file
+ global _x_wait_vsync :proc\r
; Written by Themie Gouthas\r
;----------------------------------------------------------------------\r
_x_get_pal_struc proc\r
-ARG PalBuff:dword,NumColors:word,StartColor:word\r
+;ARG PalBuff:dword,NumColors:word,StartColor:word\r
push bp ; Set up stack frame\r
mov bp,sp\r
push di\r
push si\r
cld\r
\r
- les di,dword ptr [PalBuff] ; Point es:di to palette buffer\r
- mov si,[StartColor] ; Store the Start Colour\r
+ les di,dword ptr [bp+4] ; Point es:di to palette buffer\r
+ mov si,[bp+10] ; Store the Start Colour\r
mov ax,si\r
stosb\r
- mov dx,[NumColors] ; Store the Number of Colours\r
+ mov dx,[bp+8] ; Store the Number of Colours\r
mov al,dl\r
stosb\r
\r
; Written by Themie Gouthas\r
;----------------------------------------------------------------------\r
_x_get_pal_raw proc\r
-ARG PalBuff:dword,NumColors:word,StartColor:word\r
+;ARG PalBuff:dword,NumColors:word,StartColor:word\r
push bp ; Set up stack frame\r
mov bp,sp\r
push di\r
push si\r
\r
- les di,dword ptr [PalBuff] ; Point es:di to palette buffer\r
+ les di,dword ptr [bp+4] ; Point es:di to palette buffer\r
\r
- mov si,[StartColor]\r
- mov cx,[NumColors]\r
+ mov si,[bp+10]\r
+ mov cx,[bp+8]\r
\r
ReadPalEntry:\r
cld\r
;\r
\r
_x_put_pix proc\r
- ARG X:word,Y:word,PgOfs:word,Color:word\r
+ ;ARG X:word,Y:word,PgOfs:word,Color:word\r
push bp ;preserve caller's stack frame\r
mov bp,sp ;point to local stack frame\r
\r
mov ax,[_ScrnLogicalByteWidth]\r
- mul [Y] ;offset of pixel's scan line in page\r
- mov bx,[X]\r
+ mul [BP+6] ;offset of pixel's scan line in page\r
+ mov bx,[BP+4]\r
shr bx,1 ;X/4 = offset of pixel in scan line\r
shr bx,1 ;X/4 = offset of pixel in scan line\r
add bx,ax ;offset of pixel in page\r
- add bx,[PgOfs] ;offset of pixel in display memory\r
+ add bx,[BP+8] ;offset of pixel in display memory\r
mov ax,SCREEN_SEG\r
mov es,ax ;point ES:BX to the pixel's address\r
\r
- mov cl,byte ptr [X]\r
+ mov cl,byte ptr [BP+4]\r
and cl,011b ;CL = pixel's plane\r
mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg\r
shl ah,cl ;set only the bit for the pixel's\r
mov dx,SC_INDEX ;set the Map Mask to enable only the\r
out dx,ax ; pixel's plane\r
\r
- mov al,byte ptr [Color]\r
+ mov al,byte ptr [BP+10]\r
mov es:[bx],al ;draw the pixel in the desired color\r
\r
pop bp ;restore caller's stack frame\r
\r
\r
_x_get_pix proc\r
- ARG x:word,y:word,PageBase:word\r
+ ;ARG x:word,y:word,PageBase:word\r
push bp ;preserve caller's stack frame\r
mov bp,sp ;point to local stack frame\r
\r
mov ax,[_ScrnLogicalByteWidth]\r
- mul [Y] ;offset of pixel's scan line in page\r
- mov bx,[X]\r
+ mul [bp+6] ;offset of pixel's scan line in page\r
+ mov bx,[bp+4]\r
shr bx,1\r
shr bx,1 ;X/4 = offset of pixel in scan line\r
add bx,ax ;offset of pixel in page\r
- add bx,[PageBase] ;offset of pixel in display memory\r
+ add bx,[bp+8] ;offset of pixel in display memory\r
mov ax,SCREEN_SEG\r
mov es,ax ;point ES:BX to the pixel's address\r
\r
- mov ah,byte ptr [X]\r
+ mov ah,byte ptr [bp+4]\r
and ah,011b ;AH = pixel's plane\r
mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
--- /dev/null
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0\r
+ DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1\r
+ DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2\r
+ DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3\r
+ DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4\r
+ DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5\r
+ DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6\r
+ DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7\r
+ DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8\r
+ DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9\r
+ DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10\r
+ DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11\r
+ DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12\r
+ DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13\r
+ DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14\r
+ DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15\r
+ DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16\r
+ DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17\r
+ DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18\r
+ DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19\r
+ DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20\r
+ DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21\r
+ DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22\r
+ DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23\r
+ DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24\r
+ DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25\r
+ DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26\r
+ DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27\r
+ DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28\r
+ DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29\r
+ DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30\r
+ DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; \r
+ DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; !\r
+ DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; "\r
+ DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; #\r
+ DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $\r
+ DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; %\r
+ DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; &\r
+ DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; '\r
+ DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; (\r
+ DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; )\r
+ DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; *\r
+ DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; +\r
+ DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; ,\r
+ DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; -\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; .\r
+ DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; /\r
+ DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0\r
+ DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1\r
+ DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2\r
+ DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3\r
+ DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4\r
+ DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5\r
+ DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6\r
+ DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7\r
+ DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8\r
+ DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9\r
+ DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; :\r
+ DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ;\r
+ DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; <\r
+ DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; =\r
+ DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; >\r
+ DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ?\r
+ DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A\r
+ DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B\r
+ DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C\r
+ DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F\r
+ DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G\r
+ DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H\r
+ DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I\r
+ DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J\r
+ DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K\r
+ DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L\r
+ DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M\r
+ DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O\r
+ DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P\r
+ DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q\r
+ DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R\r
+ DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S\r
+ DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T\r
+ DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U\r
+ DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V\r
+ DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W\r
+ DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X\r
+ DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y\r
+ DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z\r
+ DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [\r
+ DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \\r
+ DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ]\r
+ DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _\r
+ DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; `\r
+ DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b\r
+ DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c\r
+ DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d\r
+ DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e\r
+ DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h\r
+ DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i\r
+ DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j\r
+ DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k\r
+ DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l\r
+ DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m\r
+ DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n\r
+ DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o\r
+ DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q\r
+ DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r\r
+ DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s\r
+ DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t\r
+ DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u\r
+ DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v\r
+ DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w\r
+ DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x\r
+ DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y\r
+ DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z\r
+ DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; {\r
+ DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; |\r
+ DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; }\r
+ DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~\r
+ DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ; \7f\r
+ DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128\r
+ DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129\r
+ DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130\r
+ DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131\r
+ DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132\r
+ DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133\r
+ DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134\r
+ DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135\r
+ DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136\r
+ DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137\r
+ DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138\r
+ DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139\r
+ DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140\r
+ DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141\r
+ DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142\r
+ DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143\r
+ DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144\r
+ DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145\r
+ DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146\r
+ DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147\r
+ DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148\r
+ DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149\r
+ DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150\r
+ DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151\r
+ DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152\r
+ DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153\r
+ DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154\r
+ DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155\r
+ DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156\r
+ DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157\r
+ DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158\r
+ DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159\r
+ DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160\r
+ DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161\r
+ DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162\r
+ DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163\r
+ DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164\r
+ DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165\r
+ DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166\r
+ DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167\r
+ DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168\r
+ DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169\r
+ DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170\r
+ DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171\r
+ DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172\r
+ DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173\r
+ DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174\r
+ DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175\r
+ DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176\r
+ DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177\r
+ DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178\r
+ DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181\r
+ DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182\r
+ DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183\r
+ DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184\r
+ DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185\r
+ DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186\r
+ DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187\r
+ DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188\r
+ DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190\r
+ DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198\r
+ DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199\r
+ DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200\r
+ DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201\r
+ DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202\r
+ DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203\r
+ DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205\r
+ DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206\r
+ DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210\r
+ DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212\r
+ DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213\r
+ DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215\r
+ DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217\r
+ DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220\r
+ DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221\r
+ DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223\r
+ DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224\r
+ DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225\r
+ DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226\r
+ DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227\r
+ DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228\r
+ DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229\r
+ DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230\r
+ DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231\r
+ DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233\r
+ DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234\r
+ DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235\r
+ DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236\r
+ DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237\r
+ DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239\r
+ DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240\r
+ DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241\r
+ DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242\r
+ DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243\r
+ DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244\r
+ DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245\r
+ DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246\r
+ DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247\r
+ DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248\r
+ DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249\r
+ DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250\r
+ DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251\r
+ DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252\r
+ DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253\r
+ DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+!ifdef __LINUX__\r
+REMOVECOMMAND=rm -f\r
+COPYCOMMAND=cp -f\r
+DIRSEP=/\r
+OBJ=o\r
+!else\r
+REMOVECOMMAND=del\r
+COPYCOMMAND=copy /y\r
+DIRSEP=\\r
+OBJ=obj\r
+!endif\r
+LIBINCS = modex.def\r
+\r
+LIBOBJS = mxbb.$(OBJ) mxcc.$(OBJ) mxcg.$(OBJ) mxcl.$(OBJ) mxcr.$(OBJ) mxfb.$(OBJ) mxfp.$(OBJ) mxgc.$(OBJ) mxgi.$(OBJ) mxgm.$(OBJ) mxgp.$(OBJ) mxgv.$(OBJ) mxhl.$(OBJ) mxit.$(OBJ) mxll.$(OBJ) mxln.$(OBJ) mxot.$(OBJ) mxpb.$(OBJ) mxpf.$(OBJ) mxpg.$(OBJ) mxpi.$(OBJ) mxpn.$(OBJ) mxpp.$(OBJ) mxra.$(OBJ) mxrp.$(OBJ) mxsa.$(OBJ) mxsc.$(OBJ) mxsi.$(OBJ) mxsl.$(OBJ) mxsm.$(OBJ) mxsp.$(OBJ) mxss.$(OBJ) mxtl.$(OBJ) mxvs.$(OBJ) mxwd.$(OBJ) mxwm.$(OBJ) mxwp.$(OBJ) mxwr.$(OBJ)\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC =wasm\r
+ASMO =-mh -0\r
+\r
+#\r
+# PAS compiler\r
+#\r
+#PASC = tpc\r
+#PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = wlib\r
+\r
+# .asm.obj:\r
+# $(ASMC) $(ASMO) $<\r
+\r
+mxbb.$(OBJ): mxbb.asm\r
+ $(ASMC) $(ASMO) mxbb.asm\r
+mxcc.$(OBJ): mxcc.asm\r
+ $(ASMC) $(ASMO) mxcc.asm\r
+mxcg.$(OBJ): mxcg.asm\r
+ $(ASMC) $(ASMO) mxcg.asm\r
+mxcl.$(OBJ): mxcl.asm\r
+ $(ASMC) $(ASMO) mxcl.asm\r
+mxcr.$(OBJ): mxcr.asm\r
+ $(ASMC) $(ASMO) mxcr.asm\r
+mxfb.$(OBJ): mxfb.asm\r
+ $(ASMC) $(ASMO) mxfb.asm\r
+mxfp.$(OBJ): mxfp.asm\r
+ $(ASMC) $(ASMO) mxfp.asm\r
+mxgc.$(OBJ): mxgc.asm\r
+ $(ASMC) $(ASMO) mxgc.asm\r
+mxgi.$(OBJ): mxgi.asm\r
+ $(ASMC) $(ASMO) mxgi.asm\r
+mxgm.$(OBJ): mxgm.asm\r
+ $(ASMC) $(ASMO) mxgm.asm\r
+mxgp.$(OBJ): mxgp.asm\r
+ $(ASMC) $(ASMO) mxgp.asm\r
+mxgv.$(OBJ): mxgv.asm\r
+ $(ASMC) $(ASMO) mxgv.asm\r
+mxhl.$(OBJ): mxhl.asm\r
+ $(ASMC) $(ASMO) mxhl.asm\r
+mxit.$(OBJ): mxit.asm\r
+ $(ASMC) $(ASMO) mxit.asm\r
+mxll.$(OBJ): mxll.asm\r
+ $(ASMC) $(ASMO) mxll.asm\r
+mxln.$(OBJ): mxln.asm\r
+ $(ASMC) $(ASMO) mxln.asm\r
+mxot.$(OBJ): mxot.asm\r
+ $(ASMC) $(ASMO) mxot.asm\r
+mxpb.$(OBJ): mxpb.asm\r
+ $(ASMC) $(ASMO) mxpb.asm\r
+mxpf.$(OBJ): mxpf.asm\r
+ $(ASMC) $(ASMO) mxpf.asm\r
+mxpg.$(OBJ): mxpg.asm\r
+ $(ASMC) $(ASMO) mxpg.asm\r
+mxpi.$(OBJ): mxpi.asm\r
+ $(ASMC) $(ASMO) mxpi.asm\r
+mxpn.$(OBJ): mxpn.asm\r
+ $(ASMC) $(ASMO) mxpn.asm\r
+mxpp.$(OBJ): mxpp.asm\r
+ $(ASMC) $(ASMO) mxpp.asm\r
+mxra.$(OBJ): mxra.asm\r
+ $(ASMC) $(ASMO) mxra.asm\r
+mxrp.$(OBJ): mxrp.asm\r
+ $(ASMC) $(ASMO) mxrp.asm\r
+mxsa.$(OBJ): mxsa.asm\r
+ $(ASMC) $(ASMO) mxsa.asm\r
+mxsc.$(OBJ): mxsc.asm\r
+ $(ASMC) $(ASMO) mxsc.asm\r
+mxsi.$(OBJ): mxsi.asm\r
+ $(ASMC) $(ASMO) mxsi.asm\r
+mxsl.$(OBJ): mxsl.asm\r
+ $(ASMC) $(ASMO) mxsl.asm\r
+mxsm.$(OBJ): mxsm.asm\r
+ $(ASMC) $(ASMO) mxsm.asm\r
+mxsp.$(OBJ): mxsp.asm\r
+ $(ASMC) $(ASMO) mxsp.asm\r
+mxss.$(OBJ): mxss.asm\r
+ $(ASMC) $(ASMO) mxss.asm\r
+mxtl.$(OBJ): mxtl.asm\r
+ $(ASMC) $(ASMO) mxtl.asm\r
+mxvs.$(OBJ): mxvs.asm\r
+ $(ASMC) $(ASMO) mxvs.asm\r
+mxwd.$(OBJ): mxwd.asm\r
+ $(ASMC) $(ASMO) mxwd.asm\r
+mxwm.$(OBJ): mxwm.asm\r
+ $(ASMC) $(ASMO) mxwm.asm\r
+mxwp.$(OBJ): mxwp.asm\r
+ $(ASMC) $(ASMO) mxwp.asm\r
+mxwr.$(OBJ): mxwr.asm\r
+ $(ASMC) $(ASMO) mxwr.asm\r
+\r
+all: $(LIBOBJS) modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+ MXCC.OBJ \\r
+ MXCG.OBJ \\r
+ MXCL.OBJ \\r
+ MXCR.OBJ \\r
+ MXFB.OBJ \\r
+ MXFP.OBJ \\r
+ MXGC.OBJ \\r
+ MXGI.OBJ \\r
+ MXGM.OBJ \\r
+ MXGP.OBJ \\r
+ MXGV.OBJ \\r
+ MXHL.OBJ \\r
+ MXIT.OBJ \\r
+ MXLL.OBJ \\r
+ MXLN.OBJ \\r
+ MXOT.OBJ \\r
+ MXPB.OBJ \\r
+ MXPF.OBJ \\r
+ MXPG.OBJ \\r
+ MXPI.OBJ \\r
+ MXPN.OBJ \\r
+ MXPP.OBJ \\r
+ MXRA.OBJ \\r
+ MXRP.OBJ \\r
+ MXSA.OBJ \\r
+ MXSC.OBJ \\r
+ MXSI.OBJ \\r
+ MXSL.OBJ \\r
+ MXSM.OBJ \\r
+ MXSP.OBJ \\r
+ MXSS.OBJ \\r
+ MXTL.OBJ \\r
+ MXVS.OBJ \\r
+ MXWD.OBJ \\r
+ MXWM.OBJ \\r
+ MXWP.OBJ \\r
+ MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+ $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+;JUMPS\r
+;LOCALS\r
+\r
+TRUE EQU 1 ; Boolean constants\r
+FALSE EQU 0\r
+\r
+USE286 = FALSE ; TRUE enables 80286 instructions\r
+USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+ P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+ P386\r
+ USE286 = TRUE\r
+ENDIF\r
+\r
+MXVERSION EQU 0128h ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC EQU 3C2h ; Miscellaneous output\r
+TS EQU 3C4h ; Timing Sequencer index register\r
+GDC EQU 3CEh ; Graphics Data Controller index register\r
+CRTC EQU 3D4h ; CRTC index register\r
+STATUS EQU 3DAh ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET EQU 0\r
+OP_MOVE EQU 0 ; Same as OP_SET\r
+OP_AND EQU 1\r
+OP_OR EQU 2\r
+OP_XOR EQU 3\r
+OP_TRANS EQU 4\r
+OP_ADD EQU 5 ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU 4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.PUSH has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+ IFB <$reg> ;; Is argument blank?\r
+ EXITM ;; Yes, exit\r
+ ELSEIFIDNI <$reg>, <FLAGS> ;; Is argument the keyword "FLAGS"?\r
+ pushf ;; Yes, push flags\r
+ ELSE\r
+ push $reg ;; Push argument\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.POP has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+ IFNB <$reg> ;; Is argument non-blank?\r
+ IFIDNI <$reg>, <FLAGS> ;; Yes, is it the keyword "FLAGS"?\r
+ popf ;; Yes, pop flags\r
+ ELSE\r
+ pop $reg ;; Pop argument\r
+ ENDIF\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter MACRO localsize\r
+ IF USE286 EQ TRUE\r
+ enter localsize, 0\r
+ ELSE\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, localsize\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.leave MACRO argsize\r
+; IF USE286 EQ TRUE\r
+; leave\r
+; ELSE\r
+; mov sp, bp\r
+; pop bp\r
+; ENDIF\r
+; IFNB <argspace>\r
+; ret argsize\r
+; ELSE\r
+; ret\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shr MACRO arg, count\r
+; IF USE286 EQ TRUE\r
+; shr arg, count\r
+; ELSE\r
+; $temp = count\r
+; WHILE $temp GT 0\r
+; shr arg, 1\r
+; $temp = $temp-1\r
+; ENDM\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shl MACRO arg, count\r
+; IF USE286 EQ TRUE\r
+; shl arg, count\r
+; ELSE\r
+; $temp = count\r
+; WHILE $temp GT 0\r
+; shl arg, 1\r
+; $temp = $temp-1\r
+; ENDM\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.chk386 MACRO name, jump\r
+; IF USE386 EQ FALSE\r
+; .OUT "Warning: ", <name>, " needs a 386 or better to run!"\r
+; jmp @@jump\r
+; ENDIF\r
+;ENDM\r
--- /dev/null
+/*\r
+ MODEX.H - C/C++ include file for the MODEX library\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_ // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT 0 // 80x25 text\r
+#define MX_320x175 1 // 320x175x256\r
+#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350 4 // 320x350x256\r
+#define MX_320x400 5 // 320x400x256, 2 pages\r
+#define MX_320x480 6 // 320x480x256, 1 page\r
+#define MX_360x175 7 // 360x175x256\r
+#define MX_360x200 8 // 360x200x256, 3 pages\r
+#define MX_360x240 9 // 360x240x256, 2 pages\r
+#define MX_360x350 10 // 360x350x256\r
+#define MX_360x400 11 // 360x400x256, 1 page\r
+#define MX_360x480 12 // 360x480x256, 1 page\r
+#define MX_400x600 13 // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN 0\r
+#define MX_FADEOUT 1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET 0 // No operator\r
+#define OP_AND 1 // And\r
+#define OP_OR 2 // Or\r
+#define OP_XOR 3 // Xor\r
+#define OP_TRANS 4 // Transparent\r
+#define OP_ADD 5 // Additive\r
+#define OP_MOVE 0 // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE unsigned char\r
+#define MXBOOL short int\r
+#define MXSINT short int\r
+#define MXUINT unsigned short int\r
+#define MXAPI far pascal\r
+#define MXPTR void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT MXAPI mxInit( void ); // Returns 0 if successful\r
+void MXAPI mxTerm( void );\r
+MXUINT MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void MXAPI mxChangeMode( MXUINT mode );\r
+void MXAPI mxSetMode( MXUINT mode );\r
+void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void MXAPI mxWriteMode( MXBYTE wm );\r
+void MXAPI mxSplitScreen( MXUINT line );\r
+void MXAPI mxStartAddress( MXUINT sa );\r
+void MXAPI mxStartLine( MXUINT sl );\r
+void MXAPI mxWaitDisplay( void );\r
+void MXAPI mxWaitRetrace( void );\r
+void MXAPI mxWritePlane( MXBYTE wp );\r
+void MXAPI mxReadPlane( MXBYTE rp );\r
+void MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL MXAPI mxGetClip( void );\r
+MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL MXAPI mxSetClip( MXBOOL );\r
+void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef MXBYTE\r
+#undef MXBOOL\r
+#undef MXSINT\r
+#undef MXUINT\r
+#undef MXPTR\r
+#undef MXAPI\r
+\r
+#endif // _MODEX_H_\r
--- /dev/null
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXPT.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
--- /dev/null
+(*\r
+ Turbo Pascal interface to the MODEX library\r
+ Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+ (* Video modes *)\r
+ MX_TEXT = 0;\r
+ MX_320x175 = 1;\r
+ MX_320x200 = 2;\r
+ MX_320x240 = 3;\r
+ MX_320x350 = 4;\r
+ MX_320x400 = 5;\r
+ MX_320x480 = 6;\r
+ MX_360x175 = 7;\r
+ MX_360x200 = 8;\r
+ MX_360x240 = 9;\r
+ MX_360x350 = 10;\r
+ MX_360x400 = 11;\r
+ MX_360x480 = 12;\r
+ MX_400x600 = 13;\r
+\r
+ (* Fade effects *)\r
+ MX_FADEIN = 0;\r
+ MX_FADEOUT = 1;\r
+\r
+ (* Raster ops *)\r
+ OP_SET = 0;\r
+ OP_AND = 1;\r
+ OP_OR = 2;\r
+ OP_XOR = 3;\r
+ OP_TRANS = 4;\r
+ OP_ADD = 5;\r
+ OP_MOVE = 0; (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt; external;\r
+procedure mxChangeMode( Mode: word ); external;\r
+procedure mxCircle; external;\r
+procedure mxColorToGray; external;\r
+procedure mxFadePalette; external;\r
+procedure mxFillBox; external;\r
+procedure mxGammaCorrect; external;\r
+procedure mxGetAspect( var AspectX, AspectY: word ); external;\r
+function mxGetClipRegion; external;\r
+function mxGetClip: boolean; external;\r
+procedure mxGetImage; external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function mxGetPixel( X, Y: word ): byte; external;\r
+procedure mxGetScreenSize( var Width, Height: word ); external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external;\r
+function mxGetVersion: word; external;\r
+procedure mxGetVirtualScreen( var Width, Height: word ); external;\r
+procedure mxInit; external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external;\r
+procedure mxOutChar( X, Y: integer; C: char ); external;\r
+procedure mxOutText( X, Y: integer; S: pointer ); external;\r
+procedure mxPan( X, Y: word ); external;\r
+procedure mxPutImage; external;\r
+procedure mxPutPixel( X, Y: word; C: byte ); external;\r
+procedure mxPutTile; external;\r
+procedure mxReadPlane( Plane: byte ); external;\r
+procedure mxRotatePalette; external;\r
+procedure mxRowAddress( RowAddress: byte ); external;\r
+function mxSetClip( Clip: boolean ): boolean; external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external;\r
+procedure mxSetColor( Index, R, G, B: word ); external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word ); external;\r
+procedure mxSetMode( Mode: word ); external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word ); external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer ); external;\r
+procedure mxSetVirtualScreen( Width, Height: word ); external;\r
+procedure mxSplitScreen( Line: word ); external;\r
+procedure mxStartAddress( StartAddress: word ); external;\r
+procedure mxStartLine; external;\r
+procedure mxStretchImage; external;\r
+procedure mxTerm; external;\r
+procedure mxTransPutTile; external;\r
+procedure mxWaitDisplay; external;\r
+procedure mxWaitRetrace; external;\r
+procedure mxWriteMode( Mode: byte ); external;\r
+procedure mxWritePlane( Plane: byte ); external;\r
+\r
+procedure mxFillPoly; external;\r
+procedure mxGouraudPoly; external;\r
+procedure mxTexturePoly; external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+ Prints a Turbo Pascal string.\r
+ Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+ S := S + #0;\r
+ mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
--- /dev/null
+(*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ MAX_SPRITE = 100;\r
+type\r
+ (* Sprite structure *)\r
+ TSprite = record\r
+ X, Y : integer; (* Sprite coordinates *)\r
+ DX,DY: integer; (* Deltas for sprite movement *)\r
+ W, H : integer; (* Sprite width and height *)\r
+ Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *)\r
+ end;\r
+ (* RGB color structure *)\r
+ TRgb = record\r
+ R, G, B: byte;\r
+ end;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *)\r
+ Palette: array[ byte ] of TRgb; (* Palette *)\r
+ Page : word; (* Page offset *)\r
+ I : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X := Random( 320 ); (* Initialize position with random values *)\r
+ S.Y := Random( 240 );\r
+ S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+ S.DY := Random( 7 )-3;\r
+ S.W := 16; (* Size is fixed in this program *)\r
+ S.H := 16;\r
+ (* The image is a square with a hole inside *)\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); (* Get new position *)\r
+ Inc( S.Y, S.DY );\r
+ (* Check sprite position, change delta if needed *)\r
+ if( S.X > 320 ) then begin\r
+ S.X := 320;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.X < -16 ) then begin\r
+ S.X := -16;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.Y > 240 ) then begin\r
+ S.Y := 240;\r
+ S.DY := -S.DY;\r
+ end;\r
+ if( S.Y < -16 ) then begin\r
+ S.Y := -16;\r
+ S.DY := -S.DY;\r
+ end;\r
+ (* Draw the sprite, note the Page offset added to the *)\r
+ (* Y coordinate of the image *)\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+ (* Initialize library *)\r
+ mxInit;\r
+\r
+ (* Enter graphics mode *)\r
+ mxSetMode( MX_320x240 );\r
+\r
+ (* Print initialization message *)\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ (* Initialize sprites *)\r
+ for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+ (* Draw background *)\r
+ for I:=1 to 192 do begin\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ end;\r
+\r
+ (* Compute and set palette *)\r
+ for I:=1 to 192 do with Palette[I+63] do begin\r
+ R := 0;\r
+ G := 0;\r
+ B := 0;\r
+ if( I < 64 ) then\r
+ R := I shr 1+31\r
+ else if( I < 128 ) then\r
+ G := (I-64) shr 1+31\r
+ else\r
+ B := (I-128) shr 1+31;\r
+ end;\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ (* Main loop *)\r
+ Page := 240;\r
+ while( not KeyPressed ) do begin\r
+ (* Set clip region to current page *)\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ (* Restore background *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ (* Draw sprites *)\r
+ for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+ (* Print message *)\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ (* Flip page *)\r
+ mxStartLine( Page );\r
+ Page := 240-Page;\r
+ (* Animate palette *)\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO02 - Texture mapping and palette rotation\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+ LSIZE = 85;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of T2DPoint;\r
+ Width : word;\r
+ Data : array[ 1..64*64 ] of byte;\r
+ end;\r
+ TQuad = record\r
+ VtxCnt : word;\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+var\r
+ Vtx : array[ 0..7 ] of TPoint;\r
+ XVtx : array[ 0..7 ] of TPoint;\r
+ VVtx : array[ 0..7 ] of T2DPoint;\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Txts : array[ 0..5 ] of TTexture;\r
+ Nrm : array[ 0..5 ] of TPoint;\r
+ XNrm : array[ 0..5 ] of TPoint;\r
+ Page : word;\r
+ Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+ I: word;\r
+begin\r
+ mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+ MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+ mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+ (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+ with Txts[Idx] do begin\r
+ Desc[0].X := $80; Desc[0].Y := $80;\r
+ Desc[1].X := $80; Desc[1].Y := $3F80;\r
+ Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+ Desc[3].X := $3F80; Desc[3].Y := $80;\r
+ Width := 64;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Build vertexes for a cube *)\r
+ with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ for I:=0 to 7 do begin (* Make points 16:16 fixed *)\r
+ Vtx[I].X := Vtx[I].X*$10000;\r
+ Vtx[I].Y := Vtx[I].Y*$10000;\r
+ Vtx[I].Z := Vtx[I].Z*$10000;\r
+ end;\r
+ (* Build faces *)\r
+ with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+ with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+ with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+ with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+ with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+ with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+ for I:=0 to 5 do Face[I].Texture := I;\r
+ (* Build textures and palette *)\r
+ Randomize;\r
+ FillChar( Palette, SizeOf(Palette), 0 );\r
+ MakePlasmaPalette( Palette, PAL_RGB );\r
+ mxSetPalette( @Palette, 0, 193 );\r
+ for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *)\r
+ (* Draw cube: backface culling is straighforward in this case, so *)\r
+ (* it can be handled by the polygon filling procedure *)\r
+ for I:=0 to 5 do\r
+ mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *)\r
+ Page := 240-Page;\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 1000; (* Number of points *)\r
+ EDGE = 70; (* Length of cube edge *)\r
+ RADIUS = 90; (* Radius of sphere *)\r
+ WAITCOUNT = 192; (* Frames to wait for non-morphing shapes *)\r
+ MS = 32; (* Number of steps for morphing *)\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+ InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+ InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+ InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+ P3DPointArray = ^T3DPointArray;\r
+var\r
+ CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+ VVtx : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+ Page : word;\r
+ Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+ L: longint;\r
+begin\r
+ L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+ Toggle := A;\r
+ if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+ I: integer;\r
+begin\r
+ New( CubeVtx );\r
+ New( SphereVtx );\r
+ New( Vtx );\r
+ New( XVtx );\r
+ (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+ Randomize;\r
+ for I:=0 to MAXVTX-1 do begin\r
+ with CubeVtx^[I] do begin\r
+ (* Build cube *)\r
+ X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Z := Toggle( EDGE*$10000 );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ end;\r
+ with SphereVtx^[I] do begin\r
+ (* Build sphere *)\r
+Retry:\r
+ X := (longint(Random(2*RADIUS))-RADIUS);\r
+ Y := (longint(Random(2*RADIUS))-RADIUS);\r
+ if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+ Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+ end;\r
+ end;\r
+ (* Initialize morphing *)\r
+ Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+ Status := 0;\r
+ Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Fully unoptimized, slowest loop I could think of! *)\r
+ for I:=0 to MAXVTX-1 do begin\r
+ Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+ Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+ Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ C := #0;\r
+ repeat\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw points *)\r
+ for I:=0 to MAXVTX-1 do\r
+ mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ Page := 240-Page;\r
+ (* Morph *)\r
+ if( Odd(Status) ) then begin\r
+ Morph;\r
+ Inc( Morph1, Delta1 );\r
+ Inc( Morph2, Delta2 );\r
+ if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+ if( Status = 4 ) then Status := 0;\r
+ end\r
+ else begin\r
+ Dec( Count );\r
+ if( Count < 0 ) then begin\r
+ Inc( Status );\r
+ Count := WAITCOUNT;\r
+ Morph1 := InitMorph1[Status];\r
+ Morph2 := InitMorph2[Status];\r
+ Delta1 := InitDelta1[Status];\r
+ Delta2 := InitDelta2[Status];\r
+ end;\r
+ end;\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO04 - Multiple textures and triple buffering (3 pages)\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 256;\r
+ MAXCUB = 2;\r
+ MAXTXT = 2;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ TxtSunDial: array[ 0..7 ] of word = (\r
+ $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+ TxtSapphire : array[ 0..7 ] of word = (\r
+ $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+ TxtMarble: array[ 0..7 ] of word = (\r
+ $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of record X, Y: word end;\r
+ Width : word;\r
+ Data : pointer;\r
+ end;\r
+ TQuad = record\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+ TCube = record\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Base : integer;\r
+ end;\r
+var\r
+ Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+ VVtx : array[ 0..MAXVTX ] of T2DPoint;\r
+ Cube : array[ 0..MAXCUB ] of TCube;\r
+ ZList : array[ 0..MAXCUB ] of integer;\r
+ VtxCnt : word;\r
+ Txts : array[ 0..MAXTXT ] of TTexture;\r
+ Page : word;\r
+ Palette : array[ byte ] of record R, G, B: byte; end;\r
+ TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+ with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+ Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+ FaceIdx: array[ 0..23 ] of integer = (\r
+ 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+ I, VC: integer;\r
+begin\r
+ VC := VtxCnt;\r
+ C.Base := VC;\r
+ AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+ for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+ for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+ P: ^word;\r
+ I: integer;\r
+begin\r
+ P := @VtxData;\r
+ with Txts[Idx] do begin\r
+ for I:=0 to 3 do begin\r
+ Desc[I].X := P^; Inc( P );\r
+ Desc[I].Y := P^; Inc( P );\r
+ end;\r
+ Width := 129;\r
+ Data := TxtDat1;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+ V: integer;\r
+ F: file;\r
+ P: array[ 1..768 ] of byte;\r
+begin\r
+ (* Initialize objects *)\r
+ VtxCnt := 0;\r
+ MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *)\r
+ Cube[0].Face[0].Texture := 0;\r
+ V := VtxCnt;\r
+ MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+ tdSetTranslation( Trans );\r
+ tdSetRotation( 32, 32, 00 );\r
+ tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *)\r
+ for I:=V to V+7 do begin\r
+ Vtx[I].X := XVtx[I].X;\r
+ Vtx[I].Y := XVtx[I].Y;\r
+ Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+ end;\r
+ MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+ (* Load texture and palette *)\r
+ Assign( F, 'DEMO04.DAT' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, P, SizeOf(P) );\r
+ mxSetPalette( @P, 0, 256 );\r
+ GetMem( TxtDat1, 63*1024 );\r
+ BlockRead( F, TxtDat1^, 129*286 );\r
+ Close( F );\r
+ TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+ (* Init textures *)\r
+ MakeTexture( 0, TxtSundial );\r
+ MakeTexture( 1, TxtMarble );\r
+ MakeTexture( 2, TxtSapphire );\r
+ Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+ I, J, K: integer;\r
+ ZMax: array[ 0..MAXCUB ] of longint;\r
+ ZI: integer;\r
+ L: longint;\r
+begin\r
+ for I:=0 to MAXCUB do begin\r
+ L := XVtx[Cube[I].Base].Z;\r
+ for J:=1 to 7 do\r
+ if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+ ZMax[I] := L;\r
+ ZList[I] := I;\r
+ end;\r
+ for I:=0 to MAXCUB-1 do begin\r
+ ZI := I;\r
+ for J:=I+1 to MAXCUB do\r
+ if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+ if( ZI <> I ) then begin\r
+ K := ZList[I];\r
+ ZList[I] := ZList[ZI];\r
+ ZList[ZI] := K;\r
+ end;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I, J, K: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ AX := 0; AY := 0; AZ := 0;\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 600*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 1 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw objects *)\r
+ SortObjects;\r
+ for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+ for J:=0 to 5 do begin\r
+ K := Face[J].Texture;\r
+ mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+ end;\r
+ end;\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO05 - A Gouraud-shaded rotating torus\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+ MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *)\r
+ MAXVTX2 = 15; RADIUS2 = 30;\r
+ MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+ MAXFACE = MAXVTX;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *)\r
+ Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *)\r
+type\r
+ TQuad = record\r
+ QVtx : array[ 0..3 ] of integer;\r
+ end;\r
+var\r
+ Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *)\r
+ VVtx : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+ Face : array[ 0..MAXFACE ] of TQuad; (* Polys *)\r
+ Culled : array[ 0..MAXFACE ] of integer;\r
+ GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *)\r
+ VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *)\r
+ Page : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+ GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ R, N, X, Y, Z: real;\r
+ I, J, K, V: integer;\r
+begin\r
+ (* Build vertexes *)\r
+ for I:=0 to MAXVTX1 do begin\r
+ K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+ R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+ for J:=0 to MAXVTX2 do begin\r
+ V := I*(MAXVTX2+1)+J; (* Index of current vertex *)\r
+ (* Compute coordinates of current vertex *)\r
+ X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *)\r
+ Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+ Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+ Vtx[V].X := Round( X )*$10000; (* Save coordinates *)\r
+ Vtx[V].Y := Round( Y )*$10000;\r
+ Vtx[V].Z := Round( Z )*$10000;\r
+ (* Compute direction of Gouraud normal thru current vertex *)\r
+ X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+ Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+ N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *)\r
+ GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *)\r
+ GNrm[V].Y := Trunc( Y*$10000/N );\r
+ GNrm[V].Z := Trunc( Z*$10000/N );\r
+ end;\r
+ end;\r
+ (* Generate faces so that depth-sorting is not needed: there are still *)\r
+ (* some *very* little errors, but this is the best I could devise *)\r
+ J := 0;\r
+ K := 0;\r
+ for I:=0 to MAXFACE do with Face[I] do begin\r
+ QVtx[0] := GetVtx( J, K );\r
+ QVtx[1] := GetVtx( J, K+1 );\r
+ QVtx[2] := GetVtx( J+1, K+1 );\r
+ QVtx[3] := GetVtx( J+1, K );\r
+ Inc( K );\r
+ if( K > MAXVTX2 ) then begin\r
+ K := 0;\r
+ Inc( J );\r
+ end;\r
+ end;\r
+{$ifndef ALTPAL}\r
+ for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *)\r
+{$else}\r
+ for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+ for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetLight( Light );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+ tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *)\r
+ tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+ (* Backplane culling is not really needed here! *)\r
+ FillChar( Culled, SizeOf(Culled), 0 );\r
+ tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 3 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw polygons *)\r
+ for I:=0 to MAXFACE do with Face[I] do\r
+ if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO06 - Magnifying glass\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ R = 40; (* Lens radius *)\r
+ K : real = 1.8; (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+ TLine = array[ 0..319 ] of byte;\r
+ PLine = ^TLine;\r
+ TScreen = array[ 0..239 ] of PLine;\r
+var\r
+ VScreen: TScreen; (* Virtual screen *)\r
+ BallX : array[ 0..R, 0..R ] of integer;\r
+ BallY : array[ 0..R, 0..R ] of integer;\r
+ Sprite : array[ -R..R, -R..R ] of byte;\r
+ Page : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+ LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+ LR := Sqrt( X*X + Y*Y );\r
+ if( LR = 0 ) then Exit;\r
+ if( LR < R ) then begin\r
+ Z := Sqrt( R*R - LR*LR );\r
+ SinA := LR / R;\r
+ SinB := SinA / K;\r
+ TgB := SinB / Sqrt( 1-SinB*SinB );\r
+ Q := LR - TgB*Z;\r
+ X := Round( X * ( Q/LR ) );\r
+ Y := Round( Y * ( Q/LR ) );\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ F : file;\r
+ Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+ X, Y,\r
+ X2, Y2 : integer;\r
+begin\r
+ (* Load background image *)\r
+ Assign( F, 'demo06.dat' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, Palette, 768 );\r
+ mxSetPalette( @Palette, 0, 256 );\r
+ for Y:=0 to 239 do begin\r
+ New( VScreen[Y] );\r
+ BlockRead( F, VScreen[Y]^, 320 );\r
+ mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+ end;\r
+ Close( F );\r
+ (* Build lens *)\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ X2 := X;\r
+ Y2 := Y;\r
+ GetCoords( X2, Y2 );\r
+ BallX[X, Y] := X2;\r
+ BallY[X, Y] := Y2;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+ X, Y: integer;\r
+begin\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ end;\r
+ end;\r
+ (* Draw the sprite *)\r
+ mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+ Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*Delta;\r
+ end;\r
+end;\r
+\r
+var\r
+ X, Y, DX, DY: integer;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240;\r
+ X := R;\r
+ Y := R;\r
+ Randomize;\r
+ DX := Delta;\r
+ DY := Delta;\r
+\r
+ (* Main loop *)\r
+ repeat\r
+ (* Update video *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ PutLens( X, Y );\r
+ mxCircle( X, Page+Y, R, 0 );\r
+ (* Update lens coordinates *)\r
+ Inc( X, DX );\r
+ Check( X+R >= 319, X, DX, 319-R, -1 );\r
+ Check( X <= R, X, DX, R, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+ Check( Y <= R, Y, DY, R, +1 );\r
+ (* Flip pages: double buffering, avoid wait for display *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Wait for hidden page to show *)\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO07 - Hardware scrolling\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ (* Change this if scrolling seems jerky (this simple program does *)\r
+ (* not handle vertical retrace/display very well) *)\r
+ STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*(Random(3)+2);\r
+ end;\r
+end;\r
+\r
+var\r
+ I, X, Y, DX, DY: integer;\r
+begin\r
+ (* Initialize library and graphics mode *)\r
+ mxInit;\r
+ mxSetMode( MX_320x200 );\r
+ (* Set a 640x400 virtual screen *)\r
+ mxSetVirtualScreen( 640, 400 );\r
+ mxSetClip( TRUE );\r
+\r
+ X := 0;\r
+ Y := 0;\r
+ DX := 1;\r
+ DY := 1;\r
+\r
+ (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+ (* 320x200 windows, while smoothly panning virtual screen *)\r
+ while( not KeyPressed ) do begin\r
+ (* Points *)\r
+ mxSetClipRegion( 0, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxPutPixel( Random(320), Random(200), Random(16) );\r
+ (* Lines *)\r
+ mxSetClipRegion( 0, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+ (* Circles *)\r
+ mxSetClipRegion( 320, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+ (* Boxes *)\r
+ mxSetClipRegion( 320, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+ (* Pan *)\r
+ Inc( X, DX );\r
+ Check( X+320 >= 639, X, DX, 319, -1 );\r
+ Check( X < 0, X, DX, 0, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+ Check( Y < 0, Y, DY, 0, +1 );\r
+ mxPan( X, Y );\r
+ mxWaitRetrace;\r
+ end;\r
+\r
+ (* Shutdown *)\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT STRUC\r
+ X DD ?\r
+ Y DD ?\r
+ Z DD ?\r
+TPOINT ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT STRUC\r
+ IX DW ?\r
+ IY DW ?\r
+TIMAGEPOINT ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv MACRO arg\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul MACRO arg\r
+ imul arg\r
+ shrd eax, edx, 16\r
+ENDM\r
--- /dev/null
+unit Plasma;\r
+interface\r
+\r
+const\r
+ PAL_RGB = 0;\r
+ PAL_CLOUDS = 1;\r
+ PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+ Color: longint;\r
+begin\r
+ Color := Abs( XA-XB )+Abs( YA-YB );\r
+ Color := Random( Color shl 1 )-Color;\r
+ Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+ if( Color < 1 ) then Color := 1;\r
+ if( Color > 192 ) then Color := 192;\r
+ if( mxGetPixel( X, Y ) = 0 ) then\r
+ mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+ X, Y, Color: integer;\r
+begin\r
+ if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+ X := (X1+X2) shr 1;\r
+ Y := (Y1+Y2) shr 1;\r
+ NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+ NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+ NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+ NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+ Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+ mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+ mxPutPixel( X, Y, Color );\r
+ Divide( X1, Y1, X, Y );\r
+ Divide( X, Y1, X2, Y );\r
+ Divide( X, Y, X2, Y2 );\r
+ Divide( X1, Y, X, Y2 );\r
+ end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+ Dec( W );\r
+ Dec( H );\r
+ mxPutPixel( X, Y, C1 );\r
+ mxPutPixel( X, Y+H, C2 );\r
+ mxPutPixel( X+W, Y+H, C3 );\r
+ mxPutPixel( X+W, Y, C4 );\r
+ Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+ TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+ I: word;\r
+begin\r
+ FillChar( TPal(Palette)[1], 192*3, 0 );\r
+ case What of\r
+ PAL_CLOUDS:\r
+ for I:=1 to 192 do begin\r
+ TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].B := 63;\r
+ end;\r
+ PAL_LANDSCAPE:\r
+ begin\r
+ for I:=0 to 31 do begin\r
+ TPal(Palette)[I+1].R := I;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := I + I shr 1+15;\r
+ end;\r
+ for I:=32 to 63 do begin\r
+ TPal(Palette)[I+1].R := 0;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := 0;\r
+ end;\r
+ for I:=64 to 191 do begin\r
+ TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+ end;\r
+ end;\r
+ else\r
+ for I:=1 to 64 do begin\r
+ TPal(Palette)[I].G := I-1;\r
+ TPal(Palette)[I].B := 64-I;\r
+ TPal(Palette)[I+64].R := I-1;\r
+ TPal(Palette)[I+64].G := 64-I;\r
+ TPal(Palette)[I+128].B := I-1;\r
+ TPal(Palette)[I+128].R := 64-I;\r
+ end;\r
+ end;\r
+end;\r
+\r
+end.
\ No newline at end of file
--- /dev/null
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+ DEFVERT = 12; (* Vertex count *)\r
+ DEFREPL = 3; (* Repetition count *)\r
+ DEFQIXS = 2; (* Qixs *)\r
+ FADESPEED = 48;\r
+type\r
+ TPoint = record\r
+ X, Y : integer;\r
+ end;\r
+ TRGB = record\r
+ R, G, B: byte;\r
+ end;\r
+ TQix = record\r
+ Color: integer;\r
+ Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+ Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+ end;\r
+var\r
+ Page : integer;\r
+ MaxX,\r
+ MaxY : word;\r
+ Qix : array[ 0..DEFQIXS-1 ] of TQix;\r
+ Pal : array[ byte ] of TRGB;\r
+\r
+type\r
+ TReal = double;\r
+ TRPoint = record\r
+ X, Y: TReal;\r
+ end;\r
+ TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+ M: TMatrix;\r
+ G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+ C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=1 to Steps do begin\r
+ Pal[Idx+1].R := Pal[Idx].R + DR;\r
+ Pal[Idx+1].G := Pal[Idx].G + DG;\r
+ Pal[Idx+1].B := Pal[Idx].B + DB;\r
+ Inc( Idx );\r
+ end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+ with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+ with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+ BumpPal( 1, 0, 2, -2, 31 );\r
+ BumpPal( 32, 2, -2, 0, 31 );\r
+ BumpPal( 63, -2, 2, 2, 31 );\r
+ BumpPal( 94, 2, 0, -2, 31 );\r
+ BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+ for I:=0 to DEFVERT-1 do begin\r
+ Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+ Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+ Qix.Delta[I].X := Random(5)+1;\r
+ Qix.Delta[I].Y := Random(5)+1;\r
+ end;\r
+ Qix.Color := Color;\r
+\r
+ (* Initialize matrix (Catmull-Rom) *)\r
+ M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+ M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+ M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+ M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+ I, J: integer;\r
+ T, T2, T3: TReal;\r
+ X0, Y0, X, Y: TReal;\r
+ Delta: TReal;\r
+begin\r
+ (* Compute coefficients *)\r
+ for I:=0 to 3 do begin\r
+ C[I].X := 0;\r
+ for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+ C[I].Y := 0;\r
+ for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+ end;\r
+ X0 := C[3].X;\r
+ Y0 := C[3].Y;\r
+ Delta := 1 / N;\r
+ T := 0;\r
+ for I:=1 to N do begin\r
+ T := T + Delta;\r
+ T2 := T*T;\r
+ T3 := T*T2;\r
+ X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+ Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+ mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+ X0 := X;\r
+ Y0 := Y;\r
+ end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+ I, J: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do begin\r
+ mxBezier( Qix, I, Idx, 12 );\r
+ end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Inc( Vert[I,Idx].X, Delta[I].X );\r
+ if( Vert[I,Idx].X < 0 ) then begin\r
+ Vert[I,Idx].X := 0;\r
+ Delta[I].X := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].X > MaxX ) then begin\r
+ Vert[I,Idx].X := MaxX;\r
+ Delta[I].X := -Random( 5 )-1;\r
+ end;\r
+ Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+ if( Vert[I,Idx].Y < 0 ) then begin\r
+ Vert[I,Idx].Y := 0;\r
+ Delta[I].Y := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].Y > MaxY ) then begin\r
+ Vert[I,Idx].Y := MaxY;\r
+ Delta[I].Y := -Random( 5 )-1;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Vert[I,Dest].X := Vert[I,Src].X;\r
+ Vert[I,Dest].Y := Vert[I,Src].Y;\r
+ end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+ Q, Idx, I, J, P, Count: integer;\r
+begin\r
+ Count := 0;\r
+ P := DEFREPL-1;\r
+ I := 0;\r
+ J := 1;\r
+ repeat\r
+ mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Copy( Qix[Q], I, P );\r
+ Update( Qix[Q], I );\r
+ for Idx:=0 to DEFREPL-1 do begin\r
+ Plot( Qix[Q], Idx );\r
+ end;\r
+ end;\r
+ I := (I+1) mod DEFREPL;\r
+ J := (J+1) mod DEFREPL;\r
+ P := (P+1) mod DEFREPL;\r
+ Inc( Count );\r
+ mxStartLine( Page );\r
+ if( Count >= FADESPEED ) then begin\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Inc( Qix[Q].Color );\r
+ if( Qix[Q].Color > 156 ) then\r
+ Qix[Q].Color := 1;\r
+ end;\r
+ Count := 0;\r
+ end;\r
+ Page := 240-Page;\r
+ until( KeyPressed );\r
+end;\r
+\r
+var\r
+ I: integer;\r
+begin\r
+ Randomize;\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ mxGetScreenSize( MaxX, MaxY );\r
+ for I:=0 to DEFQIXS-1 do\r
+ Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+ InitPalette;\r
+ mxSetPalette( @Pal, 0, 157 );\r
+ Page := 240;\r
+ Dec( MaxX );\r
+ Dec( MaxY );\r
+ AnimateQix;\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin LABEL DWORD\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+tblCos LABEL DWORD\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
--- /dev/null
+COMMENT /\r
+ Fixed-point math functions and 3D transforms\r
+ Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC tdFixedMul\r
+PUBLIC tdGetNormal\r
+PUBLIC tdRotate\r
+PUBLIC tdGetSurfaceLight\r
+PUBLIC tdSetLight\r
+PUBLIC tdSetRotation\r
+PUBLIC tdSetTranslation\r
+PUBLIC tdTransform\r
+PUBLIC tdTransformToImage\r
+PUBLIC tdTransformLight\r
+PUBLIC tdBackPlaneCull\r
+PUBLIC tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA'\r
+ ASSUME ds:MATH_DATA\r
+\r
+INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table\r
+\r
+XRotation TPOINT <> ; 3x3 rotation matrix\r
+YRotation TPOINT <>\r
+ZRotation TPOINT <>\r
+\r
+Translation TPOINT <> ; Translation vector\r
+\r
+Light TPOINT <> ; Light vector\r
+AmbientLight DW 00 ; Ambient light\r
+\r
+XScale DD 10000h ; Scaling factor for X coordinate\r
+YScale DD 10000h ; Scaling factor for Y coordinate\r
+PerspectiveDistance DD 20000000h\r
+\r
+MATH_DATA ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective PROC PASCAL FAR\r
+ ARG Perspective:DWORD, \\r
+ ScaleX:DWORD, \\r
+ ScaleY:DWORD\r
+ USES ds\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov eax, [Perspective]\r
+ mov [PerspectiveDistance], eax\r
+ mov eax, [ScaleX]\r
+ mov [XScale], eax\r
+ mov eax, [ScaleY]\r
+ mov [YScale], eax\r
+\r
+ ret\r
+tdSetPerspective ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+; RX = X-axis rotation angle\r
+; RY = X-axis rotation angle\r
+; RZ = X-axis rotation angle\r
+; Output:\r
+; none\r
+;\r
+tdSetRotation PROC PASCAL FAR\r
+ ARG RX:WORD, \\r
+ RY:WORD, \\r
+ RZ:WORD\r
+ USES ds, si, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov bx, [RZ]\r
+ mov si, [RY]\r
+ mov di, [RX]\r
+ shl bx, 2\r
+ shl si, 2\r
+ shl di, 2\r
+\r
+ push ebp ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.Y], edx\r
+\r
+ mov eax, tblSin[si]\r
+ sar eax, 8 ; Convert fixed 8:24 to fixed 16:16\r
+ mov [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si] ; EDX:EAX = fixed 16:48\r
+ shrd eax, edx, 24 ; EAX = fixed 8:24\r
+ imul tblSin[di] ; EDX:EAX = fixed 16:48\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[di]\r
+ add eax, ebp\r
+ adc edx, ecx ; EDX:EAX = fixed 16:48\r
+ neg edx\r
+ mov [YRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblSin[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [YRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblSin[di]\r
+ mov [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [ZRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[di]\r
+ add eax, ebp\r
+ add edx, ecx\r
+ neg edx\r
+ mov [ZRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblCos[di]\r
+ mov [ZRotation.Z], edx\r
+\r
+ pop ebp ; Restore EBP\r
+\r
+ ret\r
+tdSetRotation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+; TV = pointer to translation vector\r
+; Output:\r
+; none\r
+;\r
+tdSetTranslation PROC PASCAL FAR\r
+ ARG TV:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [TV]\r
+ mov eax, es:[di].X\r
+ mov [Translation.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Translation.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Translation.Z], eax\r
+\r
+ ret\r
+tdSetTranslation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransform PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ LOCAL Adjust:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+ ALIGN DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ mov ebx, eax\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16)\r
+ mov es:[di].Z, eax\r
+; Get perspective factor\r
+ mov ebx, [PerspectiveDistance]\r
+ sub eax, ebx\r
+ neg eax ; EAX = PD - Z\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx ; EAX = fixed 16:16 result\r
+ mov [Adjust], eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.X]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Y]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdTransform ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TIMAGEPOINT\r
+; Count = number of entries to transform\r
+; DeltaX = translation distance for the X coordinate\r
+; DeltaY = translation distance for the Y coordinate\r
+; Output:\r
+; the maximum Z value\r
+;\r
+tdTransformToImage PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD\r
+ LOCAL Adjust:DWORD, \\r
+ Max:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+ mov [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+ mov eax, fs:[si].Z\r
+ cmp eax, [Max]\r
+ jle @@1\r
+ mov [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+ mov ax, WORD PTR fs:[si].X[2]\r
+ add ax, [DeltaX]\r
+ mov es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+ mov ax, WORD PTR fs:[si].Y[2]\r
+ add ax, [DeltaY]\r
+ mov es:[di].IY, ax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TIMAGEPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ mov eax, [Max]\r
+ shld edx, eax, 16\r
+ ret\r
+tdTransformToImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+; Light = pointer to light vector\r
+; Output:\r
+; none\r
+;\r
+tdSetLight PROC PASCAL FAR\r
+ ARG L:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [L]\r
+ mov eax, es:[di].X\r
+ mov [Light.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Light.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Light.Z], eax\r
+\r
+ ret\r
+tdSetLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+; Normals = pointer to an array of surface normals\r
+; Lights = pointer to an array of integer to be filled with\r
+; light intensity\r
+; Count = number of elements to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransformLight PROC PASCAL FAR\r
+ ARG Normals:DWORD, \\r
+ Lights:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov fs, ax\r
+ ASSUME fs:MATH_DATA\r
+\r
+ lds si, [Normals]\r
+ les di, [Lights]\r
+ ASSUME ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+ mov eax, ds:[si].Z\r
+ imul [Light.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, ds:[si].Y\r
+ imul [Light.Y]\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, ds:[si].X\r
+ imul [Light.X]\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = fixed 32:32 intensity\r
+ add dx, [AmbientLight]\r
+ test dx, dx\r
+ jg @@1\r
+ xor dx, dx ; Return 0 for no light\r
+@@1:\r
+ mov es:[di], dx\r
+ inc di\r
+ inc di\r
+ add si, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ASSUME fs:NOTHING\r
+ ret\r
+tdTransformLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+; Normal = pointer to TPOINT surface normal vector\r
+; Output:\r
+; AX = light intensity (>=0)\r
+; Notes:\r
+; the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight PROC PASCAL FAR\r
+ ARG Normal:DWORD\r
+ USES ds, esi, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [Normal]\r
+\r
+; Transform Z coordinate\r
+ mov eax, es:[di].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.Z]\r
+ shrd eax, edx, 16\r
+ mov esi, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, es:[di].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add esi, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, es:[di].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add eax, esi\r
+ shr eax, 16\r
+\r
+; Add ambient light\r
+ add ax, [AmbientLight]\r
+ test ax, ax\r
+ jge @@Exit\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ ret\r
+tdGetSurfaceLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdRotate PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdRotate ENDP\r
+\r
+tdFixedMul PROC PASCAL FAR\r
+ ARG F1:DWORD, \\r
+ F2:DWORD\r
+\r
+ mov eax, [F1]\r
+ imul [F2]\r
+ shr eax, 16\r
+\r
+ ret\r
+tdFixedMul ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+ push esi\r
+ push edi\r
+\r
+ add eax, eax\r
+ adc edx, 0\r
+ mov eax, edx ; Just discard the low bits\r
+\r
+ mov esi, eax\r
+ xor edi, edi\r
+ shld edi, esi, 16\r
+ shl esi, 16\r
+@@Loop:\r
+ mov ebx, eax\r
+ mul eax\r
+ add eax, esi\r
+ adc edx, edi\r
+ shrd eax, edx, 1\r
+ shr edx, 1\r
+ div ebx\r
+ cmp eax, ebx\r
+ jne @@Loop\r
+\r
+; Adjust EAX\r
+ shl eax, 8\r
+\r
+ pop edi\r
+ pop esi\r
+ ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+; Dest = pointer to TPOINT (vector) result\r
+; P1, P2, P3 = pointer to TPOINT points on surface\r
+; Output:\r
+; none\r
+; Notes:\r
+; the normal is given by the cross-product between (P3-P1) and\r
+; (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal PROC PASCAL FAR\r
+ ARG Dest:DWORD, \\r
+ P1:DWORD, \\r
+ P2:DWORD, \\r
+ P3:DWORD\r
+ LOCAL V1:TPOINT, \\r
+ V2:TPOINT, \\r
+ N:TPOINT\r
+ USES ds, si, es, di\r
+\r
+; Get vector V1\r
+ lds si, [P1]\r
+ les di, [P3]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V1.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V1.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V1.Z], eax\r
+\r
+; Get vector V2\r
+ les di, [P2]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V2.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V2.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+ mov eax, [V1.Z]\r
+ imul [V2.Y]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Y]\r
+ imul [V2.Z]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.X], eax\r
+\r
+ mov eax, [V1.X]\r
+ imul [V2.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Z]\r
+ imul [V2.X]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Y], eax\r
+\r
+ mov eax, [V1.Y]\r
+ imul [V2.X]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.X]\r
+ imul [V2.Y]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Z], eax\r
+\r
+; Get normal length\r
+ mov eax, [N.X]\r
+ imul eax\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [N.Y]\r
+ imul eax\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, [N.Z]\r
+ imul eax\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+ call subSqrt ; EAX = normal length\r
+ mov ebx, eax\r
+\r
+; Adjust vector and save it\r
+ les di, [Dest]\r
+ mov eax, [N.X]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].X, eax\r
+ mov eax, [N.Y]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Y, eax\r
+ mov eax, [N.Z]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Z, eax\r
+\r
+ ret\r
+tdGetNormal ENDP\r
+\r
+TPOLY STRUC\r
+ Vtx DW 4 DUP(?)\r
+TPOLY ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+; Poly = pointer to an array of TPOLY\r
+; Vertex = pointer to an array of TPOINT\r
+; Dest = pointer to an array of integer\r
+; Count = number of polygons to check\r
+; Step = size of TPOLY structure\r
+; Output:\r
+; if the n-th polygon is invisible the n-th entry of the\r
+; Dest array is set to -1, other entries are not modified\r
+; (so it's possible to use the Light array for Dest, because\r
+; the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+ ARG Step:WORD, \\r
+ Poly:DWORD, \\r
+ Vertex:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ds, WORD PTR Vertex[2]\r
+ les di, [Poly]\r
+ mov fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+ mov ax, es:[di].Vtx[2] ; Index of 2nd vertex\r
+ shl ax, 2\r
+ mov bx, ax\r
+ shl ax, 1\r
+ add bx, ax ; BX = index*SIZE TPOINT\r
+ add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex\r
+ mov ax, es:[di].Vtx[4] ; Index of 3rd vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex\r
+ mov ecx, ds:[si].X\r
+ sub ecx, ds:[bx].X ; ECX = V3.X-V2.X\r
+ mov edx, ds:[si].Y\r
+ sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y\r
+ mov ax, es:[di].Vtx[0] ; Index of 1st vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 1st vertex\r
+ mov eax, ds:[si].X\r
+ sub eax, ds:[bx].X ; EAX = V1.X-V2.X\r
+ mov esi, ds:[si].Y\r
+ sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y\r
+ imul edx\r
+ mov ebx, eax\r
+ xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+ mov eax, esi\r
+ imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ jl @@Next ; Polygon is visible\r
+ mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry\r
+ mov WORD PTR fs:[bx], -1 ; Remove polygon\r
+@@Next:\r
+ add WORD PTR [Dest], 2 ; Next entry for dest\r
+ add di, [Step] ; Next polygon\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT ENDS\r
+END\r
--- /dev/null
+typedef struct {\r
+ long x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT TVECTOR\r
+#define PPOINT PVECTOR\r
+\r
+#define VPTR void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+unit ThreeD;\r
+interface\r
+\r
+type\r
+ TVector = record\r
+ X, Y, Z : longint;\r
+ end;\r
+ TPoint = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight; external;\r
+procedure tdSetRotation( RX, RY, RZ: word ); external;\r
+procedure tdGetNormal; external;\r
+procedure tdSetTranslation( var TV: TVector ); external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate; external;\r
+function tdTransformToImage; external;\r
+procedure tdSetLight( var Light: TVector ); external;\r
+procedure tdSetPerspective; external;\r
+procedure tdTransformLight; external;\r
+function tdFixedMul( F1, F2: longint ): longint; external;\r
+procedure tdBackPlaneCull; external;\r
+{$L THREED}\r
+\r
+end.\r
--- /dev/null
+/*\r
+ * DEMO01 - Sprites, page flipping and palette rotation\r
+ * Copyright (c) 1994 Alessandro Scotti\r
+ */\r
+#include ../../x/modex.h\r
+\r
+#DEFINE MAX_SPRITE 100\r
+\r
+typedef unsigned char byte;\r
+typedef unsigned short word;\r
+typedef unsigned long dword;\r
+\r
+/* Sprite structure */\r
+typedef struct {\r
+ int X, Y; /* Sprite coordinates */\r
+ int DX,DY; /* Deltas for sprite movement */\r
+ int W, H; /* Sprite width and height */\r
+ byte Image[16,16]; /* Sprite image data */\r
+} TSprite;\r
+\r
+/* RGB color structure */\r
+typedef struct {\r
+ byte R, G, B;\r
+} TRgb;\r
+Tsprite S[MAX_SPRITE]; /* An array of sprites */\r
+TRgb Palette[ byte ]; /* Palette */\r
+word Page; /* Page offset */\r
+word i;\r
+\r
+/* Initializes a sprite structure */\r
+void sxInit(TSprite *S)\r
+{\r
+//word i;\r
+\r
+S->X = rand( 320 ); /* Initialize position with random values */\r
+S->Y = rand( 240 );\r
+S->DX = rand( 7 )-3; /* Initialize speed with random values */\r
+S->DY = rand( 7 )-3;\r
+S->W = 16; /* Size is fixed in this program */\r
+S->H = 16;\r
+/* The image is a square with a hole inside */\r
+FillChar( S->Image, SizeOf(S->Image), rand(15)+1 );\r
+ for(i=5; i<=12;i++)\r
+ {\r
+ FillChar( S->Image[ i, 5 ], 8, 0 );\r
+ }\r
+}\r
+\r
+/* Moves a sprite */\r
+void sxMove(TSprite *S)\r
+{\r
+//Inc( S.X, S.DX ); /* Get new position */\r
+//Inc( S.Y, S.DY );\r
+/* Check sprite position, change delta if needed */\r
+if( S->X > 320 ){\r
+ S->X = 320;\r
+S->DX = -S->DX;\r
+}\r
+if( S->X < -16 ){\r
+ S->X = -16;\r
+S->DX = -S->DX;\r
+}\r
+if( S->Y > 240 ){\r
+ S.Y = 240;\r
+ S->DY = -S->DY;\r
+}\r
+if( S->Y < -16 ){\r
+ S->Y = -16;\r
+ S->DY = -S->DY;\r
+}\r
+/* Draw the sprite, note the Page offset added to the */\r
+/* Y coordinate of the image */\r
+mxPutImage( S.Image, S->X, Page+S->Y, S->W, S->H, OP_TRANS );\r
+}\r
+\r
+void main()\r
+{\r
+ int i;\r
+ //TSprite S;\r
+ /* Initialize library */\r
+ mxInit();\r
+ \r
+ /* Enter graphics mode */\r
+ mxSetMode( MX_320x240 );\r
+ \r
+ /* Print initialization message */\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+ \r
+ /* Initialize sprites */\r
+ for(i=1;i<=MAX_SPRITE;i++)\r
+ sxInit( &S[i] );\r
+ \r
+ /* Draw background */\r
+ for(i=1;i<=192;i++)\r
+ {\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ }\r
+ \r
+ /* Compute and set palette */\r
+ for(i=1;i<= 192;Palette[i+63])\r
+ {\r
+ short R = 0;\r
+ short G = 0;\r
+ short B = 0;\r
+ if( i < 64 )\r
+ R = i >> 1+31;\r
+ else if( i < 128 )\r
+ G = (i-64) >> 1+31;\r
+ else\r
+ B = (i-128) >> 1+31;\r
+ }\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ \r
+ /* Main loop */\r
+ short Page = 240;\r
+ while(!kbhit())\r
+ {\r
+ /* Set clip region to current page */\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ /* Restore background */\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ /* Draw sprites */\r
+ for(i=1; i <= MAX_SPRITE; sxMove( S[i] ));\r
+ /* Print message */\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ /* Flip page */\r
+ mxStartLine( Page );\r
+ Page = 240-Page;\r
+ /* Animate palette */\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ }\r
+ \r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+ \r
+}\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN PRO\r
+;NOWARN RES\r
+INCLUDE modex.def\r
+\r
+PUBLIC mxBitBlt\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN subHorizontalLineInfo : NEAR\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+; SX, SY = source coordinates\r
+; Width = source width\r
+; Height = source height\r
+; DX, DY = destination coordinates\r
+; Output:\r
+; none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt PROC FAR\r
+ ARG DestY:WORD, \\r
+ DestX:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ SY:WORD, \\r
+ SX:WORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ SourceOffset:WORD, \\r
+ DestOffset:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ WritePlane:BYTE, \\r
+ LeftMask:BYTE, \\r
+ RightMask:BYTE = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Exit now if null width\r
+ cmp [Width], 0\r
+ je @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+ mov ax, [SX]\r
+ and al, 03h ; AL = source plane\r
+ mov dx, [DestX]\r
+ and dl, 03h ; DL = destination plane\r
+ mov bx, OFFSET subPlaneBlt\r
+ cmp al, dl ; Same source and destination plane?\r
+ jne @@BitBlt ; No, use slow procedure\r
+ mov bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+ call bx\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt PROC NEAR\r
+; Get horizontal line info and address of destination\r
+ mov bx, [DestX]\r
+ mov ax, [DestY]\r
+ mov cx, [Width]\r
+ call subHorizontalLineInfo\r
+ mov [LeftMask], al\r
+ mov [RightMask], ah\r
+ mov [Width], cx\r
+\r
+; Setup segments\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov es, ax\r
+\r
+; Get address of source pixel\r
+ mov ax, [SY]\r
+ mul [mx_BytesPerLine]\r
+ mov si, [SX]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+; Set write mode 1\r
+ mov dx, GDC\r
+ mov ax, 4105h\r
+ out dx, ax\r
+ cld\r
+\r
+; Move left block\r
+@@L0:\r
+ mov ah, [LeftMask]\r
+ or ah, ah\r
+ jz @@C0\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov ax, [mx_BytesPerLine]\r
+ dec ax\r
+ mov cx, [Height]\r
+ .push si, di\r
+@@L1:\r
+ movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec cx\r
+ jnz @@L1\r
+ .pop si, di\r
+ inc si\r
+ inc di\r
+\r
+; Move center block\r
+@@C0:\r
+ mov bx, [Width]\r
+ test bx, bx\r
+ jz @@R0\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Enable all planes\r
+ mov ax, [mx_BytesPerLine]\r
+ sub ax, bx\r
+ mov dx, [Height]\r
+ .push si, di\r
+@@C1:\r
+ mov cx, bx ; CX = image width\r
+ rep movsb ; Cannot use "movsw" here!\r
+ add si, ax ; Next scan line\r
+ add di, ax ; Next scan line\r
+ dec dx ; All lines processed?\r
+ jnz @@C1 ; No, continue\r
+ .pop si, di\r
+ add si, bx\r
+ add di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+ mov ah, [RightMask]\r
+ or ah, ah\r
+ jz @@Done\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov ax, [mx_BytesPerLine]\r
+ dec ax\r
+ mov cx, [Height]\r
+@@R1:\r
+ movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec cx\r
+ jnz @@R1\r
+\r
+@@Done:\r
+ mov dx, GDC\r
+ mov ax, 4005h\r
+ out dx, ax ; Restore write mode 0\r
+\r
+@@Exit:\r
+ ret\r
+subMoveBlt ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt PROC NEAR\r
+; Compute extra bytes and width count for each plane\r
+ mov cx, [Width]\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Get pixel addresses\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov es, ax\r
+ mov ax, [SY]\r
+ mul [mx_BytesPerLine]\r
+ mov si, [SX]\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax ; DS:SI points to source\r
+ mov [SourceOffset], si\r
+ mov ax, [DestY]\r
+ mul [mx_BytesPerLine]\r
+ mov di, [DestX]\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax ; ES:DI points to destination\r
+ mov [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+ mov ax, [SX]\r
+ and al, 03h\r
+ mov [ReadPlane], al\r
+ mov cx, [DestX]\r
+ and cl, 03h\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Ready to move now\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0\r
+ je @@Done\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov ax, [mx_BytesPerLine]\r
+ sub ax, ss:[bx] ; AX = extra bytes per line\r
+@@Loop:\r
+ mov cx, ss:[bx]\r
+ shr cx, 1\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+ add si, ax\r
+ add di, ax\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ and [ReadPlane], 03h ; Should be faster on 386 using\r
+ jnz @@ReadPlaneOk ; BTR and ADC...\r
+ inc [SourceOffset]\r
+@@ReadPlaneOk:\r
+ rol [WritePlane], 1\r
+ adc [DestOffset], 0\r
+ mov si, [SourceOffset]\r
+ mov di, [DestOffset]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Done:\r
+ ret\r
+subPlaneBlt ENDP\r
+\r
+mxBitBlt ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCC.ASM - Fast clip line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC xsubClipLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+tblGroups LABEL WORD\r
+ DW 10, tbl00\r
+ DW 10, tbl10\r
+ DW 9, tbl20\r
+ DW -1, 0\r
+ DW 10, tbl40\r
+ DW 10, tbl50\r
+ DW 9, tbl60\r
+ DW -1, 0\r
+ DW 6, tbl80\r
+ DW 6, tbl90\r
+ DW 5, tblA0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+ DW -1, 0\r
+tbl00 DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A\r
+tbl10 DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A\r
+tbl20 DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29\r
+tbl40 DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A\r
+tbl50 DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A\r
+tbl60 DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69\r
+tbl80 DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86\r
+tbl90 DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96\r
+tblA0 DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5\r
+\r
+ccTT: clc\r
+ ret\r
+ccFF: stc\r
+ ret\r
+\r
+; Group 00 -------------------------------------------------\r
+;\r
+cc00:\r
+ clc\r
+ ret\r
+cc01:\r
+ jmp ClipQLeft\r
+cc02:\r
+ jmp ClipQRight\r
+cc04:\r
+ jmp ClipQTop\r
+cc05:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge ccTT\r
+ jmp ClipQTop\r
+cc06:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jge ccTT\r
+ jmp ClipQTop\r
+cc08:\r
+ jmp ClipQBottom\r
+cc09:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jle ccTT\r
+ jmp ClipQBottom\r
+cc0A:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jle ccTT\r
+ jmp ClipQBottom\r
+\r
+; Group 10 -------------------------------------------------\r
+;\r
+cc10FF:\r
+ stc\r
+ ret\r
+cc10TT:\r
+ clc\r
+ ret\r
+cc10:\r
+ jmp ClipPLeft\r
+cc12:\r
+ call ClipPLeft\r
+ jmp ClipQRight\r
+cc14:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc10FF\r
+ jmp ClipQTop\r
+cc16:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc10FF\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX2]\r
+ jle cc10TT\r
+ jmp ClipQRight\r
+cc18:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc10FF\r
+ jmp ClipQBottom\r
+cc1A:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc10FF\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX2]\r
+ jle cc10TT\r
+ jmp ClipQRight\r
+\r
+; Group 20 -------------------------------------------------\r
+;\r
+cc20TT:\r
+ clc\r
+ ret\r
+cc20FF:\r
+ stc\r
+ ret\r
+cc20:\r
+ jmp ClipPRight\r
+cc21:\r
+ call ClipPRight\r
+ jmp ClipQLeft\r
+cc24:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc20FF\r
+ jmp ClipQTop\r
+cc25:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc20FF\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX1]\r
+ jge cc20TT\r
+ jmp ClipQLeft\r
+cc28:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc20FF\r
+ jmp ClipQBottom\r
+cc29:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc20FF\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX1]\r
+ jge cc20TT\r
+ jmp ClipQLeft\r
+\r
+; Group 40 -------------------------------------------------\r
+;\r
+cc40TT:\r
+ clc\r
+ ret\r
+cc40FF:\r
+ stc\r
+ ret\r
+cc40:\r
+ jmp ClipPTop\r
+cc41:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jl cc40FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge cc40TT\r
+ jmp ClipQTop\r
+cc42:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jg cc40FF\r
+ jmp ClipQRight\r
+cc48:\r
+ call ClipPTop\r
+ jmp ClipQBottom\r
+cc49:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jl cc40FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jle cc40TT\r
+ jmp ClipQBottom\r
+cc4A:\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jg cc40FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jle cc40TT\r
+ jmp ClipQBottom\r
+\r
+\r
+; Group 50 -------------------------------------------------\r
+;\r
+cc50TT:\r
+ clc\r
+ ret\r
+cc50FF:\r
+ stc\r
+ ret\r
+cc50:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc50TT\r
+ jmp ClipPTop\r
+cc52:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jl cc50FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jge cc50TT\r
+ jmp ClipPLeft\r
+cc58:\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX1]\r
+ jl cc50FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX1]\r
+ jge cc50TT\r
+ jmp ClipPLeft\r
+cc5A:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc50FF\r
+ call ClipQRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc50FF\r
+ cmp si, [mx_ClipY2]\r
+ jle cc50TT\r
+ jmp ClipQBottom\r
+\r
+; Group 60 -------------------------------------------------\r
+;\r
+cc60TT:\r
+ clc\r
+ ret\r
+cc60FF:\r
+ stc\r
+ ret\r
+cc60:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+cc61:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jl cc60FF\r
+ call ClipPTop\r
+ cmp di, [mx_ClipX2]\r
+ jle cc60TT\r
+ jmp ClipPRight\r
+cc68:\r
+ call ClipQBottom\r
+ cmp cx, [mx_ClipX2]\r
+ jg cc60FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+cc69:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jl cc60FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jg cc60FF\r
+ cmp si, [mx_ClipY2]\r
+ jle cc69_1\r
+ call ClipQBottom\r
+cc69_1:\r
+ cmp bx, [mx_ClipY1]\r
+ jge cc60TT\r
+ jmp ClipPTop\r
+\r
+; Group 80 -------------------------------------------------\r
+;\r
+cc80TT:\r
+ clc\r
+ ret\r
+cc80FF:\r
+ stc\r
+ ret\r
+cc80:\r
+ jmp ClipPBottom\r
+cc81:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jl cc80FF\r
+ jmp ClipQLeft\r
+cc82:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jg cc80FF\r
+ jmp ClipQRight\r
+cc84:\r
+ call ClipPBottom\r
+ jmp ClipQTop\r
+cc85:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jl cc80FF\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY1]\r
+ jge cc80FF\r
+ jmp ClipQTop\r
+cc86:\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jg cc80FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY1]\r
+ jge cc80TT\r
+ jmp ClipQTop\r
+\r
+; Group 90 -------------------------------------------------\r
+;\r
+cc90TT:\r
+ clc\r
+ ret\r
+cc90FF:\r
+ stc\r
+ ret\r
+cc90:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc90TT\r
+ jmp ClipPBottom\r
+cc92:\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jg cc90FF\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX1]\r
+ jge cc90TT\r
+ jmp ClipPLeft\r
+cc94:\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX1]\r
+ jl cc90FF\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc90TT\r
+ jmp ClipPBottom\r
+cc96:\r
+ call ClipPLeft\r
+ cmp bx, [mx_ClipY1]\r
+ jl cc90FF\r
+ call ClipQRight\r
+ cmp si, [mx_ClipY2]\r
+ jg cc90FF\r
+ cmp bx, [mx_ClipY2]\r
+ jle cc96_1\r
+ call ClipPBottom\r
+cc96_1:\r
+ cmp si, [mx_ClipY1]\r
+ jge cc90TT\r
+ jmp ClipQTop\r
+\r
+; Group A0 -------------------------------------------------\r
+;\r
+ccA0TT:\r
+ clc\r
+ ret\r
+ccA0FF:\r
+ stc\r
+ ret\r
+ccA0:\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+ccA1:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jg ccA0FF\r
+ call ClipPBottom\r
+ cmp di, [mx_ClipX2]\r
+ jle ccA0TT\r
+ jmp ClipPRight\r
+ccA4:\r
+ call ClipQTop\r
+ cmp cx, [mx_ClipX2]\r
+ jg ccA0FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+ccA5:\r
+ call ClipQLeft\r
+ cmp si, [mx_ClipY2]\r
+ jg ccA0FF\r
+ call ClipPRight\r
+ cmp bx, [mx_ClipY1]\r
+ jl ccA0FF\r
+ cmp si, [mx_ClipY1]\r
+ jge ccA5_1\r
+ call ClipQTop\r
+ccA5_1:\r
+ cmp bx, [mx_ClipY2]\r
+ jle ccA0TT\r
+ jmp ClipPBottom\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX1\r
+ClipPLeft:\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov dx, [mx_ClipX1]\r
+ sub dx, di\r
+ imul dx\r
+ mov bp, cx\r
+ sub bp, di\r
+ idiv bp\r
+ add bx, ax\r
+ mov di, [mx_ClipX1]\r
+ clc\r
+ ret\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX2\r
+ClipPRight:\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov dx, [mx_ClipX2]\r
+ sub dx, di\r
+ imul dx\r
+ mov bp, cx\r
+ sub bp, di\r
+ idiv bp\r
+ add bx, ax\r
+ mov di, [mx_ClipX2]\r
+ clc\r
+ ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY2\r
+ClipPBottom:\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov dx, [mx_ClipY2]\r
+ sub dx, bx\r
+ imul dx\r
+ mov bp, si\r
+ sub bp, bx\r
+ idiv bp\r
+ add di, ax\r
+ mov bx, [mx_ClipY2]\r
+ clc\r
+ ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY1\r
+ClipPTop:\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov dx, [mx_ClipY1]\r
+ sub dx, bx\r
+ imul dx\r
+ mov bp, si\r
+ sub bp, bx\r
+ idiv bp\r
+ add di, ax\r
+ mov bx, [mx_ClipY1]\r
+ clc\r
+ ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQLeft:\r
+ mov ax, bx\r
+ sub ax, si\r
+ mov dx, [mx_ClipX1]\r
+ sub dx, cx\r
+ imul dx\r
+ mov bp, di\r
+ sub bp, cx\r
+ idiv bp\r
+ add si, ax\r
+ mov cx, [mx_ClipX1]\r
+ clc\r
+ ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQRight:\r
+ mov ax, bx\r
+ sub ax, si\r
+ mov dx, [mx_ClipX2]\r
+ sub dx, cx\r
+ imul dx\r
+ mov bp, di\r
+ sub bp, cx\r
+ idiv bp\r
+ add si, ax\r
+ mov cx, [mx_ClipX2]\r
+ clc\r
+ ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQBottom:\r
+ mov ax, di\r
+ sub ax, cx\r
+ mov dx, [mx_ClipY2]\r
+ sub dx, si\r
+ imul dx\r
+ mov bp, bx\r
+ sub bp, si\r
+ idiv bp\r
+ add cx, ax\r
+ mov si, [mx_ClipY2]\r
+ clc\r
+ ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQTop:\r
+ mov ax, di\r
+ sub ax, cx\r
+ mov dx, [mx_ClipY1]\r
+ sub dx, si\r
+ imul dx\r
+ mov bp, bx\r
+ sub bp, si\r
+ idiv bp\r
+ add cx, ax\r
+ mov si, [mx_ClipY1]\r
+ clc\r
+ ret\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was\r
+; supposed to be twice as fast as Cohen-Sutherland, but my\r
+; tests show only a very small increase in speed and a noticeable\r
+; increase of the program size! Maybe this is caused by the\r
+; slow speed of VGA cards, so probably a better test should\r
+; be performed with lines drawn in RAM.\r
+;\r
+; Input:\r
+; AX, BX = X1, Y1\r
+; CX, DX = X2, Y2\r
+; Output:\r
+; CF = set if line is full clipped\r
+; AX, BX = clipped X1, Y1\r
+; CX, DX = clipped X2, Y2\r
+; Note:\r
+; destroys SI, DI\r
+;\r
+xsubClipLine PROC NEAR\r
+ push bp\r
+ xor si, si ; SPY code\r
+\r
+ cmp dx, [mx_ClipY2]\r
+ jle @@1\r
+ or si, 08h\r
+ jmp @@2\r
+@@1:\r
+ cmp dx, [mx_ClipY1]\r
+ jge @@2\r
+ or si, 04h\r
+@@2:\r
+\r
+ cmp cx, [mx_ClipX2]\r
+ jle @@3\r
+ or si, 02h\r
+ jmp @@4\r
+@@3:\r
+ cmp cx, [mx_ClipX1]\r
+ jge @@4\r
+ or si, 01h\r
+@@4:\r
+\r
+ cmp bx, [mx_ClipY2]\r
+ jle @@5\r
+ or si, 80h\r
+ jmp @@6\r
+@@5:\r
+ cmp bx, [mx_ClipY1]\r
+ jge @@6\r
+ or si, 40h\r
+@@6:\r
+\r
+ cmp ax, [mx_ClipX2]\r
+ jle @@7\r
+ or si, 20h\r
+ jmp @@8\r
+@@7:\r
+ cmp ax, [mx_ClipX1]\r
+ jge @@8\r
+ or si, 10h\r
+@@8:\r
+\r
+ mov di, si\r
+ and di, 000Fh ; Index of procedure\r
+ and si, 00F0h\r
+ .shr si, 2 ; Index of group (times 4)\r
+ cmp di, cs:tblGroups[si] ; Is index within range?\r
+ jg @@Exit ; No, line is full clipped\r
+ mov si, cs:tblGroups[si+2] ; Get offset of group table\r
+ shl di, 1 ; We must index word elements\r
+ add si, di ; Make full offset\r
+ mov di, ax ; Move X1 to DI and free AX\r
+ mov si, cs:[si] ; Get subroutine address\r
+ xchg dx, si ; Move Y2 to SI and free DX\r
+ call dx ; Call the proper subroutine\r
+ mov ax, di ; Restore AX to X1\r
+ mov dx, si ; Restore DX to Y2\r
+ pop bp\r
+ ret\r
+\r
+@@Exit:\r
+ pop bp\r
+ stc\r
+ ret\r
+xsubClipLine ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCG.ASM - Color to gray conversion\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxColorToGray\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Converts RGB colors to gray shades.\r
+;\r
+; Input:\r
+; CPal = pointer to color palette\r
+; GPal = pointer to destination (gray) palette\r
+; Count = number of colors to convert\r
+; Output:\r
+; none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxColorToGray PROC FAR\r
+ ARG Count:WORD, \\r
+ DPal:DWORD, \\r
+ SPal:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov cx, [Count]\r
+ jcxz @@Exit\r
+ lds si, [SPal]\r
+ les di, [DPal]\r
+ cld\r
+; We use the standard formula\r
+; gray=(red*30 + green*59 + blue*11)/100\r
+; in the equivalent form\r
+; gray=(red*77 + green*151 + blue*28)/256\r
+; which doesn't need the last divide.\r
+ mov bx, 77 SHL 8 + 151\r
+@@Loop:\r
+ lodsb ; Red\r
+ mul bh\r
+ mov dx, ax\r
+ lodsb ; Green\r
+ mul bl\r
+ add dx, ax\r
+ lodsb ; Blue\r
+ mov ah, 28\r
+ mul ah\r
+ add ax, dx\r
+ mov al, ah\r
+ stosw ; Save new RGB\r
+ stosb\r
+ loop @@Loop\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxColorToGray ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCL.ASM - Bresenham circle\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxCircle\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a circle using the Bresenham algorithm.\r
+;\r
+; Input:\r
+; XC, YC = center coordinates\r
+; Radius = circle radius\r
+; Color = circle color\r
+; Output:\r
+; none\r
+; Note:\r
+; computes only points in the first octant, all other\r
+; points are obtained by symmetry.\r
+;\r
+mxCircle PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ Radius:WORD, \\r
+ YC:WORD, \\r
+ XC:WORD = ARG_SIZE\r
+ LOCAL Delta:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+\r
+ xor si, si ; X\r
+ mov di, [Radius] ; Y\r
+ mov ax, 3\r
+ sub ax, di\r
+ sub ax, di\r
+ mov [Delta], ax ; Delta = 3-R*2\r
+\r
+ mov ds, [mx_VideoSegment]\r
+\r
+@@Loop:\r
+ cmp si, di ;\r
+ jg @@Done ; Exit when X > Y\r
+; Draw points\r
+ mov ax, si\r
+ mov bx, di\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ neg ax\r
+ mov bx, di\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ mov bx, di\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, si\r
+ neg ax\r
+ mov bx, di\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ mov bx, si\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ neg ax\r
+ mov bx, si\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ mov bx, si\r
+ neg bx\r
+ call @@subPutPixel\r
+ mov ax, di\r
+ neg ax\r
+ mov bx, si\r
+ neg bx\r
+ call @@subPutPixel\r
+; Moves coordinates to next point\r
+ mov ax, [Delta]\r
+ test ax, ax\r
+ jl @@Next\r
+ mov ax, di\r
+ .shl ax, 2\r
+ sub ax, 4\r
+ sub [Delta], ax\r
+ dec di\r
+@@Next:\r
+ mov ax, si\r
+ .shl ax, 2\r
+ add ax, 6\r
+ add [Delta], ax\r
+ inc si\r
+ jmp @@Loop\r
+\r
+@@Done:\r
+ xor ax, ax\r
+ .pop ds, si, di\r
+ .leave ARG_SIZE\r
+\r
+;---------------------------------------\r
+; Put pixel function.\r
+; Input:\r
+; BX = X coordinate (relative to center)\r
+; AX = Y coordinate (relative to center)\r
+; DS = video segment\r
+@@subPutPixel:\r
+ add bx, [XC] ; Get absolute coordinates\r
+ add ax, [YC]\r
+\r
+ cmp bx, [mx_ClipX1] ; Clip pixel\r
+ jl @@subExit\r
+ cmp bx, [mx_ClipX2]\r
+ jg @@subExit\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@subExit\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@subExit\r
+\r
+ mul [mx_BytesPerLine] ; Get pixel offset\r
+ mov cx, bx ; Save X coordinate\r
+ .shr bx, 2\r
+ add bx, ax ; DS:BX = pixel offset\r
+\r
+ and cl, 3 ; Set write plane\r
+ mov ax, 0102h\r
+ shl ah, cl\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ mov al, [Color] ; Write pixel\r
+ mov ds:[bx], al\r
+\r
+@@subExit:\r
+ retn\r
+mxCircle ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXCR.ASM - Clip functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetSysClipRegion\r
+PUBLIC mxGetClipRegion\r
+PUBLIC mxSetClipRegion\r
+PUBLIC mxSetClip\r
+PUBLIC mxGetClip\r
+\r
+PUBLIC subClipBox\r
+PUBLIC subClipImage\r
+\r
+PUBLIC mx_ClipX1\r
+PUBLIC mx_ClipY1\r
+PUBLIC mx_ClipX2\r
+PUBLIC mx_ClipY2\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_ClipX1 DW ? ; Clip coordinates\r
+mx_ClipY1 DW ?\r
+mx_ClipX2 DW ?\r
+mx_ClipY2 DW ?\r
+\r
+mx_SysClipX1 DW ? ; System clip coordinates\r
+mx_SysClipY1 DW ? ; (active when mx_ClipStatus is FALSE)\r
+mx_SysClipX2 DW ?\r
+mx_SysClipY2 DW ?\r
+\r
+mx_UserClipX1 DW ? ; User clip coordinates\r
+mx_UserClipY1 DW ? ; (active when mx_ClipStatus is TRUE)\r
+mx_UserClipX2 DW ?\r
+mx_UserClipY2 DW ?\r
+\r
+mx_ClipStatus DB ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Toggles clipping between user and system regions.\r
+;\r
+; Input:\r
+; ClipStatus = TRUE (FALSE) to enable (disable) clipping\r
+; Output:\r
+; AX = old clip status\r
+;\r
+mxSetClip PROC FAR\r
+ ARG ClipStatus:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [mx_UserClipX1]\r
+ mov bx, [mx_UserClipY1]\r
+ mov cx, [mx_UserClipX2]\r
+ mov dx, [mx_UserClipY2]\r
+ cmp [ClipStatus], TRUE\r
+ je @@Done\r
+ mov ax, [mx_SysClipX1]\r
+ mov bx, [mx_SysClipY1]\r
+ mov cx, [mx_SysClipX2]\r
+ mov dx, [mx_SysClipY2]\r
+@@Done:\r
+ mov [mx_ClipX1], ax\r
+ mov [mx_ClipY1], bx\r
+ mov [mx_ClipX2], cx\r
+ mov [mx_ClipY2], dx\r
+\r
+ mov al, [ClipStatus]\r
+ xchg al, [mx_ClipStatus]\r
+ xor ah, ah\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetClip ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current clipping status.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; TRUE (FALSE) if clipping enabled (disabled)\r
+;\r
+mxGetClip PROC FAR\r
+ ASSUME ds:NOTHING\r
+ mov al, [mx_ClipStatus]\r
+ xor ah, ah\r
+ ret\r
+mxGetClip ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the system clip region and disables user clipping.\r
+;\r
+; Input:\r
+; Width = width in pixels of clip region\r
+; Height = height in pixels of clip region\r
+; Output:\r
+; old clip status.\r
+;\r
+mxSetSysClipRegion PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ xor ax, ax ; Sys clip region always starts at (0,0)\r
+ mov [mx_SysClipX1], ax\r
+ mov [mx_SysClipY1], ax\r
+ mov ax, [Width]\r
+ dec ax\r
+ mov [mx_SysClipX2], ax\r
+ mov ax, [Height]\r
+ dec ax\r
+ mov [mx_SysClipY2], ax\r
+\r
+ IF USE286 EQ TRUE\r
+ push FALSE\r
+ ELSE\r
+ mov ax, FALSE\r
+ push ax\r
+ ENDIF\r
+ call mxSetClip\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetSysClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the clip region.\r
+;\r
+; Input:\r
+; X, Y = coordinates of top left corner of clip region\r
+; Width = width in pixels of clip region\r
+; Height = height in pixels of clip region\r
+; Output:\r
+; none (no checking on parameters)\r
+;\r
+mxSetClipRegion PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [X]\r
+ mov [mx_UserClipX1], ax\r
+ mov ax, [Y]\r
+ mov [mx_UserClipY1], ax\r
+ mov ax, [Width]\r
+ add ax, [X]\r
+ dec ax\r
+ mov [mx_UserClipX2], ax\r
+ mov ax, [Height]\r
+ add ax, [Y]\r
+ dec ax\r
+ mov [mx_UserClipY2], ax\r
+\r
+ mov al, [mx_ClipStatus]\r
+ cmp al, TRUE\r
+ jne @@Exit\r
+ push ax\r
+ call mxSetClip\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current user clip region.\r
+;\r
+; Input:\r
+; X, Y = pointers to integer coordinates of top left corner\r
+; Width = pointer to word width of clip region\r
+; Height = pointer to word height of clip region\r
+; Output:\r
+; AX = current clip status\r
+;\r
+mxGetClipRegion PROC FAR\r
+ ARG Height:DWORD, \\r
+ Width:DWORD, \\r
+ Y:DWORD, \\r
+ X:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push es, di\r
+\r
+ mov ax, [mx_UserClipX1]\r
+ les di, [X]\r
+ mov es:[di], ax\r
+ mov ax, [mx_UserClipY1]\r
+ les di, [Y]\r
+ mov es:[di], ax\r
+\r
+ mov ax, [mx_UserClipX2]\r
+ sub ax, [mx_UserClipX1]\r
+ inc ax\r
+ les di, [Width]\r
+ mov es:[di], ax\r
+ mov ax, [mx_UserClipY2]\r
+ sub ax, [mx_UserClipY1]\r
+ inc ax\r
+ les di, [Height]\r
+ mov es:[di], ax\r
+\r
+ mov al, [mx_ClipStatus]\r
+ xor ah, ah\r
+ .pop es, di\r
+ .leave ARG_SIZE\r
+mxGetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+; This function assumes that a "raw" image has to be clipped,\r
+; so it returns in SI the number of "raw" bytes to skip if\r
+; X, Y were clipped.\r
+;\r
+; Input:\r
+; BX, AX = X, Y coordinates of rectangle (signed)\r
+; CX = box width\r
+; DX = box height\r
+; Output:\r
+; CF = set if rectangle is full clipped\r
+; BX, AX = new X, Y coordinates of rectangle\r
+; CX, DX = clipped width and height\r
+; SI = number of bytes to skip before copying a buffer\r
+; DI destroyed\r
+;\r
+subClipImage PROC NEAR\r
+ ASSUME ds:NOTHING\r
+ xor si, si\r
+\r
+; Check clip height\r
+ mov di, [mx_ClipY1]\r
+ cmp ax, di\r
+ jge @@CheckBottom\r
+ sub di, ax ; Number of lines to clip\r
+ sub dx, di ; New box height\r
+ jle @@Exit\r
+ mov ax, di\r
+ mov di, dx ; Save box height into DI\r
+ mul cx ; DX:AX = number of bytes to skip\r
+ mov si, ax\r
+ mov dx, di ; Restore box height\r
+ mov ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+ mov di, [mx_ClipY2]\r
+ cmp ax, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, dx\r
+ sub di, ax\r
+ jge @@DoneHeight ; None, continue\r
+ add dx, di ; Clip lines\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+ mov di, [mx_ClipX1]\r
+ cmp bx, di\r
+ jge @@CheckRight\r
+ sub di, bx ; Number of columns to clip left\r
+ sub cx, di\r
+ jle @@Exit\r
+ add si, di ; Update skip count\r
+ mov bx, [mx_ClipX1]\r
+@@CheckRight:\r
+ mov di, [mx_ClipX2]\r
+ cmp bx, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, bx\r
+ sub di, cx\r
+ jge @@DoneWidth ; None, exit\r
+ add cx, di ; New box width\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+ clc\r
+ ret\r
+@@Exit:\r
+ stc\r
+ ret\r
+subClipImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+;\r
+; Input:\r
+; BX, AX = X, Y coordinates of rectangle (signed)\r
+; CX = box width\r
+; DX = box height\r
+; Output:\r
+; CF = set if rectangle is full clipped\r
+; BX, AX = new X, Y coordinates of rectangle\r
+; CX, DX = clipped width and height\r
+; DI destroyed\r
+;\r
+subClipBox PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+; Check clip height\r
+ mov di, [mx_ClipY1]\r
+ cmp ax, di\r
+ jge @@CheckBottom\r
+ sub di, ax ; Number of lines to clip\r
+ sub dx, di ; New box height\r
+ jle @@Exit\r
+ mov ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+ mov di, [mx_ClipY2]\r
+ cmp ax, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, dx\r
+ sub di, ax ; Clipped some point?\r
+ jge @@DoneHeight ; No, continue\r
+ add dx, di ; Clip lines (DI is negative)\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+ mov di, [mx_ClipX1]\r
+ cmp bx, di\r
+ jge @@CheckRight\r
+ sub di, bx ; Number of columns to clip left\r
+ sub cx, di\r
+ jle @@Exit\r
+ mov bx, [mx_ClipX1]\r
+@@CheckRight:\r
+ mov di, [mx_ClipX2]\r
+ cmp bx, di\r
+ jg @@Exit\r
+ inc di\r
+ sub di, bx\r
+ sub di, cx ; Clipped some point?\r
+ jge @@DoneWidth ; No, exit\r
+ add cx, di ; New box width (DI is negative)\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+ clc\r
+ ret\r
+@@Exit:\r
+ stc\r
+ ret\r
+subClipBox ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXEL.ASM - Mid-point ellipse\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxEllipse\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws an ellipse using the mid-point algorithm.\r
+;\r
+; Input:\r
+; XC, YC = center coordinates\r
+; A = horizontal radius\r
+; B = vertical radius\r
+; Color = ellipse color\r
+; Output:\r
+; none\r
+; Note:\r
+; computes only points in the first quadrant, all other\r
+; points are obtained by symmetry.\r
+;\r
+mxEllipse PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ B:WORD, \\r
+ A:WORD, \\r
+ YC:WORD, \\r
+ XC:WORD = ARG_SIZE\r
+ LOCAL A2:DWORD, \\r
+ B2:DWORD, \\r
+ CC:DWORD, \\r
+ DD:DWORD, \\r
+ X:DWORD, \\r
+ Y:DWORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+\r
+ .chk386 mxEllipse, @@Exit\r
+\r
+; Initialize variables\r
+ xor eax, eax\r
+ mov [X], ax ; X = 0\r
+ mov ax, [A]\r
+ mul eax ; EAX = A*A\r
+ mov [DD], eax ; DD = A*A\r
+ shl eax, 1\r
+ mov [CC], eax ; CC = 2*A*A\r
+ shl eax, 1\r
+ mov [A2], eax ; A2 = 4*A*A\r
+ movzx edx, [B]\r
+ mov [Y], edx\r
+ mul edx ; EAX = 4*A*A*B\r
+ sub [DD], eax ; DD = A*A - 4*A*A*B\r
+ movzx eax, [B]\r
+ mul eax ; EAX = B*B\r
+ shl eax, 2 ; EAX = 4*B*B\r
+ mov [B2], eax ; B2 = 4*B*B\r
+ add [CC], eax ; CC = 2*A*A + 4*B*B\r
+ add [D1], eax ; DD = A*A - 4*A*A*B + 4*B*B\r
+\r
+; Draw initial points\r
+ call subPlot4\r
+\r
+; First loop\r
+@@Loop1:\r
+ mov eax, [X] ; Check slope\r
+ mul [B2]\r
+ mov ecx, eax\r
+ mov eax, [Y]\r
+ mul [A2]\r
+ sub eax, ecx\r
+ sub eax, [CC] ; EAX = Y*A2 - X*B2 - CC\r
+ jle @@Done1 ; Crossed critical point, jump to next loop\r
+\r
+ mov ecx, [DD] ; Get error\r
+ test ecx, ecx ; Positive?\r
+ jl @@Draw1 ; No, use default step\r
+\r
+ mov eax, 1\r
+ sub eax, [Y]\r
+ mul [A2]\r
+ shl eax, 1\r
+ add ecx, eax ; Bump error\r
+ dec WORD PTR [Y] ; Decrement Y coordinate\r
+\r
+@@Draw1:\r
+ mov eax, [X]\r
+ shl eax, 1\r
+ add eax, 3\r
+ mul [B2]\r
+ add ecx, eax ; Bump error\r
+ mov [DD], ecx ; Save error\r
+ inc WORD PTR [X] ; Increment X coordinate\r
+\r
+ call subPlot4 ; Draw points\r
+ jmp @@Loop1\r
+@@Done1:\r
+\r
+; Initialize variables\r
+ shr [B2], 2\r
+ mov eax, [X]\r
+ mul eax\r
+ add [X]\r
+ shl eax, 2\r
+ inc eax\r
+ mul [B2]\r
+ mov [DD], eax\r
+ mov eax, [Y]\r
+ mul eax\r
+ add [Y]\r
+ dec eax\r
+ add [Y]\r
+ sub eax, [B2]\r
+ add [DD], eax\r
+ shl [B2], 3\r
+ inc WORD PTR [X]\r
+\r
+; Second loop\r
+@@Loop2:\r
+ cmp WORD PTR [Y], 0\r
+ ja @@Done2\r
+\r
+ mov ecx, [DD]\r
+ test ecx, ecx\r
+ jge @@Draw2\r
+\r
+ mov eax, [X]\r
+ inc eax\r
+ mul [B2]\r
+ add ecx, eax\r
+ inc WORD PTR [X]\r
+\r
+@@Draw2:\r
+ mov eax, [Y]\r
+ shl eax, 1\r
+ sub eax, 3\r
+ neg eax\r
+ imul [A2]\r
+ add ecx, eax\r
+ dec WORD PTR [Y]\r
+\r
+ call subPlot4\r
+ jmp @@Loop2\r
+@@Done2:\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxEllipse ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXFB.ASM - Fill box function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFillBox\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN subClipBox : NEAR\r
+EXTRN subHorizontalLineInfo : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Raster op functions. Raster op is limited to OP_MOVE,\r
+; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to\r
+; perform the selected logical functions on up to four\r
+; pixel at a time.\r
+;\r
+subRepFill PROC NEAR\r
+ mov ah, al\r
+ shr cx, 1\r
+ rep stosw\r
+ rcl cx, 1\r
+ rep stosb\r
+ ret\r
+subRepFill ENDP\r
+;\r
+subFill PROC NEAR\r
+@@Loop:\r
+ mov ds:[bx], al\r
+ add bx, dx\r
+ loop @@Loop\r
+ ret\r
+subFill ENDP\r
+;\r
+subRepMove PROC NEAR\r
+ mov si, di\r
+@@Loop:\r
+ mov ah, ds:[si] ; Dummy read to latch the data\r
+ mov ds:[si], al\r
+ inc si\r
+ loop @@Loop\r
+ ret\r
+subRepMove ENDP\r
+;\r
+subMove PROC NEAR\r
+@@Loop:\r
+ mov ah, ds:[bx] ; Dummy read to latch the data\r
+ mov ds:[bx], al\r
+ add bx, dx\r
+ loop @@Loop\r
+ ret\r
+subMove ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a rectangle with a specified color.\r
+;\r
+; Input:\r
+; X, Y = X, Y coordinates of rectangle\r
+; Width = width of rectangle\r
+; Height = height of rectangle\r
+; Color = fill color\r
+; Op = raster operator\r
+; Output:\r
+; none\r
+;\r
+; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR.\r
+;\r
+mxFillBox PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:BYTE:2, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL LeftMask:BYTE, \\r
+ RightMask:BYTE, \\r
+ FillFunction:WORD, \\r
+ RepFillFunction:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Clip rectangle\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipBox\r
+ jc @@Exit ; Full clipped\r
+\r
+ mov [Height], dx ; Save clipped height\r
+ call subHorizontalLineInfo ; Get additional info, init DI\r
+ mov [Width], cx\r
+ mov [LeftMask], al\r
+ mov [RightMask], ah\r
+\r
+; Initialize segments\r
+ mov ax, [mx_VideoSegment]\r
+ mov es, ax ; ES:DI points to pixel\r
+ mov ds, ax\r
+ cld ; Clear direction flag\r
+\r
+; Select fill functions\r
+ mov [FillFunction], OFFSET subFill\r
+ mov [RepFillFunction], OFFSET subRepFill\r
+ mov ax, [Op] ; Get raster op\r
+ cmp al, OP_XOR\r
+ ja @@1 ; Assume it's a fill\r
+ cmp al, OP_MOVE\r
+ je @@1\r
+ .shl al, 3\r
+ mov ah, al\r
+ mov al, 03h\r
+ mov dx, GDC\r
+ out dx, ax ; Set GDC logical function\r
+ mov [FillFunction], OFFSET subMove\r
+ mov [RepFillFunction], OFFSET subRepMove\r
+@@1:\r
+\r
+; Fill left block\r
+@@L0:\r
+ mov ah, [LeftMask]\r
+ or ah, ah\r
+ jz @@C0 ; Nothing to do, go to center block\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov dx, [mx_BytesPerLine]\r
+ mov cx, [Height]\r
+ mov bx, di\r
+ mov al, [Color]\r
+ call [FillFunction] ; Fill this column\r
+ inc di ; Update starting video offset\r
+\r
+; Fill center block\r
+@@C0:\r
+ mov cx, [Width]\r
+ jcxz @@R0 ; Nothing to do, go to right block\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Write to all planes\r
+ mov al, [Color]\r
+ mov bx, di\r
+ mov dx, [Height]\r
+ push di ; Save pixel address\r
+@@C1:\r
+ mov di, bx ; Update video offset\r
+ call [RepFillFunction] ; Fill current scan line\r
+ mov cx, [Width] ; Restore byte count\r
+ add bx, [mx_BytesPerLine] ; Bump to next scan line\r
+ dec dx ; Done all lines?\r
+ jnz @@C1 ; No, continue\r
+ pop di ; Restore pixel address\r
+ add di, [Width] ; Go to right block\r
+\r
+; Fill right block\r
+@@R0:\r
+ mov ah, [RightMask]\r
+ or ah, ah\r
+ jz @@Done ; Nothing to do, exit\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax ; Set write plane mask\r
+ mov dx, [mx_BytesPerLine]\r
+ mov cx, [Height]\r
+ mov bx, di\r
+ mov al, [Color]\r
+ call [FillFunction] ; Fill this column\r
+\r
+; Restore VGA registers\r
+@@Done:\r
+ mov dx, GDC\r
+ mov ax, 0003h\r
+ out dx, ax ; Set logical function to "move"\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxFillBox ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXFP.ASM - Fade palette function\r
+; Copyright (c) 1992-1994 ARTIS s.r.l.\r
+; Author: Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFadePalette\r
+\r
+MAXCOLOR EQU 256\r
+FADE_IN EQU 0\r
+FADE_OUT EQU 1\r
+\r
+; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
+; the delay between two consecutive passes (FADE_DELAY). Below are the\r
+; default values, used when no parameters are specified.\r
+;\r
+FADE_DELAY EQU 1 ; Vert. retraces between video updates\r
+FADE_SPEED EQU 48 ; Speed of effect (max 127)\r
+\r
+; Bit field record for fade commands\r
+;\r
+FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fades a VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to source/destination palette\r
+; Command = fading direction and optional parameters\r
+; Start = index of first color to fade\r
+; Count = number of color to fade\r
+; Red = destination red\r
+; Green = destination green\r
+; Blue = destination blue\r
+; Output:\r
+; none\r
+; Notes:\r
+; - about 1.5 Kbytes of stack space are needed for internal buffers;\r
+; - the Command argument usually is 0 to fade in and 1 to fade out,\r
+; however additional parameters may be specified. To set the effect\r
+; speed, i.e. the number of iterations needed to completely fade a\r
+; palette, shift the value one bit left and "or" it with the\r
+; direction bit (range is 0..127). To set the delay between two\r
+; consecutive passes, shift it eight bits left (range is 0..255).\r
+;\r
+mxFadePalette PROC FAR\r
+ ARG bBlue:WORD, \\r
+ bGreen:WORD, \\r
+ bRed:WORD, \\r
+ wCount:WORD, \\r
+ wStartIdx:WORD, \\r
+ wCommand:WORD, \\r
+ vfpPalette:DWORD = ARG_SIZE\r
+ LOCAL bSPalette:BYTE:MAXCOLOR*3, \\r
+ bDPalette:BYTE:MAXCOLOR*3, \\r
+ bLoopIndex:BYTE, \\r
+ bLoopStep:BYTE, \\r
+ bLoopCount:BYTE, \\r
+ wDelay:WORD, \\r
+ wSpeed:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push si, di, ds, es ; Save registers\r
+;\r
+; Check parameters and setup variables\r
+;\r
+@@GetDelay:\r
+ mov [wDelay], FADE_DELAY ; Set default delay\r
+ mov ax, [wCommand] ; Get command word\r
+ and ax, MASK fpDELAY ; Mask delay command\r
+ jz @@GetSpeed ; No command, get speed\r
+ IF USE286 EQ TRUE\r
+ shr ax, fpDELAY\r
+ ELSE\r
+ mov cl, fpDELAY ; Get size of delay field\r
+ shr ax, cl ; Right justify the field\r
+ ENDIF\r
+ mov [wDelay], ax ; Set new delay\r
+\r
+@@GetSpeed:\r
+ mov ax, [wCommand] ; Get command\r
+ and ax, MASK fpSPEED ; Mask speed\r
+ IF USE286 EQ TRUE\r
+ shr ax, fpSPEED\r
+ ELSE\r
+ mov cl, fpSPEED ; Get size of speed field\r
+ shr ax, cl ; Right justify the field\r
+ ENDIF\r
+ or ax, ax ; Any speed specified?\r
+ jnz @@SetVariables ; Yes, set variables\r
+ mov ax, FADE_SPEED ; Set default speed\r
+\r
+@@SetVariables:\r
+ mov [wSpeed], ax ; Set speed\r
+ inc ax ; Number of iterations\r
+ mov [bLoopCount], al ; Set loop count\r
+ mov [bLoopStep], 1 ; Assume we're fading in\r
+ mov [bLoopIndex], 0\r
+;\r
+; Check bounds for bad values\r
+;\r
+ mov ax, [wStartIdx] ; Get first index\r
+ cmp ax, MAXCOLOR ; Is in the valid range?\r
+ jae @@Exit ; No, exit\r
+ add ax, [wCount] ; Get last index\r
+ cmp ax, MAXCOLOR ; Is in the valid range?\r
+ jbe @@BoundsOk ; Yes, continue\r
+ mov ax, MAXCOLOR\r
+ sub ax, [wStartIdx]\r
+ mov [wCount], ax ; Set count to maximum value\r
+ or ax, ax\r
+ jz @@Exit ; Nothing to do, exit\r
+@@BoundsOk:\r
+;\r
+; Copy the source palette in a local array: if we fade in it's ready to\r
+; use, otherwise we'll overwrite it later\r
+;\r
+ mov cx, [wCount]\r
+ mov ax, cx\r
+ shl ax, 1\r
+ add cx, ax ; CX = wCount * 3\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [bSPalette] ; ES:DI points to local palette\r
+ mov ax, [wStartIdx]\r
+ mov si, ax\r
+ shl ax, 1\r
+ add ax, si\r
+ lds si, [vfpPalette] ; DS:SI points to user palette\r
+ add si, ax ; Skip unused entries\r
+ cld\r
+ shr cx, 1\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+;\r
+; Check direction\r
+;\r
+ test [wCommand], MASK fpDIRECTION ; Are we fading in?\r
+ jz @@Main ; Yes, ok to continue\r
+ mov ax, [wSpeed] ; Get speed\r
+ mov [bLoopIndex], al ; Exchange first and last index\r
+ mov [bLoopStep], -1 ; Move backward\r
+ mov ax, ss ; Overwrite our copy of\r
+ mov ds, ax ; user palette with the\r
+ mov es, ax ; current active palette\r
+ lea di, [bSPalette]\r
+ mov ax, [wStartIdx]\r
+ mov cx, [wCount]\r
+ call ReadPalette ; Read current palette\r
+;\r
+; Prepare variables and registers for fading\r
+;\r
+@@Main:\r
+ mov bh, BYTE PTR [bRed] ; Destination red\r
+ and bh, 00111111b ; Be sure it's a valid VGA value\r
+ mov bl, BYTE PTR [bGreen] ; Destination green\r
+ and bl, 00111111b ; Be sure it's a valid VGA value\r
+ mov dh, BYTE PTR [bBlue] ; Destination blue\r
+ and dh, 00111111b ; Be sure it's a valid VGA value\r
+ mov dl, [bLoopIndex] ; Loop index\r
+ mov ax, ss ; All tables are stored\r
+ mov ds, ax ; in the stack segment,\r
+ mov es, ax ; set DS and ES\r
+;\r
+; Main loop\r
+;\r
+@@Loop:\r
+ mov ax, [wCount] ; Store count in AX\r
+ mov cx, [wSpeed] ; Set maximum speed in CX\r
+ lea si, [bSPalette] ; DS:SI points to source palette\r
+ lea di, [bDPalette] ; ES:DI points to dest. palette\r
+ call RecalcPalette ; Build a faded palette\r
+\r
+ .push bx, dx ; Save registers we need\r
+ lea si, [bDPalette] ; DS:SI points to palette\r
+ mov ax, [wStartIdx] ; First index to write\r
+ mov bx, [wCount] ; Total entries to write\r
+ mov cx, [wDelay] ; Fade delay between updates\r
+ call WritePalette ; Write palette\r
+ .pop bx, dx ; Restore BX and DX\r
+\r
+ add dl, [bLoopStep] ; Change fade intensity\r
+ dec [bLoopCount] ; Done?\r
+ jnz @@Loop ; No, loop again\r
+\r
+@@Exit:\r
+ .pop si, di, ds, es ; Restore registers\r
+ .leave ARG_SIZE\r
+mxFadePalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Calculates a partially faded palette.\r
+;\r
+; Input:\r
+; AX = number of entries in palette\r
+; CX = maximum fade intensity (same as fade speed)\r
+; DS:SI = pointer to source palette\r
+; ES:DI = pointer to destination palette\r
+; BH = destination red\r
+; BL = destination green\r
+; DH = destination blue\r
+; DL = relative intensity of destination palette\r
+; Note:\r
+; it's important that a new palette can be calculated in less\r
+; than 1/70th of second. Fading to any RGB value requires use\r
+; of "imul" instructions: "idiv" may be replaced with faster\r
+; "sar", but only when the number of passes is a power of two,\r
+; thus reducing the range of selectable speeds.\r
+; In both cases an extimate of CPU cycles required by this\r
+; procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
+; CPU and a 256 color palette, so we keep "idiv" and hope\r
+; the target machine to be at least a 6 Mhz 80286 (that's not\r
+; asking too much...).\r
+;\r
+RecalcPalette PROC NEAR\r
+ cld\r
+ push bp ; Save BP\r
+ mov bp, ax ; Copy counter in BP\r
+@@Loop:\r
+ lodsb ; Red: read value\r
+ sub al, bh ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, bh ; Add destination value...\r
+ stosb ; ...and store it\r
+ lodsb ; Green: read value\r
+ sub al, bl ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, bl ; Add destination value...\r
+ stosb ; ...and store it\r
+ lodsb ; Blue: read value\r
+ sub al, dh ; Subtract destination value\r
+ imul dl ; Scale to desired weight\r
+ idiv cl ; Put value in AL\r
+ add al, dh ; Add destination value...\r
+ stosb ; ...and store it\r
+ dec bp\r
+ jnz @@Loop\r
+ pop bp ; Restore BP\r
+ ret\r
+RecalcPalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Writes a 256 color palette.\r
+;\r
+; Input:\r
+; AX = index of first color to write\r
+; BX = number of colors to write (each color is an RGB triplet)\r
+; CX = number of vertical retraces to wait before writing to DACs\r
+; DS:SI = pointer to first entry of palette\r
+;\r
+WritePalette PROC NEAR\r
+ ASSUME ds:NOTHING\r
+ mov ah, al ; Save index\r
+ mov dx, 03DAh ; Input status register\r
+@@Delay1:\r
+ in al, dx\r
+ test al, 08h\r
+ jnz @@Delay1 ; Wait for display mode\r
+@@Delay2:\r
+ in al, dx\r
+ test al, 08h\r
+ jz @@Delay2 ; Wait for vertical retrace mode\r
+ loop @@Delay1 ; Repeat CX times\r
+@@Write:\r
+ mov cx, bx ; Get number of colors\r
+ mov dx, 03C8h ; PEL write address register\r
+ mov al, ah ; Restore index\r
+ out dx, al ; Select index of first color\r
+ inc dx ; PEL data register\r
+ cld ; Move forward\r
+ cli ; Disable interrupts\r
+@@Loop:\r
+ lodsb\r
+ out dx, al ; Red\r
+ lodsb\r
+ out dx, al ; Green\r
+ lodsb\r
+ out dx, al ; Blue\r
+ loop @@Loop ; Loop until done\r
+ sti ; Enable interrupts\r
+ ret\r
+WritePalette ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Reads the current palette.\r
+;\r
+; Input:\r
+; AX = index of first color to read\r
+; CX = number of colors\r
+; ES:DI = pointer to destination buffer\r
+;\r
+ReadPalette PROC NEAR\r
+ mov dx, 03C7h\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+ cld\r
+@@Loop:\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ loop @@Loop\r
+ ret\r
+ReadPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGC.ASM - Get color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetColor\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the selected DAC register.\r
+;\r
+; Input:\r
+; Index = color index (0-255)\r
+; R, G, B = byte pointers to red, green and blue\r
+; Output:\r
+; none\r
+;\r
+mxGetColor PROC FAR\r
+ ARG B:DWORD, \\r
+ G:DWORD, \\r
+ R:DWORD, \\r
+ Index:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [Index]\r
+ mov dx, 3C7h ; PEL read address register\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+\r
+ lds si, [R]\r
+ in al, dx\r
+ mov ds:[si], al\r
+ lds si, [G]\r
+ in al, dx\r
+ mov ds:[si], al\r
+ lds si, [B]\r
+ in al, dx\r
+ mov ds:[si], al\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetColor ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGI.ASM - Get image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies an image from screen to memory.\r
+;\r
+; Input:\r
+; Image = pointer to buffer for image\r
+; X, Y = coordinates of image on screen\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+;\r
+mxGetImage PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ ReadPlane:BYTE, \\r
+ Count:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov si, bx\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax\r
+ mov [PixelOffset], si\r
+ mov ds, [mx_VideoSegment] ; DS:SI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov di, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[di], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec di\r
+ dec di\r
+ jge @@PatchLoop\r
+\r
+; Get image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov es, WORD PTR Image[2] ; ES:DI will point to image\r
+ mov ah, [ReadPlane]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov di, WORD PTR Image[0]\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov si, [PixelOffset] ; DS:SI points to video memory\r
+@@Loop:\r
+ .push si, di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+@@MoveLoop:\r
+ movsb\r
+ add di, 3\r
+ dec cx\r
+ jnz @@MoveLoop\r
+ .pop si, di\r
+ add di, [Width] ; Go to next image line\r
+ add si, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc ah\r
+ test ah, 04h ; Plane wraparound?\r
+ jz @@PlaneOk ; No\r
+ inc [PixelOffset] ; Yes, bump video pointer\r
+ and ah, 03h\r
+@@PlaneOk:\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGetImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGM.ASM - Gamma correction\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGammaCorrect\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+mx_tblGamma LABEL BYTE\r
+ DB 00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34\r
+ DB 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46\r
+ DB 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55\r
+ DB 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Correct palette colors (gamma is 2.3).\r
+;\r
+; Input:\r
+; CPal = pointer to color palette\r
+; GPal = pointer to destination (gamma corrected) palette\r
+; Count = number of colors to convert\r
+; Output:\r
+; none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxGammaCorrect PROC FAR\r
+ ARG Count:WORD, \\r
+ DPal:DWORD, \\r
+ SPal:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov cx, [Count]\r
+ jcxz @@Exit ; Exit now if nothing to do\r
+ lds si, [SPal]\r
+ les di, [DPal]\r
+ mov bx, OFFSET mx_tblGamma ; Setup BX for XLAT instruction\r
+ cld\r
+ mov ax, cx ; AX = Count\r
+ add cx, cx ; CX = Count*2\r
+ add cx, ax ; CX = Count*3\r
+@@Loop:\r
+ lodsb\r
+ xlat mx_tblGamma\r
+ stosb\r
+ loop @@Loop\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGammaCorrect ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGP.ASM - Get palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetPalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to palette data (R,G,B)\r
+; Start = index of first color to get\r
+; Count = number of color to get\r
+; Output:\r
+; none\r
+;\r
+mxGetPalette PROC FAR\r
+ ARG Count:WORD, \\r
+ Start:WORD, \\r
+ Buffer:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push es, di\r
+\r
+ les di, [Buffer]\r
+ mov cx, [Count]\r
+ mov ax, [Start]\r
+ mov dx, 3C7h ; PEL read address register\r
+ out dx, al\r
+ inc dx\r
+ inc dx\r
+ cld\r
+@@Loop:\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ in al, dx\r
+ stosb\r
+ loop @@Loop ; Loop until done\r
+\r
+ .pop es, di\r
+ .leave ARG_SIZE\r
+mxGetPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXGV.ASM - Get version function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetVersion\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the library version.\r
+;\r
+mxGetVersion PROC FAR\r
+ mov ax, MXVERSION\r
+ ret\r
+mxGetVersion ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXHL.ASM - Horizontal line mask utility\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC subHorizontalLineInfo\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+tblLeftSize DW 00h, 03h, 02h, 01h\r
+tblLeftMask DB 00h, 0Eh, 0Ch, 08h\r
+tblRightMask DB 00h, 01h, 03h, 07h\r
+tblPatchMask DB 02h, 06h\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Prepares register for fast horizontal line drawing.\r
+;\r
+; Input:\r
+; BX, AX = X, Y address of left pixel\r
+; CX = line width\r
+; Output:\r
+; DI = left pixel offset in video memory\r
+; AL = left block write plane mask (0 = none)\r
+; AH = right block write plane mask (0 = none)\r
+; CX = center block width in 4-pixel blocks\r
+;\r
+subHorizontalLineInfo PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax ; Offset of left pixel\r
+\r
+ and bx, 03h\r
+ mov al, tblLeftMask[bx]\r
+ shl bx, 1\r
+ sub cx, tblLeftSize[bx]\r
+ jge @@1 ; Ok to continue\r
+\r
+; Special case: start and end in the middle of a 4-pixel block.\r
+; There are only three cases:\r
+; Pixels Left mask CX CX+2 Patch mask Result\r
+; 1) ..o. ..xx -1 1 .xx. ..x.\r
+; 2) .oo. .xxx -1 1 .xx. .xx.\r
+; 3) .o.. .xxx -2 0 .x.. .x..\r
+; All other cases are automatically handled with the standard masks.\r
+ mov bx, cx\r
+ inc bx\r
+ inc bx\r
+ and al, tblPatchMask[bx] ; Combine masks\r
+ xor ah, ah ; No right block\r
+ xor cx, cx ; No center block\r
+ jmp @@Exit\r
+\r
+@@1:\r
+ mov bx, cx\r
+ and bx, 03h\r
+ mov ah, tblRightMask[bx]\r
+ shr cx, 2\r
+\r
+@@Exit:\r
+ ret\r
+subHorizontalLineInfo ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxInit\r
+PUBLIC mxTerm\r
+\r
+PUBLIC mx_VideoSegment\r
+PUBLIC mx_CodeSegment\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW 0A000h\r
+mx_CodeSegment DW SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; AX = 0 on success\r
+;\r
+mxInit PROC FAR\r
+ LOCAL Result:WORD, \\r
+ VideoSeg:WORD, \\r
+ CStoDSalias:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov [Result], -1 ; Assume an error\r
+ mov [VideoSeg], 0A000h ; Real mode video segment\r
+ mov [CStoDSalias], cs ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+ mov ax, 1686h\r
+ int 2Fh\r
+ or ax, ax\r
+ jnz @@1 ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+ mov ax, 000Ah ; DMPI: create data alias\r
+ mov bx, cs\r
+ int 31h\r
+ jc @@Exit ; Exit if service failed\r
+ mov [CStoDSalias], ax ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+ mov ax, 0002h\r
+ mov bx, 0A000h ; Real mode segment of video\r
+ int 31h ; DPMI: get segment selector\r
+ jc @@Exit ; Exit if service failed\r
+ mov [VideoSeg], ax ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+ mov ds, [CStoDSalias]\r
+ ASSUME ds:MX_TEXT\r
+ mov [mx_CodeSegment], ds\r
+ mov ax, [VideoSeg]\r
+ mov [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+ mov [Result], 0\r
+\r
+@@Exit:\r
+ mov ax, [Result]\r
+ .pop ds, si, es, di\r
+ .leave\r
+mxInit ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; always 0.\r
+;\r
+mxTerm PROC FAR\r
+ ASSUME ds:NOTHING\r
+ xor ax, ax\r
+ ret\r
+mxTerm ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLL.ASM - Load latches\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxLoadLatches\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Loads the specified value into the VGA latches.\r
+;\r
+; Input:\r
+; BL = value to load into latches\r
+; Output:\r
+; none\r
+; Changes:\r
+; bit mask register to FFh;\r
+; function select register to "move";\r
+; write mode to 00h.\r
+; Note:\r
+; this is for internal use only.\r
+;\r
+mxLoadLatches PROC NEAR\r
+ ASSUME ds:NOTHING\r
+\r
+ .push ds, si\r
+ mov dx, GDC\r
+ mov ax, 0FF08h\r
+ out dx, ax ; Set bit mask to FFh\r
+ mov ax, 0003h\r
+ out dx, ax ; Set function to "move"\r
+ mov ax, 0005h\r
+ out dx, ax ; Set write mode\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax\r
+ mov si, 0FFFFh\r
+ mov bh, 8 ; BH = write plane mask\r
+ mov cx, 3 ; CX = count = read plane\r
+; Saves old values and force BL into latches\r
+@@SetLoop:\r
+ mov dx, GDC\r
+ mov al, 04h\r
+ mov ah, cl\r
+ out dx, ax ; Select read plane\r
+ mov dx, TS\r
+ mov al, 02h\r
+ mov ah, bh\r
+ out dx, ax ; Select write plane\r
+ mov al, ds:[si]\r
+ push ax\r
+ mov ds:[si], bl\r
+ mov al, ds:[di] ; Force value into latch\r
+ shr bh, 1 ; Next write plane\r
+ loop @@SetLoop\r
+; Restore previous values\r
+ mov cx, 3\r
+ mov bh, 8\r
+ mov dx, TS\r
+@@ResetLoop:\r
+ mov al, 02h\r
+ mov ah, bh\r
+ out dx, ax ; Select write plane\r
+ pop ax\r
+ mov ds:[si], al\r
+ shr bh, 1 ; Next write plane\r
+ loop @@ResetLoop\r
+; Exit\r
+ .pop ds, si\r
+ ret\r
+mxLoadLatches ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+tblDrawFunc LABEL WORD\r
+ DW subWidthMove\r
+ DW subHeightMove\r
+ DW subWidthOp\r
+ DW subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+; X1, Y1 = start point\r
+; X2, Y2 = end point\r
+; Color = line color\r
+; Op = raster operator\r
+; Output:\r
+; none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD, \\r
+ Y2:WORD, \\r
+ X2:WORD, \\r
+ Y1:WORD, \\r
+ X1:WORD = ARG_SIZE\r
+ LOCAL Width:WORD, \\r
+ Height:WORD, \\r
+ ErrorAdd:WORD, \\r
+ ErrorSub:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD, \\r
+ P1:BYTE, \\r
+ P2:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, di\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [X1]\r
+ mov bx, [Y1]\r
+ mov cx, [X2]\r
+ mov dx, [Y2]\r
+ call subClipLine\r
+ jc @@Exit ; Line is full clipped\r
+\r
+; Get width\r
+ mov si, cx\r
+ xchg ax, si ; SI = X1, AX = X2\r
+ sub ax, si\r
+ jge @@1\r
+; Swap points, we want X1 < X2\r
+ xchg si, cx ; Swap X1 and X2\r
+ xchg bx, dx ; Swap Y1 and Y2\r
+ neg ax\r
+@@1:\r
+ mov [Width], ax\r
+\r
+; Get height\r
+ mov cx, [mx_BytesPerLine] ; We don't need X2 anymore\r
+ mov ax, dx\r
+ sub ax, bx\r
+ jge @@2\r
+ neg cx ; Move from bottom to top\r
+ neg ax ; Get absolute value of AX\r
+@@2:\r
+ mov [Height], ax\r
+ mov [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+ mov ax, bx\r
+ mul [mx_BytesPerLine]\r
+ mov cx, si ; CX = X1\r
+ shr si, 1\r
+ shr si, 1\r
+ add si, ax ; SI = pixel offset\r
+ and cl, 03h\r
+ mov ax, 1102h\r
+ shl ah, cl\r
+ mov [WritePlane], ah\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov ax, [mx_VideoSegment]\r
+ mov ds, ax ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+ xor bx, bx\r
+ mov al, BYTE PTR [Op]\r
+ cmp al, OP_MOVE\r
+ je @@3\r
+ and al, 03h\r
+ shl al, 1\r
+ shl al, 1\r
+ shl al, 1\r
+ mov ah, al\r
+ mov al, 03h\r
+ mov dx, GDC\r
+ out dx, ax ; Set logical function\r
+ inc bx\r
+ inc bx\r
+@@3:\r
+ mov ax, [Width]\r
+ mov cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+ cmp ax, cx\r
+ jae @@4\r
+ inc bx\r
+@@4:\r
+ shl bx, 1\r
+ call tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+ cmp BYTE PTR [Op], OP_MOVE\r
+ je @@Exit\r
+ mov ax, 0003h\r
+ mov dx, GDC\r
+ out dx, ax\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+; AX, BX = X1, Y1\r
+; CX, DX = X2, Y2\r
+; Output:\r
+; CF = set if line is full clipped\r
+; AX, BX = clipped X1, Y1\r
+; CX, DX = clipped X2, Y2\r
+; Note:\r
+; destroys SI, DI\r
+;\r
+subClipLine PROC NEAR\r
+ mov di, ax ; Copy X1 to DI and free AX\r
+ mov si, dx ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+ xor al, al\r
+@@P2X1: cmp cx, [mx_ClipX1]\r
+ jge @@P2X2\r
+ or al, 1\r
+@@P2X2: cmp cx, [mx_ClipX2]\r
+ jle @@P2Y1\r
+ or al, 2\r
+@@P2Y1: cmp si, [mx_ClipY1]\r
+ jge @@P2Y2\r
+ or al, 4\r
+@@P2Y2: cmp si, [mx_ClipY2]\r
+ jle @@P2XY\r
+ or al, 8\r
+@@P2XY: mov [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+ xor al, al\r
+@@P1X1: cmp di, [mx_ClipX1]\r
+ jge @@P1X2\r
+ or al, 1\r
+@@P1X2: cmp di, [mx_ClipX2]\r
+ jle @@P1Y1\r
+ or al, 2\r
+@@P1Y1: cmp bx, [mx_ClipY1]\r
+ jge @@P1Y2\r
+ or al, 4\r
+@@P1Y2: cmp bx, [mx_ClipY2]\r
+ jle @@P1XY\r
+ or al, 8\r
+@@P1XY: mov [P1], al\r
+; Check codes for trivial cases\r
+ mov ah, [P2]\r
+ test al, ah ; Is line invisible?\r
+ jnz @@FullClip ; Yes, exit\r
+ or ah, al ; Both points clipped?\r
+ jz @@Done ; Yes, exit\r
+; Calculate deltas\r
+ mov ax, cx\r
+ sub ax, di\r
+ mov [DeltaX], ax\r
+ mov ax, si\r
+ sub ax, bx\r
+ mov [DeltaY], ax\r
+ mov al, [P1] ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+ test al, al ; Is first point clipped?\r
+ jnz @@ClipX1 ; No, continue\r
+ xchg cx, di ; Swap points...\r
+ xchg bx, si\r
+ xchg al, [P2] ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+ test al, 1\r
+ jz @@ClipX2\r
+ mov ax, [mx_ClipX1]\r
+ sub ax, di\r
+ mov di, [mx_ClipX1]\r
+ jmp @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+ test al, 2\r
+ jz @@ClipY1\r
+ mov ax, [mx_ClipX2]\r
+ sub ax, di\r
+ mov di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+ imul [DeltaY]\r
+ idiv [DeltaX]\r
+ add bx, ax\r
+ mov al, 8\r
+ cmp bx, [mx_ClipY2]\r
+ jg @@CheckLoop\r
+ mov al, 4\r
+ cmp bx, [mx_ClipY1]\r
+ jl @@CheckLoop\r
+ xor al, al\r
+ jmp @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+ test al, 4\r
+ jz @@ClipY2\r
+ mov ax, [mx_ClipY1]\r
+ sub ax, bx\r
+ mov bx, [mx_ClipY1]\r
+ jmp @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+ mov ax, [mx_ClipY2]\r
+ sub ax, bx\r
+ mov bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+ imul [DeltaX]\r
+ idiv [DeltaY]\r
+ add di, ax\r
+ mov al, 1\r
+ cmp di, [mx_ClipX1]\r
+ jl @@CheckLoop\r
+ mov al, 2\r
+ cmp di, [mx_ClipX2]\r
+ jg @@CheckLoop\r
+ xor al, al\r
+@@CheckLoop:\r
+ mov ah, [P2]\r
+ test al, ah\r
+ jnz @@FullClip\r
+ or ah, al\r
+ jnz @@ClipLoop\r
+\r
+@@Done:\r
+ mov ax, di\r
+ mov dx, si\r
+ clc\r
+ ret\r
+@@FullClip:\r
+ stc\r
+ ret\r
+subClipLine ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove PROC NEAR\r
+ mov di, ax\r
+ neg di ; Initialize error term\r
+ shl cx, 1\r
+ mov [ErrorAdd], cx\r
+ mov cx, ax\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov al, 02h\r
+ mov ah, [WritePlane]\r
+ mov bl, BYTE PTR [Color]\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ rol ah, 1\r
+ adc si, 0\r
+ out dx, ax\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ add si, [DeltaY]\r
+ sub di, [ErrorSub]\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subWidthMove ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove PROC NEAR\r
+ mov di, cx\r
+ neg di ; Initialize error term\r
+ shl ax, 1\r
+ mov [ErrorAdd], ax\r
+ mov ax, cx\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov bl, BYTE PTR [Color]\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ add si, [DeltaY]\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ rol ah, 1 ; Next write plane\r
+ adc si, 0 ; Bump video offset if plane overflows\r
+ out dx, ax\r
+ sub di, [ErrorSub] ; Adjust error down\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subHeightMove ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp PROC NEAR\r
+ mov di, ax\r
+ neg di ; Initialize error term\r
+ shl cx, 1\r
+ mov [ErrorAdd], cx\r
+ mov cx, ax\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov al, 02h\r
+ mov ah, [WritePlane]\r
+ mov bl, BYTE PTR [Color]\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov bh, ds:[si] ; Latch data\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ rol ah, 1\r
+ adc si, 0\r
+ out dx, ax\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ add si, [DeltaY]\r
+ sub di, [ErrorSub]\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subWidthOp ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp PROC NEAR\r
+ mov di, cx\r
+ neg di ; Initialize error term\r
+ shl ax, 1\r
+ mov [ErrorAdd], ax\r
+ mov ax, cx\r
+ shl ax, 1\r
+ mov [ErrorSub], ax\r
+ mov bl, BYTE PTR [Color]\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ inc cx\r
+@@Loop:\r
+ mov bh, ds:[si]\r
+ mov ds:[si], bl\r
+ dec cx\r
+ jz @@Exit\r
+ add si, [DeltaY]\r
+ add di, [ErrorAdd]\r
+ jl @@Loop\r
+ rol ah, 1 ; Next write plane\r
+ adc si, 0 ; Bump video offset if plane overflows\r
+ out dx, ax\r
+ sub di, [ErrorSub] ; Adjust error down\r
+ jmp @@Loop\r
+@@Exit:\r
+ ret\r
+subHeightOp ENDP\r
+\r
+mxLine ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxOutChar\r
+PUBLIC mxOutText\r
+PUBLIC mxSetFont\r
+PUBLIC mxSetTextColor\r
+PUBLIC mxGetTextStep\r
+PUBLIC mxSetTextStep\r
+\r
+MAX_WIDTH EQU 16 ; Must be <= 16\r
+MAX_HEIGHT EQU 32\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mxPutImage : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default LABEL\r
+ INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont LABEL WORD\r
+ DW fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth DW 8 ; Font width in pixels\r
+mx_FontHeight DW 8 ; Font height in pixels\r
+mx_FontCharSize DW 8 ; Size in bytes of a font character\r
+mx_FontColor DW 00FFh ; Color: foreground + background*256\r
+mx_FontOp DW OP_MOVE ; Raster op\r
+mx_DeltaX DW 8 ; Horizontal step\r
+mx_DeltaY DW 0 ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+; Font = pointer to font data\r
+; Width = width of font character in pixels\r
+; Height = height of font character in pixels\r
+; Output:\r
+; AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+; word is used to select one of the system fonts.\r
+;\r
+mxSetFont PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Font:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, WORD PTR Font[2] ; Get font segment\r
+ test ax, ax ; Null segment?\r
+ jnz @@UserFont ; No, install user font\r
+\r
+; Install system font\r
+ mov ax, WORD PTR Font[0] ; Get font number\r
+ cmp ax, MX_MAXSYSFONT ; Check range\r
+ jb @@SystemFont\r
+ xor ax, ax ; Out of range, use default font\r
+@@SystemFont:\r
+ shl ax, 1\r
+ shl ax, 1\r
+ mov bx, ax\r
+ mov ax, tbl_SystemFont[bx] ; Get font offset\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov WORD PTR mx_FontPtr[2], cs\r
+ mov al, BYTE PTR tbl_SystemFont[bx+2]\r
+ xor ah, ah\r
+ mov [mx_FontWidth], ax\r
+ mov [mx_DeltaX], ax\r
+ mov dl, BYTE PTR tbl_SystemFont[bx+3]\r
+ xor dh, dh\r
+ mov [mx_FontHeight], dx\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov [mx_DeltaX], ax\r
+ xor ax, ax\r
+ mov [mx_DeltaY], ax\r
+ jmp @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+ mov ax, -1 ; Assume an error\r
+ mov bx, [Width]\r
+ cmp bx, MAX_WIDTH\r
+ ja @@Exit ; Invalid character width\r
+ mov dx, [Height]\r
+ cmp dx, MAX_HEIGHT\r
+ ja @@Exit ; Invalid character height\r
+ mov [mx_FontWidth], bx\r
+ mov [mx_FontHeight], dx\r
+ mov ax, bx\r
+ add ax, 7\r
+ .shr ax, 3\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov ax, WORD PTR Font[0]\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov ax, WORD PTR Font[2]\r
+ mov WORD PTR mx_FontPtr[2], ax\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetFont ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+; Color = text color (foreground + background*256)\r
+; Op = raster op\r
+; Output:\r
+; none\r
+;\r
+mxSetTextColor PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [Color]\r
+ mov [mx_FontColor], ax\r
+ mov ax, [Op]\r
+ mov [mx_FontOp], ax\r
+\r
+ xor ax, ax\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetTextColor ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+; X, Y = video coordinates\r
+; C = character to print\r
+; Output:\r
+; none\r
+;\r
+mxOutChar PROC FAR\r
+ ARG C:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \\r
+ Count:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+ lds si, DWORD PTR [mx_FontPtr]\r
+ mov al, [C]\r
+ xor ah, ah\r
+ mul [mx_FontCharSize] ; Offset into font\r
+ add si, ax ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [Image]\r
+ mov dx, [mx_FontColor]\r
+ mov ax, [mx_FontHeight]\r
+ mov [Count], ax\r
+@@HeightLoop:\r
+ mov cx, [mx_FontWidth]\r
+ mov bh, ds:[si]\r
+ inc si ; Get a byte from font data\r
+ cmp cx, 8\r
+ jbe @@WidthLoop ; Ok for width <= 8\r
+ mov bl, ds:[si] ; Get another byte\r
+ inc si\r
+@@WidthLoop:\r
+ mov al, dl ; Assume foreground color\r
+ shl bx, 1 ; Is font bit set?\r
+ jc @@1 ; Yes, foreground is just great\r
+ mov al, dh ; Get background color\r
+@@1:\r
+ mov es:[di], al ; Put pixel into image\r
+ inc di\r
+ dec cx\r
+ jnz @@WidthLoop\r
+ dec [Count]\r
+ jnz @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+ lea ax, [Image]\r
+ push es\r
+ push ax ; Pointer to image\r
+ push [X]\r
+ push [Y] ; Image coordinates\r
+ push [mx_FontWidth]\r
+ push [mx_FontHeight] ; Image size\r
+ push [mx_FontOp] ; Raster op\r
+ call mxPutImage ; Write character\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxOutChar ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+; X, Y = text coordinates\r
+; S = pointer to ASCIIZ string\r
+; Output:\r
+; none\r
+;\r
+mxOutText PROC FAR\r
+ ARG S:DWORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [S]\r
+@@Loop:\r
+ mov al, ds:[si]\r
+ test al, al ; End of string?\r
+ jz @@Exit ; Yes, exit\r
+ inc si\r
+ push [X] ; Display character\r
+ push [Y]\r
+ push ax\r
+ call mxOutChar\r
+ mov ax, [mx_DeltaX]\r
+ add [X], ax ; Bump X coordinate\r
+ mov ax, [mx_DeltaY]\r
+ add [Y], ax ; Bump Y coordinate\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+ ret\r
+mxOutText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = horizontal distance in pixels\r
+; DeltaY = vertical distance in pixels\r
+; Output:\r
+; none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep PROC FAR\r
+ ARG DeltaY:WORD, \\r
+ DeltaX:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [DeltaX]\r
+ mov [mx_DeltaX], ax\r
+ mov ax, [DeltaY]\r
+ mov [mx_DeltaY], ax\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetTextStep ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = pointer to horizontal distance in pixels (integer)\r
+; DeltaY = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+; none\r
+;\r
+mxGetTextStep PROC FAR\r
+ ARG DeltaY:DWORD, \\r
+ DeltaX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [mx_DeltaX]\r
+ lds si, [DeltaX]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_DeltaY]\r
+ lds si, [DeltaY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetTextStep ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPB.ASM - Scan buffer for convex polygon fills\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mx_ScanBuffer\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+ALIGN 4\r
+\r
+mx_ScanBuffer LABEL\r
+ DW POLYSCANBUFSIZE DUP(?)\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxFillPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT STRUC\r
+ X DW ?\r
+ Y DW ?\r
+TPOINT ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN STRUC\r
+ Y1 DW ?\r
+ Y2 DW ?\r
+TSCAN ENDS\r
+\r
+MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+EXTRN mx_ScanBuffer : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+;\r
+; Input:\r
+; DS:BX = pointer to start point (X1, Y1)\r
+; DS:SI = pointer to end point (X2, Y2)\r
+; ES:DI = pointer to edge buffer\r
+; Output:\r
+; ES:DI = updated pointer to edge buffer\r
+; Notes:\r
+; must preserve DS:SI.\r
+;\r
+subScan PROC NEAR\r
+ mov cx, ds:[si].X\r
+ sub cx, ds:[bx].X ; Get width\r
+ jg @@1\r
+ ret\r
+@@1:\r
+ push bp ; Save BP\r
+\r
+ mov ax, ds:[si].Y\r
+ mov bx, ds:[bx].Y\r
+ sub ax, bx ; Get height\r
+ jg @@T2B ; Scan top to bottom\r
+ jl @@B2T ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+ mov ax, bx\r
+@@V:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@V\r
+ jmp @@Exit\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@T2BLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@T2BLoop\r
+ jmp @@Exit\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+@@B2TLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@B2TLoop\r
+\r
+@@Exit:\r
+ pop bp ; Restore BP\r
+ ret\r
+subScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+;\r
+; Input:\r
+; Count = number of vertexes\r
+; Map = indexes of points and colors (integer)\r
+; Points = array of points (integer X, Y coordinates)\r
+; Color = base color\r
+; Output:\r
+; none\r
+; Notes:\r
+; vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxFillPoly PROC FAR\r
+ ARG Color:WORD, \\r
+ Points:DWORD, \\r
+ Map:DWORD, \\r
+ Count:WORD = ARG_SIZE\r
+ LOCAL WritePlane:BYTE:2, \\r
+ ScanOffsetT:WORD, \\r
+ ScanOffsetB:WORD, \\r
+ ScanCount:WORD, \\r
+ Holder:WORD, \\r
+ Height:WORD, \\r
+ MinIdxT:WORD, \\r
+ MinIdxB:WORD, \\r
+ MaxIdx:WORD, \\r
+ Width:WORD, \\r
+ BoxX1:WORD, \\r
+ BoxY1:WORD, \\r
+ BoxX2:WORD, \\r
+ BoxY2::WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+ mov cx, [Count]\r
+ cmp cx, 3\r
+ jb @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+ les di, [Map]\r
+ lds si, [Points] ; Pointer to vertex array\r
+ mov [BoxX1], 32767\r
+ mov [BoxX2], -32768\r
+ mov [BoxY1], 32767\r
+ mov [BoxY2], -32768\r
+\r
+ xor dx, dx\r
+@@MinMaxLoop:\r
+ mov bx, es:[di] ; Get index of vertex\r
+ .shl bx, 2 ; Get offset in point array\r
+ add bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+ mov ax, ds:[bx].X ; Get X coordinate\r
+ cmp ax, [BoxX1]\r
+ jge @@CheckMaxX\r
+ mov [BoxX1], ax\r
+ mov [MinIdxT], dx\r
+ mov [MinIdxB], dx\r
+@@CheckMaxX:\r
+ cmp ax, [BoxX2]\r
+ jle @@CheckMinY\r
+ mov [BoxX2], ax\r
+ mov [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+ mov ax, ds:[bx].Y\r
+ cmp ax, [BoxY1]\r
+ jge @@CheckMaxY\r
+ mov [BoxY1], ax\r
+@@CheckMaxY:\r
+ cmp ax, [BoxY2]\r
+ jle @@CheckDone\r
+ mov [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+ inc di ; Next map entry\r
+ inc dx\r
+ inc di\r
+ inc dx\r
+ dec cx\r
+ jnz @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+ mov ax, [BoxX2]\r
+ cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxX1]\r
+ cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get width\r
+ jle @@Exit ; Exit if not positive\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxY1]\r
+ cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get height\r
+ jle @@Exit ; Exit if not positive\r
+\r
+ dec [Count]\r
+ shl [Count], 1 ; We'll work with word offsets\r
+ mov es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+ mov ax, OFFSET mx_ScanBuffer\r
+ mov [ScanOffsetT], ax\r
+ mov si, [MinIdxT] ; Offset of bottom point index\r
+@@STLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of top point #1\r
+ dec si ; Next point\r
+ dec si\r
+ test si, si\r
+ jnl @@ST1\r
+ mov si, [Count]\r
+@@ST1:\r
+ mov [MinIdxT], si ; Save new index of top point\r
+ mov si, ds:[bx+si] ; Get index of top point #2\r
+ .shl di, 2 ; Convert indexes to offsets\r
+ .shl si, 2\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetT]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetT], di\r
+ mov si, [MinIdxT]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@STLoop ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+ mov ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+ mov [ScanOffsetB], ax\r
+ mov si, [MinIdxB] ; Offset of bottom point index\r
+@@SBLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of bottom point #1\r
+ inc si ; Next bottom point\r
+ inc si\r
+ cmp si, [Count]\r
+ jbe @@SB1\r
+ xor si, si\r
+@@SB1:\r
+ mov [MinIdxB], si ; Save new index of bottom point\r
+ mov si, ds:[bx+si] ; Get index of bottom point #2\r
+ .shl di, 2 ; Convert indexes to offsets\r
+ .shl si, 2\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetB]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetB], di\r
+ mov si, [MinIdxB]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@SBLoop ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+ mov si, OFFSET mx_ScanBuffer\r
+ mov ax, [BoxX1]\r
+ mov cx, [BoxX2]\r
+ sub cx, ax ; CX = bounding box width\r
+ mov bx, [mx_ClipX1]\r
+ sub bx, ax\r
+ jle @@ClipL1 ; No need to clip left\r
+ sub cx, bx ; Update width\r
+ add ax, bx ; BoxX1 = mx_ClipX1\r
+ mov [BoxX1], ax\r
+ .shl bx, 2 ; Warning!!! This is an hand-coded\r
+ add si, bx ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+ mov bx, ax\r
+ add bx, cx ; Last scan column\r
+ sub bx, [mx_ClipX2]\r
+ jle @@ClipL2 ; No need to clip right\r
+ sub cx, bx ; Clip right\r
+@@ClipL2:\r
+ test cx, cx ; Is clipped width positive?\r
+ jle @@Exit ; No, exit\r
+ mov [ScanCount], cx ; Save number of columns to draw\r
+ mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
+ mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+ mov ax, [BoxY1]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@ClipTB ; Need to clip top\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@ClipTB ; Need to clip bottom\r
+ jmp @@ClipYExit ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+ mov di, cx ; DI = scan count\r
+ inc di ; Increment count for pre-loop test\r
+ sub si, SIZE TSCAN\r
+@@ClipYLoop:\r
+ dec di ; Any column left?\r
+ jz @@ClipYExit ; No, exit\r
+ add si, SIZE TSCAN\r
+ mov ax, ds:[si].Y1 ; Y1\r
+ mov cx, ds:[si].Y2 ; Y2\r
+ mov dx, [mx_ClipY2]\r
+ cmp ax, dx ; Full clipped?\r
+ jg @@ClipYClip ; Yes, skip this column\r
+ cmp cx, dx ; Need to clip bottom?\r
+ jle @@ClipY1 ; No, continue\r
+; Clip bottom\r
+ mov ds:[si].Y2, dx\r
+ mov bx, cx\r
+ sub bx, dx ; Clip distance\r
+ sub cx, ax ; Height\r
+ jle @@ClipYClip\r
+ mov cx, ds:[si].Y2\r
+@@ClipY1:\r
+ mov dx, [mx_ClipY1]\r
+ cmp cx, dx ; Full top clipped?\r
+ jl @@ClipYClip ; Yes, skip\r
+ sub cx, ax ; Get height\r
+ jle @@ClipYClip ; Skip if not positive\r
+ cmp ax, dx ; Need to clip top?\r
+ jge @@ClipYLoop ; No, continue\r
+; Clip top\r
+ mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
+ sub dx, ax ; DX = number of pixels clipped\r
+ cmp cx, dx\r
+ ja @@ClipYLoop ; Not clipped, continue\r
+@@ClipYClip:\r
+ mov ds:[si].Y1, -1 ; Mark column as clipped\r
+ jmp @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+ mov es, [mx_VideoSegment]\r
+ mov si, [ScanOffsetT]\r
+ mov cl, BYTE PTR [BoxX1] ; Init write plane\r
+ and cl, 03h\r
+ mov al, 11h\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+ .shr [BoxX1], 2\r
+@@DrawLoop:\r
+ mov ax, ds:[si].Y1\r
+ test ax, ax ; Was column clipped?\r
+ js @@DrawNext ; Yes, skip\r
+ mov cx, ds:[si].Y2\r
+ sub cx, ax ; CX = height\r
+ jle @@DrawNext\r
+ mul [mx_BytesPerLine] ; Get pixel address\r
+ add ax, [BoxX1]\r
+ mov di, ax\r
+ mov ah, [WritePlane]\r
+ mov dx, TS\r
+ mov al, 02h\r
+ out dx, ax\r
+ mov ax, [Color]\r
+ mov dx, [mx_BytesPerLine]\r
+ shr cx, 1\r
+ jnc @@FillScan\r
+ mov es:[di], al\r
+ add di, dx\r
+ jcxz @@DrawNext\r
+@@FillScan:\r
+ mov es:[di], al\r
+ add di, dx\r
+ mov es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jnz @@FillScan\r
+@@DrawNext:\r
+ rol [WritePlane], 1\r
+ adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
+ add si, SIZE TSCAN\r
+ dec [ScanCount]\r
+ jnz @@DrawLoop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxFillPoly ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill with Gouraud shading\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGouraudPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT STRUC\r
+ X DW ?\r
+ Y DW ?\r
+TPOINT ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN STRUC\r
+ Y1 DW ?\r
+ E1 DB ?\r
+ C1 DB ?\r
+ Y2 DW ?\r
+ E2 DB ?\r
+ C2 DB ?\r
+TSCAN ENDS\r
+\r
+MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+EXTRN mx_ScanBuffer : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+; Also interpolates color for shading.\r
+;\r
+; Input:\r
+; DS:BX = pointer to start point (X1, Y1)\r
+; DS:SI = pointer to end point (X2, Y2)\r
+; ES:DI = pointer to edge buffer\r
+; DX = start color\r
+; AX = end color\r
+; Output:\r
+; ES:DI = updated pointer to edge buffer\r
+; Notes:\r
+; must preserve DS:SI.\r
+;\r
+subScan PROC NEAR\r
+ mov cx, ds:[si].X\r
+ sub cx, ds:[bx].X ; Get width\r
+ jg @@1\r
+ ret\r
+@@1:\r
+ push bp ; Save BP\r
+ push di ; Save scan info offset\r
+ push cx ; Save height\r
+ push ax ; Save colors\r
+ push dx\r
+\r
+ mov ax, ds:[si].Y\r
+ mov bx, ds:[bx].Y\r
+ sub ax, bx ; Get height\r
+ jg @@T2B ; Scan top to bottom\r
+ jl @@B2T ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+ mov ax, bx\r
+@@V:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@V\r
+ jmp @@GetColorInfo\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@T2BLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@T2BLoop\r
+ jmp @@GetColorInfo\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+@@B2TLoop:\r
+ mov es:[di].Y1, ax\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@B2TLoop\r
+\r
+; Now get the color info\r
+@@GetColorInfo:\r
+ pop bx ; Restore colors\r
+ pop ax\r
+ pop cx ; Height\r
+ pop di ; ES:DI -> scan info\r
+\r
+ sub ax, bx ; Get color range\r
+ jg @@CL2R\r
+ jl @@CR2L\r
+\r
+; Special case: same color\r
+ mov ah, bl\r
+ mov al, 80h\r
+@@CV:\r
+ mov WORD PTR es:[di].E1, ax\r
+ add di, SIZE TSCAN\r
+ dec cx\r
+ jnz @@CV\r
+ jmp @@Exit\r
+\r
+; Scan left to right\r
+@@CL2R:\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx ; BP:BX = fixed 16:16 step\r
+ mov dx, 8000h\r
+@@CL2RLoop:\r
+ mov es:[di].C1, al\r
+ mov es:[di].E1, dh\r
+ add di, SIZE TSCAN\r
+ add dx, bx\r
+ adc ax, bp\r
+ dec cx\r
+ jnz @@CL2RLoop\r
+ jmp @@Exit\r
+\r
+; Scan right to left\r
+@@CR2L:\r
+ neg ax\r
+ cwd\r
+ div cx\r
+ mov bp, ax\r
+ xor ax, ax\r
+ div cx\r
+ xchg ax, bx\r
+ mov dx, 8000h\r
+\r
+@@CR2LLoop:\r
+ mov es:[di].C1, al\r
+ mov es:[di].E1, dh\r
+ add di, SIZE TSCAN\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ dec cx\r
+ jnz @@CR2LLoop\r
+\r
+@@Exit:\r
+ pop bp\r
+ ret\r
+subScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a scan column.\r
+;\r
+; Input:\r
+; DS:SI = current TSCAN\r
+; ES:DI = address of top pixel\r
+; CX = number of pixels to write\r
+; DX = base color\r
+; Output:\r
+; none\r
+;\r
+subFillScan PROC NEAR\r
+ mov ax, WORD PTR ds:[si].E2\r
+ mov bx, WORD PTR ds:[si].E1\r
+ cmp ah, bh\r
+ jg @@L2R ; Color increases\r
+ jl @@R2L ; Color decreases\r
+\r
+; Special case: color doesn't change\r
+ add ax, dx\r
+ mov dx, [mx_BytesPerLine]\r
+@@V:\r
+ mov es:[di], ah\r
+ add di, dx\r
+ dec cx\r
+ jnz @@V\r
+ ret\r
+\r
+; Color increases\r
+@@L2R:\r
+ .push bp, si\r
+ mov si, bx\r
+ add si, dx ; Relocate color\r
+ sub ax, bx\r
+ xor dx, dx\r
+ div cx\r
+ mov bp, ax ; BP = color step, integer part\r
+ xor ax, ax\r
+ div cx\r
+ mov bx, ax ; BX = color step, fractional part\r
+ mov dx, 8000h\r
+ mov ax, [mx_BytesPerLine]\r
+ xchg si, ax\r
+@@L2RLoop:\r
+ mov es:[di], ah\r
+ add dx, bx\r
+ adc ax, bp\r
+ add di, si\r
+ dec cx\r
+ jnz @@L2RLoop\r
+ .pop bp, si\r
+ ret\r
+\r
+; Color decreases\r
+@@R2L:\r
+ .push bp, si\r
+ mov si, bx\r
+ add si, dx ; Relocate color\r
+ sub ax, bx\r
+ neg ax\r
+ xor dx, dx\r
+ div cx\r
+ mov bp, ax ; BP = color step, integer part\r
+ xor ax, ax\r
+ div cx\r
+ mov bx, ax ; BX = color step, fractional part\r
+ mov dx, 8000h\r
+ mov ax, [mx_BytesPerLine]\r
+ xchg si, ax\r
+@@R2LLoop:\r
+ mov es:[di], ah\r
+ sub dx, bx\r
+ sbb ax, bp\r
+ add di, si\r
+ dec cx\r
+ jnz @@R2LLoop\r
+ .pop bp, si\r
+ ret\r
+subFillScan ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+; Interpolates pixel colors using the Gouraud algorithm.\r
+;\r
+; Input:\r
+; Count = number of vertexes\r
+; Map = indexes of points and colors (integer)\r
+; Points = array of points (integer X, Y coordinates)\r
+; Colors = array of colors (integer)\r
+; Color = base color\r
+; Output:\r
+; none\r
+; Notes:\r
+; vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxGouraudPoly PROC FAR\r
+ ARG Color:WORD, \\r
+ Colors:DWORD, \\r
+ Points:DWORD, \\r
+ Map:DWORD, \\r
+ Count:WORD = ARG_SIZE\r
+ LOCAL WritePlane:BYTE:2, \\r
+ ScanOffsetT:WORD, \\r
+ ScanOffsetB:WORD, \\r
+ ScanCount:WORD, \\r
+ Holder:WORD, \\r
+ Height:WORD, \\r
+ MinIdxT:WORD, \\r
+ MinIdxB:WORD, \\r
+ MaxIdx:WORD, \\r
+ Width:WORD, \\r
+ BoxX1:WORD, \\r
+ BoxY1:WORD, \\r
+ BoxX2:WORD, \\r
+ BoxY2::WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+ mov cx, [Count]\r
+ cmp cx, 3\r
+ jb @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+ les di, [Map]\r
+ lds si, [Points] ; Pointer to vertex array\r
+ mov [BoxX1], 32767\r
+ mov [BoxX2], -32768\r
+ mov [BoxY1], 32767\r
+ mov [BoxY2], -32768\r
+\r
+ xor dx, dx\r
+@@MinMaxLoop:\r
+ mov bx, es:[di] ; Get index of vertex\r
+ .shl bx, 2 ; Get offset in point array\r
+ add bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+ mov ax, ds:[bx].X ; Get X coordinate\r
+ cmp ax, [BoxX1]\r
+ jge @@CheckMaxX\r
+ mov [BoxX1], ax\r
+ mov [MinIdxT], dx\r
+ mov [MinIdxB], dx\r
+@@CheckMaxX:\r
+ cmp ax, [BoxX2]\r
+ jle @@CheckMinY\r
+ mov [BoxX2], ax\r
+ mov [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+ mov ax, ds:[bx].Y\r
+ cmp ax, [BoxY1]\r
+ jge @@CheckMaxY\r
+ mov [BoxY1], ax\r
+@@CheckMaxY:\r
+ cmp ax, [BoxY2]\r
+ jle @@CheckDone\r
+ mov [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+ inc di ; Next map entry\r
+ inc di\r
+ inc dx\r
+ inc dx\r
+ dec cx\r
+ jnz @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+ mov ax, [BoxX2]\r
+ cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxX1]\r
+ cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get width\r
+ jle @@Exit ; Exit if not positive\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
+ jl @@Exit\r
+ mov bx, [BoxY1]\r
+ cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
+ jg @@Exit\r
+ sub ax, bx ; Get height\r
+ jle @@Exit ; Exit if not positive\r
+\r
+ dec [Count]\r
+ shl [Count], 1 ; We'll work with word offsets\r
+ mov es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+ mov ax, OFFSET mx_ScanBuffer\r
+ mov [ScanOffsetT], ax\r
+ mov si, [MinIdxT] ; Offset of bottom point index\r
+@@STLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of top point #1\r
+ dec si ; Next point\r
+ dec si\r
+ test si, si\r
+ jnl @@ST1\r
+ mov si, [Count]\r
+@@ST1:\r
+ mov [MinIdxT], si ; Save new index of top point\r
+ mov si, ds:[bx+si] ; Get index of top point #2\r
+ lds bx, [Colors] ; Get pointer to color array\r
+ shl di, 1 ; Convert indexes to offsets\r
+ shl si, 1\r
+ mov ax, ds:[bx+si] ; Get colors\r
+ mov dx, ds:[bx+di]\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ shl si, 1\r
+ shl di, 1\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetT]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetT], di\r
+ mov si, [MinIdxT]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@STLoop ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+ mov ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+ mov [ScanOffsetB], ax\r
+ mov si, [MinIdxB] ; Offset of bottom point index\r
+@@SBLoop:\r
+ lds bx, [Map] ; DS:BX -> map table\r
+ mov di, ds:[bx+si] ; Index of bottom point #1\r
+ inc si ; Next bottom point\r
+ inc si\r
+ cmp si, [Count]\r
+ jbe @@SB1\r
+ xor si, si\r
+@@SB1:\r
+ mov [MinIdxB], si ; Save new index of bottom point\r
+ mov si, ds:[bx+si] ; Get index of bottom point #2\r
+ lds bx, [Colors] ; Get pointer to color array\r
+ shl di, 1 ; Convert indexes to offsets\r
+ shl si, 1\r
+ mov ax, ds:[bx+si] ; Get colors\r
+ mov dx, ds:[bx+di]\r
+ lds bx, [Points] ; DS:BX -> point array\r
+ shl si, 1\r
+ shl di, 1\r
+ add si, bx ; DS:SI -> top point #2\r
+ add bx, di ; DS:BX -> top point #1\r
+ mov di, [ScanOffsetB]\r
+ call subScan ; Scan edge\r
+ mov [ScanOffsetB], di\r
+ mov si, [MinIdxB]\r
+ cmp si, [MaxIdx] ; End of edge?\r
+ jne @@SBLoop ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+ mov si, OFFSET mx_ScanBuffer\r
+ mov ax, [BoxX1]\r
+ mov cx, [BoxX2]\r
+ sub cx, ax ; CX = bounding box width\r
+ mov bx, [mx_ClipX1]\r
+ sub bx, ax\r
+ jle @@ClipL1 ; No need to clip left\r
+ sub cx, bx ; Update width\r
+ add ax, bx ; BoxX1 = mx_ClipX1\r
+ mov [BoxX1], ax\r
+ .shl bx, 3 ; Warning!!! This is an hand-coded\r
+ add si, bx ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+ mov bx, ax\r
+ add bx, cx ; Last scan column\r
+ sub bx, [mx_ClipX2]\r
+ jle @@ClipL2 ; No need to clip right\r
+ sub cx, bx ; Clip right\r
+@@ClipL2:\r
+ test cx, cx ; Is clipped width positive?\r
+ jle @@Exit ; No, exit\r
+ mov [ScanCount], cx ; Save number of columns to draw\r
+ mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
+ mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+ mov ax, [BoxY1]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@ClipTB ; Need to clip top\r
+ mov ax, [BoxY2]\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@ClipTB ; Need to clip bottom\r
+ jmp @@ClipYExit ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+ mov di, cx ; DI = scan count\r
+ inc di ; Increment count for pre-loop test\r
+ sub si, SIZE TSCAN\r
+@@ClipYLoop:\r
+ dec di ; Any column left?\r
+ jz @@ClipYExit ; No, exit\r
+ add si, SIZE TSCAN\r
+ mov ax, ds:[si].Y1 ; Y1\r
+ mov cx, ds:[si].Y2 ; Y2\r
+ mov dx, [mx_ClipY2]\r
+ cmp ax, dx ; Full clipped?\r
+ jg @@ClipYClip ; Yes, skip this column\r
+ cmp cx, dx ; Need to clip bottom?\r
+ jle @@ClipY1 ; No, continue\r
+; Clip bottom, need to scale colors too\r
+ mov ds:[si].Y2, dx\r
+ mov bx, cx\r
+ sub bx, dx ; Clip distance\r
+ sub cx, ax ; Height\r
+ jle @@ClipYClip\r
+ mov ax, WORD PTR ds:[si].E1\r
+ sub ax, WORD PTR ds:[si].E2\r
+ imul bx\r
+ idiv cx\r
+ add WORD PTR ds:[si].E2, ax\r
+ mov ax, ds:[si].Y1 ; Restore AX and CX\r
+ mov cx, ds:[si].Y2\r
+@@ClipY1:\r
+ mov dx, [mx_ClipY1]\r
+ cmp cx, dx ; Full top clipped?\r
+ jl @@ClipYClip ; Yes, skip\r
+ sub cx, ax ; Get height\r
+ jle @@ClipYClip ; Skip if not positive\r
+ cmp ax, dx ; Need to clip top?\r
+ jge @@ClipYLoop ; No, continue\r
+; Clip top, need to scale colors too\r
+ mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
+ sub dx, ax ; DX = number of pixels clipped\r
+ cmp cx, dx\r
+ jbe @@ClipYClip ; Full clipped, skip\r
+ mov ax, WORD PTR ds:[si].E2\r
+ sub ax, WORD PTR ds:[si].E1 ; AX = color distance\r
+ imul dx\r
+ idiv cx\r
+ add WORD PTR ds:[si].E1, ax ; Update starting color\r
+ jmp @@ClipYLoop\r
+@@ClipYClip:\r
+ mov ds:[si].Y1, -1 ; Mark column as clipped\r
+ jmp @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+ mov es, [mx_VideoSegment]\r
+ mov si, [ScanOffsetT]\r
+ mov cl, BYTE PTR [BoxX1] ; Init write plane\r
+ and cl, 03h\r
+ mov al, 11h\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+ .shr [BoxX1], 2\r
+ mov ax, [Color] ; Make 8:8 fixed color\r
+ mov ah, al\r
+ xor al, al\r
+ mov [Color], ax\r
+@@DrawLoop:\r
+ mov ax, ds:[si].Y1\r
+ test ax, ax ; Was column clipped?\r
+ js @@DrawNext ; Yes, skip\r
+ mov cx, ds:[si].Y2\r
+ sub cx, ax ; CX = height\r
+ jle @@DrawNext\r
+ mul [mx_BytesPerLine] ; Get pixel address\r
+ add ax, [BoxX1]\r
+ mov di, ax\r
+ mov ah, [WritePlane]\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax\r
+ mov dx, [Color]\r
+ call subFillScan\r
+@@DrawNext:\r
+ rol [WritePlane], 1\r
+ adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
+ add si, SIZE TSCAN\r
+ dec [ScanCount]\r
+ jnz @@DrawLoop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxGouraudPoly ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove PROC NEAR\r
+ shr cx, 1 ; Make CX even\r
+ jc @@Odd ; Special case if odd byte\r
+@@Loop: movsb\r
+ add si, 3\r
+ movsb\r
+ add si, 3\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: movsb\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ and es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ and es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ or es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ or es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ xor es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ xor es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip: inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+ ret\r
+subAdd ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxPutImage PROC FAR\r
+ ARG Op:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+ mov cl, [ReadPlane]\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov si, WORD PTR Image[0]\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov di, [PixelOffset]\r
+@@Loop:\r
+ push si\r
+ push di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+ mov ah, [OpInfo] ; Transparent color for subTrans\r
+ call [MoveFunction]\r
+ pop di\r
+ pop si\r
+ add si, [Width] ; Go to next image line\r
+ add di, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ rol [WritePlane], 1\r
+ adc [PixelOffset], 0\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPan\r
+\r
+EXTRN mxWaitDisplay : FAR\r
+EXTRN mxStartAddress : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+; X, Y = new X, Y coordinates of view screen\r
+; Output:\r
+; none\r
+;\r
+mxPan PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov ax, [Y]\r
+ mul [mx_BytesPerLine]\r
+ mov dx, [X]\r
+ shr dx, 1\r
+ shr dx, 1\r
+ add ax, dx\r
+ push ax ; Push the start address\r
+ call mxWaitDisplay\r
+ call mxStartAddress\r
+\r
+ mov dx, 03DAh ; Set the pixel pan register\r
+ in al, dx\r
+ mov dx, 03C0h\r
+ mov al, 33h\r
+ out dx, al\r
+ mov al, BYTE PTR [X]\r
+ and al, 3\r
+ shl al, 1\r
+ out dx, al\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxPan ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPP.ASM - Get/put pixel functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxGetPixel\r
+PUBLIC mxPutPixel\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_ClipX1 : WORD\r
+EXTRN mx_ClipY1 : WORD\r
+EXTRN mx_ClipX2 : WORD\r
+EXTRN mx_ClipY2 : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets a pixel.\r
+;\r
+; Input:\r
+; X, Y = pixel coordinates\r
+; Output:\r
+; pixel color\r
+;\r
+mxGetPixel PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ xor ax, ax\r
+ mov si, [X]\r
+ cmp si, [mx_ClipX1]\r
+ jl @@Exit\r
+ cmp si, [mx_ClipX2]\r
+ jg @@Exit\r
+ mov bx, [Y]\r
+ cmp bx, [mx_ClipY1]\r
+ jl @@Exit\r
+ cmp bx, [mx_ClipY2]\r
+ jg @@Exit\r
+\r
+ mov al, 04h ; Set read plane\r
+ mov ah, BYTE PTR [X]\r
+ and ah, 3\r
+ mov dx, GDC\r
+ out dx, ax\r
+\r
+ mov ds, [mx_VideoSegment]\r
+ mov ax, bx\r
+ mul [mx_BytesPerLine]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+ mov al, ds:[si] ; Get pixel value\r
+ xor ah, ah\r
+\r
+@@Exit:\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetPixel ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Puts a pixel of the specified color.\r
+;\r
+; Input:\r
+; X, Y = pixel coordinates\r
+; Color = pixel color\r
+; Output:\r
+; none\r
+;\r
+mxPutPixel PROC FAR\r
+ ARG Color:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov si, [X]\r
+ cmp si, [mx_ClipX1]\r
+ jl @@Exit\r
+ cmp si, [mx_ClipX2]\r
+ jg @@Exit\r
+ mov ax, [Y]\r
+ cmp ax, [mx_ClipY1]\r
+ jl @@Exit\r
+ cmp ax, [mx_ClipY2]\r
+ jg @@Exit\r
+\r
+ mov ds, [mx_VideoSegment]\r
+ mul [mx_BytesPerLine]\r
+ .shr si, 2\r
+ add si, ax\r
+\r
+ mov cl, BYTE PTR [X] ; Set write plane\r
+ and cl, 3\r
+ mov ax, 0102h\r
+ shl ah, cl\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ mov al, [Color] ; Write pixel\r
+ mov ds:[si], al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxPutPixel ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXRA.ASM - Row address\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxRowAddress\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the row address register.\r
+;\r
+; Input:\r
+; RowAddress = row size in words\r
+; Output:\r
+; none\r
+;\r
+mxRowAddress PROC FAR\r
+ ARG RowAddress:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ mov dx, CRTC\r
+ mov al, 13h\r
+ mov ah, [RowAddress]\r
+ out dx, ax\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxRowAddress ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXRP.ASM - Rotate palette function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxRotatePalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates the palette of the specified number of colors.\r
+;\r
+; Input:\r
+; Palette = pointer to palette\r
+; Count = number of colors to rotate\r
+; Step = step size\r
+; Output:\r
+; none\r
+;\r
+; Note: if Step is positive palette is rotated left to right, otherwise\r
+; right to left.\r
+;\r
+mxRotatePalette PROC FAR\r
+ ARG Step:WORD, \\r
+ Count:WORD, \\r
+ Palette:DWORD = ARG_SIZE\r
+ LOCAL Holder:BYTE:768 = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov bx, [Count]\r
+ add bx, bx\r
+ add bx, [Count] ; BX = Count*3\r
+\r
+ lds si, [Palette] ; DS:SI -> palette\r
+ push ss\r
+ pop es\r
+ lea di, Holder ; ES:DI -> local space\r
+ cld\r
+\r
+ mov ax, [Step]\r
+ mov dx, ax\r
+ test ax, ax\r
+ jz @@Exit ; Nothing to do, exit\r
+ jl @@RightToLeft\r
+\r
+@@LeftToRight:\r
+ add ax, ax\r
+ add dx, ax ; DX = Step*3\r
+ sub bx, dx ; BX = (Count-Step)*3\r
+ add si, bx\r
+ push si\r
+ mov cx, dx\r
+ rep movsb\r
+ mov es, WORD PTR Palette[2]\r
+ mov di, si\r
+ dec di ; ES:DI -> last byte of palette\r
+ pop si\r
+ dec si\r
+ mov cx, bx\r
+ std\r
+ rep movsb\r
+ push ss\r
+ pop ds\r
+ lea si, Holder\r
+ les di, [Palette]\r
+ mov cx, dx\r
+ cld\r
+ rep movsb\r
+ jmp @@Exit\r
+\r
+@@RightToLeft:\r
+ add ax, ax\r
+ add dx, ax\r
+ neg dx ; DX = Step*3\r
+ sub bx, dx ; BX = (Count-Step)*3\r
+ mov cx, dx\r
+ rep movsb\r
+ les di, [Palette]\r
+ mov cx, bx\r
+ rep movsb\r
+ push ss\r
+ pop ds\r
+ lea si, Holder\r
+ mov cx, dx\r
+ rep movsb\r
+\r
+@@Exit:\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxRotatePalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSA.ASM - Start address function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStartAddress\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Modifies the starting address of video memory.\r
+;\r
+; Input:\r
+; StartAddr = new start address of video memory\r
+; Output:\r
+; none\r
+;\r
+mxStartAddress PROC FAR\r
+ ARG StartAddr:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov bx, [StartAddr]\r
+ mov dx, CRTC\r
+ mov al, 0Ch ; Linear Starting Address high\r
+ mov ah, bh\r
+ cli\r
+ out dx, ax\r
+ mov al, 0Dh ; Linear Starting Address low\r
+ mov ah, bl\r
+ out dx, ax\r
+ sti\r
+\r
+ .leave ARG_SIZE\r
+mxStartAddress ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSC.ASM - Set color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetColor\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the selected DAC register.\r
+;\r
+; Input:\r
+; Index = index of color to set\r
+; R, G, B = color components\r
+; Output:\r
+; none\r
+;\r
+mxSetColor PROC FAR\r
+ ARG B:BYTE:2, \\r
+ G:BYTE:2, \\r
+ R:BYTE:2, \\r
+ Index:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [Index]\r
+ mov dx, 3C8h ; PEL write address register\r
+ out dx, al\r
+ inc dx\r
+\r
+ mov al, [R]\r
+ out dx, al\r
+ mov al, [G]\r
+ out dx, al\r
+ mov al, [B]\r
+ out dx, al\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxSetColor ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Stretch image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStretchImage\r
+\r
+EXTRN subClipBox : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Stretches and copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; NewWidth = new width of image in pixels\r
+; NewHeight = new height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxStretchImage PROC FAR\r
+ ARG Op:WORD, \\r
+ NewHeight:WORD, \\r
+ NewWidth:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WidthStep:DWORD, \\r
+ HeightStep:DWORD, \\r
+ ImageLo:WORD, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Get width stretch factor\r
+ IF USE386 EQ TRUE\r
+ movzx edx, [Width]\r
+ xor eax, eax\r
+ movzx ebx, [NewWidth]\r
+ shl ebx, 16\r
+ idiv ebx\r
+ mov [WidthStep], eax\r
+ ELSE\r
+ xor dx, dx ; Width stretch factor\r
+ mov ax, [Width]\r
+ mov bx, [NewWidth]\r
+ div bx\r
+ mov WORD PTR WidthStep[2], ax\r
+ xor ax, ax\r
+ div bx\r
+ mov WORD PTR WidthStep[0], ax\r
+ ENDIF\r
+; Get height stretch factor\r
+ IF USE386 EQ TRUE\r
+ movzx edx, [Height]\r
+ xor eax, eax\r
+ movzx ebx, [NewHeight]\r
+ shl ebx, 16\r
+ idiv ebx\r
+ mov [HeightStep], eax\r
+ ELSE\r
+ xor dx, dx\r
+ mov ax, [Height]\r
+ mov bx, [NewHeight]\r
+ div bx\r
+ mov WORD PTR HeightStep[2], ax\r
+ xor ax, ax\r
+ div bx\r
+ mov WORD PTR HeightStep[0], ax\r
+ ENDIF\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [NewWidth]\r
+ mov dx, [NewHeight]\r
+ call subClipBox\r
+ jc @@Exit ; Full clipped\r
+ mov [NewWidth], cx\r
+ mov [NewHeight], dx\r
+ sub [X], bx\r
+ sub [Y], ax\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl ; Set read plane\r
+ mov cl, bl\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al ; Set write plane\r
+\r
+; Relocate image origin if previously clipped\r
+ mov ax, [Y]\r
+ test ax, ax\r
+ jz @@OriginYDone\r
+ IF USE386 EQ TRUE\r
+ shl eax, 16\r
+ imul [HeightStep]\r
+ mov ax, [Width]\r
+ mul dx\r
+ ELSE\r
+ mov bx, ax\r
+ mul WORD PTR HeightStep[0]\r
+ mov cx, dx\r
+ mov ax, bx\r
+ mul WORD PTR HeightStep[2]\r
+ add ax, cx\r
+ mul [Width]\r
+ ENDIF\r
+ add WORD PTR [Image], ax\r
+@@OriginYDone:\r
+ mov ax, [X]\r
+ test ax, ax\r
+ jz @@OriginXDone\r
+ IF USE386 EQ TRUE\r
+ shl eax, 16\r
+ imul [WidthStep]\r
+ add WORD PTR [Image], dx\r
+ ELSE\r
+ mov bx, ax\r
+ mul WORD PTR WidthStep[0]\r
+ mov cx, dx\r
+ mov ax, bx\r
+ mul WORD PTR WidthStep[2]\r
+ add ax, cx\r
+ add WORD PTR [Image], ax\r
+ ENDIF\r
+@@OriginXDone:\r
+ mov ax, WORD PTR HeightStep[2]\r
+ mul [Width]\r
+ mov WORD PTR HeightStep[2], ax\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ mov ds, WORD PTR Image[2]\r
+ xor ax, ax\r
+ mov [ImageLo], ax\r
+@@Loop:\r
+ mov si, WORD PTR Image[0] ; Get pointer to image\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov cx, [NewHeight]\r
+ mov di, [PixelOffset] ; ES:DI points to video memory\r
+ mov ah, [OpInfo] ; Additional raster op info\r
+ xor bx, bx\r
+ mov dx, [mx_BytesPerLine]\r
+ call [MoveFunction] ; Draw column\r
+ inc [ReadPlane] ; Next read plane\r
+ rol [WritePlane], 1 ; Next write plane\r
+ adc [PixelOffset], 0 ; Update video offset if needed\r
+ mov dx, WORD PTR WidthStep[0]\r
+ mov ax, WORD PTR WidthStep[2]\r
+ add [ImageLo], dx\r
+ adc WORD PTR Image[0], ax ; Next image column\r
+ dec [NewWidth]\r
+ jnz @@Loop ; Repeat for all columns\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions, on entry:\r
+; AH = additional raster op info (e.g. transparent color)\r
+; BX = 0,\r
+; CX = pixel count,\r
+; DX = mx_BytesPerLine.\r
+;\r
+subMove PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ mov es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ and es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ or es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ xor es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip:\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ add di, dx\r
+ dec cx\r
+ jz @@Exit\r
+ add si, WORD PTR HeightStep[2]\r
+ add bx, WORD PTR HeightStep[0]\r
+ jnc @@Loop\r
+ add si, [Width]\r
+ jmp @@Loop\r
+@@Exit: ret\r
+subAdd ENDP\r
+\r
+mxStretchImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Start line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxStartLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes the video start address to the specified line.\r
+;\r
+; Input:\r
+; Line = new start line\r
+; Output:\r
+; none\r
+;\r
+mxStartLine PROC FAR\r
+ ARG Line:WORD = ARG_SIZE\r
+ .enter 0\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [Line] ; Get video offset\r
+ mul [mx_BytesPerLine]\r
+ xchg ax, bx ; Copy it into BX\r
+\r
+; Wait display\r
+ mov dx, STATUS\r
+@@1: in al, dx\r
+ test al, 08h\r
+ jnz @@1\r
+\r
+; Set starting address\r
+ mov dx, CRTC\r
+ mov al, 0Ch ; Linear Starting Address high\r
+ mov ah, bh\r
+ cli\r
+ out dx, ax\r
+ mov al, 0Dh ; Linear Starting Address low\r
+ mov ah, bl\r
+ out dx, ax\r
+ sti\r
+\r
+; Wait retrace\r
+ mov dx, STATUS\r
+@@2: in al,dx\r
+ test al, 08h\r
+ jz @@2\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxChangeMode\r
+PUBLIC mxGetAspect\r
+PUBLIC mxGetScreenSize\r
+PUBLIC mxSetMode\r
+\r
+PUBLIC mx_ScreenWidth\r
+PUBLIC mx_ScreenHeight\r
+PUBLIC mx_BytesPerLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mxSetSysClipRegion : FAR\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_ScreenWidth DW ? ; Current screen width\r
+mx_ScreenHeight DW ?\r
+mx_AspectX DW ? ; Aspect ratio for current mode\r
+mx_AspectY DW ?\r
+mx_BytesPerLine DW 0 ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine LABEL WORD ; CRTC\r
+ DW 04009h ; Cell height: 1 scan line\r
+ DW 00014h ; Double word mode off\r
+ DW 0E317h ; Byte mode on\r
+ DW 0\r
+TBL_DoubleLine LABEL WORD ; CRTC\r
+ DW 04109h ; Cell height: 2 scan lines\r
+ DW 00014h\r
+ DW 0E317h\r
+ DW 0\r
+TBL_Width320 LABEL WORD ; CRTC\r
+ DW 05F00h ; Horizontal total\r
+ DW 04F01h ; Horizontal displayed\r
+ DW 05002h ; Start horizontal blanking\r
+ DW 08203h ; End horizontal blanking\r
+ DW 05404h ; Start horizontal sync\r
+ DW 08005h ; End horizontal sync\r
+ DW 02813h ; Row address\r
+ DW 0\r
+TBL_Width360 LABEL WORD ; CRTC\r
+ DW 06B00h ; Horizontal total\r
+ DW 05901h ; Horizontal displayed\r
+ DW 05A02h ; Start horizontal blanking\r
+ DW 08E03h ; End horizontal blanking\r
+ DW 05E04h ; Start horizontal sync\r
+ DW 08A05h ; End horizontal sync\r
+ DW 02D13h ; Row address\r
+ DW 0\r
+TBL_Height175 LABEL WORD ; CRTC\r
+ DW 0BF06h ; Vertical total\r
+ DW 01F07h ; Overflow\r
+ DW 08310h ; Start vertical sync\r
+ DW 08511h ; End vertical sync\r
+ DW 05D12h ; Vertical displayed\r
+ DW 06315h ; Start vertical blanking\r
+ DW 0BA16h ; End vertical blanking\r
+ DW 0\r
+TBL_Height200 LABEL WORD ; CRTC\r
+ DW 0BF06h ; Vertical total\r
+ DW 01F07h ; Overflow\r
+ DW 09C10h ; Start vertical sync\r
+ DW 08E11h ; End vertical sync\r
+ DW 08F12h ; Vertical displayed\r
+ DW 09615h ; Start vertical blanking\r
+ DW 0B916h ; End vertical blanking\r
+ DW 0\r
+TBL_Height240 LABEL WORD ; CRTC\r
+ DW 00D06h ; Vertical total\r
+ DW 03E07h ; Overflow\r
+ DW 0EA10h ; Start vertical sync\r
+ DW 08C11h ; End vertical sync\r
+ DW 0DF12h ; Vertical displayed\r
+ DW 0E715h ; Start vertical blanking\r
+ DW 00616h ; End vertical blanking\r
+ DW 0\r
+TBL_Tweak400x600:\r
+ DW 07400h\r
+ DW 06301h\r
+ DW 06402h\r
+ DW 09703h\r
+ DW 06804h\r
+ DW 09505h\r
+ DW 08606h\r
+ DW 0F007h\r
+ DW 06009h\r
+ DW 0310Fh\r
+ DW 05B10h\r
+ DW 08D11h\r
+ DW 05712h\r
+ DW 03213h\r
+ DW 00014h\r
+ DW 06015h\r
+ DW 08016h\r
+ DW 0E317h\r
+ DW 0\r
+\r
+TBL_320x200:\r
+ DB 63h ; 400 scan lines, 25 MHz clock\r
+ DW 6, 5 ; Aspect: 6/5 = 1.2:1\r
+ DW 320, 200 ; Size\r
+ DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x240:\r
+ DB 0E3h ; 400 scan lines, 25 MHz clock\r
+ DW 1, 1 ; Aspect: 1/1 = 1:1\r
+ DW 320, 240 ; Size\r
+ DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x400:\r
+ DB 63h ; 480 scan lines, 25 MHz clock\r
+ DW 6, 10 ; Aspect: 6/10 = 0.6:1\r
+ DW 320, 400 ; Size\r
+ DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+ DW 819 ; Max height\r
+TBL_320x480:\r
+ DB 0E3h ; 480 scan lines, 25 MHz clock\r
+ DW 1, 2 ; Aspect: 1/2 = 0.5:1\r
+ DW 320, 480 ; Size\r
+ DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+ DW 819 ; Max height\r
+TBL_360x200:\r
+ DB 067h ; 400 scan lines, 28 MHz clock\r
+ DW 27, 20 ; Aspect: 27/20 = 1.35:1\r
+ DW 360, 200 ; Size\r
+ DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x240:\r
+ DB 0E7h ; 480 scan lines, 28 MHz clock\r
+ DW 9, 8 ; Aspect: 9/8 = 1.125:1\r
+ DW 360, 240 ; Size\r
+ DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x400:\r
+ DB 067h ; 400 scan lines, 28 MHz clock\r
+ DW 27, 40 ; Aspect: 27/40 = 0.675:1\r
+ DW 360, 400 ; Size\r
+ DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x480:\r
+ DB 0E7h ; 480 scan lines, 28 MHz clock\r
+ DW 9, 16 ; Aspect: 9/16 = 0.5625:1\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_320x175:\r
+ DB 0A3h\r
+ DW 0, 0 ; Aspect:\r
+ DW 320, 175\r
+ DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+ DW 819\r
+TBL_320x350:\r
+ DB 0A3h\r
+ DW 0, 0 ; Aspect:\r
+ DW 320, 175\r
+ DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+ DW 819\r
+TBL_360x175:\r
+ DB 0A7h\r
+ DW 0, 0 ; Aspect:\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+ DW 728 ; Max height\r
+TBL_360x350:\r
+ DB 0A7h\r
+ DW 0, 0 ; Aspect:\r
+ DW 360, 480 ; Size\r
+ DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+ DW 728 ; Max height\r
+TBL_400x600:\r
+ DB 0E7h ; 28 MHz clock\r
+ DW 1, 2 ; Aspect: 1/2 = 0.5:1\r
+ DW 400, 600 ; Size\r
+ DW TBL_Tweak400x600, 0\r
+ DW 655 ; Max height\r
+\r
+TBL_Mode LABEL WORD\r
+ DW TBL_320x175\r
+ DW TBL_320x200\r
+ DW TBL_320x240\r
+ DW TBL_320x350\r
+ DW TBL_320x400\r
+ DW TBL_320x480\r
+ DW TBL_360x175\r
+ DW TBL_360x200\r
+ DW TBL_360x240\r
+ DW TBL_360x350\r
+ DW TBL_360x400\r
+ DW TBL_360x480\r
+ DW TBL_400x600\r
+\r
+MAXVMODE EQU ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText PROC NEAR\r
+ ASSUME ds:MX_TEXT\r
+ mov ax, 0003h\r
+ int 10h ; Call BIOS set mode\r
+\r
+ mov [mx_ScreenHeight], 0\r
+ mov [mx_BytesPerLine], 0\r
+ ret\r
+subText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+; Mode = mode to select (MX_???x???)\r
+; Output:\r
+; none\r
+;\r
+mxSetMode PROC FAR\r
+ ARG Mode:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov si, [Mode]\r
+ cmp si, MAXVMODE ; Is it a valid mode?\r
+ ja @@Exit ; No, exit\r
+ test si, si ; Text mode?\r
+ jnz @@Set ; No, handle it\r
+\r
+ call subText ; Back to text mode\r
+ jmp @@Exit ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+ dec si ; Skip text mode\r
+ shl si, 1\r
+ mov si, TBL_Mode[si]\r
+ cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+ push si ; Save SI\r
+ mov ax, 0013h\r
+ int 10h ; Use BIOS to set 320x200 linear mode\r
+ pop si ; Restore SI\r
+\r
+ mov dx, TS\r
+ mov ax, 0604h\r
+ out dx, ax ; Disable chain-4 mode\r
+ mov ax, 0100h\r
+ out dx, ax ; Reset\r
+ mov dx, MISC\r
+ lodsb\r
+ out dx, al ; New timing/size\r
+ mov dx, TS\r
+ mov ax, 0300h\r
+ out dx, ax ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ and al, 7Fh ; Clear write protect bit\r
+ out dx, al\r
+\r
+ lodsw ; Get X aspect\r
+ mov [mx_AspectX], ax\r
+ lodsw ; Get Y aspect\r
+ mov [mx_AspectY], ax\r
+ lodsw ; Get screen width\r
+ mov [mx_ScreenWidth], ax\r
+ shr ax, 1\r
+ shr ax, 1 ; Divide by four to get bytes per line\r
+ mov [mx_BytesPerLine], ax\r
+ lodsw ; Get screen height\r
+ mov [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+ mov bx, si\r
+ mov dx, CRTC\r
+@@TableLoop:\r
+ mov si, ds:[bx] ; DS:SI -> table of CRTC registers\r
+ inc bx\r
+ inc bx ; DS:BX -> offset of next table\r
+ test si, si ; Last table?\r
+ jz @@EndLoop ; Yes, exit loop\r
+@@Loop:\r
+ lodsw ; Get CRTC register index and value\r
+ test ax, ax ; End of table?\r
+ jz @@TableLoop ; Yes, go to next table\r
+ out dx, ax ; Set register AL to value AH\r
+ jmp @@Loop ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+ push [mx_ScreenWidth]\r
+ push WORD PTR ds:[bx]\r
+ call mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+ mov dx, TS\r
+ mov ax, 0F02h\r
+ out dx, ax ; Enable all planes\r
+ mov es, [mx_VideoSegment]\r
+ xor di, di\r
+ mov cx, 8000h\r
+ xor ax, ax\r
+ rep stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ or al, 80h ; Set write protect bit\r
+ out dx, al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ mov ax, [mx_ScreenWidth]\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxSetMode ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+; Mode = mode to select (MX_???x???)\r
+; Output:\r
+; none\r
+; Notes:\r
+; this function assumes that mxSetMode and mxSetVirtualScreen\r
+; have been called first. View size is rearranged to match the\r
+; specified mode, but video memory is not cleared.\r
+; Differences from mxSetMode:\r
+; - video BIOS is not called to initialize graphics;\r
+; - row address register is not modified;\r
+; - video memory is not cleared;\r
+; - mx_BytesPerLine is not modified;\r
+; - system clip region is not modified.\r
+;\r
+mxChangeMode PROC FAR\r
+ ARG Mode:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov si, [Mode]\r
+ cmp si, MAXVMODE ; Is it a valid mode?\r
+ ja @@Exit ; No, exit\r
+ test si, si ; Text mode?\r
+ jz @@Exit ; Yes, exit\r
+\r
+ dec si ; Skip text mode\r
+ shl si, 1\r
+ mov si, TBL_Mode[si]\r
+ cld\r
+\r
+ mov dx, TS\r
+ mov ax, 0604h\r
+ out dx, ax ; Disable chain-4 mode\r
+ mov ax, 0100h\r
+ out dx, ax ; Reset\r
+ mov dx, MISC\r
+ lodsb\r
+ out dx, al ; New timing/size\r
+ mov dx, TS\r
+ mov ax, 0300h\r
+ out dx, ax ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ and al, 7Fh ; Clear write protect bit\r
+ out dx, al\r
+\r
+ lodsw ; Get X aspect\r
+ mov [mx_AspectX], ax\r
+ lodsw ; Get Y aspect\r
+ mov [mx_AspectY], ax\r
+ lodsw ; Get screen width\r
+ mov [mx_ScreenWidth], ax\r
+ lodsw ; Get screen height\r
+ mov [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+ mov bx, si\r
+ mov dx, CRTC\r
+@@TableLoop:\r
+ mov si, ds:[bx] ; DS:SI -> table of CRTC registers\r
+ inc bx\r
+ inc bx ; DS:BX -> offset of next table\r
+ test si, si ; Last table?\r
+ jz @@EndLoop ; Yes, exit loop\r
+@@Loop:\r
+ lodsw ; Get CRTC register index and value\r
+ test ax, ax ; End of table?\r
+ jz @@TableLoop ; Yes, go to next table\r
+ cmp al, 13h ; Row address register?\r
+ je @@Loop ; Yes, ignore it\r
+ out dx, ax ; Set register AL to value AH\r
+ jmp @@Loop ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+ mov dx, CRTC\r
+ mov al, 11h\r
+ out dx, al ; Vertical sync end register\r
+ inc dx\r
+ in al, dx\r
+ or al, 80h ; Set write protect bit\r
+ out dx, al\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ mov ax, [mx_ScreenWidth]\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxChangeMode ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+; AspectX = pointer to aspect X\r
+; AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect PROC FAR\r
+ ARG AspectY:DWORD, \\r
+ AspectX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [AspectX]\r
+ mov ax, [mx_AspectX]\r
+ mov ds:[si], ax\r
+ lds si, [AspectY]\r
+ mov ax, [mx_AspectY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetAspect ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+; Width = pointer to screen width\r
+; Height = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+ ARG SizeY:DWORD, \\r
+ SizeX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [SizeX]\r
+ mov ax, [mx_ScreenWidth]\r
+ mov ds:[si], ax\r
+ lds si, [SizeY]\r
+ mov ax, [mx_ScreenHeight]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSP.ASM - Set palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetPalette\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the VGA palette.\r
+;\r
+; Input:\r
+; Buffer = pointer to palette data (R,G,B)\r
+; Start = index of first color to set\r
+; Count = number of color to set\r
+; Output:\r
+; none\r
+;\r
+mxSetPalette PROC FAR\r
+ ARG Count:WORD, \\r
+ Start:WORD, \\r
+ Buffer:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ lds si, [Buffer]\r
+ mov cx, [Count]\r
+ mov ax, [Start]\r
+ mov dx, 3C8h ; PEL write address register\r
+ out dx, al\r
+ inc dx\r
+ cld\r
+ cli ; Disable interrupts\r
+@@Loop:\r
+ lodsb\r
+ out dx, al ; Red\r
+ lodsb\r
+ out dx, al ; Green\r
+ lodsb\r
+ out dx, al ; Blue\r
+ loop @@Loop ; Loop until done\r
+ sti ; Enable interrupts\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxSetPalette ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXSS.ASM - Split screen function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSplitScreen\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Splits the screen.\r
+;\r
+; Input:\r
+; Line = scan line at which screen has to be splitted\r
+; Output:\r
+; none\r
+;\r
+mxSplitScreen PROC FAR\r
+ ARG Line:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+; Modify the line compare value: bits 0-7 are in the Line Compare\r
+; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7)\r
+; and bit 9 is in the Maximum Row Address register (CRTC #9)\r
+ mov ax, [Line]\r
+ shl ax, 1 ; Adjust line for mode "X"\r
+ mov bh, ah\r
+ mov bl, ah\r
+ and bx, 0201h\r
+ mov cl, 4\r
+ shl bx, cl\r
+ shl bh, 1\r
+ mov dx, CRTC\r
+; Write bits 0-7 to line compare register\r
+ mov ah, al\r
+ mov al, 18h\r
+ out dx, ax\r
+; Write bit 8 to overflow register\r
+ mov al, 07h\r
+ out dx, al\r
+ inc dx\r
+ in al, dx\r
+ dec dx\r
+ mov ah, al\r
+ and ah, 11101111b\r
+ or ah, bl\r
+ mov al, 07h\r
+ out dx, ax\r
+; Write bit 9 to maximum row address register\r
+ mov al, 09h\r
+ out dx, al\r
+ inc dx\r
+ in al, dx\r
+ dec dx\r
+ mov ah, al\r
+ and ah, 10111111b\r
+ or ah, bh\r
+ mov al, 09h\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxSplitScreen ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutTile\r
+PUBLIC mxTransPutTile\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+ shr cx, 1 ; Move line\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutTile ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxTransPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+; Move one line\r
+ jcxz @@MoveLineDone\r
+@@MoveLineLoop:\r
+ mov al, ds:[si]\r
+ test al, al\r
+ jz @@MoveLineNext\r
+ mov es:[di], al\r
+@@MoveLineNext:\r
+ inc si\r
+ inc di\r
+ dec cx\r
+ jnz @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxTransPutTile ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXVS.ASM - Set/get virtual screen\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxSetVirtualScreen\r
+PUBLIC mxGetVirtualScreen\r
+\r
+EXTRN mxRowAddress : FAR\r
+EXTRN mxSetSysClipRegion : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+EXTRN mx_CodeSegment : WORD\r
+\r
+mx_VirtualWidth DW ? ; Virtual screen size\r
+mx_VirtualHeight DW ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the virtual screen.\r
+;\r
+; Input:\r
+; Width = virtual screen width\r
+; Height = virtual screen height\r
+; Output:\r
+; 0 on success, else invalid parameters\r
+;\r
+mxSetVirtualScreen PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds\r
+\r
+; Set DS to code segment\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, 1 ; Assume an error\r
+ cmp [Width], 320 ; Check width\r
+ jb @@Exit\r
+ push ax ; Save return code\r
+ mov dx, 0004h\r
+ xor ax, ax ; DX:AX = 256K\r
+ div [Width] ; Max height in AX\r
+ cmp [Height], ax\r
+ pop ax ; Restore return code\r
+ ja @@Exit ; Exit if bad heigth\r
+\r
+ mov ax, [Width]\r
+ and ax, 0FFF8h ; Align to byte\r
+ mov [mx_VirtualWidth], ax\r
+ shr ax, 1\r
+ shr ax, 1\r
+ mov [mx_BytesPerLine], ax\r
+ shr ax, 1\r
+ push ax\r
+ call mxRowAddress ; Set row address\r
+ mov ax, [Height]\r
+ mov [mx_VirtualHeight], ax\r
+\r
+ push [Width]\r
+ push [Height]\r
+ call mxSetSysClipRegion\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetVirtualScreen ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current virtual screen size.\r
+;\r
+; Input:\r
+; Width = pointer to virtual screen width\r
+; Height = pointer to virtual screen height\r
+; Output:\r
+; none\r
+;\r
+mxGetVirtualScreen PROC FAR\r
+ ARG Height:DWORD, \\r
+ Width:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si\r
+\r
+ mov ax, [mx_VirtualWidth]\r
+ lds si, [Width]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_VirtualHeight]\r
+ lds si, [Height]\r
+ mov ds:[si], ax\r
+\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetVirtualScreen ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWD.ASM - Wait display function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWaitDisplay\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for display start.\r
+;\r
+mxWaitDisplay PROC FAR\r
+ mov dx, STATUS\r
+@@1: in al, dx\r
+ test al, 08h\r
+ jnz @@1\r
+ ret\r
+mxWaitDisplay ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWM.ASM - Set write mode function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWriteMode\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write mode.\r
+;\r
+; Input:\r
+; Mode = write mode (0,1,2,3)\r
+; Output:\r
+; none\r
+;\r
+mxWriteMode PROC FAR\r
+ ARG Mode:BYTE:2 = ARG_SIZE\r
+ .enter 0\r
+\r
+ mov dx, GDC\r
+ mov ah, [Mode]\r
+ and ah, 00000011b\r
+ or ah, 01000000b\r
+ mov al, 05h\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxWriteMode ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWP.ASM - Set write/read plane functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWritePlane\r
+PUBLIC mxReadPlane\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write plane(s).\r
+;\r
+; Input:\r
+; Plane = write plane(s) to set (bit 0 enables plane 0,\r
+; bit 1 enables plane 1 and so on, different planes\r
+; may be selected at the same time)\r
+; Output:\r
+; none\r
+;\r
+mxWritePlane PROC FAR\r
+ ARG Plane:BYTE:2 = ARG_SIZE\r
+ .enter 0\r
+\r
+ mov ah, [Plane]\r
+ and ah, 00001111b ; Mask off unused bits\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax\r
+\r
+ .leave ARG_SIZE\r
+mxWritePlane ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the read plane.\r
+;\r
+; Input:\r
+; Plane = read plane to set (0,1,2,3)\r
+; Output:\r
+; none\r
+;\r
+mxReadPlane PROC FAR\r
+ ARG Plane:BYTE:2 = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ mov al, 04h\r
+ mov ah, [Plane]\r
+ and ah, 0000011b ; Mask off unused bits\r
+ mov dx, GDC\r
+ out dx, ax\r
+ .leave ARG_SIZE\r
+mxReadPlane ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXWR.ASM - Wait vertical retrace function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxWaitRetrace\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for vertical retrace start.\r
+;\r
+mxWaitRetrace PROC FAR\r
+ mov dx, STATUS\r
+@@1: in al,dx\r
+ test al, 08h\r
+ jz @@1\r
+ ret\r
+mxWaitRetrace ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0\r
+ DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1\r
+ DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2\r
+ DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3\r
+ DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4\r
+ DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5\r
+ DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6\r
+ DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7\r
+ DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8\r
+ DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9\r
+ DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10\r
+ DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11\r
+ DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12\r
+ DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13\r
+ DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14\r
+ DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15\r
+ DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16\r
+ DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17\r
+ DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18\r
+ DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19\r
+ DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20\r
+ DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21\r
+ DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22\r
+ DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23\r
+ DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24\r
+ DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25\r
+ DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26\r
+ DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27\r
+ DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28\r
+ DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29\r
+ DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30\r
+ DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; \r
+ DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; !\r
+ DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; "\r
+ DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; #\r
+ DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $\r
+ DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; %\r
+ DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; &\r
+ DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; '\r
+ DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; (\r
+ DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; )\r
+ DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; *\r
+ DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; +\r
+ DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; ,\r
+ DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; -\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; .\r
+ DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; /\r
+ DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0\r
+ DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1\r
+ DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2\r
+ DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3\r
+ DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4\r
+ DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5\r
+ DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6\r
+ DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7\r
+ DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8\r
+ DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9\r
+ DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; :\r
+ DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ;\r
+ DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; <\r
+ DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; =\r
+ DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; >\r
+ DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ?\r
+ DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A\r
+ DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B\r
+ DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C\r
+ DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F\r
+ DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G\r
+ DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H\r
+ DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I\r
+ DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J\r
+ DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K\r
+ DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L\r
+ DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M\r
+ DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O\r
+ DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P\r
+ DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q\r
+ DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R\r
+ DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S\r
+ DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T\r
+ DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U\r
+ DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V\r
+ DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W\r
+ DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X\r
+ DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y\r
+ DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z\r
+ DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [\r
+ DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \\r
+ DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ]\r
+ DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _\r
+ DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; `\r
+ DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b\r
+ DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c\r
+ DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d\r
+ DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e\r
+ DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h\r
+ DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i\r
+ DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j\r
+ DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k\r
+ DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l\r
+ DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m\r
+ DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n\r
+ DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o\r
+ DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q\r
+ DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r\r
+ DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s\r
+ DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t\r
+ DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u\r
+ DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v\r
+ DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w\r
+ DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x\r
+ DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y\r
+ DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z\r
+ DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; {\r
+ DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; |\r
+ DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; }\r
+ DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~\r
+ DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ; \7f\r
+ DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128\r
+ DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129\r
+ DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130\r
+ DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131\r
+ DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132\r
+ DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133\r
+ DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134\r
+ DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135\r
+ DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136\r
+ DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137\r
+ DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138\r
+ DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139\r
+ DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140\r
+ DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141\r
+ DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142\r
+ DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143\r
+ DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144\r
+ DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145\r
+ DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146\r
+ DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147\r
+ DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148\r
+ DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149\r
+ DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150\r
+ DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151\r
+ DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152\r
+ DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153\r
+ DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154\r
+ DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155\r
+ DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156\r
+ DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157\r
+ DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158\r
+ DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159\r
+ DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160\r
+ DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161\r
+ DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162\r
+ DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163\r
+ DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164\r
+ DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165\r
+ DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166\r
+ DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167\r
+ DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168\r
+ DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169\r
+ DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170\r
+ DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171\r
+ DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172\r
+ DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173\r
+ DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174\r
+ DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175\r
+ DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176\r
+ DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177\r
+ DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178\r
+ DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181\r
+ DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182\r
+ DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183\r
+ DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184\r
+ DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185\r
+ DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186\r
+ DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187\r
+ DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188\r
+ DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190\r
+ DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198\r
+ DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199\r
+ DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200\r
+ DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201\r
+ DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202\r
+ DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203\r
+ DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205\r
+ DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206\r
+ DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210\r
+ DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212\r
+ DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213\r
+ DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215\r
+ DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217\r
+ DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220\r
+ DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221\r
+ DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223\r
+ DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224\r
+ DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225\r
+ DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226\r
+ DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227\r
+ DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228\r
+ DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229\r
+ DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230\r
+ DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231\r
+ DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233\r
+ DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234\r
+ DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235\r
+ DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236\r
+ DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237\r
+ DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239\r
+ DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240\r
+ DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241\r
+ DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242\r
+ DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243\r
+ DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244\r
+ DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245\r
+ DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246\r
+ DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247\r
+ DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248\r
+ DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249\r
+ DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250\r
+ DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251\r
+ DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252\r
+ DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253\r
+ DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+!ifdef __LINUX__\r
+REMOVECOMMAND=rm -f\r
+COPYCOMMAND=cp -f\r
+DIRSEP=/\r
+OBJ=o\r
+!else\r
+REMOVECOMMAND=del\r
+COPYCOMMAND=copy /y\r
+DIRSEP=\\r
+OBJ=obj\r
+!endif\r
+LIBINCS = modex.def\r
+\r
+LIBOBJS = mxbb.$(OBJ) mxcc.$(OBJ) mxcg.$(OBJ) mxcl.$(OBJ) mxcr.$(OBJ) mxfb.$(OBJ) mxgc.$(OBJ) mxgi.$(OBJ) mxgm.$(OBJ) mxgp.$(OBJ) mxgv.$(OBJ) mxhl.$(OBJ) mxit.$(OBJ) mxll.$(OBJ) mxln.$(OBJ) mxot.$(OBJ) mxpb.$(OBJ) mxpf.$(OBJ) mxpg.$(OBJ) mxpi.$(OBJ) mxpn.$(OBJ) mxpp.$(OBJ) mxra.$(OBJ) mxrp.$(OBJ) mxsa.$(OBJ) mxsc.$(OBJ) mxsi.$(OBJ) mxsl.$(OBJ) mxsm.$(OBJ) mxsp.$(OBJ) mxss.$(OBJ) mxtl.$(OBJ) mxvs.$(OBJ) mxwd.$(OBJ) mxwm.$(OBJ) mxwp.$(OBJ) mxwr.$(OBJ)\r
+#mxfp.$(OBJ) \r
+#\r
+# ASM compiler\r
+#\r
+ASMC =wasm\r
+ASMO =-mh -0\r
+\r
+#\r
+# PAS compiler\r
+#\r
+#PASC = tpc\r
+#PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = wlib\r
+\r
+# .asm.obj:\r
+# $(ASMC) $(ASMO) $<\r
+\r
+mxbb.$(OBJ): mxbb.asm\r
+ $(ASMC) $(ASMO) mxbb.asm\r
+mxcc.$(OBJ): mxcc.asm\r
+ $(ASMC) $(ASMO) mxcc.asm\r
+mxcg.$(OBJ): mxcg.asm\r
+ $(ASMC) $(ASMO) mxcg.asm\r
+mxcl.$(OBJ): mxcl.asm\r
+ $(ASMC) $(ASMO) mxcl.asm\r
+mxcr.$(OBJ): mxcr.asm\r
+ $(ASMC) $(ASMO) mxcr.asm\r
+mxfb.$(OBJ): mxfb.asm\r
+ $(ASMC) $(ASMO) mxfb.asm\r
+mxfp.$(OBJ): mxfp.asm\r
+ $(ASMC) $(ASMO) mxfp.asm\r
+mxgc.$(OBJ): mxgc.asm\r
+ $(ASMC) $(ASMO) mxgc.asm\r
+mxgi.$(OBJ): mxgi.asm\r
+ $(ASMC) $(ASMO) mxgi.asm\r
+mxgm.$(OBJ): mxgm.asm\r
+ $(ASMC) $(ASMO) mxgm.asm\r
+mxgp.$(OBJ): mxgp.asm\r
+ $(ASMC) $(ASMO) mxgp.asm\r
+mxgv.$(OBJ): mxgv.asm\r
+ $(ASMC) $(ASMO) mxgv.asm\r
+mxhl.$(OBJ): mxhl.asm\r
+ $(ASMC) $(ASMO) mxhl.asm\r
+mxit.$(OBJ): mxit.asm\r
+ $(ASMC) $(ASMO) mxit.asm\r
+mxll.$(OBJ): mxll.asm\r
+ $(ASMC) $(ASMO) mxll.asm\r
+mxln.$(OBJ): mxln.asm\r
+ $(ASMC) $(ASMO) mxln.asm\r
+mxot.$(OBJ): mxot.asm\r
+ $(ASMC) $(ASMO) mxot.asm\r
+mxpb.$(OBJ): mxpb.asm\r
+ $(ASMC) $(ASMO) mxpb.asm\r
+mxpf.$(OBJ): mxpf.asm\r
+ $(ASMC) $(ASMO) mxpf.asm\r
+mxpg.$(OBJ): mxpg.asm\r
+ $(ASMC) $(ASMO) mxpg.asm\r
+mxpi.$(OBJ): mxpi.asm\r
+ $(ASMC) $(ASMO) mxpi.asm\r
+mxpn.$(OBJ): mxpn.asm\r
+ $(ASMC) $(ASMO) mxpn.asm\r
+mxpp.$(OBJ): mxpp.asm\r
+ $(ASMC) $(ASMO) mxpp.asm\r
+mxra.$(OBJ): mxra.asm\r
+ $(ASMC) $(ASMO) mxra.asm\r
+mxrp.$(OBJ): mxrp.asm\r
+ $(ASMC) $(ASMO) mxrp.asm\r
+mxsa.$(OBJ): mxsa.asm\r
+ $(ASMC) $(ASMO) mxsa.asm\r
+mxsc.$(OBJ): mxsc.asm\r
+ $(ASMC) $(ASMO) mxsc.asm\r
+mxsi.$(OBJ): mxsi.asm\r
+ $(ASMC) $(ASMO) mxsi.asm\r
+mxsl.$(OBJ): mxsl.asm\r
+ $(ASMC) $(ASMO) mxsl.asm\r
+mxsm.$(OBJ): mxsm.asm\r
+ $(ASMC) $(ASMO) mxsm.asm\r
+mxsp.$(OBJ): mxsp.asm\r
+ $(ASMC) $(ASMO) mxsp.asm\r
+mxss.$(OBJ): mxss.asm\r
+ $(ASMC) $(ASMO) mxss.asm\r
+mxtl.$(OBJ): mxtl.asm\r
+ $(ASMC) $(ASMO) mxtl.asm\r
+mxvs.$(OBJ): mxvs.asm\r
+ $(ASMC) $(ASMO) mxvs.asm\r
+mxwd.$(OBJ): mxwd.asm\r
+ $(ASMC) $(ASMO) mxwd.asm\r
+mxwm.$(OBJ): mxwm.asm\r
+ $(ASMC) $(ASMO) mxwm.asm\r
+mxwp.$(OBJ): mxwp.asm\r
+ $(ASMC) $(ASMO) mxwp.asm\r
+mxwr.$(OBJ): mxwr.asm\r
+ $(ASMC) $(ASMO) mxwr.asm\r
+\r
+all: $(LIBOBJS) modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+ MXCC.OBJ \\r
+ MXCG.OBJ \\r
+ MXCL.OBJ \\r
+ MXCR.OBJ \\r
+ MXFB.OBJ \\r
+ MXFP.OBJ \\r
+ MXGC.OBJ \\r
+ MXGI.OBJ \\r
+ MXGM.OBJ \\r
+ MXGP.OBJ \\r
+ MXGV.OBJ \\r
+ MXHL.OBJ \\r
+ MXIT.OBJ \\r
+ MXLL.OBJ \\r
+ MXLN.OBJ \\r
+ MXOT.OBJ \\r
+ MXPB.OBJ \\r
+ MXPF.OBJ \\r
+ MXPG.OBJ \\r
+ MXPI.OBJ \\r
+ MXPN.OBJ \\r
+ MXPP.OBJ \\r
+ MXRA.OBJ \\r
+ MXRP.OBJ \\r
+ MXSA.OBJ \\r
+ MXSC.OBJ \\r
+ MXSI.OBJ \\r
+ MXSL.OBJ \\r
+ MXSM.OBJ \\r
+ MXSP.OBJ \\r
+ MXSS.OBJ \\r
+ MXTL.OBJ \\r
+ MXVS.OBJ \\r
+ MXWD.OBJ \\r
+ MXWM.OBJ \\r
+ MXWP.OBJ \\r
+ MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+ $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+;JUMPS\r
+;LOCALS\r
+\r
+TRUE EQU 1 ; Boolean constants\r
+FALSE EQU 0\r
+\r
+USE286 = FALSE ; TRUE enables 80286 instructions\r
+USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+ P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+ P386\r
+ USE286 = TRUE\r
+ENDIF\r
+\r
+MXVERSION EQU 0128h ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC EQU 3C2h ; Miscellaneous output\r
+TS EQU 3C4h ; Timing Sequencer index register\r
+GDC EQU 3CEh ; Graphics Data Controller index register\r
+CRTC EQU 3D4h ; CRTC index register\r
+STATUS EQU 3DAh ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET EQU 0\r
+OP_MOVE EQU 0 ; Same as OP_SET\r
+OP_AND EQU 1\r
+OP_OR EQU 2\r
+OP_XOR EQU 3\r
+OP_TRANS EQU 4\r
+OP_ADD EQU 5 ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU 4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.PUSH has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+ IFB <$reg> ;; Is argument blank?\r
+ EXITM ;; Yes, exit\r
+ ELSEIFIDNI <$reg>, <FLAGS> ;; Is argument the keyword "FLAGS"?\r
+ pushf ;; Yes, push flags\r
+ ELSE\r
+ push $reg ;; Push argument\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.POP has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+ IFNB <$reg> ;; Is argument non-blank?\r
+ IFIDNI <$reg>, <FLAGS> ;; Yes, is it the keyword "FLAGS"?\r
+ popf ;; Yes, pop flags\r
+ ELSE\r
+ pop $reg ;; Pop argument\r
+ ENDIF\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter MACRO localsize\r
+ IF USE286 EQ TRUE\r
+ enter localsize, 0\r
+ ELSE\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, localsize\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.leave MACRO argsize\r
+; IF USE286 EQ TRUE\r
+; leave\r
+; ELSE\r
+; mov sp, bp\r
+; pop bp\r
+; ENDIF\r
+; IFNB <argspace>\r
+; ret argsize\r
+; ELSE\r
+; ret\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shr MACRO arg, count\r
+; IF USE286 EQ TRUE\r
+; shr arg, count\r
+; ELSE\r
+; $temp = count\r
+; WHILE $temp GT 0\r
+; shr arg, 1\r
+; $temp = $temp-1\r
+; ENDM\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shl MACRO arg, count\r
+; IF USE286 EQ TRUE\r
+; shl arg, count\r
+; ELSE\r
+; $temp = count\r
+; WHILE $temp GT 0\r
+; shl arg, 1\r
+; $temp = $temp-1\r
+; ENDM\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.chk386 MACRO name, jump\r
+; IF USE386 EQ FALSE\r
+; .OUT "Warning: ", <name>, " needs a 386 or better to run!"\r
+; jmp @@jump\r
+; ENDIF\r
+;ENDM\r
--- /dev/null
+/*\r
+ MODEX.H - C/C++ include file for the MODEX library\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_ // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT 0 // 80x25 text\r
+#define MX_320x175 1 // 320x175x256\r
+#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350 4 // 320x350x256\r
+#define MX_320x400 5 // 320x400x256, 2 pages\r
+#define MX_320x480 6 // 320x480x256, 1 page\r
+#define MX_360x175 7 // 360x175x256\r
+#define MX_360x200 8 // 360x200x256, 3 pages\r
+#define MX_360x240 9 // 360x240x256, 2 pages\r
+#define MX_360x350 10 // 360x350x256\r
+#define MX_360x400 11 // 360x400x256, 1 page\r
+#define MX_360x480 12 // 360x480x256, 1 page\r
+#define MX_400x600 13 // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN 0\r
+#define MX_FADEOUT 1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET 0 // No operator\r
+#define OP_AND 1 // And\r
+#define OP_OR 2 // Or\r
+#define OP_XOR 3 // Xor\r
+#define OP_TRANS 4 // Transparent\r
+#define OP_ADD 5 // Additive\r
+#define OP_MOVE 0 // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE unsigned char\r
+#define MXBOOL short int\r
+#define MXSINT short int\r
+#define MXUINT unsigned short int\r
+#define MXAPI far pascal\r
+#define MXPTR void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT MXAPI mxInit( void ); // Returns 0 if successful\r
+void MXAPI mxTerm( void );\r
+MXUINT MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void MXAPI mxChangeMode( MXUINT mode );\r
+void MXAPI mxSetMode( MXUINT mode );\r
+void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void MXAPI mxWriteMode( MXBYTE wm );\r
+void MXAPI mxSplitScreen( MXUINT line );\r
+void MXAPI mxStartAddress( MXUINT sa );\r
+void MXAPI mxStartLine( MXUINT sl );\r
+void MXAPI mxWaitDisplay( void );\r
+void MXAPI mxWaitRetrace( void );\r
+void MXAPI mxWritePlane( MXBYTE wp );\r
+void MXAPI mxReadPlane( MXBYTE rp );\r
+void MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL MXAPI mxGetClip( void );\r
+MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL MXAPI mxSetClip( MXBOOL );\r
+void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef MXBYTE\r
+#undef MXBOOL\r
+#undef MXSINT\r
+#undef MXUINT\r
+#undef MXPTR\r
+#undef MXAPI\r
+\r
+#endif // _MODEX_H_\r
--- /dev/null
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXPT.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
--- /dev/null
+(*\r
+ Turbo Pascal interface to the MODEX library\r
+ Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+ (* Video modes *)\r
+ MX_TEXT = 0;\r
+ MX_320x175 = 1;\r
+ MX_320x200 = 2;\r
+ MX_320x240 = 3;\r
+ MX_320x350 = 4;\r
+ MX_320x400 = 5;\r
+ MX_320x480 = 6;\r
+ MX_360x175 = 7;\r
+ MX_360x200 = 8;\r
+ MX_360x240 = 9;\r
+ MX_360x350 = 10;\r
+ MX_360x400 = 11;\r
+ MX_360x480 = 12;\r
+ MX_400x600 = 13;\r
+\r
+ (* Fade effects *)\r
+ MX_FADEIN = 0;\r
+ MX_FADEOUT = 1;\r
+\r
+ (* Raster ops *)\r
+ OP_SET = 0;\r
+ OP_AND = 1;\r
+ OP_OR = 2;\r
+ OP_XOR = 3;\r
+ OP_TRANS = 4;\r
+ OP_ADD = 5;\r
+ OP_MOVE = 0; (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt; external;\r
+procedure mxChangeMode( Mode: word ); external;\r
+procedure mxCircle; external;\r
+procedure mxColorToGray; external;\r
+procedure mxFadePalette; external;\r
+procedure mxFillBox; external;\r
+procedure mxGammaCorrect; external;\r
+procedure mxGetAspect( var AspectX, AspectY: word ); external;\r
+function mxGetClipRegion; external;\r
+function mxGetClip: boolean; external;\r
+procedure mxGetImage; external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function mxGetPixel( X, Y: word ): byte; external;\r
+procedure mxGetScreenSize( var Width, Height: word ); external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external;\r
+function mxGetVersion: word; external;\r
+procedure mxGetVirtualScreen( var Width, Height: word ); external;\r
+procedure mxInit; external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external;\r
+procedure mxOutChar( X, Y: integer; C: char ); external;\r
+procedure mxOutText( X, Y: integer; S: pointer ); external;\r
+procedure mxPan( X, Y: word ); external;\r
+procedure mxPutImage; external;\r
+procedure mxPutPixel( X, Y: word; C: byte ); external;\r
+procedure mxPutTile; external;\r
+procedure mxReadPlane( Plane: byte ); external;\r
+procedure mxRotatePalette; external;\r
+procedure mxRowAddress( RowAddress: byte ); external;\r
+function mxSetClip( Clip: boolean ): boolean; external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external;\r
+procedure mxSetColor( Index, R, G, B: word ); external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word ); external;\r
+procedure mxSetMode( Mode: word ); external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word ); external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer ); external;\r
+procedure mxSetVirtualScreen( Width, Height: word ); external;\r
+procedure mxSplitScreen( Line: word ); external;\r
+procedure mxStartAddress( StartAddress: word ); external;\r
+procedure mxStartLine; external;\r
+procedure mxStretchImage; external;\r
+procedure mxTerm; external;\r
+procedure mxTransPutTile; external;\r
+procedure mxWaitDisplay; external;\r
+procedure mxWaitRetrace; external;\r
+procedure mxWriteMode( Mode: byte ); external;\r
+procedure mxWritePlane( Plane: byte ); external;\r
+\r
+procedure mxFillPoly; external;\r
+procedure mxGouraudPoly; external;\r
+procedure mxTexturePoly; external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+ Prints a Turbo Pascal string.\r
+ Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+ S := S + #0;\r
+ mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
--- /dev/null
+(*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ MAX_SPRITE = 100;\r
+type\r
+ (* Sprite structure *)\r
+ TSprite = record\r
+ X, Y : integer; (* Sprite coordinates *)\r
+ DX,DY: integer; (* Deltas for sprite movement *)\r
+ W, H : integer; (* Sprite width and height *)\r
+ Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *)\r
+ end;\r
+ (* RGB color structure *)\r
+ TRgb = record\r
+ R, G, B: byte;\r
+ end;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *)\r
+ Palette: array[ byte ] of TRgb; (* Palette *)\r
+ Page : word; (* Page offset *)\r
+ I : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X := Random( 320 ); (* Initialize position with random values *)\r
+ S.Y := Random( 240 );\r
+ S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+ S.DY := Random( 7 )-3;\r
+ S.W := 16; (* Size is fixed in this program *)\r
+ S.H := 16;\r
+ (* The image is a square with a hole inside *)\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); (* Get new position *)\r
+ Inc( S.Y, S.DY );\r
+ (* Check sprite position, change delta if needed *)\r
+ if( S.X > 320 ) then begin\r
+ S.X := 320;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.X < -16 ) then begin\r
+ S.X := -16;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.Y > 240 ) then begin\r
+ S.Y := 240;\r
+ S.DY := -S.DY;\r
+ end;\r
+ if( S.Y < -16 ) then begin\r
+ S.Y := -16;\r
+ S.DY := -S.DY;\r
+ end;\r
+ (* Draw the sprite, note the Page offset added to the *)\r
+ (* Y coordinate of the image *)\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+ (* Initialize library *)\r
+ mxInit;\r
+\r
+ (* Enter graphics mode *)\r
+ mxSetMode( MX_320x240 );\r
+\r
+ (* Print initialization message *)\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ (* Initialize sprites *)\r
+ for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+ (* Draw background *)\r
+ for I:=1 to 192 do begin\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ end;\r
+\r
+ (* Compute and set palette *)\r
+ for I:=1 to 192 do with Palette[I+63] do begin\r
+ R := 0;\r
+ G := 0;\r
+ B := 0;\r
+ if( I < 64 ) then\r
+ R := I shr 1+31\r
+ else if( I < 128 ) then\r
+ G := (I-64) shr 1+31\r
+ else\r
+ B := (I-128) shr 1+31;\r
+ end;\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ (* Main loop *)\r
+ Page := 240;\r
+ while( not KeyPressed ) do begin\r
+ (* Set clip region to current page *)\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ (* Restore background *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ (* Draw sprites *)\r
+ for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+ (* Print message *)\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ (* Flip page *)\r
+ mxStartLine( Page );\r
+ Page := 240-Page;\r
+ (* Animate palette *)\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO02 - Texture mapping and palette rotation\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+ LSIZE = 85;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of T2DPoint;\r
+ Width : word;\r
+ Data : array[ 1..64*64 ] of byte;\r
+ end;\r
+ TQuad = record\r
+ VtxCnt : word;\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+var\r
+ Vtx : array[ 0..7 ] of TPoint;\r
+ XVtx : array[ 0..7 ] of TPoint;\r
+ VVtx : array[ 0..7 ] of T2DPoint;\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Txts : array[ 0..5 ] of TTexture;\r
+ Nrm : array[ 0..5 ] of TPoint;\r
+ XNrm : array[ 0..5 ] of TPoint;\r
+ Page : word;\r
+ Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+ I: word;\r
+begin\r
+ mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+ MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+ mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+ (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+ with Txts[Idx] do begin\r
+ Desc[0].X := $80; Desc[0].Y := $80;\r
+ Desc[1].X := $80; Desc[1].Y := $3F80;\r
+ Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+ Desc[3].X := $3F80; Desc[3].Y := $80;\r
+ Width := 64;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Build vertexes for a cube *)\r
+ with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ for I:=0 to 7 do begin (* Make points 16:16 fixed *)\r
+ Vtx[I].X := Vtx[I].X*$10000;\r
+ Vtx[I].Y := Vtx[I].Y*$10000;\r
+ Vtx[I].Z := Vtx[I].Z*$10000;\r
+ end;\r
+ (* Build faces *)\r
+ with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+ with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+ with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+ with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+ with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+ with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+ for I:=0 to 5 do Face[I].Texture := I;\r
+ (* Build textures and palette *)\r
+ Randomize;\r
+ FillChar( Palette, SizeOf(Palette), 0 );\r
+ MakePlasmaPalette( Palette, PAL_RGB );\r
+ mxSetPalette( @Palette, 0, 193 );\r
+ for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *)\r
+ (* Draw cube: backface culling is straighforward in this case, so *)\r
+ (* it can be handled by the polygon filling procedure *)\r
+ for I:=0 to 5 do\r
+ mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *)\r
+ Page := 240-Page;\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 1000; (* Number of points *)\r
+ EDGE = 70; (* Length of cube edge *)\r
+ RADIUS = 90; (* Radius of sphere *)\r
+ WAITCOUNT = 192; (* Frames to wait for non-morphing shapes *)\r
+ MS = 32; (* Number of steps for morphing *)\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+ InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+ InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+ InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+ P3DPointArray = ^T3DPointArray;\r
+var\r
+ CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+ VVtx : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+ Page : word;\r
+ Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+ L: longint;\r
+begin\r
+ L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+ Toggle := A;\r
+ if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+ I: integer;\r
+begin\r
+ New( CubeVtx );\r
+ New( SphereVtx );\r
+ New( Vtx );\r
+ New( XVtx );\r
+ (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+ Randomize;\r
+ for I:=0 to MAXVTX-1 do begin\r
+ with CubeVtx^[I] do begin\r
+ (* Build cube *)\r
+ X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Z := Toggle( EDGE*$10000 );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ end;\r
+ with SphereVtx^[I] do begin\r
+ (* Build sphere *)\r
+Retry:\r
+ X := (longint(Random(2*RADIUS))-RADIUS);\r
+ Y := (longint(Random(2*RADIUS))-RADIUS);\r
+ if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+ Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+ end;\r
+ end;\r
+ (* Initialize morphing *)\r
+ Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+ Status := 0;\r
+ Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Fully unoptimized, slowest loop I could think of! *)\r
+ for I:=0 to MAXVTX-1 do begin\r
+ Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+ Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+ Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ C := #0;\r
+ repeat\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw points *)\r
+ for I:=0 to MAXVTX-1 do\r
+ mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ Page := 240-Page;\r
+ (* Morph *)\r
+ if( Odd(Status) ) then begin\r
+ Morph;\r
+ Inc( Morph1, Delta1 );\r
+ Inc( Morph2, Delta2 );\r
+ if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+ if( Status = 4 ) then Status := 0;\r
+ end\r
+ else begin\r
+ Dec( Count );\r
+ if( Count < 0 ) then begin\r
+ Inc( Status );\r
+ Count := WAITCOUNT;\r
+ Morph1 := InitMorph1[Status];\r
+ Morph2 := InitMorph2[Status];\r
+ Delta1 := InitDelta1[Status];\r
+ Delta2 := InitDelta2[Status];\r
+ end;\r
+ end;\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO04 - Multiple textures and triple buffering (3 pages)\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 256;\r
+ MAXCUB = 2;\r
+ MAXTXT = 2;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ TxtSunDial: array[ 0..7 ] of word = (\r
+ $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+ TxtSapphire : array[ 0..7 ] of word = (\r
+ $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+ TxtMarble: array[ 0..7 ] of word = (\r
+ $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of record X, Y: word end;\r
+ Width : word;\r
+ Data : pointer;\r
+ end;\r
+ TQuad = record\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+ TCube = record\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Base : integer;\r
+ end;\r
+var\r
+ Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+ VVtx : array[ 0..MAXVTX ] of T2DPoint;\r
+ Cube : array[ 0..MAXCUB ] of TCube;\r
+ ZList : array[ 0..MAXCUB ] of integer;\r
+ VtxCnt : word;\r
+ Txts : array[ 0..MAXTXT ] of TTexture;\r
+ Page : word;\r
+ Palette : array[ byte ] of record R, G, B: byte; end;\r
+ TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+ with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+ Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+ FaceIdx: array[ 0..23 ] of integer = (\r
+ 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+ I, VC: integer;\r
+begin\r
+ VC := VtxCnt;\r
+ C.Base := VC;\r
+ AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+ for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+ for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+ P: ^word;\r
+ I: integer;\r
+begin\r
+ P := @VtxData;\r
+ with Txts[Idx] do begin\r
+ for I:=0 to 3 do begin\r
+ Desc[I].X := P^; Inc( P );\r
+ Desc[I].Y := P^; Inc( P );\r
+ end;\r
+ Width := 129;\r
+ Data := TxtDat1;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+ V: integer;\r
+ F: file;\r
+ P: array[ 1..768 ] of byte;\r
+begin\r
+ (* Initialize objects *)\r
+ VtxCnt := 0;\r
+ MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *)\r
+ Cube[0].Face[0].Texture := 0;\r
+ V := VtxCnt;\r
+ MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+ tdSetTranslation( Trans );\r
+ tdSetRotation( 32, 32, 00 );\r
+ tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *)\r
+ for I:=V to V+7 do begin\r
+ Vtx[I].X := XVtx[I].X;\r
+ Vtx[I].Y := XVtx[I].Y;\r
+ Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+ end;\r
+ MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+ (* Load texture and palette *)\r
+ Assign( F, 'DEMO04.DAT' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, P, SizeOf(P) );\r
+ mxSetPalette( @P, 0, 256 );\r
+ GetMem( TxtDat1, 63*1024 );\r
+ BlockRead( F, TxtDat1^, 129*286 );\r
+ Close( F );\r
+ TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+ (* Init textures *)\r
+ MakeTexture( 0, TxtSundial );\r
+ MakeTexture( 1, TxtMarble );\r
+ MakeTexture( 2, TxtSapphire );\r
+ Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+ I, J, K: integer;\r
+ ZMax: array[ 0..MAXCUB ] of longint;\r
+ ZI: integer;\r
+ L: longint;\r
+begin\r
+ for I:=0 to MAXCUB do begin\r
+ L := XVtx[Cube[I].Base].Z;\r
+ for J:=1 to 7 do\r
+ if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+ ZMax[I] := L;\r
+ ZList[I] := I;\r
+ end;\r
+ for I:=0 to MAXCUB-1 do begin\r
+ ZI := I;\r
+ for J:=I+1 to MAXCUB do\r
+ if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+ if( ZI <> I ) then begin\r
+ K := ZList[I];\r
+ ZList[I] := ZList[ZI];\r
+ ZList[ZI] := K;\r
+ end;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I, J, K: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ AX := 0; AY := 0; AZ := 0;\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 600*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 1 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw objects *)\r
+ SortObjects;\r
+ for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+ for J:=0 to 5 do begin\r
+ K := Face[J].Texture;\r
+ mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+ end;\r
+ end;\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO05 - A Gouraud-shaded rotating torus\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+ MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *)\r
+ MAXVTX2 = 15; RADIUS2 = 30;\r
+ MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+ MAXFACE = MAXVTX;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *)\r
+ Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *)\r
+type\r
+ TQuad = record\r
+ QVtx : array[ 0..3 ] of integer;\r
+ end;\r
+var\r
+ Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *)\r
+ VVtx : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+ Face : array[ 0..MAXFACE ] of TQuad; (* Polys *)\r
+ Culled : array[ 0..MAXFACE ] of integer;\r
+ GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *)\r
+ VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *)\r
+ Page : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+ GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ R, N, X, Y, Z: real;\r
+ I, J, K, V: integer;\r
+begin\r
+ (* Build vertexes *)\r
+ for I:=0 to MAXVTX1 do begin\r
+ K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+ R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+ for J:=0 to MAXVTX2 do begin\r
+ V := I*(MAXVTX2+1)+J; (* Index of current vertex *)\r
+ (* Compute coordinates of current vertex *)\r
+ X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *)\r
+ Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+ Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+ Vtx[V].X := Round( X )*$10000; (* Save coordinates *)\r
+ Vtx[V].Y := Round( Y )*$10000;\r
+ Vtx[V].Z := Round( Z )*$10000;\r
+ (* Compute direction of Gouraud normal thru current vertex *)\r
+ X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+ Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+ N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *)\r
+ GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *)\r
+ GNrm[V].Y := Trunc( Y*$10000/N );\r
+ GNrm[V].Z := Trunc( Z*$10000/N );\r
+ end;\r
+ end;\r
+ (* Generate faces so that depth-sorting is not needed: there are still *)\r
+ (* some *very* little errors, but this is the best I could devise *)\r
+ J := 0;\r
+ K := 0;\r
+ for I:=0 to MAXFACE do with Face[I] do begin\r
+ QVtx[0] := GetVtx( J, K );\r
+ QVtx[1] := GetVtx( J, K+1 );\r
+ QVtx[2] := GetVtx( J+1, K+1 );\r
+ QVtx[3] := GetVtx( J+1, K );\r
+ Inc( K );\r
+ if( K > MAXVTX2 ) then begin\r
+ K := 0;\r
+ Inc( J );\r
+ end;\r
+ end;\r
+{$ifndef ALTPAL}\r
+ for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *)\r
+{$else}\r
+ for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+ for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetLight( Light );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+ tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *)\r
+ tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+ (* Backplane culling is not really needed here! *)\r
+ FillChar( Culled, SizeOf(Culled), 0 );\r
+ tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 3 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw polygons *)\r
+ for I:=0 to MAXFACE do with Face[I] do\r
+ if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO06 - Magnifying glass\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ R = 40; (* Lens radius *)\r
+ K : real = 1.8; (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+ TLine = array[ 0..319 ] of byte;\r
+ PLine = ^TLine;\r
+ TScreen = array[ 0..239 ] of PLine;\r
+var\r
+ VScreen: TScreen; (* Virtual screen *)\r
+ BallX : array[ 0..R, 0..R ] of integer;\r
+ BallY : array[ 0..R, 0..R ] of integer;\r
+ Sprite : array[ -R..R, -R..R ] of byte;\r
+ Page : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+ LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+ LR := Sqrt( X*X + Y*Y );\r
+ if( LR = 0 ) then Exit;\r
+ if( LR < R ) then begin\r
+ Z := Sqrt( R*R - LR*LR );\r
+ SinA := LR / R;\r
+ SinB := SinA / K;\r
+ TgB := SinB / Sqrt( 1-SinB*SinB );\r
+ Q := LR - TgB*Z;\r
+ X := Round( X * ( Q/LR ) );\r
+ Y := Round( Y * ( Q/LR ) );\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ F : file;\r
+ Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+ X, Y,\r
+ X2, Y2 : integer;\r
+begin\r
+ (* Load background image *)\r
+ Assign( F, 'demo06.dat' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, Palette, 768 );\r
+ mxSetPalette( @Palette, 0, 256 );\r
+ for Y:=0 to 239 do begin\r
+ New( VScreen[Y] );\r
+ BlockRead( F, VScreen[Y]^, 320 );\r
+ mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+ end;\r
+ Close( F );\r
+ (* Build lens *)\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ X2 := X;\r
+ Y2 := Y;\r
+ GetCoords( X2, Y2 );\r
+ BallX[X, Y] := X2;\r
+ BallY[X, Y] := Y2;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+ X, Y: integer;\r
+begin\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ end;\r
+ end;\r
+ (* Draw the sprite *)\r
+ mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+ Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*Delta;\r
+ end;\r
+end;\r
+\r
+var\r
+ X, Y, DX, DY: integer;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240;\r
+ X := R;\r
+ Y := R;\r
+ Randomize;\r
+ DX := Delta;\r
+ DY := Delta;\r
+\r
+ (* Main loop *)\r
+ repeat\r
+ (* Update video *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ PutLens( X, Y );\r
+ mxCircle( X, Page+Y, R, 0 );\r
+ (* Update lens coordinates *)\r
+ Inc( X, DX );\r
+ Check( X+R >= 319, X, DX, 319-R, -1 );\r
+ Check( X <= R, X, DX, R, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+ Check( Y <= R, Y, DY, R, +1 );\r
+ (* Flip pages: double buffering, avoid wait for display *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Wait for hidden page to show *)\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO07 - Hardware scrolling\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ (* Change this if scrolling seems jerky (this simple program does *)\r
+ (* not handle vertical retrace/display very well) *)\r
+ STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*(Random(3)+2);\r
+ end;\r
+end;\r
+\r
+var\r
+ I, X, Y, DX, DY: integer;\r
+begin\r
+ (* Initialize library and graphics mode *)\r
+ mxInit;\r
+ mxSetMode( MX_320x200 );\r
+ (* Set a 640x400 virtual screen *)\r
+ mxSetVirtualScreen( 640, 400 );\r
+ mxSetClip( TRUE );\r
+\r
+ X := 0;\r
+ Y := 0;\r
+ DX := 1;\r
+ DY := 1;\r
+\r
+ (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+ (* 320x200 windows, while smoothly panning virtual screen *)\r
+ while( not KeyPressed ) do begin\r
+ (* Points *)\r
+ mxSetClipRegion( 0, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxPutPixel( Random(320), Random(200), Random(16) );\r
+ (* Lines *)\r
+ mxSetClipRegion( 0, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+ (* Circles *)\r
+ mxSetClipRegion( 320, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+ (* Boxes *)\r
+ mxSetClipRegion( 320, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+ (* Pan *)\r
+ Inc( X, DX );\r
+ Check( X+320 >= 639, X, DX, 319, -1 );\r
+ Check( X < 0, X, DX, 0, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+ Check( Y < 0, Y, DY, 0, +1 );\r
+ mxPan( X, Y );\r
+ mxWaitRetrace;\r
+ end;\r
+\r
+ (* Shutdown *)\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT STRUC\r
+ X DD ?\r
+ Y DD ?\r
+ Z DD ?\r
+TPOINT ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT STRUC\r
+ IX DW ?\r
+ IY DW ?\r
+TIMAGEPOINT ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv MACRO arg\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul MACRO arg\r
+ imul arg\r
+ shrd eax, edx, 16\r
+ENDM\r
--- /dev/null
+unit Plasma;\r
+interface\r
+\r
+const\r
+ PAL_RGB = 0;\r
+ PAL_CLOUDS = 1;\r
+ PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+ Color: longint;\r
+begin\r
+ Color := Abs( XA-XB )+Abs( YA-YB );\r
+ Color := Random( Color shl 1 )-Color;\r
+ Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+ if( Color < 1 ) then Color := 1;\r
+ if( Color > 192 ) then Color := 192;\r
+ if( mxGetPixel( X, Y ) = 0 ) then\r
+ mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+ X, Y, Color: integer;\r
+begin\r
+ if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+ X := (X1+X2) shr 1;\r
+ Y := (Y1+Y2) shr 1;\r
+ NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+ NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+ NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+ NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+ Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+ mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+ mxPutPixel( X, Y, Color );\r
+ Divide( X1, Y1, X, Y );\r
+ Divide( X, Y1, X2, Y );\r
+ Divide( X, Y, X2, Y2 );\r
+ Divide( X1, Y, X, Y2 );\r
+ end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+ Dec( W );\r
+ Dec( H );\r
+ mxPutPixel( X, Y, C1 );\r
+ mxPutPixel( X, Y+H, C2 );\r
+ mxPutPixel( X+W, Y+H, C3 );\r
+ mxPutPixel( X+W, Y, C4 );\r
+ Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+ TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+ I: word;\r
+begin\r
+ FillChar( TPal(Palette)[1], 192*3, 0 );\r
+ case What of\r
+ PAL_CLOUDS:\r
+ for I:=1 to 192 do begin\r
+ TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].B := 63;\r
+ end;\r
+ PAL_LANDSCAPE:\r
+ begin\r
+ for I:=0 to 31 do begin\r
+ TPal(Palette)[I+1].R := I;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := I + I shr 1+15;\r
+ end;\r
+ for I:=32 to 63 do begin\r
+ TPal(Palette)[I+1].R := 0;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := 0;\r
+ end;\r
+ for I:=64 to 191 do begin\r
+ TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+ end;\r
+ end;\r
+ else\r
+ for I:=1 to 64 do begin\r
+ TPal(Palette)[I].G := I-1;\r
+ TPal(Palette)[I].B := 64-I;\r
+ TPal(Palette)[I+64].R := I-1;\r
+ TPal(Palette)[I+64].G := 64-I;\r
+ TPal(Palette)[I+128].B := I-1;\r
+ TPal(Palette)[I+128].R := 64-I;\r
+ end;\r
+ end;\r
+end;\r
+\r
+end.
\ No newline at end of file
--- /dev/null
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+ DEFVERT = 12; (* Vertex count *)\r
+ DEFREPL = 3; (* Repetition count *)\r
+ DEFQIXS = 2; (* Qixs *)\r
+ FADESPEED = 48;\r
+type\r
+ TPoint = record\r
+ X, Y : integer;\r
+ end;\r
+ TRGB = record\r
+ R, G, B: byte;\r
+ end;\r
+ TQix = record\r
+ Color: integer;\r
+ Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+ Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+ end;\r
+var\r
+ Page : integer;\r
+ MaxX,\r
+ MaxY : word;\r
+ Qix : array[ 0..DEFQIXS-1 ] of TQix;\r
+ Pal : array[ byte ] of TRGB;\r
+\r
+type\r
+ TReal = double;\r
+ TRPoint = record\r
+ X, Y: TReal;\r
+ end;\r
+ TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+ M: TMatrix;\r
+ G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+ C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=1 to Steps do begin\r
+ Pal[Idx+1].R := Pal[Idx].R + DR;\r
+ Pal[Idx+1].G := Pal[Idx].G + DG;\r
+ Pal[Idx+1].B := Pal[Idx].B + DB;\r
+ Inc( Idx );\r
+ end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+ with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+ with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+ BumpPal( 1, 0, 2, -2, 31 );\r
+ BumpPal( 32, 2, -2, 0, 31 );\r
+ BumpPal( 63, -2, 2, 2, 31 );\r
+ BumpPal( 94, 2, 0, -2, 31 );\r
+ BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+ for I:=0 to DEFVERT-1 do begin\r
+ Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+ Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+ Qix.Delta[I].X := Random(5)+1;\r
+ Qix.Delta[I].Y := Random(5)+1;\r
+ end;\r
+ Qix.Color := Color;\r
+\r
+ (* Initialize matrix (Catmull-Rom) *)\r
+ M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+ M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+ M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+ M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+ I, J: integer;\r
+ T, T2, T3: TReal;\r
+ X0, Y0, X, Y: TReal;\r
+ Delta: TReal;\r
+begin\r
+ (* Compute coefficients *)\r
+ for I:=0 to 3 do begin\r
+ C[I].X := 0;\r
+ for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+ C[I].Y := 0;\r
+ for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+ end;\r
+ X0 := C[3].X;\r
+ Y0 := C[3].Y;\r
+ Delta := 1 / N;\r
+ T := 0;\r
+ for I:=1 to N do begin\r
+ T := T + Delta;\r
+ T2 := T*T;\r
+ T3 := T*T2;\r
+ X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+ Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+ mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+ X0 := X;\r
+ Y0 := Y;\r
+ end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+ I, J: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do begin\r
+ mxBezier( Qix, I, Idx, 12 );\r
+ end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Inc( Vert[I,Idx].X, Delta[I].X );\r
+ if( Vert[I,Idx].X < 0 ) then begin\r
+ Vert[I,Idx].X := 0;\r
+ Delta[I].X := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].X > MaxX ) then begin\r
+ Vert[I,Idx].X := MaxX;\r
+ Delta[I].X := -Random( 5 )-1;\r
+ end;\r
+ Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+ if( Vert[I,Idx].Y < 0 ) then begin\r
+ Vert[I,Idx].Y := 0;\r
+ Delta[I].Y := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].Y > MaxY ) then begin\r
+ Vert[I,Idx].Y := MaxY;\r
+ Delta[I].Y := -Random( 5 )-1;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Vert[I,Dest].X := Vert[I,Src].X;\r
+ Vert[I,Dest].Y := Vert[I,Src].Y;\r
+ end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+ Q, Idx, I, J, P, Count: integer;\r
+begin\r
+ Count := 0;\r
+ P := DEFREPL-1;\r
+ I := 0;\r
+ J := 1;\r
+ repeat\r
+ mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Copy( Qix[Q], I, P );\r
+ Update( Qix[Q], I );\r
+ for Idx:=0 to DEFREPL-1 do begin\r
+ Plot( Qix[Q], Idx );\r
+ end;\r
+ end;\r
+ I := (I+1) mod DEFREPL;\r
+ J := (J+1) mod DEFREPL;\r
+ P := (P+1) mod DEFREPL;\r
+ Inc( Count );\r
+ mxStartLine( Page );\r
+ if( Count >= FADESPEED ) then begin\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Inc( Qix[Q].Color );\r
+ if( Qix[Q].Color > 156 ) then\r
+ Qix[Q].Color := 1;\r
+ end;\r
+ Count := 0;\r
+ end;\r
+ Page := 240-Page;\r
+ until( KeyPressed );\r
+end;\r
+\r
+var\r
+ I: integer;\r
+begin\r
+ Randomize;\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ mxGetScreenSize( MaxX, MaxY );\r
+ for I:=0 to DEFQIXS-1 do\r
+ Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+ InitPalette;\r
+ mxSetPalette( @Pal, 0, 157 );\r
+ Page := 240;\r
+ Dec( MaxX );\r
+ Dec( MaxY );\r
+ AnimateQix;\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin LABEL DWORD\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+tblCos LABEL DWORD\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
--- /dev/null
+COMMENT /\r
+ Fixed-point math functions and 3D transforms\r
+ Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC tdFixedMul\r
+PUBLIC tdGetNormal\r
+PUBLIC tdRotate\r
+PUBLIC tdGetSurfaceLight\r
+PUBLIC tdSetLight\r
+PUBLIC tdSetRotation\r
+PUBLIC tdSetTranslation\r
+PUBLIC tdTransform\r
+PUBLIC tdTransformToImage\r
+PUBLIC tdTransformLight\r
+PUBLIC tdBackPlaneCull\r
+PUBLIC tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA'\r
+ ASSUME ds:MATH_DATA\r
+\r
+INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table\r
+\r
+XRotation TPOINT <> ; 3x3 rotation matrix\r
+YRotation TPOINT <>\r
+ZRotation TPOINT <>\r
+\r
+Translation TPOINT <> ; Translation vector\r
+\r
+Light TPOINT <> ; Light vector\r
+AmbientLight DW 00 ; Ambient light\r
+\r
+XScale DD 10000h ; Scaling factor for X coordinate\r
+YScale DD 10000h ; Scaling factor for Y coordinate\r
+PerspectiveDistance DD 20000000h\r
+\r
+MATH_DATA ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective PROC PASCAL FAR\r
+ ARG Perspective:DWORD, \\r
+ ScaleX:DWORD, \\r
+ ScaleY:DWORD\r
+ USES ds\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov eax, [Perspective]\r
+ mov [PerspectiveDistance], eax\r
+ mov eax, [ScaleX]\r
+ mov [XScale], eax\r
+ mov eax, [ScaleY]\r
+ mov [YScale], eax\r
+\r
+ ret\r
+tdSetPerspective ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+; RX = X-axis rotation angle\r
+; RY = X-axis rotation angle\r
+; RZ = X-axis rotation angle\r
+; Output:\r
+; none\r
+;\r
+tdSetRotation PROC PASCAL FAR\r
+ ARG RX:WORD, \\r
+ RY:WORD, \\r
+ RZ:WORD\r
+ USES ds, si, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov bx, [RZ]\r
+ mov si, [RY]\r
+ mov di, [RX]\r
+ shl bx, 2\r
+ shl si, 2\r
+ shl di, 2\r
+\r
+ push ebp ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.Y], edx\r
+\r
+ mov eax, tblSin[si]\r
+ sar eax, 8 ; Convert fixed 8:24 to fixed 16:16\r
+ mov [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si] ; EDX:EAX = fixed 16:48\r
+ shrd eax, edx, 24 ; EAX = fixed 8:24\r
+ imul tblSin[di] ; EDX:EAX = fixed 16:48\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[di]\r
+ add eax, ebp\r
+ adc edx, ecx ; EDX:EAX = fixed 16:48\r
+ neg edx\r
+ mov [YRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblSin[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [YRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblSin[di]\r
+ mov [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [ZRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[di]\r
+ add eax, ebp\r
+ add edx, ecx\r
+ neg edx\r
+ mov [ZRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblCos[di]\r
+ mov [ZRotation.Z], edx\r
+\r
+ pop ebp ; Restore EBP\r
+\r
+ ret\r
+tdSetRotation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+; TV = pointer to translation vector\r
+; Output:\r
+; none\r
+;\r
+tdSetTranslation PROC PASCAL FAR\r
+ ARG TV:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [TV]\r
+ mov eax, es:[di].X\r
+ mov [Translation.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Translation.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Translation.Z], eax\r
+\r
+ ret\r
+tdSetTranslation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransform PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ LOCAL Adjust:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+ ALIGN DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ mov ebx, eax\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16)\r
+ mov es:[di].Z, eax\r
+; Get perspective factor\r
+ mov ebx, [PerspectiveDistance]\r
+ sub eax, ebx\r
+ neg eax ; EAX = PD - Z\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx ; EAX = fixed 16:16 result\r
+ mov [Adjust], eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.X]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Y]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdTransform ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TIMAGEPOINT\r
+; Count = number of entries to transform\r
+; DeltaX = translation distance for the X coordinate\r
+; DeltaY = translation distance for the Y coordinate\r
+; Output:\r
+; the maximum Z value\r
+;\r
+tdTransformToImage PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD\r
+ LOCAL Adjust:DWORD, \\r
+ Max:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+ mov [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+ mov eax, fs:[si].Z\r
+ cmp eax, [Max]\r
+ jle @@1\r
+ mov [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+ mov ax, WORD PTR fs:[si].X[2]\r
+ add ax, [DeltaX]\r
+ mov es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+ mov ax, WORD PTR fs:[si].Y[2]\r
+ add ax, [DeltaY]\r
+ mov es:[di].IY, ax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TIMAGEPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ mov eax, [Max]\r
+ shld edx, eax, 16\r
+ ret\r
+tdTransformToImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+; Light = pointer to light vector\r
+; Output:\r
+; none\r
+;\r
+tdSetLight PROC PASCAL FAR\r
+ ARG L:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [L]\r
+ mov eax, es:[di].X\r
+ mov [Light.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Light.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Light.Z], eax\r
+\r
+ ret\r
+tdSetLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+; Normals = pointer to an array of surface normals\r
+; Lights = pointer to an array of integer to be filled with\r
+; light intensity\r
+; Count = number of elements to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransformLight PROC PASCAL FAR\r
+ ARG Normals:DWORD, \\r
+ Lights:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov fs, ax\r
+ ASSUME fs:MATH_DATA\r
+\r
+ lds si, [Normals]\r
+ les di, [Lights]\r
+ ASSUME ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+ mov eax, ds:[si].Z\r
+ imul [Light.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, ds:[si].Y\r
+ imul [Light.Y]\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, ds:[si].X\r
+ imul [Light.X]\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = fixed 32:32 intensity\r
+ add dx, [AmbientLight]\r
+ test dx, dx\r
+ jg @@1\r
+ xor dx, dx ; Return 0 for no light\r
+@@1:\r
+ mov es:[di], dx\r
+ inc di\r
+ inc di\r
+ add si, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ASSUME fs:NOTHING\r
+ ret\r
+tdTransformLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+; Normal = pointer to TPOINT surface normal vector\r
+; Output:\r
+; AX = light intensity (>=0)\r
+; Notes:\r
+; the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight PROC PASCAL FAR\r
+ ARG Normal:DWORD\r
+ USES ds, esi, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [Normal]\r
+\r
+; Transform Z coordinate\r
+ mov eax, es:[di].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.Z]\r
+ shrd eax, edx, 16\r
+ mov esi, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, es:[di].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add esi, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, es:[di].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add eax, esi\r
+ shr eax, 16\r
+\r
+; Add ambient light\r
+ add ax, [AmbientLight]\r
+ test ax, ax\r
+ jge @@Exit\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ ret\r
+tdGetSurfaceLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdRotate PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdRotate ENDP\r
+\r
+tdFixedMul PROC PASCAL FAR\r
+ ARG F1:DWORD, \\r
+ F2:DWORD\r
+\r
+ mov eax, [F1]\r
+ imul [F2]\r
+ shr eax, 16\r
+\r
+ ret\r
+tdFixedMul ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+ push esi\r
+ push edi\r
+\r
+ add eax, eax\r
+ adc edx, 0\r
+ mov eax, edx ; Just discard the low bits\r
+\r
+ mov esi, eax\r
+ xor edi, edi\r
+ shld edi, esi, 16\r
+ shl esi, 16\r
+@@Loop:\r
+ mov ebx, eax\r
+ mul eax\r
+ add eax, esi\r
+ adc edx, edi\r
+ shrd eax, edx, 1\r
+ shr edx, 1\r
+ div ebx\r
+ cmp eax, ebx\r
+ jne @@Loop\r
+\r
+; Adjust EAX\r
+ shl eax, 8\r
+\r
+ pop edi\r
+ pop esi\r
+ ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+; Dest = pointer to TPOINT (vector) result\r
+; P1, P2, P3 = pointer to TPOINT points on surface\r
+; Output:\r
+; none\r
+; Notes:\r
+; the normal is given by the cross-product between (P3-P1) and\r
+; (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal PROC PASCAL FAR\r
+ ARG Dest:DWORD, \\r
+ P1:DWORD, \\r
+ P2:DWORD, \\r
+ P3:DWORD\r
+ LOCAL V1:TPOINT, \\r
+ V2:TPOINT, \\r
+ N:TPOINT\r
+ USES ds, si, es, di\r
+\r
+; Get vector V1\r
+ lds si, [P1]\r
+ les di, [P3]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V1.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V1.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V1.Z], eax\r
+\r
+; Get vector V2\r
+ les di, [P2]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V2.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V2.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+ mov eax, [V1.Z]\r
+ imul [V2.Y]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Y]\r
+ imul [V2.Z]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.X], eax\r
+\r
+ mov eax, [V1.X]\r
+ imul [V2.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Z]\r
+ imul [V2.X]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Y], eax\r
+\r
+ mov eax, [V1.Y]\r
+ imul [V2.X]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.X]\r
+ imul [V2.Y]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Z], eax\r
+\r
+; Get normal length\r
+ mov eax, [N.X]\r
+ imul eax\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [N.Y]\r
+ imul eax\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, [N.Z]\r
+ imul eax\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+ call subSqrt ; EAX = normal length\r
+ mov ebx, eax\r
+\r
+; Adjust vector and save it\r
+ les di, [Dest]\r
+ mov eax, [N.X]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].X, eax\r
+ mov eax, [N.Y]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Y, eax\r
+ mov eax, [N.Z]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Z, eax\r
+\r
+ ret\r
+tdGetNormal ENDP\r
+\r
+TPOLY STRUC\r
+ Vtx DW 4 DUP(?)\r
+TPOLY ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+; Poly = pointer to an array of TPOLY\r
+; Vertex = pointer to an array of TPOINT\r
+; Dest = pointer to an array of integer\r
+; Count = number of polygons to check\r
+; Step = size of TPOLY structure\r
+; Output:\r
+; if the n-th polygon is invisible the n-th entry of the\r
+; Dest array is set to -1, other entries are not modified\r
+; (so it's possible to use the Light array for Dest, because\r
+; the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+ ARG Step:WORD, \\r
+ Poly:DWORD, \\r
+ Vertex:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ds, WORD PTR Vertex[2]\r
+ les di, [Poly]\r
+ mov fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+ mov ax, es:[di].Vtx[2] ; Index of 2nd vertex\r
+ shl ax, 2\r
+ mov bx, ax\r
+ shl ax, 1\r
+ add bx, ax ; BX = index*SIZE TPOINT\r
+ add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex\r
+ mov ax, es:[di].Vtx[4] ; Index of 3rd vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex\r
+ mov ecx, ds:[si].X\r
+ sub ecx, ds:[bx].X ; ECX = V3.X-V2.X\r
+ mov edx, ds:[si].Y\r
+ sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y\r
+ mov ax, es:[di].Vtx[0] ; Index of 1st vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 1st vertex\r
+ mov eax, ds:[si].X\r
+ sub eax, ds:[bx].X ; EAX = V1.X-V2.X\r
+ mov esi, ds:[si].Y\r
+ sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y\r
+ imul edx\r
+ mov ebx, eax\r
+ xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+ mov eax, esi\r
+ imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ jl @@Next ; Polygon is visible\r
+ mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry\r
+ mov WORD PTR fs:[bx], -1 ; Remove polygon\r
+@@Next:\r
+ add WORD PTR [Dest], 2 ; Next entry for dest\r
+ add di, [Step] ; Next polygon\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT ENDS\r
+END\r
--- /dev/null
+typedef struct {\r
+ long x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT TVECTOR\r
+#define PPOINT PVECTOR\r
+\r
+#define VPTR void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+unit ThreeD;\r
+interface\r
+\r
+type\r
+ TVector = record\r
+ X, Y, Z : longint;\r
+ end;\r
+ TPoint = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight; external;\r
+procedure tdSetRotation( RX, RY, RZ: word ); external;\r
+procedure tdGetNormal; external;\r
+procedure tdSetTranslation( var TV: TVector ); external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate; external;\r
+function tdTransformToImage; external;\r
+procedure tdSetLight( var Light: TVector ); external;\r
+procedure tdSetPerspective; external;\r
+procedure tdTransformLight; external;\r
+function tdFixedMul( F1, F2: longint ): longint; external;\r
+procedure tdBackPlaneCull; external;\r
+{$L THREED}\r
+\r
+end.\r
--- /dev/null
+/*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+#include ../../x/\r
+\r
+#DEFINE MAX_SPRITE 100\r
+\r
+/* Sprite structure */\r
+typedef struct {\r
+ int X, Y; /* Sprite coordinates */\r
+ int DX,DY; /* Deltas for sprite movement */\r
+ int W, H; /* Sprite width and height */\r
+ unsigned char Image[16,16]; /* Sprite image data */\r
+} TSprite;\r
+\r
+/* RGB color structure */\r
+typedef struct {\r
+ R, G, B: byte;\r
+} TRgb;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; /* An array of sprites */\r
+ Palette: array[ byte ] of TRgb; /* Palette */\r
+ Page : word; /* Page offset */\r
+ I : word;\r
+\r
+/* Initializes a sprite structure */\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X = Random( 320 ); /* Initialize position with random values */\r
+ S.Y = Random( 240 );\r
+ S.DX = Random( 7 )-3; /* Initialize speed with random values */\r
+ S.DY = Random( 7 )-3;\r
+ S.W = 16; /* Size is fixed in this program */\r
+ S.H = 16;\r
+ /* The image is a square with a hole inside */\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+}\r
+\r
+/* Moves a sprite */\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); /* Get new position */\r
+ Inc( S.Y, S.DY );\r
+ /* Check sprite position, change delta if needed */\r
+ if( S.X > 320 ) then begin\r
+ S.X = 320;\r
+ S.DX = -S.DX;\r
+ }\r
+ if( S.X < -16 ) then begin\r
+ S.X = -16;\r
+ S.DX = -S.DX;\r
+ }\r
+ if( S.Y > 240 ) then begin\r
+ S.Y = 240;\r
+ S.DY = -S.DY;\r
+ }\r
+ if( S.Y < -16 ) then begin\r
+ S.Y = -16;\r
+ S.DY = -S.DY;\r
+ }\r
+ /* Draw the sprite, note the Page offset added to the */\r
+ /* Y coordinate of the image */\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+}\r
+\r
+void main()\r
+{\r
+ int i;\r
+ /* Initialize library */\r
+ mxInit();\r
+\r
+ /* Enter graphics mode */\r
+ mxSetMode( MX_320x240 );\r
+\r
+ /* Print initialization message */\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ /* Initialize sprites */\r
+ for(i=1;i<=MAX_SPRITE;i++)\r
+ sxInit( S[i] );\r
+\r
+ /* Draw background */\r
+ for(i=1;i<=192;i++)\r
+ {\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ }\r
+\r
+ /* Compute and set palette */\r
+ for(i=1;i<= 192;Palette[i+63])\r
+ {\r
+ short R = 0;\r
+ short G = 0;\r
+ short B = 0;\r
+ if( i < 64 )\r
+ R = i shr 1+31\r
+ else if( i < 128 )\r
+ G = (i-64) shr 1+31\r
+ else\r
+ B = (i-128) shr 1+31;\r
+ }\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ /* Main loop */\r
+ short Page = 240;\r
+ while(!kbhit())\r
+ {\r
+ /* Set clip region to current page */\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ /* Restore background */\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ /* Draw sprites */\r
+ for(i=1; i <= MAX_SPRITE; sxMove( S[i] ));\r
+ /* Print message */\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ /* Flip page */\r
+ mxStartLine( Page );\r
+ Page = 240-Page;\r
+ /* Animate palette */\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ }\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+\r
+}\r
--- /dev/null
+ PUBLIC MXBITBLT
+ EXTRN SUBHORIZONTALLINEINFO:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXBITBLT:
+ push bp
+ mov bp,sp
+ sub sp,16H
+ push ds
+ push si
+ push es
+ push di
+ cmp word ptr 0cH[bp],0
+ je L$2
+ mov ax,word ptr 10H[bp]
+ and al,3
+ mov dx,word ptr 8[bp]
+ and dl,3
+ mov bx,offset L$10
+ cmp al,dl
+ jne L$1
+ mov bx,offset L$3
+L$1:
+ call bx
+L$2:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+L$3:
+ mov bx,word ptr 8[bp]
+ mov ax,word ptr 6[bp]
+ mov cx,word ptr 0cH[bp]
+ call near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+ mov byte ptr -14H[bp],al
+ mov byte ptr -16H[bp],ah
+ mov word ptr 0cH[bp],cx
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ mov es,ax
+ mov ax,word ptr 0eH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov si,word ptr 10H[bp]
+ shr si,1
+ shr si,1
+ add si,ax
+ mov dx,3ceH
+ mov ax,4105H
+ out dx,ax
+ cld
+ mov ah,byte ptr -14H[bp]
+ or ah,ah
+ je L$5
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ dec ax
+ mov cx,word ptr 0aH[bp]
+ push si
+ push di
+L$4:
+ movsb
+ add si,ax
+ add di,ax
+ dec cx
+ jne L$4
+ pop di
+ pop si
+ inc si
+ inc di
+L$5:
+ mov bx,word ptr 0cH[bp]
+ test bx,bx
+ je L$7
+ mov dx,3c4H
+ mov ax,0f02H
+ out dx,ax
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ sub ax,bx
+ mov dx,word ptr 0aH[bp]
+ push si
+ push di
+L$6:
+ mov cx,bx
+ rep movsb
+ add si,ax
+ add di,ax
+ dec dx
+ jne L$6
+ pop di
+ pop si
+ add si,bx
+ add di,bx
+L$7:
+ mov ah,byte ptr -16H[bp]
+ or ah,ah
+ je L$9
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ dec ax
+ mov cx,word ptr 0aH[bp]
+L$8:
+ movsb
+ add si,ax
+ add di,ax
+ dec cx
+ jne L$8
+L$9:
+ mov dx,3ceH
+ mov ax,4005H
+ out dx,ax
+ ret
+L$10:
+ mov cx,word ptr 0cH[bp]
+ mov bx,cx
+ shr bx,1
+ shr bx,1
+ and cl,3
+ mov al,8
+ shr al,cl
+ mov si,6
+L$11:
+ mov word ptr -8[bp+si],bx
+ shr al,1
+ adc bx,0
+ dec si
+ dec si
+ jge L$11
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ mov es,ax
+ mov ax,word ptr 0eH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov si,word ptr 10H[bp]
+ shr si,1
+ shr si,1
+ add si,ax
+ mov word ptr -0aH[bp],si
+ mov ax,word ptr 6[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,word ptr 8[bp]
+ shr di,1
+ shr di,1
+ add di,ax
+ mov word ptr -0cH[bp],di
+ mov ax,word ptr 10H[bp]
+ and al,3
+ mov byte ptr -10H[bp],al
+ mov cx,word ptr 8[bp]
+ and cl,3
+ mov al,11H
+ shl al,cl
+ mov byte ptr -12H[bp],al
+ cld
+ mov byte ptr -0eH[bp],4
+ lea bx,-8[bp]
+L$12:
+ cmp word ptr ss:[bx],0
+ je L$15
+ mov ah,byte ptr -12H[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov ah,byte ptr -10H[bp]
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov dx,word ptr 0aH[bp]
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ sub ax,word ptr ss:[bx]
+L$13:
+ mov cx,word ptr ss:[bx]
+ shr cx,1
+ rep movsw
+ rcl cx,1
+ rep movsb
+ add si,ax
+ add di,ax
+ dec dx
+ jne L$13
+ inc bx
+ inc bx
+ inc byte ptr -10H[bp]
+ and byte ptr -10H[bp],3
+ jne L$14
+ inc word ptr -0aH[bp]
+L$14:
+ rol byte ptr -12H[bp],1
+ adc word ptr -0cH[bp],0
+ mov si,word ptr -0aH[bp]
+ mov di,word ptr -0cH[bp]
+ dec byte ptr -0eH[bp]
+ jne L$12
+L$15:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC XSUBCLIPLINE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ or al,byte ptr [bx+si]
+L$2:
+ DW offset L$3
+ or al,byte ptr [bx+si]
+ DW offset L$4
+ or word ptr [bx+si],ax
+ DW offset L$5
+; ????
+ inc word ptr [bx+si]
+ add byte ptr [bp+si],cl
+ add byte ptr 0a00H[bx+si],al
+ add byte ptr 900H[bp],dl
+ add byte ptr -100H[si],ch
+ inc word ptr [bx+si]
+ add byte ptr ds:[0c000H],al
+ add byte ptr ds:[0ce00H],al
+ add byte ptr [di],al
+ add ah,bl
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ DB 0
+L$3:
+ DW offset MX_TEXT+0ecH
+ DW offset MX_TEXT+0eeH
+ DW offset MX_TEXT+0f1H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+0f4H
+ DW offset MX_TEXT+0f7H
+ DW offset MX_TEXT+104H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+111H
+ DW offset MX_TEXT+114H
+ DW offset MX_TEXT+121H
+L$4:
+ DW offset MX_TEXT+132H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+135H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+13bH
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+148H
+ DW offset L$7
+ DW offset L$10
+ DW offset L$7
+ DW offset L$11
+L$5:
+ DW offset L$14
+ DW offset L$15
+ DW offset L$7
+ DW offset L$7
+ DW offset L$16
+ DW offset L$17
+ DW offset L$7
+ DW offset L$7
+ DW offset L$18
+ DW offset L$19
+ DW offset L$22
+ DW offset L$23
+ DW offset L$24
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$25
+ DW offset L$26
+ DW offset L$27
+ DW offset L$30
+ DW offset L$7
+ DW offset L$31
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$32
+ DW offset L$7
+ DW offset L$33
+ DW offset L$36
+ DW offset L$37
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$38
+ DW offset L$39
+ DW offset L$43
+ DW offset L$44
+ DW offset L$45
+ DW offset L$7
+ DW offset L$46
+ DW offset L$47
+ DW offset L$48
+ DW offset L$51
+ DW offset L$7
+ DW offset L$52
+ DW offset L$7
+ DW offset L$53
+ DW offset L$7
+ DW offset L$54
+ DW offset L$58
+ DW offset L$59
+ DW offset L$7
+ DW offset L$7
+ DW offset L$60
+ DW offset L$61
+L$6:
+ clc
+ ret
+L$7:
+ stc
+ ret
+ clc
+ ret
+ jmp near ptr L$67
+ jmp near ptr L$68
+ jmp near ptr L$70
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$6
+ jmp near ptr L$70
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$6
+ jmp near ptr L$70
+ jmp near ptr L$69
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$6
+ jmp near ptr L$69
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$6
+ jmp near ptr L$69
+L$8:
+ stc
+ ret
+L$9:
+ clc
+ ret
+ jmp near ptr L$63
+ call near ptr L$63
+ jmp near ptr L$68
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$8
+ jmp near ptr L$70
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$8
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$9
+ jmp near ptr L$68
+L$10:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$8
+ jmp near ptr L$69
+L$11:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$8
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$9
+ jmp near ptr L$68
+L$12:
+ clc
+ ret
+L$13:
+ stc
+ ret
+L$14:
+ jmp near ptr L$64
+L$15:
+ call near ptr L$64
+ jmp near ptr L$67
+L$16:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$13
+ jmp near ptr L$70
+L$17:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$13
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$12
+ jmp near ptr L$67
+L$18:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$13
+ jmp near ptr L$69
+L$19:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$13
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$12
+ jmp near ptr L$67
+L$20:
+ clc
+ ret
+L$21:
+ stc
+ ret
+L$22:
+ jmp near ptr L$66
+L$23:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$21
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$20
+ jmp near ptr L$70
+L$24:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$21
+ jmp near ptr L$68
+L$25:
+ call near ptr L$66
+ jmp near ptr L$69
+L$26:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$21
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$20
+ jmp near ptr L$69
+L$27:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$21
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$20
+ jmp near ptr L$69
+L$28:
+ clc
+ ret
+L$29:
+ stc
+ ret
+L$30:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$28
+ jmp near ptr L$66
+L$31:
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY1
+ jl L$29
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$28
+ jmp near ptr L$63
+L$32:
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX1
+ jl L$29
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$28
+ jmp near ptr L$63
+L$33:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$29
+ call near ptr L$68
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$29
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$28
+ jmp near ptr L$69
+L$34:
+ clc
+ ret
+L$35:
+ stc
+ ret
+L$36:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$34
+ jmp near ptr L$66
+L$37:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jl L$35
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX2
+ jle L$34
+ jmp near ptr L$64
+L$38:
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX2
+ jg L$35
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$34
+ jmp near ptr L$66
+L$39:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jl L$35
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$35
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$40
+ call near ptr L$69
+L$40:
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$34
+ jmp near ptr L$66
+L$41:
+ clc
+ ret
+L$42:
+ stc
+ ret
+L$43:
+ jmp near ptr L$65
+L$44:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$42
+ jmp near ptr L$67
+L$45:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$42
+ jmp near ptr L$68
+L$46:
+ call near ptr L$65
+ jmp near ptr L$70
+L$47:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$42
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$42
+ jmp near ptr L$70
+L$48:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$42
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$41
+ jmp near ptr L$70
+L$49:
+ clc
+ ret
+L$50:
+ stc
+ ret
+L$51:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$49
+ jmp near ptr L$65
+L$52:
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$50
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$49
+ jmp near ptr L$63
+L$53:
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX1
+ jl L$50
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$49
+ jmp near ptr L$65
+L$54:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$50
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$50
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$55
+ call near ptr L$65
+L$55:
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$49
+ jmp near ptr L$70
+L$56:
+ clc
+ ret
+L$57:
+ stc
+ ret
+L$58:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$56
+ jmp near ptr L$65
+L$59:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$57
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX2
+ jle L$56
+ jmp L$64
+L$60:
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX2
+ jg L$57
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$56
+ jmp L$65
+L$61:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$57
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$57
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$62
+ call near ptr L$70
+L$62:
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$56
+ jmp L$65
+L$63:
+ mov ax,si
+ sub ax,bx
+ mov dx,word ptr cs:MX_CLIPX1
+ sub dx,di
+ imul dx
+ mov bp,cx
+ sub bp,di
+ idiv bp
+ add bx,ax
+ mov di,word ptr cs:MX_CLIPX1
+ clc
+ ret
+L$64:
+ mov ax,si
+ sub ax,bx
+ mov dx,word ptr cs:MX_CLIPX2
+ sub dx,di
+ imul dx
+ mov bp,cx
+ sub bp,di
+ idiv bp
+ add bx,ax
+ mov di,word ptr cs:MX_CLIPX2
+ clc
+ ret
+L$65:
+ mov ax,cx
+ sub ax,di
+ mov dx,word ptr cs:MX_CLIPY2
+ sub dx,bx
+ imul dx
+ mov bp,si
+ sub bp,bx
+ idiv bp
+ add di,ax
+ mov bx,word ptr cs:MX_CLIPY2
+ clc
+ ret
+L$66:
+ mov ax,cx
+ sub ax,di
+ mov dx,word ptr cs:MX_CLIPY1
+ sub dx,bx
+ imul dx
+ mov bp,si
+ sub bp,bx
+ idiv bp
+ add di,ax
+ mov bx,word ptr cs:MX_CLIPY1
+ clc
+ ret
+L$67:
+ mov ax,bx
+ sub ax,si
+ mov dx,word ptr cs:MX_CLIPX1
+ sub dx,cx
+ imul dx
+ mov bp,di
+ sub bp,cx
+ idiv bp
+ add si,ax
+ mov cx,word ptr cs:MX_CLIPX1
+ clc
+ ret
+L$68:
+ mov ax,bx
+ sub ax,si
+ mov dx,word ptr cs:MX_CLIPX2
+ sub dx,cx
+ imul dx
+ mov bp,di
+ sub bp,cx
+ idiv bp
+ add si,ax
+ mov cx,word ptr cs:MX_CLIPX2
+ clc
+ ret
+L$69:
+ mov ax,di
+ sub ax,cx
+ mov dx,word ptr cs:MX_CLIPY2
+ sub dx,si
+ imul dx
+ mov bp,bx
+ sub bp,si
+ idiv bp
+ add cx,ax
+ mov si,word ptr cs:MX_CLIPY2
+ clc
+ ret
+L$70:
+ mov ax,di
+ sub ax,cx
+ mov dx,word ptr cs:MX_CLIPY1
+ sub dx,si
+ imul dx
+ mov bp,bx
+ sub bp,si
+ idiv bp
+ add cx,ax
+ mov si,word ptr cs:MX_CLIPY1
+ clc
+ ret
+XSUBCLIPLINE:
+ push bp
+ xor si,si
+ cmp dx,word ptr cs:MX_CLIPY2
+ jle L$71
+ or si,8
+ jmp L$72
+L$71:
+ cmp dx,word ptr cs:MX_CLIPY1
+ jge L$72
+ or si,4
+L$72:
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$73
+ or si,2
+ jmp L$74
+L$73:
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$74
+ or si,1
+L$74:
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$75
+ or si,80H
+ jmp L$76
+L$75:
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$76
+ or si,40H
+L$76:
+ cmp ax,word ptr cs:MX_CLIPX2
+ jle L$77
+ or si,20H
+ jmp L$78
+L$77:
+ cmp ax,word ptr cs:MX_CLIPX1
+ jge L$78
+ or si,10H
+L$78:
+ mov di,si
+ and di,0fH
+ and si,0f0H
+ shr si,1
+ shr si,1
+ cmp di,word ptr cs:L$1[si]
+ jg L$79
+ mov si,word ptr cs:L$2[si]
+ shl di,1
+ add si,di
+ mov di,ax
+ mov si,word ptr cs:[si]
+ xchg si,dx
+ call dx
+ mov ax,di
+ mov dx,si
+ pop bp
+ ret
+L$79:
+ pop bp
+ stc
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXCOLORTOGRAY
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCOLORTOGRAY:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 6[bp]
+ jcxz L$2
+ lds si,dword ptr 0cH[bp]
+ les di,dword ptr 8[bp]
+ cld
+ mov bx,4d97H
+L$1:
+ lodsb
+ mul bh
+ mov dx,ax
+ lodsb
+ mul bl
+ add dx,ax
+ lodsb
+ mov ah,1cH
+ mul ah
+ add ax,dx
+ mov al,ah
+ stosw
+ stosb
+ loop L$1
+L$2:
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0aH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXCIRCLE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCIRCLE:
+ push bp
+ mov bp,sp
+ sub sp,2
+ push ds
+ push si
+ push di
+ xor si,si
+ mov di,word ptr 8[bp]
+ mov ax,3
+ sub ax,di
+ sub ax,di
+ mov word ptr -2[bp],ax
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+L$1:
+ cmp si,di
+ jg L$3
+ mov ax,si
+ mov bx,di
+ call near ptr L$4
+ mov ax,si
+ neg ax
+ mov bx,di
+ call near ptr L$4
+ mov ax,si
+ mov bx,di
+ neg bx
+ call near ptr L$4
+ mov ax,si
+ neg ax
+ mov bx,di
+ neg bx
+ call near ptr L$4
+ mov ax,di
+ mov bx,si
+ call near ptr L$4
+ mov ax,di
+ neg ax
+ mov bx,si
+ call near ptr L$4
+ mov ax,di
+ mov bx,si
+ neg bx
+ call near ptr L$4
+ mov ax,di
+ neg ax
+ mov bx,si
+ neg bx
+ call near ptr L$4
+ mov ax,word ptr -2[bp]
+ test ax,ax
+ jl L$2
+ mov ax,di
+ shl ax,1
+ shl ax,1
+ sub ax,4
+ sub word ptr -2[bp],ax
+ dec di
+L$2:
+ mov ax,si
+ shl ax,1
+ shl ax,1
+ add ax,6
+ add word ptr -2[bp],ax
+ inc si
+ jmp L$1
+L$3:
+ xor ax,ax
+ pop di
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+L$4:
+ add bx,word ptr 0cH[bp]
+ add ax,word ptr 0aH[bp]
+ cmp bx,word ptr cs:MX_CLIPX1
+ jl L$5
+ cmp bx,word ptr cs:MX_CLIPX2
+ jg L$5
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$5
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$5
+ mul word ptr cs:MX_BYTESPERLINE
+ mov cx,bx
+ shr bx,1
+ shr bx,1
+ add bx,ax
+ and cl,3
+ mov ax,102H
+ shl ah,cl
+ mov dx,3c4H
+ out dx,ax
+ mov al,byte ptr 6[bp]
+ mov byte ptr [bx],al
+L$5:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MX_CLIPX1
+ PUBLIC MX_CLIPY1
+ PUBLIC MX_CLIPX2
+ PUBLIC MX_CLIPY2
+ PUBLIC MXSETCLIP
+ PUBLIC MXGETCLIP
+ PUBLIC MXSETSYSCLIPREGION
+ PUBLIC MXSETCLIPREGION
+ PUBLIC MXGETCLIPREGION
+ PUBLIC SUBCLIPIMAGE
+ PUBLIC SUBCLIPBOX
+ EXTRN MX_CODESEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_CLIPX1:
+ add byte ptr [bx+si],al
+MX_CLIPY1:
+ add byte ptr [bx+si],al
+MX_CLIPX2:
+ add byte ptr [bx+si],al
+MX_CLIPY2:
+ add byte ptr [bx+si],al
+L$1:
+ add byte ptr [bx+si],al
+L$2:
+ add byte ptr [bx+si],al
+L$3:
+ add byte ptr [bx+si],al
+L$4:
+ add byte ptr [bx+si],al
+L$5:
+ add byte ptr [bx+si],al
+L$6:
+ add byte ptr [bx+si],al
+L$7:
+ add byte ptr [bx+si],al
+L$8:
+ add byte ptr [bx+si],al
+L$9:
+ DB 0
+MXSETCLIP:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr L$5
+ mov bx,word ptr L$6
+ mov cx,word ptr L$7
+ mov dx,word ptr L$8
+ cmp byte ptr 6[bp],1
+ je L$10
+ mov ax,word ptr L$1
+ mov bx,word ptr L$2
+ mov cx,word ptr L$3
+ mov dx,word ptr L$4
+L$10:
+ mov word ptr MX_CLIPX1,ax
+ mov word ptr MX_CLIPY1,bx
+ mov word ptr MX_CLIPX2,cx
+ mov word ptr MX_CLIPY2,dx
+ mov al,byte ptr 6[bp]
+ xchg byte ptr L$9,al
+ xor ah,ah
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 2
+MXGETCLIP:
+ mov al,byte ptr cs:L$9
+ xor ah,ah
+ retf
+MXSETSYSCLIPREGION:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ xor ax,ax
+ mov word ptr L$1,ax
+ mov word ptr L$2,ax
+ mov ax,word ptr 8[bp]
+ dec ax
+ mov word ptr L$3,ax
+ mov ax,word ptr 6[bp]
+ dec ax
+ mov word ptr L$4,ax
+ mov ax,0
+ push ax
+ push cs
+ call near ptr MXSETCLIP
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXSETCLIPREGION:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 0cH[bp]
+ mov word ptr L$5,ax
+ mov ax,word ptr 0aH[bp]
+ mov word ptr L$6,ax
+ mov ax,word ptr 8[bp]
+ add ax,word ptr 0cH[bp]
+ dec ax
+ mov word ptr L$7,ax
+ mov ax,word ptr 6[bp]
+ add ax,word ptr 0aH[bp]
+ dec ax
+ mov word ptr L$8,ax
+ mov al,byte ptr L$9
+ cmp al,1
+ jne L$11
+ push ax
+ push cs
+ call near ptr MXSETCLIP
+L$11:
+ xor ax,ax
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MXGETCLIPREGION:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push es
+ push di
+ mov ax,word ptr cs:L$5
+ les di,dword ptr 12H[bp]
+ mov word ptr es:[di],ax
+ mov ax,word ptr cs:L$6
+ les di,dword ptr 0eH[bp]
+ mov word ptr es:[di],ax
+ mov ax,word ptr cs:L$7
+ sub ax,word ptr cs:L$5
+ inc ax
+ les di,dword ptr 0aH[bp]
+ mov word ptr es:[di],ax
+ mov ax,word ptr cs:L$8
+ sub ax,word ptr cs:L$6
+ inc ax
+ les di,dword ptr 6[bp]
+ mov word ptr es:[di],ax
+ mov al,byte ptr cs:L$9
+ xor ah,ah
+ pop di
+ pop es
+ mov sp,bp
+ pop bp
+ retf 10H
+SUBCLIPIMAGE:
+ xor si,si
+ mov di,word ptr cs:MX_CLIPY1
+ cmp ax,di
+ jge L$12
+ sub di,ax
+ sub dx,di
+ jle L$16
+ mov ax,di
+ mov di,dx
+ mul cx
+ mov si,ax
+ mov dx,di
+ mov ax,word ptr cs:MX_CLIPY1
+L$12:
+ mov di,word ptr cs:MX_CLIPY2
+ cmp ax,di
+ jg L$16
+ inc di
+ sub di,dx
+ sub di,ax
+ jge L$13
+ add dx,di
+L$13:
+ mov di,word ptr cs:MX_CLIPX1
+ cmp bx,di
+ jge L$14
+ sub di,bx
+ sub cx,di
+ jle L$16
+ add si,di
+ mov bx,word ptr cs:MX_CLIPX1
+L$14:
+ mov di,word ptr cs:MX_CLIPX2
+ cmp bx,di
+ jg L$16
+ inc di
+ sub di,bx
+ sub di,cx
+ jge L$15
+ add cx,di
+L$15:
+ clc
+ ret
+L$16:
+ stc
+ ret
+SUBCLIPBOX:
+ mov di,word ptr cs:MX_CLIPY1
+ cmp ax,di
+ jge L$17
+ sub di,ax
+ sub dx,di
+ jle L$21
+ mov ax,word ptr cs:MX_CLIPY1
+L$17:
+ mov di,word ptr cs:MX_CLIPY2
+ cmp ax,di
+ jg L$21
+ inc di
+ sub di,dx
+ sub di,ax
+ jge L$18
+ add dx,di
+L$18:
+ mov di,word ptr cs:MX_CLIPX1
+ cmp bx,di
+ jge L$19
+ sub di,bx
+ sub cx,di
+ jle L$21
+ mov bx,word ptr cs:MX_CLIPX1
+L$19:
+ mov di,word ptr cs:MX_CLIPX2
+ cmp bx,di
+ jg L$21
+ inc di
+ sub di,bx
+ sub di,cx
+ jge L$20
+ add cx,di
+L$20:
+ clc
+ ret
+L$21:
+ stc
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXFILLBOX
+ EXTRN SUBCLIPBOX:BYTE
+ EXTRN SUBHORIZONTALLINEINFO:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ mov ah,al
+ shr cx,1
+ rep stosw
+ rcl cx,1
+ rep stosb
+ ret
+L$2:
+ mov byte ptr [bx],al
+ add bx,dx
+ loop L$2
+ ret
+L$3:
+ mov si,di
+L$4:
+ mov ah,byte ptr [si]
+ mov byte ptr [si],al
+ inc si
+ loop L$4
+ ret
+L$5:
+ mov ah,byte ptr [bx]
+ mov byte ptr [bx],al
+ add bx,dx
+ loop L$5
+ ret
+MXFILLBOX:
+ push bp
+ mov bp,sp
+ sub sp,8
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 10H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov cx,word ptr 0cH[bp]
+ mov dx,word ptr 0aH[bp]
+ call near ptr MX_TEXT:SUBCLIPBOX
+ jae L$6
+ jmp near ptr L$12
+L$6:
+ mov word ptr 0aH[bp],dx
+ call near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+ mov word ptr 0cH[bp],cx
+ mov byte ptr -2[bp],al
+ mov byte ptr -4[bp],ah
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov es,ax
+ mov ds,ax
+ cld
+ mov word ptr -6[bp],offset L$2
+ mov word ptr -8[bp],offset L$1
+ mov ax,word ptr 6[bp]
+ cmp al,3
+ ja L$7
+ cmp al,0
+ je L$7
+ shl al,1
+ shl al,1
+ shl al,1
+ mov ah,al
+ mov al,3
+ mov dx,3ceH
+ out dx,ax
+ mov word ptr -6[bp],offset L$5
+ mov word ptr -8[bp],offset L$3
+L$7:
+ mov ah,byte ptr -2[bp]
+ or ah,ah
+ je L$8
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ mov cx,word ptr 0aH[bp]
+ mov bx,di
+ mov al,byte ptr 8[bp]
+ call word ptr -6[bp]
+ inc di
+L$8:
+ mov cx,word ptr 0cH[bp]
+ jcxz L$10
+ mov dx,3c4H
+ mov ax,0f02H
+ out dx,ax
+ mov al,byte ptr 8[bp]
+ mov bx,di
+ mov dx,word ptr 0aH[bp]
+ push di
+L$9:
+ mov di,bx
+ call word ptr -8[bp]
+ mov cx,word ptr 0cH[bp]
+ add bx,word ptr cs:MX_BYTESPERLINE
+ dec dx
+ jne L$9
+ pop di
+ add di,word ptr 0cH[bp]
+L$10:
+ mov ah,byte ptr -4[bp]
+ or ah,ah
+ je L$11
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ mov cx,word ptr 0aH[bp]
+ mov bx,di
+ mov al,byte ptr 8[bp]
+ call word ptr -6[bp]
+L$11:
+ mov dx,3ceH
+ mov ax,3
+ out dx,ax
+L$12:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXFADEPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+ inc bx
+ outsw
+ jo L$5
+ jb L$4
+ push 2074H
+ sub byte ptr 29H[bp+di],ah
+ and byte ptr [bx+di],dh
+ cmp word ptr [bx+di],di
+ xor ch,byte ptr [di]
+ xor word ptr [bx+di],di
+ cmp word ptr [si],si
+ and byte ptr 52H[bx+di],al
+ push sp
+ dec cx
+ push bx
+ and byte ptr 2eH[bp+di],dh
+ jb L$1
+ insb
+ and byte ptr cs:6cH[bx+di],al
+ insb
+ and byte ptr 69H[bp+si],dh
+ push 7374H
+ and byte ptr 65H[bp+si],dh
+ jae L$7
+ jb L$9
+ DB 65H, 64H, 2eH
+MXFADEPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,60aH
+ push si
+ push di
+ push ds
+ push es
+ mov word ptr -608H[bp],1
+ mov ax,word ptr 10H[bp]
+ and ax,0ff00H
+L$1:
+ je L$2
+ mov cl,8
+ shr ax,cl
+ mov word ptr -608H[bp],ax
+L$2:
+ mov ax,word ptr 10H[bp]
+ and ax,0feH
+ mov cl,1
+ shr ax,cl
+ or ax,ax
+ jne L$3
+ mov ax,30H
+L$3:
+ mov word ptr -60aH[bp],ax
+L$4:
+ inc ax
+ mov byte ptr -606H[bp],al
+ mov byte ptr -604H[bp],1
+ DB 0c6H, 86H, 0feH, 0f9H
+L$5:
+ add byte ptr 0e46H[bp+di],cl
+ cmp ax,100H
+ jb L$6
+ jmp near ptr L$12
+L$6:
+ add ax,word ptr 0cH[bp]
+ cmp ax,100H
+ jbe L$8
+ mov ax,100H
+ sub ax,word ptr 0eH[bp]
+ DB 89H, 46H
+L$7:
+ or al,0bH
+ ????
+ jne L$8
+ jmp near ptr L$12
+L$8:
+ mov cx,word ptr 0cH[bp]
+ mov ax,cx
+ shl ax,1
+ add cx,ax
+ mov ax,ss
+L$9:
+ mov es,ax
+ lea di,-300H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov si,ax
+ shl ax,1
+ add ax,si
+ lds si,dword ptr 12H[bp]
+ add si,ax
+ cld
+ shr cx,1
+ rep movsw
+ rcl cx,1
+ rep movsb
+ test word ptr 10H[bp],1
+ je L$10
+ mov ax,word ptr -60aH[bp]
+ mov byte ptr -602H[bp],al
+ mov byte ptr -604H[bp],0ffH
+ mov ax,ss
+ mov ds,ax
+ mov es,ax
+ lea di,-300H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov cx,word ptr 0cH[bp]
+ call near ptr L$19
+L$10:
+ mov bh,byte ptr 0aH[bp]
+ and bh,3fH
+ mov bl,byte ptr 8[bp]
+ and bl,3fH
+ mov dh,byte ptr 6[bp]
+ and dh,3fH
+ mov dl,byte ptr -602H[bp]
+ mov ax,ss
+ mov ds,ax
+ mov es,ax
+L$11:
+ mov ax,word ptr 0cH[bp]
+ mov cx,word ptr -60aH[bp]
+ lea si,-300H[bp]
+ lea di,-600H[bp]
+ call near ptr L$13
+ push bx
+ push dx
+ lea si,-600H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov bx,word ptr 0cH[bp]
+ mov cx,word ptr -608H[bp]
+ call near ptr L$15
+ pop dx
+ pop bx
+ add dl,byte ptr -604H[bp]
+ dec byte ptr -606H[bp]
+ jne L$11
+L$12:
+ pop es
+ pop ds
+ pop di
+ pop si
+ mov sp,bp
+ pop bp
+ retf 10H
+L$13:
+ cld
+ push bp
+ mov bp,ax
+L$14:
+ lodsb
+ sub al,bh
+ imul dl
+ idiv cl
+ add al,bh
+ stosb
+ lodsb
+ sub al,bl
+ imul dl
+ idiv cl
+ add al,bl
+ stosb
+ lodsb
+ sub al,dh
+ imul dl
+ idiv cl
+ add al,dh
+ stosb
+ dec bp
+ jne L$14
+ pop bp
+ ret
+L$15:
+ mov ah,al
+ mov dx,3daH
+L$16:
+ in al,dx
+ test al,8
+ jne L$16
+L$17:
+ in al,dx
+ test al,8
+ je L$17
+ loop L$16
+ mov cx,bx
+ mov dx,3c8H
+ mov al,ah
+ out dx,al
+ inc dx
+ cld
+ cli
+L$18:
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ loop L$18
+ sti
+ ret
+L$19:
+ mov dx,3c7H
+ out dx,al
+ inc dx
+ inc dx
+ cld
+L$20:
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ loop L$20
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGETCOLOR
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETCOLOR:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr 12H[bp]
+ mov dx,3c7H
+ out dx,al
+ inc dx
+ inc dx
+ lds si,dword ptr 0eH[bp]
+ in al,dx
+ mov byte ptr [si],al
+ lds si,dword ptr 0aH[bp]
+ in al,dx
+ mov byte ptr [si],al
+ lds si,dword ptr 6[bp]
+ in al,dx
+ mov byte ptr [si],al
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0eH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGETIMAGE
+ EXTRN SUBCLIPIMAGE:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETIMAGE:
+ push bp
+ mov bp,sp
+ sub sp,10H
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 0cH[bp]
+ mov ax,word ptr 0aH[bp]
+ mov cx,word ptr 8[bp]
+ mov dx,word ptr 6[bp]
+ call near ptr MX_TEXT:SUBCLIPIMAGE
+ jae L$1
+ jmp near ptr L$7
+L$1:
+ mov word ptr 6[bp],dx
+ add word ptr 0eH[bp],si
+ mul word ptr cs:MX_BYTESPERLINE
+ mov si,bx
+ shr si,1
+ shr si,1
+ add si,ax
+ mov word ptr -0aH[bp],si
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+ and bl,3
+ mov byte ptr -0eH[bp],bl
+ mov bx,cx
+ shr bx,1
+ shr bx,1
+ and cl,3
+ mov al,8
+ shr al,cl
+ mov di,6
+L$2:
+ mov word ptr -8[bp+di],bx
+ shr al,1
+ adc bx,0
+ dec di
+ dec di
+ jge L$2
+ cld
+ mov byte ptr -10H[bp],4
+ lea bx,-8[bp]
+ mov es,word ptr 10H[bp]
+ mov ah,byte ptr -0eH[bp]
+L$3:
+ cmp word ptr ss:[bx],0
+ je L$7
+ mov di,word ptr 0eH[bp]
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov dx,word ptr 6[bp]
+ mov si,word ptr -0aH[bp]
+L$4:
+ push si
+ push di
+ mov cx,word ptr ss:[bx]
+L$5:
+ movsb
+ add di,3
+ dec cx
+ jne L$5
+ pop di
+ pop si
+ add di,word ptr 8[bp]
+ add si,word ptr cs:MX_BYTESPERLINE
+ dec dx
+ jne L$4
+ inc bx
+ inc bx
+ inc ah
+ test ah,4
+ je L$6
+ inc word ptr -0aH[bp]
+ and ah,3
+L$6:
+ inc word ptr 0eH[bp]
+ dec byte ptr -10H[bp]
+ jne L$3
+L$7:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGAMMACORRECT
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bp+si],cl
+ push cs
+ adc word ptr [bp+di],dx
+ adc ax,1817H
+ sbb bl,byte ptr [bp+di]
+ sbb al,1dH
+ pop ds
+ and byte ptr [bx+di],ah
+ and ah,byte ptr [bp+di]
+ and al,25H
+ and ax,2726H
+ sub byte ptr [bx+di],ch
+ sub word ptr [bp+si],bp
+ sub bp,word ptr [si]
+ sub al,2dH
+ das
+ xor byte ptr [bx+si],dh
+ xor word ptr [bx+di],si
+ xor dh,byte ptr [bp+di]
+ xor si,word ptr [si]
+ xor al,35H
+ xor ax,3636H
+ aaa
+ aaa
+ cmp byte ptr [bx+si],bh
+ cmp word ptr [bx+di],di
+ cmp bh,byte ptr [bp+si]
+ cmp di,word ptr [bp+di]
+ cmp al,3cH
+ cmp ax,3e3dH
+ aas
+ aas
+MXGAMMACORRECT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 6[bp]
+ jcxz L$3
+ lds si,dword ptr 0cH[bp]
+ les di,dword ptr 8[bp]
+ mov bx,offset L$1
+ cld
+ mov ax,cx
+ add cx,cx
+ add cx,ax
+L$2:
+ lodsb
+ xlat word ptr cs:[bx]
+ stosb
+ loop L$2
+L$3:
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0aH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGETPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push es
+ push di
+ les di,dword ptr 0aH[bp]
+ mov cx,word ptr 6[bp]
+ mov ax,word ptr 8[bp]
+ mov dx,3c7H
+ out dx,al
+ inc dx
+ inc dx
+ cld
+L$1:
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ loop L$1
+ pop di
+ pop es
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGETVERSION
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETVERSION:
+ mov ax,128H
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC SUBHORIZONTALLINEINFO
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bx+si],al
+ add ax,word ptr [bx+si]
+ add al,byte ptr [bx+si]
+ add word ptr [bx+si],ax
+L$2:
+ add byte ptr ds:[80cH],cl
+L$3:
+ add byte ptr [bx+di],al
+ add ax,word ptr [bx]
+L$4:
+ DB 2, 6
+SUBHORIZONTALLINEINFO:
+ ;DD ds:[63278]
+ ASSUME ds:NOTHING
+ add byte ptr -2e05H[bp+di],cl
+ out dx,ax
+ shr di,1
+ add di,ax
+ and bx,3
+ mov al,byte ptr cs:L$2[bx]
+ shl bx,1
+ sub cx,word ptr cs:L$1[bx]
+ jge L$5
+ mov bx,cx
+ inc bx
+ inc bx
+ and al,byte ptr cs:L$4[bx]
+ xor ah,ah
+ xor cx,cx
+ jmp L$6
+L$5:
+ mov bx,cx
+ and bx,3
+ mov ah,byte ptr cs:L$3[bx]
+ shr cx,1
+ shr cx,1
+L$6:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxInit\r
+PUBLIC mxTerm\r
+\r
+PUBLIC mx_VideoSegment\r
+PUBLIC mx_CodeSegment\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW 0A000h\r
+mx_CodeSegment DW SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; AX = 0 on success\r
+;\r
+mxInit PROC FAR\r
+ LOCAL Result:WORD, \\r
+ VideoSeg:WORD, \\r
+ CStoDSalias:WORD = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+ mov [Result], -1 ; Assume an error\r
+ mov [VideoSeg], 0A000h ; Real mode video segment\r
+ mov [CStoDSalias], cs ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+ mov ax, 1686h\r
+ int 2Fh\r
+ or ax, ax\r
+ jnz @@1 ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+ mov ax, 000Ah ; DMPI: create data alias\r
+ mov bx, cs\r
+ int 31h\r
+ jc @@Exit ; Exit if service failed\r
+ mov [CStoDSalias], ax ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+ mov ax, 0002h\r
+ mov bx, 0A000h ; Real mode segment of video\r
+ int 31h ; DPMI: get segment selector\r
+ jc @@Exit ; Exit if service failed\r
+ mov [VideoSeg], ax ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+ mov ds, [CStoDSalias]\r
+ ASSUME ds:MX_TEXT\r
+ mov [mx_CodeSegment], ds\r
+ mov ax, [VideoSeg]\r
+ mov [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+ mov [Result], 0\r
+\r
+@@Exit:\r
+ mov ax, [Result]\r
+ .pop ds, si, es, di\r
+; .leave\r
+mxInit ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+; none\r
+; Output:\r
+; always 0.\r
+;\r
+mxTerm PROC FAR\r
+ ASSUME ds:NOTHING\r
+ xor ax, ax\r
+ ret\r
+mxTerm ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+ PUBLIC MXLOADLATCHES
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXLOADLATCHES:
+ push ds
+ push si
+ mov dx,3ceH
+ mov ax,0ff08H
+ out dx,ax
+ mov ax,3
+ out dx,ax
+ mov ax,5
+ out dx,ax
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ mov si,0ffffH
+ mov bh,8
+ mov cx,3
+L$1:
+ mov dx,3ceH
+ mov al,4
+ mov ah,cl
+ out dx,ax
+ mov dx,3c4H
+ mov al,2
+ mov ah,bh
+ out dx,ax
+ mov al,byte ptr [si]
+ push ax
+ mov byte ptr [si],bl
+ mov al,byte ptr [di]
+ shr bh,1
+ loop L$1
+ mov cx,3
+ mov bh,8
+ mov dx,3c4H
+L$2:
+ mov al,2
+ mov ah,bh
+ out dx,ax
+ pop ax
+ mov byte ptr [si],al
+ shr bh,1
+ loop L$2
+ pop si
+ pop ds
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXLINE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ DW offset L$29
+ DW offset L$32
+ DW offset L$35
+ DW offset L$38
+MXLINE:
+ push bp
+ mov bp,sp
+ sub sp,12H
+ push ds
+ push si
+ push di
+ mov ax,word ptr 10H[bp]
+ mov bx,word ptr 0eH[bp]
+ mov cx,word ptr 0cH[bp]
+ mov dx,word ptr 0aH[bp]
+ call near ptr L$8
+ jae L$2
+ jmp near ptr L$7
+L$2:
+ mov si,cx
+ xchg ax,si
+ sub ax,si
+ jge L$3
+ xchg cx,si
+ xchg dx,bx
+ neg ax
+L$3:
+ mov word ptr -2[bp],ax
+ mov cx,word ptr cs:MX_BYTESPERLINE
+ mov ax,dx
+ sub ax,bx
+ jge L$4
+ neg cx
+ neg ax
+L$4:
+ mov word ptr -4[bp],ax
+ mov word ptr -0cH[bp],cx
+ mov ax,bx
+ mul word ptr cs:MX_BYTESPERLINE
+ mov cx,si
+ shr si,1
+ shr si,1
+ add si,ax
+ and cl,3
+ mov ax,1102H
+ shl ah,cl
+ mov byte ptr -12H[bp],ah
+ mov dx,3c4H
+ out dx,ax
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ xor bx,bx
+ mov al,byte ptr 6[bp]
+ cmp al,0
+ je L$5
+ and al,3
+ shl al,1
+ shl al,1
+ shl al,1
+ mov ah,al
+ mov al,3
+ mov dx,3ceH
+ out dx,ax
+ inc bx
+ inc bx
+L$5:
+ mov ax,word ptr -2[bp]
+ mov cx,word ptr -4[bp]
+ cmp ax,cx
+ jae L$6
+ inc bx
+L$6:
+ shl bx,1
+ call word ptr cs:L$1[bx]
+ cmp byte ptr 6[bp],0
+ je L$7
+ mov ax,3
+ mov dx,3ceH
+ out dx,ax
+L$7:
+ xor ax,ax
+ pop di
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+L$8:
+ mov di,ax
+ mov si,dx
+ xor al,al
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$9
+ or al,1
+L$9:
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$10
+ or al,2
+L$10:
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$11
+ or al,4
+L$11:
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$12
+ or al,8
+L$12:
+ mov byte ptr -10H[bp],al
+ xor al,al
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$13
+ or al,1
+L$13:
+ cmp di,word ptr cs:MX_CLIPX2
+ jle L$14
+ or al,2
+L$14:
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$15
+ or al,4
+L$15:
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$16
+ or al,8
+L$16:
+ mov byte ptr -0eH[bp],al
+ mov ah,byte ptr -10H[bp]
+ test ah,al
+ je L$17
+ jmp near ptr L$28
+L$17:
+ or ah,al
+ jne L$18
+ jmp near ptr L$27
+L$18:
+ mov ax,cx
+ sub ax,di
+ mov word ptr -0aH[bp],ax
+ mov ax,si
+ sub ax,bx
+ mov word ptr -0cH[bp],ax
+ mov al,byte ptr -0eH[bp]
+L$19:
+ test al,al
+ jne L$20
+ xchg di,cx
+ xchg si,bx
+ xchg byte ptr -10H[bp],al
+L$20:
+ test al,1
+ je L$21
+ mov ax,word ptr cs:MX_CLIPX1
+ sub ax,di
+ mov di,word ptr cs:MX_CLIPX1
+ jmp L$22
+L$21:
+ test al,2
+ je L$23
+ mov ax,word ptr cs:MX_CLIPX2
+ sub ax,di
+ mov di,word ptr cs:MX_CLIPX2
+L$22:
+ imul word ptr -0cH[bp]
+ idiv word ptr -0aH[bp]
+ add bx,ax
+ mov al,8
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$26
+ mov al,4
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$26
+ xor al,al
+ jmp L$26
+L$23:
+ test al,4
+ je L$24
+ mov ax,word ptr cs:MX_CLIPY1
+ sub ax,bx
+ mov bx,word ptr cs:MX_CLIPY1
+ jmp L$25
+L$24:
+ mov ax,word ptr cs:MX_CLIPY2
+ sub ax,bx
+ mov bx,word ptr cs:MX_CLIPY2
+L$25:
+ imul word ptr -0aH[bp]
+ idiv word ptr -0cH[bp]
+ add di,ax
+ mov al,1
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$26
+ mov al,2
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$26
+ xor al,al
+L$26:
+ mov ah,byte ptr -10H[bp]
+ test ah,al
+ jne L$28
+ or ah,al
+ je L$27
+ jmp near ptr L$19
+L$27:
+ mov ax,di
+ mov dx,si
+ clc
+ ret
+L$28:
+ stc
+ ret
+L$29:
+ mov di,ax
+ neg di
+ shl cx,1
+ mov word ptr -6[bp],cx
+ mov cx,ax
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov al,2
+ mov ah,byte ptr -12H[bp]
+ mov bl,byte ptr 8[bp]
+ mov dx,3c4H
+ inc cx
+L$30:
+ mov byte ptr [si],bl
+ dec cx
+ je L$31
+ rol ah,1
+ adc si,0
+ out dx,ax
+ add di,word ptr -6[bp]
+ jl L$30
+ add si,word ptr -0cH[bp]
+ sub di,word ptr -8[bp]
+ jmp L$30
+L$31:
+ ret
+L$32:
+ mov di,cx
+ neg di
+ shl ax,1
+ mov word ptr -6[bp],ax
+ mov ax,cx
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov bl,byte ptr 8[bp]
+ mov ah,byte ptr -12H[bp]
+ mov al,2
+ mov dx,3c4H
+ inc cx
+L$33:
+ mov byte ptr [si],bl
+ dec cx
+ je L$34
+ add si,word ptr -0cH[bp]
+ add di,word ptr -6[bp]
+ jl L$33
+ rol ah,1
+ adc si,0
+ out dx,ax
+ sub di,word ptr -8[bp]
+ jmp L$33
+L$34:
+ ret
+L$35:
+ mov di,ax
+ neg di
+ shl cx,1
+ mov word ptr -6[bp],cx
+ mov cx,ax
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov al,2
+ mov ah,byte ptr -12H[bp]
+ mov bl,byte ptr 8[bp]
+ mov dx,3c4H
+ inc cx
+L$36:
+ mov bh,byte ptr [si]
+ mov byte ptr [si],bl
+ dec cx
+ je L$37
+ rol ah,1
+ adc si,0
+ out dx,ax
+ add di,word ptr -6[bp]
+ jl L$36
+ add si,word ptr -0cH[bp]
+ sub di,word ptr -8[bp]
+ jmp L$36
+L$37:
+ ret
+L$38:
+ mov di,cx
+ neg di
+ shl ax,1
+ mov word ptr -6[bp],ax
+ mov ax,cx
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov bl,byte ptr 8[bp]
+ mov ah,byte ptr -12H[bp]
+ mov al,2
+ mov dx,3c4H
+ inc cx
+L$39:
+ mov bh,byte ptr [si]
+ mov byte ptr [si],bl
+ dec cx
+ je L$40
+ add si,word ptr -0cH[bp]
+ add di,word ptr -6[bp]
+ jl L$39
+ rol ah,1
+ adc si,0
+ out dx,ax
+ sub di,word ptr -8[bp]
+ jmp L$39
+L$40:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSETFONT
+ PUBLIC MXSETTEXTCOLOR
+ PUBLIC MXOUTCHAR
+ PUBLIC MXOUTTEXT
+ PUBLIC MXSETTEXTSTEP
+ PUBLIC MXGETTEXTSTEP
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MXPUTIMAGE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+; Default 8x8 font
+fnt_Default LABEL BYTE
+ INCLUDE DEFAULT.FNT
+
+; Table of system fonts
+tbl_SystemFont LABEL WORD
+ DW fnt_Default, 8, 8
+
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2
+
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT
+mx_FontWidth DW 8 ; Font width in pixels
+mx_FontHeight DW 8 ; Font height in pixels
+mx_FontCharSize DW 8 ; Size in bytes of a font character
+mx_FontColor DW 00FFh ; Color: foreground + background*256
+mx_FontOp DW 0 ; Raster op
+mx_DeltaX DW 8 ; Horizontal step
+mx_DeltaY DW 0 ; Vertical step
+
+L$1:
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ; The label referred to here is an undefined location
+ ;;;;ffff
+ ;jle 0xff8bh
+ movsw
+ and word ptr -7e67H[di],7e7eH
+ call bx
+ call bx
+ out 0ffH,ax
+ jle L$9
+; ;????
+; ;????
+; ;????
+ jl L$7
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],bh
+L$2:
+ jl L$2
+ jl L$8
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],bh
+ adc byte ptr -2[si],dl
+ push sp
+ adc dh,bh
+ adc byte ptr [bx+si],bh
+L$3:
+ jl L$3
+L$4:
+ ;????
+ jl L$5
+ inc byte ptr [bx+si]
+ sbb byte ptr [si],bh
+ jle L$11
+ cmp al,18H
+ add bh,bh
+ out 0c3H,ax
+ DB 81H, 81H, 0c3H, 0e7H
+L$5:
+ inc word ptr [bx+si]
+ cmp al,66H
+ inc dx
+ inc dx
+ DB 66H, 3cH
+L$6:
+ add bh,bh
+ ret
+ cwd
+ mov bp,99bdH
+L$7:
+ ret
+ inc word ptr [bx]
+ add ax,word ptr [di]
+ ; The label referred to here is an undefined location
+ ;;;;;0ffff
+ ;;;;;js 0ffffffe1H
+ DB 84H
+L$8:
+ test byte ptr 7cH[bx+si],bh
+ add byte ptr 7c82H[bp+si],10H
+ cmp byte ptr [bx+si],dl
+ sbb al,10H
+ sbb al,10H
+ adc byte ptr [bx+si],dl
+ xor byte ptr [bx+si],dh
+ and bh,byte ptr ds:[2222H]
+ ;;;;;pushad
+ cwd
+ pop dx
+ cmp al,0e7H
+ out 3cH,ax
+ pop dx
+ cwd
+ add byte ptr [bx+si],dl
+ xor byte ptr -10H[bx+si],dh
+L$9:
+ jo L$10
+ adc byte ptr [bx+si],al
+ add al,0e0H
+ ;;;;lock loopnz L$6
+ adc byte ptr [bx+si],38H
+ push sp
+ adc byte ptr [bx+si],dl
+ push sp
+ cmp byte ptr [bx+si],dl
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ add byte ptr [bx+si],cl
+ jle L$4
+ xchg ax,dx
+ jb L$10
+ adc dl,byte ptr [bp+si]
+ add byte ptr [si],bh
+ and bl,byte ptr [bx+si]
+ and al,24H
+ sbb byte ptr 3cH[si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ DB 0, 3eH
+ ;;;;DD ds:[03eh]
+L$10:
+ add byte ptr [bx+si],bh
+ push sp
+ DB 10H
+L$11:
+ adc byte ptr [bx+si],dl
+ push sp
+ cmp dh,bh
+ add byte ptr [bx+si],dl
+ cmp byte ptr 10H[si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr 38H[si],dl
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],cl
+ add al,0feH
+ add al,8
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],ah
+ inc ax
+ inc byte ptr 20H[bx+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr -380H[bx+si],0
+ add byte ptr [bx+si],al
+ and al,42H
+ inc word ptr 24H[bp+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],bh
+L$12:
+ jl L$12
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ;????
+ jl L$15
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ and al,24H
+ add byte ptr [bx+si],al
+ DB 0
+L$13:
+ add byte ptr [bx+si],al
+ and al,24H
+ ;;;;jle 140H
+ ;;;;jle 142H
+L$14:
+ and al,0
+ cmp byte ptr 50H[si],dl
+ cmp byte ptr [si],dl
+ push sp
+ cmp byte ptr [bx+si],dl
+ add byte ptr [bp+si],al
+ inc sp
+ or byte ptr [bx+si],dl
+ and byte ptr [bp+si],al
+ cmp byte ptr 38H[si],al
+ ;;;;pusha
+ xchg ax,sp
+L$15:
+ DB 88H
+L$16:
+ ;;;;je 138H
+ and byte ptr [bx+si],ah
+ inc ax
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ and byte ptr 40H[bx+si],al
+ inc ax
+ and byte ptr [bx+si],dl
+ add byte ptr 20H[bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],ah
+L$17:
+ inc ax
+ add byte ptr [bx+si],al
+ and al,18H
+ jle L$18
+ and al,0
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ jl L$18
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ and byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cld
+ DB 0
+L$18:
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add al,8
+ adc byte ptr [bx+si],ah
+ inc ax
+L$19:
+ add byte ptr [bx+si],7cH
+ ;????
+ DB 8aH, 92H
+L$20:
+ mov byte ptr tbl_SystemFont[bx+2],al
+ DD L$21
+L$21:
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],bh
+ add byte ptr L$13[bx+si],bh
+ add al,18H
+ ;;;;pusha
+ cmp ah,0
+ js L$14
+ add al,38H
+ add al,84H
+ js L$22
+L$22:
+ sbb al,24H
+ inc sp
+ test dh,bh
+ add al,0eH
+ add ah,bh
+ cmp al,4
+ add al,84H
+ js L$23
+L$23:
+ js L$16
+ cmp al,84H
+ test byte ptr [bx+si],bh
+ cld
+ add al,4
+ or byte ptr [bx+si],dl
+ and byte ptr [bx+si],ah
+ add byte ptr -7cH[bx+si],bh
+ test byte ptr -7cH[bx+si],bh
+ test byte ptr [bx+si],bh
+ js L$17
+ test byte ptr 4[si],bh
+ test byte ptr [bx+si],bh
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],ah
+ or byte ptr [bx+si],dl
+ and byte ptr 20H[bx+si],al
+ adc byte ptr [bx+si],cl
+ add byte ptr [bx+si],al
+ add ah,bh
+ add byte ptr [bx+si],al
+ cld
+ add byte ptr [bx+si],al
+ inc ax
+ and byte ptr [bx+si],dl
+ or byte ptr [bx+si],dl
+ and byte ptr [bx+si],al
+ js L$19
+ add al,8
+ adc byte ptr [bx+si],al
+L$24:
+ adc byte ptr [bx+si],al
+ jl L$20
+ mov dx,0bea6H
+ cmp byte ptr [si],78H
+ test byte ptr -7b04H[si],al
+ test byte ptr -800H[si],al
+ test byte ptr -7b08H[si],al
+ test al,bh
+ add byte ptr -7cH[bx+si],bh
+ add byte ptr -7b80H[bx+si],78H
+ add al,dh
+ mov byte ptr -7b7cH[si],al
+ mov al,dh
+ add ah,bh
+ add byte ptr -7f10H[bx+si],80H
+ cld
+ add ah,bh
+ add byte ptr -7f10H[bx+si],80H
+ add byte ptr [bx+si],78H
+ test byte ptr -7b64H[bx+si],al
+ test byte ptr [bx+si],bh
+ test byte ptr -37cH[si],al
+ test byte ptr 84H[si],al
+ cmp byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ cmp byte ptr [bx+si],al
+ sbb al,8
+ or byte ptr [bx+si],cl
+ mov byte ptr 70H[bx+si],cl
+ test byte ptr -1f70H[bx+si],cl
+ nop
+ mov byte ptr -8000H[si],al
+ add byte ptr -7f80H[bx+si],80H
+ cld
+ add dh,al
+ stosb
+ xchg ax,dx
+ add byte ptr -7d7eH[bp+si],0
+ add dl,0a2H
+ xchg ax,dx
+ mov al,byte ptr 82H[bp]
+ js L$24
+ test byte ptr -7b7cH[si],al
+ js L$25
+L$25:
+ clc
+ test byte ptr -7f08H[si],al
+ add byte ptr 7800H[bx+si],84H
+ test byte ptr -776cH[si],al
+ jbe L$26
+L$26:
+ clc
+ test byte ptr -6f08H[si],al
+ mov byte ptr 7800H[si],al
+ test byte ptr 478H[bx+si],al
+ test byte ptr [bx+si],bh
+ ;????
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr -7b7cH[si],al
+ test byte ptr 7884H[si],al
+ add byte ptr -7b7cH[si],al
+ test byte ptr 3048H[si],al
+ add byte ptr -7d7eH[bp+si],al
+ adc byte ptr -3956H[bp+si],0
+ add byte ptr 28H[si],10H
+ sub byte ptr -7eH[si],al
+ add byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add dh,bh
+ add al,8
+ adc byte ptr [bx+si],ah
+ inc ax
+ inc byte ptr [bx+si]
+ js L$32
+ inc ax
+ inc ax
+ inc ax
+ inc ax
+ js L$27
+L$27:
+ add byte ptr 2040H[bx+si],al
+ adc byte ptr [bx+si],cl
+ add al,0
+ js L$29
+ or byte ptr [bx+si],cl
+ or byte ptr [bx+si],cl
+ js L$28
+L$28:
+ adc byte ptr [bx+si],ch
+L$29:
+ inc sp
+ add byte ptr [bx+si],0
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add bh,bh
+ and byte ptr [bx+si],ah
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$30
+L$30:
+ add byte ptr 40H[bx+si],al
+ js L$33
+ inc sp
+ js L$31
+L$31:
+ add byte ptr [bx+si],al
+L$32:
+ cmp al,40H
+ inc ax
+ inc ax
+ cmp al,0
+ add byte ptr [si],al
+ add al,3cH
+ inc sp
+ inc sp
+ cmp al,0
+ add byte ptr [bx+si],al
+ cmp byte ptr 7cH[si],al
+ inc ax
+ cmp al,0
+ add byte ptr [si],cl
+ adc byte ptr [si],bh
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp al,44H
+ inc sp
+ cmp al,4
+ cmp byte ptr [bx+si],al
+ inc ax
+ inc ax
+ js L$35
+ inc sp
+ inc sp
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add al,0
+ add al,4
+ add al,44H
+ cmp byte ptr [bx+si],al
+L$33:
+ inc ax
+ inc ax
+ push ax
+ ;;;;pusha
+ push ax
+ dec ax
+ add byte ptr [bx+si],al
+ xor byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add byte ptr 54H[bx+si],ch
+ push sp
+ inc sp
+ inc sp
+ add byte ptr [bx+si],al
+ add byte ptr 44H[bx+si],bh
+ inc sp
+ inc sp
+ inc sp
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bh
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+L$34:
+ js L$42
+ inc sp
+ js L$41
+ inc ax
+ DB 0
+L$35:
+ add byte ptr [si],bh
+ inc sp
+ inc sp
+ cmp al,4
+ add al,0
+ add byte ptr 60H[si],bl
+ inc ax
+ inc ax
+ inc ax
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bh
+L$36:
+ inc ax
+ jl L$38
+ jl L$37
+L$37:
+ add byte ptr [bx+si],dl
+L$38:
+ cmp byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ sbb byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ sub byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add byte ptr 44H[si],al
+L$39:
+ push sp
+ push sp
+ ;;;;insb
+ add byte ptr [bx+si],al
+ add byte ptr 28H[si],al
+L$40:
+ adc byte ptr [bx+si],ch
+ inc sp
+L$41:
+ DB 0
+L$42:
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp al,4
+ jl L$43
+L$43:
+ add byte ptr 4[si],bh
+ cmp byte ptr 7cH[bx+si],al
+ add byte ptr [bx+si],al
+ or byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dh
+ adc byte ptr [bx+si],dl
+ or byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ and byte ptr [bx+si],dl
+ adc byte ptr [bx+si],bl
+ adc byte ptr [bx+si],dl
+ and byte ptr -68H[si],ah
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ sub byte ptr -7eH[si],al
+ cmp dh,0
+ jl L$34
+ add byte ptr 7c80H[bx+si],4
+ jl L$44
+L$44:
+ sub byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ cmp al,0
+ jl L$54
+ jl L$53
+ jl L$45
+L$45:
+ jle L$36
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$46
+L$46:
+ and al,0
+L$47:
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$48
+L$48:
+ js L$49
+L$49:
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$50
+L$50:
+ sbb byte ptr [bx+si],bl
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$51
+L$51:
+ add byte ptr [bx+si],al
+ js L$39
+ cmp byte ptr 8[bx+si],38H
+ jl L$40
+ cmp byte ptr 7cH[si],al
+ inc ax
+ cmp al,0
+ dec ax
+ add byte ptr [bx+si],bh
+ inc sp
+ jl L$55
+ cmp al,0
+ js L$52
+L$52:
+ cmp byte ptr 7cH[si],al
+ inc ax
+L$53:
+ cmp al,0
+L$54:
+ add byte ptr [bx+si],ch
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],ch
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],dh
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ dec ax
+ add byte ptr -7cH[bx+si],bh
+ cld
+ test byte ptr 3000H[si],al
+ xor byte ptr -7cH[bx+si],bh
+ cld
+ test byte ptr 3800H[si],al
+ add ah,bh
+ xor al,80H
+ cld
+ add byte ptr [bx+si],al
+ add byte ptr 8[bp],bh
+ jle L$59
+L$55:
+ jle L$56
+L$56:
+ jle L$47
+ nop
+ cld
+ nop
+ nop
+ sahf
+ add byte ptr -7eH[si],bh
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ sub byte ptr [bx+si],al
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ jo L$57
+L$57:
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ cmp byte ptr [si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ jo L$58
+L$58:
+ inc sp
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ sub byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp al,4
+ jl L$64
+ add byte ptr -7cH[bx+si],bh
+ test byte ptr 78H[si],al
+ dec ax
+ add byte ptr -7b7cH[si],al
+ DB 84H
+L$59:
+ ;;;;js 4d8H
+ add byte ptr [bx+si],dl
+ cmp byte ptr 40H[bx+si],al
+ inc ax
+ cmp byte ptr [bx+si],dl
+ cmp byte ptr 40H[si],al
+ loopnz L$66
+ inc ax
+ cmp ah,44H
+ jl L$60
+ jl L$61
+ jl L$62
+ add al,dh
+ mov byte ptr -7d09H[bp+si],cl
+ add byte ptr 0c00H[bp+si],12H
+ DB 10H
+L$60:
+ sbb byte ptr [bx+si],dh
+L$61:
+ DB 10H, 90H
+L$62:
+ ;;;;pusha
+ cmp al,0
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$63
+L$63:
+ add byte ptr [bx+si],bl
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ DB 1cH
+L$64:
+ add byte ptr [bx+si],bh
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ sbb al,0
+ inc sp
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ jl L$65
+L$65:
+ js L$67
+ inc sp
+L$66:
+ inc sp
+ inc sp
+ add byte ptr [si],bh
+ inc sp
+ push sp
+ dec sp
+ inc sp
+ add byte ptr [bx+si],bl
+ and al,24H
+ push ds
+ add byte ptr ds:[0],bh
+ sbb al,22H
+ and bl,byte ptr [si]
+ add byte ptr ds:[0],bh
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],ah
+ inc ax
+ inc dx
+ cmp al,0
+ add byte ptr [bx+si],al
+ add ah,bh
+ add byte ptr [bx+si],0
+ add byte ptr [bx+si],al
+ cld
+ add al,4
+ add byte ptr [bx+si],al
+ inc ax
+ inc sp
+ dec ax
+ push di
+ and word ptr 4[bx],ax
+ pop es
+ inc ax
+ inc sp
+ dec ax
+ push dx
+ dec dx
+ pop ds
+ DB 2
+L$67:
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+L$68:
+ adc byte ptr [bx+si],al
+ add byte ptr [si],ah
+L$69:
+ dec ax
+ nop
+ dec ax
+ and al,0
+ add byte ptr [bx+si],al
+ dec ax
+ and al,12H
+ and al,48H
+ add byte ptr [bx+si],al
+ and cl,byte ptr -77deH[bx+si]
+ and cl,byte ptr -77deH[bx+si]
+ push bp
+ stosb
+ push bp
+ stosb
+ push bp
+ stosb
+ push bp
+ stosb
+ ;????
+ ja L$68
+ out dx,al
+ ;????
+ ja L$69
+ out dx,al
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ clc
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb al,bh
+ sbb al,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr ds:[3636H],dh
+ div byte ptr ss:[3636H]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ;????
+ add byte ptr ss:[bx+si],al
+ clc
+ sbb al,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr ds:[0f636H],dh
+ push es
+ div byte ptr ds:[3636H]
+ add byte ptr ss:[bx+si],al
+ inc byte ptr ds:[36f6H]
+ test byte ptr ss:[0feH],0
+ add byte ptr ds:[3636H],dh
+ inc byte ptr ss:[bx+si]
+ add byte ptr [bx+si],al
+ sbb byte ptr [bx+si],bl
+ clc
+ sbb al,bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add al,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb bh,bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add bh,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add bh,bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb bh,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr ds:[3636H],dh
+ aaa
+ aaa
+ xor byte ptr [bx],bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bh
+ xor byte ptr [bx],dh
+ test word ptr ss:[bx+si],0ffH
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc word ptr [bx+si]
+ div word ptr ds:[3636H]
+ aaa
+ xor byte ptr [bx],dh
+ add byte ptr ss:[bx+si],al
+ inc word ptr [bx+si]
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ test word ptr ss:[bx+si],36f7H
+ sbb byte ptr ss:[bx+si],bl
+ inc word ptr [bx+si]
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ inc word ptr ss:[bx+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc word ptr [bx+si]
+ call dword ptr [bx+si]
+ sbb byte ptr [bx+si],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ push word ptr ds:[3636H]
+ aas
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bh
+ push word ptr ss:[3636H]
+ sbb byte ptr [bx+si],bl
+ call dword ptr [bx+si]
+ call dword ptr [bx+si]
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ clc
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bl
+ DB 18H
+L$70:
+ sbb byte ptr [bx+si],bl
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ add bh,bh
+ ;????
+ ;????
+ push ax
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ ;????
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr -6cH[bp+si],ah
+ mov byte ptr 62H[si],dl
+ add al,dh
+ mov al,dh
+ mov byte ptr -7f10H[bx+si],cl
+ add al,bh
+ mov byte ptr -7f80H[bx+si],al
+ add byte ptr [bx+si],0
+ cld
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ add ah,bh
+ test byte ptr 20H[bx+si],al
+ inc ax
+ test ah,bh
+ add byte ptr [si],bh
+ inc ax
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ js L$71
+ inc ax
+ add byte ptr ds:[848H],dh
+ or byte ptr [bx+si],cl
+ or byte ptr [bx+si],al
+ cmp byte ptr [bx+si],dl
+ cmp byte ptr 44H[si],al
+ cmp byte ptr [bx+si],dl
+ cmp byte ptr -7cH[bx+si],bh
+ test ah,bh
+ test byte ptr 78H[si],al
+ js L$70
+ test byte ptr 4848H[si],al
+ int 3
+ add byte ptr 4[bx+si],bh
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ;;;;insb
+ xchg ax,dx
+ xchg ax,dx
+ ;;;;insb
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp al,byte ptr 5aH[si]
+ and bl,byte ptr [si]
+ sbb byte ptr [bx+si],ah
+ inc ax
+ js L$73
+ and byte ptr [bx+si],bl
+L$71:
+ add byte ptr -7cH[bx+si],bh
+ test byte ptr -7b7cH[si],al
+ test byte ptr [bx+si],al
+ add ah,bh
+ add ah,bh
+ add ah,bh
+ add byte ptr [bx+si],al
+ and byte ptr [bx+si],ah
+ clc
+ and byte ptr [bx+si],ah
+ add al,bh
+ add byte ptr [bx+si],ah
+ adc byte ptr [bx+si],cl
+ adc byte ptr [bx+si],ah
+ add byte ptr [si],bh
+ or byte ptr [bx+si],dl
+ and byte ptr [bx+si],dl
+ or byte ptr [bx+si],al
+ jl L$72
+L$72:
+ or al,12H
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ nop
+ ;;;;pusha
+ add byte ptr [bx+si],dl
+ add byte ptr [si],bh
+L$73:
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ xor cl,byte ptr [si]
+ xor cl,byte ptr [si]
+ add byte ptr [bx+si],bh
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ sbb byte ptr [bx+si],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ add byte ptr [bx+si],al
+ add byte ptr ds:[808H],cl
+ or byte ptr 28H[bx+si],cl
+ sbb byte ptr [bx+si],cl
+ cmp byte ptr [si],ah
+ and al,24H
+ and al,0
+ add byte ptr [bx+si],al
+ cmp al,4
+ cmp al,20H
+ cmp al,0
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp al,3cH
+ cmp al,3cH
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+L$74:
+ DW offset L$1
+L$75:
+ DB 8
+L$76:
+ add byte ptr [bx+si],cl
+ DB 0
+L$77:
+ DW offset L$1
+L$78:
+ DW seg L$1
+L$79:
+ or byte ptr [bx+si],al
+L$80:
+ or byte ptr [bx+si],al
+L$81:
+ or byte ptr [bx+si],al
+L$82:
+ inc word ptr [bx+si]
+L$83:
+ add byte ptr [bx+si],al
+L$84:
+ or byte ptr [bx+si],al
+L$85:
+ add byte ptr [bx+si],al
+MXSETFONT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 0cH[bp]
+ test ax,ax
+ jne L$87
+ mov ax,word ptr 0aH[bp]
+ cmp ax,1
+ jb L$86
+ xor ax,ax
+L$86:
+ shl ax,1
+ shl ax,1
+ mov bx,ax
+ mov ax,word ptr L$74[bx]
+ mov word ptr L$77,ax
+ mov word ptr L$78,cs
+ mov al,byte ptr L$75[bx]
+ xor ah,ah
+ mov word ptr L$79,ax
+ mov word ptr L$84,ax
+ mov dl,byte ptr L$76[bx]
+ xor dh,dh
+ mov word ptr L$80,dx
+ mul dx
+ mov word ptr L$81,ax
+ mov word ptr L$84,ax
+ xor ax,ax
+ mov word ptr L$85,ax
+ jmp L$88
+L$87:
+ mov ax,0ffffH
+ mov bx,word ptr 8[bp]
+ cmp bx,10H
+ ja L$88
+ mov dx,word ptr 6[bp]
+ cmp dx,20H
+ ja L$88
+ mov word ptr L$79,bx
+ mov word ptr L$80,dx
+ mov ax,bx
+ add ax,7
+ shr ax,1
+ shr ax,1
+ shr ax,1
+ mul dx
+ mov word ptr L$81,ax
+ mov ax,word ptr 0aH[bp]
+ mov word ptr L$77,ax
+ mov ax,word ptr 0cH[bp]
+ mov word ptr L$78,ax
+ xor ax,ax
+L$88:
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MXSETTEXTCOLOR:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 8[bp]
+ mov word ptr L$82,ax
+ mov ax,word ptr 6[bp]
+ mov word ptr L$83,ax
+ xor ax,ax
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXOUTCHAR:
+ push bp
+ mov bp,sp
+ sub sp,202H
+ push ds
+ push si
+ push es
+ push di
+ lds si,dword ptr cs:L$77
+ mov al,byte ptr 6[bp]
+ xor ah,ah
+ mul word ptr cs:L$81
+ add si,ax
+ mov ax,ss
+ mov es,ax
+ lea di,-200H[bp]
+ mov dx,word ptr cs:L$82
+ mov ax,word ptr cs:L$80
+ mov word ptr -202H[bp],ax
+L$89:
+ mov cx,word ptr cs:L$79
+ mov bh,byte ptr [si]
+ inc si
+ cmp cx,8
+ jbe L$90
+ mov bl,byte ptr [si]
+ inc si
+L$90:
+ mov al,dl
+ shl bx,1
+ jb L$91
+ mov al,dh
+L$91:
+ mov byte ptr es:[di],al
+ inc di
+ dec cx
+ jne L$90
+ dec word ptr -202H[bp]
+ jne L$89
+ lea ax,-200H[bp]
+ push es
+ push ax
+ push word ptr 0aH[bp]
+ push word ptr 8[bp]
+ push word ptr cs:L$79
+ push word ptr cs:L$80
+ push word ptr cs:L$83
+ push cs
+ call near ptr MX_TEXT:MXPUTIMAGE
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 6
+MXOUTTEXT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 6[bp]
+L$92:
+ mov al,byte ptr [si]
+ test al,al
+ je L$93
+ inc si
+ push word ptr 0cH[bp]
+ push word ptr 0aH[bp]
+ push ax
+ push cs
+ call near ptr MXOUTCHAR
+ mov ax,word ptr cs:L$84
+ add word ptr 0cH[bp],ax
+ mov ax,word ptr cs:L$85
+ add word ptr 0aH[bp],ax
+ dec word ptr -202H[bp]
+ jne L$92
+L$93:
+ xor ax,ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+ retf
+MXSETTEXTSTEP:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 8[bp]
+ mov word ptr L$84,ax
+ mov ax,word ptr 6[bp]
+ mov word ptr L$85,ax
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXGETTEXTSTEP:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr cs:L$84
+ lds si,dword ptr 0aH[bp]
+ mov word ptr [si],ax
+ mov ax,word ptr cs:L$85
+ lds si,dword ptr 6[bp]
+ mov word ptr [si],ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN PRO\r
+;NOWARN RES ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxOutChar\r
+PUBLIC mxOutText\r
+PUBLIC mxSetFont\r
+PUBLIC mxSetTextColor\r
+PUBLIC mxGetTextStep\r
+PUBLIC mxSetTextStep\r
+\r
+MAX_WIDTH EQU 16 ; Must be <= 16\r
+MAX_HEIGHT EQU 32\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mxPutImage : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default LABEL BYTE\r
+ INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont LABEL WORD\r
+ DW fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth DW 8 ; Font width in pixels\r
+mx_FontHeight DW 8 ; Font height in pixels\r
+mx_FontCharSize DW 8 ; Size in bytes of a font character\r
+mx_FontColor DW 00FFh ; Color: foreground + background*256\r
+mx_FontOp DW OP_MOVE ; Raster op\r
+mx_DeltaX DW 8 ; Horizontal step\r
+mx_DeltaY DW 0 ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+; Font = pointer to font data\r
+; Width = width of font character in pixels\r
+; Height = height of font character in pixels\r
+; Output:\r
+; AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+; word is used to select one of the system fonts.\r
+;\r
+mxSetFont PROC FAR\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,0\r
+ push ds\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, WORD PTR Font[2] ; Get font segment\r
+ test ax, ax ; Null segment?\r
+ jnz @@UserFont ; No, install user font\r
+\r
+; Install system font\r
+ mov ax, WORD PTR Font[0] ; Get font number\r
+ cmp ax, MX_MAXSYSFONT ; Check range\r
+ jb @@SystemFont\r
+ xor ax, ax ; Out of range, use default font\r
+@@SystemFont:\r
+ shl ax, 1\r
+ shl ax, 1\r
+ mov bx, ax\r
+ mov ax, tbl_SystemFont[bx] ; Get font offset\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov WORD PTR mx_FontPtr[2], cs\r
+ mov al, BYTE PTR tbl_SystemFont[bx+2]\r
+ xor ah, ah\r
+ mov [mx_FontWidth], ax\r
+ mov [mx_DeltaX], ax\r
+ mov dl, BYTE PTR tbl_SystemFont[bx+3]\r
+ xor dh, dh\r
+ mov [mx_FontHeight], dx\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov [mx_DeltaX], ax\r
+ xor ax, ax\r
+ mov [mx_DeltaY], ax\r
+ jmp @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+ mov ax, -1 ; Assume an error\r
+ mov bx, [bp+8]\r
+ cmp bx, MAX_WIDTH\r
+ ja @@Exit ; Invalid character width\r
+ mov dx, [bp+4]\r
+ cmp dx, MAX_HEIGHT\r
+ ja @@Exit ; Invalid character height\r
+ mov [mx_FontWidth], bx\r
+ mov [mx_FontHeight], dx\r
+ mov ax, bx\r
+ add ax, 7\r
+ shr ax, 1\r
+ shr ax, 1\r
+ shr ax, 1\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov ax, WORD PTR Font[0]\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov ax, WORD PTR Font[2]\r
+ mov WORD PTR mx_FontPtr[2], ax\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ ;.leave ARG_SIZE\r
+mxSetFont ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+; Color = text color (foreground + background*256)\r
+; Op = raster op\r
+; Output:\r
+; none\r
+;\r
+mxSetTextColor PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [Color]\r
+ mov [mx_FontColor], ax\r
+ mov ax, [Op]\r
+ mov [mx_FontOp], ax\r
+\r
+ xor ax, ax\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetTextColor ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+; X, Y = video coordinates\r
+; C = character to print\r
+; Output:\r
+; none\r
+;\r
+mxOutChar PROC FAR\r
+ ARG C:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \\r
+ Count:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+ lds si, DWORD PTR [mx_FontPtr]\r
+ mov al, [C]\r
+ xor ah, ah\r
+ mul [mx_FontCharSize] ; Offset into font\r
+ add si, ax ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [Image]\r
+ mov dx, [mx_FontColor]\r
+ mov ax, [mx_FontHeight]\r
+ mov [Count], ax\r
+@@HeightLoop:\r
+ mov cx, [mx_FontWidth]\r
+ mov bh, ds:[si]\r
+ inc si ; Get a byte from font data\r
+ cmp cx, 8\r
+ jbe @@WidthLoop ; Ok for width <= 8\r
+ mov bl, ds:[si] ; Get another byte\r
+ inc si\r
+@@WidthLoop:\r
+ mov al, dl ; Assume foreground color\r
+ shl bx, 1 ; Is font bit set?\r
+ jc @@1 ; Yes, foreground is just great\r
+ mov al, dh ; Get background color\r
+@@1:\r
+ mov es:[di], al ; Put pixel into image\r
+ inc di\r
+ dec cx\r
+ jnz @@WidthLoop\r
+ dec [Count]\r
+ jnz @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+ lea ax, [Image]\r
+ push es\r
+ push ax ; Pointer to image\r
+ push [X]\r
+ push [Y] ; Image coordinates\r
+ push [mx_FontWidth]\r
+ push [mx_FontHeight] ; Image size\r
+ push [mx_FontOp] ; Raster op\r
+ call mxPutImage ; Write character\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxOutChar ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+; X, Y = text coordinates\r
+; S = pointer to ASCIIZ string\r
+; Output:\r
+; none\r
+;\r
+mxOutText PROC FAR\r
+ ARG S:DWORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [S]\r
+@@Loop:\r
+ mov al, ds:[si]\r
+ test al, al ; End of string?\r
+ jz @@Exit ; Yes, exit\r
+ inc si\r
+ push [X] ; Display character\r
+ push [Y]\r
+ push ax\r
+ call mxOutChar\r
+ mov ax, [mx_DeltaX]\r
+ add [X], ax ; Bump X coordinate\r
+ mov ax, [mx_DeltaY]\r
+ add [Y], ax ; Bump Y coordinate\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+ ret\r
+mxOutText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = horizontal distance in pixels\r
+; DeltaY = vertical distance in pixels\r
+; Output:\r
+; none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep PROC FAR\r
+ ARG DeltaY:WORD, \\r
+ DeltaX:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [DeltaX]\r
+ mov [mx_DeltaX], ax\r
+ mov ax, [DeltaY]\r
+ mov [mx_DeltaY], ax\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetTextStep ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = pointer to horizontal distance in pixels (integer)\r
+; DeltaY = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+; none\r
+;\r
+mxGetTextStep PROC FAR\r
+ ARG DeltaY:DWORD, \\r
+ DeltaX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [mx_DeltaX]\r
+ lds si, [DeltaX]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_DeltaY]\r
+ lds si, [DeltaY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetTextStep ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+ PUBLIC MX_SCANBUFFER
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCANBUFFER:
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXFILLPOLY
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MX_SCANBUFFER:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ mov cx,word ptr [si]
+ sub cx,word ptr [bx]
+ jg L$2
+ ret
+L$2:
+ push bp
+ mov ax,word ptr 2[si]
+ mov bx,word ptr 2[bx]
+ sub ax,bx
+ jg L$4
+ jl L$6
+ mov ax,bx
+L$3:
+ mov word ptr es:[di],ax
+ add di,4
+ dec cx
+ jne L$3
+ jmp L$8
+L$4:
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$5:
+ mov word ptr es:[di],ax
+ add di,4
+ add dx,bx
+ adc ax,bp
+ dec cx
+ jne L$5
+ jmp L$8
+L$6:
+ neg ax
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$7:
+ mov word ptr es:[di],ax
+ add di,4
+ sub dx,bx
+ sbb ax,bp
+ dec cx
+ jne L$7
+L$8:
+ pop bp
+ ret
+MXFILLPOLY:
+ push bp
+ mov bp,sp
+ sub sp,1eH
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 10H[bp]
+ cmp cx,3
+ jae L$9
+ jmp near ptr L$36
+L$9:
+ les di,dword ptr 0cH[bp]
+ lds si,dword ptr 8[bp]
+ mov word ptr -16H[bp],7fffH
+ mov word ptr -1aH[bp],8000H
+ mov word ptr -18H[bp],7fffH
+ mov word ptr -1eH[bp],8000H
+ xor dx,dx
+L$10:
+ mov bx,word ptr es:[di]
+ shl bx,1
+ shl bx,1
+ add bx,si
+ mov ax,word ptr [bx]
+ cmp ax,word ptr -16H[bp]
+ jge L$11
+ mov word ptr -16H[bp],ax
+ mov word ptr -0eH[bp],dx
+ mov word ptr -10H[bp],dx
+L$11:
+ cmp ax,word ptr -1aH[bp]
+ jle L$12
+ mov word ptr -1aH[bp],ax
+ mov word ptr -12H[bp],dx
+L$12:
+ mov ax,word ptr 2[bx]
+ cmp ax,word ptr -18H[bp]
+ jge L$13
+ mov word ptr -18H[bp],ax
+L$13:
+ cmp ax,word ptr -1eH[bp]
+ jle L$14
+ mov word ptr -1eH[bp],ax
+L$14:
+ inc di
+ inc dx
+ inc di
+ inc dx
+ dec cx
+ jne L$10
+ mov ax,word ptr -1aH[bp]
+ cmp ax,word ptr cs:MX_CLIPX1
+ jge L$15
+ jmp near ptr L$36
+L$15:
+ mov bx,word ptr -16H[bp]
+ cmp bx,word ptr cs:MX_CLIPX2
+ jle L$16
+ jmp near ptr L$36
+L$16:
+ sub ax,bx
+ jg L$17
+ jmp near ptr L$36
+L$17:
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jge L$18
+ jmp near ptr L$36
+L$18:
+ mov bx,word ptr -18H[bp]
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$19
+ jmp near ptr L$36
+L$19:
+ sub ax,bx
+ jg L$20
+ jmp near ptr L$36
+L$20:
+ dec word ptr 10H[bp]
+ shl word ptr 10H[bp],1
+ mov es,word ptr cs:MX_CODESEGMENT
+ mov ax,offset MX_TEXT:MX_SCANBUFFER
+ mov word ptr -4[bp],ax
+ mov si,word ptr -0eH[bp]
+L$21:
+ lds bx,dword ptr 0cH[bp]
+ mov di,word ptr [bx+si]
+ dec si
+ dec si
+ test si,si
+ jge L$22
+ mov si,word ptr 10H[bp]
+L$22:
+ mov word ptr -0eH[bp],si
+ mov si,word ptr [bx+si]
+ shl di,1
+ shl di,1
+ shl si,1
+ shl si,1
+ lds bx,dword ptr 8[bp]
+ add si,bx
+ add bx,di
+ mov di,word ptr -4[bp]
+ call near ptr L$1
+ mov word ptr -4[bp],di
+ mov si,word ptr -0eH[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$21
+ mov ax,offset MX_TEXT:MX_SCANBUFFER+2
+ mov word ptr -6[bp],ax
+ mov si,word ptr -10H[bp]
+L$23:
+ lds bx,dword ptr 0cH[bp]
+ mov di,word ptr [bx+si]
+ inc si
+ inc si
+ cmp si,word ptr 10H[bp]
+ jbe L$24
+ xor si,si
+L$24:
+ mov word ptr -10H[bp],si
+ mov si,word ptr [bx+si]
+ shl di,1
+ shl di,1
+ shl si,1
+ shl si,1
+ lds bx,dword ptr 8[bp]
+ add si,bx
+ add bx,di
+ mov di,word ptr -6[bp]
+ call near ptr L$1
+ mov word ptr -6[bp],di
+ mov si,word ptr -10H[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$23
+ mov si,offset MX_TEXT:MX_SCANBUFFER
+ mov ax,word ptr -16H[bp]
+ mov cx,word ptr -1aH[bp]
+ sub cx,ax
+ mov bx,word ptr cs:MX_CLIPX1
+ sub bx,ax
+ jle L$25
+ sub cx,bx
+ add ax,bx
+ mov word ptr -16H[bp],ax
+ shl bx,1
+ shl bx,1
+ add si,bx
+L$25:
+ mov bx,ax
+ add bx,cx
+ sub bx,word ptr cs:MX_CLIPX2
+ jle L$26
+ sub cx,bx
+L$26:
+ test cx,cx
+ jg L$27
+ jmp near ptr L$36
+L$27:
+ mov word ptr -8[bp],cx
+ mov word ptr -4[bp],si
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr -18H[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$28
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$28
+ jmp L$32
+L$28:
+ mov di,cx
+ inc di
+ sub si,4
+L$29:
+ dec di
+ je L$32
+ add si,4
+ mov ax,word ptr [si]
+ mov cx,word ptr 2[si]
+ mov dx,word ptr cs:MX_CLIPY2
+ cmp ax,dx
+ jg L$31
+ cmp cx,dx
+ jle L$30
+ mov word ptr 2[si],dx
+ mov bx,cx
+ sub bx,dx
+ sub cx,ax
+ jle L$31
+ mov cx,word ptr 2[si]
+L$30:
+ mov dx,word ptr cs:MX_CLIPY1
+ cmp cx,dx
+ jl L$31
+ sub cx,ax
+ jle L$31
+ cmp ax,dx
+ jge L$29
+ mov word ptr [si],dx
+ sub dx,ax
+ cmp cx,dx
+ ja L$29
+L$31:
+ mov word ptr [si],0ffffH
+ jmp L$29
+L$32:
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ mov si,word ptr -4[bp]
+ mov cl,byte ptr -16H[bp]
+ and cl,3
+ mov al,11H
+ shl al,cl
+ mov byte ptr -2[bp],al
+ shr word ptr -16H[bp],1
+ shr word ptr -16H[bp],1
+L$33:
+ mov ax,word ptr [si]
+ test ax,ax
+ js L$35
+ mov cx,word ptr 2[si]
+ sub cx,ax
+ jle L$35
+ mul word ptr cs:MX_BYTESPERLINE
+ add ax,word ptr -16H[bp]
+ mov di,ax
+ mov ah,byte ptr -2[bp]
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov ax,word ptr 6[bp]
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ shr cx,1
+ jae L$34
+ mov byte ptr es:[di],al
+ add di,dx
+ jcxz L$35
+L$34:
+ mov byte ptr es:[di],al
+ add di,dx
+ mov byte ptr es:[di],al
+ add di,dx
+ dec cx
+ jne L$34
+L$35:
+ rol byte ptr -2[bp],1
+ adc word ptr -16H[bp],0
+ add si,4
+ dec word ptr -8[bp]
+ jne L$33
+L$36:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGOURAUDPOLY
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MX_SCANBUFFER:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ mov cx,word ptr [si]
+ sub cx,word ptr [bx]
+ jg L$2
+ ret
+L$2:
+ push bp
+ push di
+ push cx
+ push ax
+ push dx
+ mov ax,word ptr 2[si]
+ mov bx,word ptr 2[bx]
+ sub ax,bx
+ jg L$4
+ jl L$6
+ mov ax,bx
+L$3:
+ mov word ptr es:[di],ax
+ add di,8
+ dec cx
+ jne L$3
+ jmp L$8
+L$4:
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$5:
+ mov word ptr es:[di],ax
+ add di,8
+ add dx,bx
+ adc ax,bp
+ dec cx
+ jne L$5
+ jmp L$8
+L$6:
+ neg ax
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$7:
+ mov word ptr es:[di],ax
+ add di,8
+ sub dx,bx
+ sbb ax,bp
+ dec cx
+ jne L$7
+L$8:
+ pop bx
+ pop ax
+ pop cx
+ pop di
+ sub ax,bx
+ jg L$10
+ jl L$12
+ mov ah,bl
+ mov al,80H
+L$9:
+ mov word ptr es:2[di],ax
+ add di,8
+ dec cx
+ jne L$9
+ jmp L$14
+L$10:
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$11:
+ mov byte ptr es:3[di],al
+ mov byte ptr es:2[di],dh
+ add di,8
+ add dx,bx
+ adc ax,bp
+ dec cx
+ jne L$11
+ jmp L$14
+L$12:
+ neg ax
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$13:
+ mov byte ptr es:3[di],al
+ mov byte ptr es:2[di],dh
+ add di,8
+ sub dx,bx
+ sbb ax,bp
+ dec cx
+ jne L$13
+L$14:
+ pop bp
+ ret
+L$15:
+ mov ax,word ptr 6[si]
+ mov bx,word ptr 2[si]
+ cmp ah,bh
+ jg L$17
+ jl L$19
+ add ax,dx
+ mov dx,word ptr cs:MX_BYTESPERLINE
+L$16:
+ mov byte ptr es:[di],ah
+ add di,dx
+ dec cx
+ jne L$16
+ ret
+L$17:
+ push bp
+ push si
+ mov si,bx
+ add si,dx
+ sub ax,bx
+ xor dx,dx
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ mov bx,ax
+ mov dx,8000H
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ xchg ax,si
+L$18:
+ mov byte ptr es:[di],ah
+ add dx,bx
+ adc ax,bp
+ add di,si
+ dec cx
+ jne L$18
+ pop si
+ pop bp
+ ret
+L$19:
+ push bp
+ push si
+ mov si,bx
+ add si,dx
+ sub ax,bx
+ neg ax
+ xor dx,dx
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ mov bx,ax
+ mov dx,8000H
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ xchg ax,si
+L$20:
+ mov byte ptr es:[di],ah
+ sub dx,bx
+ sbb ax,bp
+ add di,si
+ dec cx
+ jne L$20
+ pop si
+ pop bp
+ ret
+MXGOURAUDPOLY:
+ push bp
+ mov bp,sp
+ sub sp,1eH
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 14H[bp]
+ cmp cx,3
+ jae L$21
+ jmp near ptr L$47
+L$21:
+ les di,dword ptr 10H[bp]
+ lds si,dword ptr 0cH[bp]
+ mov word ptr -16H[bp],7fffH
+ mov word ptr -1aH[bp],8000H
+ mov word ptr -18H[bp],7fffH
+ mov word ptr -1eH[bp],8000H
+ xor dx,dx
+L$22:
+ mov bx,word ptr es:[di]
+ shl bx,1
+ shl bx,1
+ add bx,si
+ mov ax,word ptr [bx]
+ cmp ax,word ptr -16H[bp]
+ jge L$23
+ mov word ptr -16H[bp],ax
+ mov word ptr -0eH[bp],dx
+ mov word ptr -10H[bp],dx
+L$23:
+ cmp ax,word ptr -1aH[bp]
+ jle L$24
+ mov word ptr -1aH[bp],ax
+ mov word ptr -12H[bp],dx
+L$24:
+ mov ax,word ptr 2[bx]
+ cmp ax,word ptr -18H[bp]
+ jge L$25
+ mov word ptr -18H[bp],ax
+L$25:
+ cmp ax,word ptr -1eH[bp]
+ jle L$26
+ mov word ptr -1eH[bp],ax
+L$26:
+ inc di
+ inc di
+ inc dx
+ inc dx
+ dec cx
+ jne L$22
+ mov ax,word ptr -1aH[bp]
+ cmp ax,word ptr cs:MX_CLIPX1
+ jge L$27
+ jmp near ptr L$47
+L$27:
+ mov bx,word ptr -16H[bp]
+ cmp bx,word ptr cs:MX_CLIPX2
+ jle L$28
+ jmp near ptr L$47
+L$28:
+ sub ax,bx
+ jg L$29
+ jmp near ptr L$47
+L$29:
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jge L$30
+ jmp near ptr L$47
+L$30:
+ mov bx,word ptr -18H[bp]
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$31
+ jmp near ptr L$47
+L$31:
+ sub ax,bx
+ jg L$32
+ jmp near ptr L$47
+L$32:
+ dec word ptr 14H[bp]
+ shl word ptr 14H[bp],1
+ mov es,word ptr cs:MX_CODESEGMENT
+ mov ax,offset MX_TEXT:MX_SCANBUFFER
+ mov word ptr -4[bp],ax
+ mov si,word ptr -0eH[bp]
+L$33:
+ lds bx,dword ptr 10H[bp]
+ mov di,word ptr [bx+si]
+ dec si
+ dec si
+ test si,si
+ jge L$34
+ mov si,word ptr 14H[bp]
+L$34:
+ mov word ptr -0eH[bp],si
+ mov si,word ptr [bx+si]
+ lds bx,dword ptr 8[bp]
+ shl di,1
+ shl si,1
+ mov ax,word ptr [bx+si]
+ mov dx,word ptr [bx+di]
+ lds bx,dword ptr 0cH[bp]
+ shl si,1
+ shl di,1
+ add si,bx
+ add bx,di
+ mov di,word ptr -4[bp]
+ call near ptr L$1
+ mov word ptr -4[bp],di
+ mov si,word ptr -0eH[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$33
+ mov ax,offset MX_TEXT:MX_SCANBUFFER+4
+ mov word ptr -6[bp],ax
+ mov si,word ptr -10H[bp]
+L$35:
+ lds bx,dword ptr 10H[bp]
+ mov di,word ptr [bx+si]
+ inc si
+ inc si
+ cmp si,word ptr 14H[bp]
+ jbe L$36
+ xor si,si
+L$36:
+ mov word ptr -10H[bp],si
+ mov si,word ptr [bx+si]
+ lds bx,dword ptr 8[bp]
+ shl di,1
+ shl si,1
+ mov ax,word ptr [bx+si]
+ mov dx,word ptr [bx+di]
+ lds bx,dword ptr 0cH[bp]
+ shl si,1
+ shl di,1
+ add si,bx
+ add bx,di
+ mov di,word ptr -6[bp]
+ call near ptr L$1
+ mov word ptr -6[bp],di
+ mov si,word ptr -10H[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$35
+ mov si,offset MX_TEXT:MX_SCANBUFFER
+ mov ax,word ptr -16H[bp]
+ mov cx,word ptr -1aH[bp]
+ sub cx,ax
+ mov bx,word ptr cs:MX_CLIPX1
+ sub bx,ax
+ jle L$37
+ sub cx,bx
+ add ax,bx
+ mov word ptr -16H[bp],ax
+ shl bx,1
+ shl bx,1
+ shl bx,1
+ add si,bx
+L$37:
+ mov bx,ax
+ add bx,cx
+ sub bx,word ptr cs:MX_CLIPX2
+ jle L$38
+ sub cx,bx
+L$38:
+ test cx,cx
+ jg L$39
+ jmp near ptr L$47
+L$39:
+ mov word ptr -8[bp],cx
+ mov word ptr -4[bp],si
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr -18H[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$40
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$40
+ jmp L$44
+L$40:
+ mov di,cx
+ inc di
+ sub si,8
+L$41:
+ dec di
+ je L$44
+ add si,8
+ mov ax,word ptr [si]
+ mov cx,word ptr 4[si]
+ mov dx,word ptr cs:MX_CLIPY2
+ cmp ax,dx
+ jg L$43
+ cmp cx,dx
+ jle L$42
+ mov word ptr 4[si],dx
+ mov bx,cx
+ sub bx,dx
+ sub cx,ax
+ jle L$43
+ mov ax,word ptr 2[si]
+ sub ax,word ptr 6[si]
+ imul bx
+ idiv cx
+ add word ptr 6[si],ax
+ mov ax,word ptr [si]
+ mov cx,word ptr 4[si]
+L$42:
+ mov dx,word ptr cs:MX_CLIPY1
+ cmp cx,dx
+ jl L$43
+ sub cx,ax
+ jle L$43
+ cmp ax,dx
+ jge L$41
+ mov word ptr [si],dx
+ sub dx,ax
+ cmp cx,dx
+ jbe L$43
+ mov ax,word ptr 6[si]
+ sub ax,word ptr 2[si]
+ imul dx
+ idiv cx
+ add word ptr 2[si],ax
+ jmp L$41
+L$43:
+ mov word ptr [si],0ffffH
+ jmp L$41
+L$44:
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ mov si,word ptr -4[bp]
+ mov cl,byte ptr -16H[bp]
+ and cl,3
+ mov al,11H
+ shl al,cl
+ mov byte ptr -2[bp],al
+ shr word ptr -16H[bp],1
+ shr word ptr -16H[bp],1
+ mov ax,word ptr 6[bp]
+ mov ah,al
+ xor al,al
+ mov word ptr 6[bp],ax
+L$45:
+ mov ax,word ptr [si]
+ test ax,ax
+ js L$46
+ mov cx,word ptr 4[si]
+ sub cx,ax
+ jle L$46
+ mul word ptr cs:MX_BYTESPERLINE
+ add ax,word ptr -16H[bp]
+ mov di,ax
+ mov ah,byte ptr -2[bp]
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov dx,word ptr 6[bp]
+ call near ptr L$15
+L$46:
+ rol byte ptr -2[bp],1
+ adc word ptr -16H[bp],0
+ add si,8
+ dec word ptr -8[bp]
+ jne L$45
+L$47:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 10H
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXPUTIMAGE
+ EXTRN SUBCLIPIMAGE:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ DW offset L$2
+ DW offset L$6
+ DW offset L$10
+ DW offset L$14
+ DW offset L$18
+ DW offset L$20
+L$2:
+ shr cx,1
+ jb L$5
+L$3:
+ movsb
+ add si,3
+ movsb
+ add si,3
+ dec cx
+ jne L$3
+L$4:
+ ret
+L$5:
+ movsb
+ add si,3
+ jcxz L$4
+ jmp L$3
+L$6:
+ shr cx,1
+ jb L$9
+L$7:
+ mov al,byte ptr [si]
+ mov ah,byte ptr 4[si]
+ and word ptr es:[di],ax
+ inc di
+ inc di
+ add si,8
+ dec cx
+ jne L$7
+L$8:
+ ret
+L$9:
+ lodsb
+ and byte ptr es:[di],al
+ inc di
+ add si,3
+ jcxz L$8
+ jmp L$7
+L$10:
+ shr cx,1
+ jb L$13
+L$11:
+ mov al,byte ptr [si]
+ mov ah,byte ptr 4[si]
+ or word ptr es:[di],ax
+ inc di
+ inc di
+ add si,8
+ dec cx
+ jne L$11
+L$12:
+ ret
+L$13:
+ lodsb
+ or byte ptr es:[di],al
+ inc di
+ add si,3
+ jcxz L$12
+ jmp L$11
+L$14:
+ shr cx,1
+ jb L$17
+L$15:
+ mov al,byte ptr [si]
+ mov ah,byte ptr 4[si]
+ xor word ptr es:[di],ax
+ inc di
+ inc di
+ add si,8
+ dec cx
+ jne L$15
+L$16:
+ ret
+L$17:
+ lodsb
+ xor byte ptr es:[di],al
+ inc di
+ add si,3
+ jcxz L$16
+ jmp L$15
+L$18:
+ mov al,byte ptr [si]
+ cmp al,ah
+ je L$19
+ mov byte ptr es:[di],al
+L$19:
+ inc di
+ add si,4
+ dec cx
+ jne L$18
+ ret
+L$20:
+ mov al,byte ptr [si]
+ add byte ptr es:[di],al
+ inc di
+ add si,4
+ dec cx
+ jne L$20
+ ret
+MXPUTIMAGE:
+ push bp
+ mov bp,sp
+ sub sp,14H
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 0eH[bp]
+ mov ax,word ptr 0cH[bp]
+ mov cx,word ptr 0aH[bp]
+ mov dx,word ptr 8[bp]
+ call near ptr MX_TEXT:SUBCLIPIMAGE
+ jae L$21
+ jmp near ptr L$26
+L$21:
+ mov word ptr 8[bp],dx
+ add word ptr 10H[bp],si
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,bx
+ shr di,1
+ shr di,1
+ add di,ax
+ mov word ptr -0aH[bp],di
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ and bl,3
+ mov byte ptr -10H[bp],bl
+ mov bx,cx
+ shr bx,1
+ shr bx,1
+ and cl,3
+ mov al,8
+ shr al,cl
+ mov si,6
+L$22:
+ mov word ptr -8[bp+si],bx
+ shr al,1
+ adc bx,0
+ dec si
+ dec si
+ jge L$22
+ mov cl,byte ptr -10H[bp]
+ mov al,11H
+ shl al,cl
+ mov byte ptr -14H[bp],al
+ mov bx,word ptr 6[bp]
+ mov byte ptr -12H[bp],bh
+ xor bh,bh
+ cmp bl,5
+ jbe L$23
+ xor bl,bl
+L$23:
+ shl bx,1
+ mov ax,word ptr cs:L$1[bx]
+ mov word ptr -0cH[bp],ax
+ cld
+ mov byte ptr -0eH[bp],4
+ lea bx,-8[bp]
+ mov ds,word ptr 12H[bp]
+L$24:
+ cmp word ptr ss:[bx],0
+ je L$26
+ mov si,word ptr 10H[bp]
+ mov ah,byte ptr -14H[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov ah,byte ptr -10H[bp]
+ and ah,3
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov dx,word ptr 8[bp]
+ mov di,word ptr -0aH[bp]
+L$25:
+ push si
+ push di
+ mov cx,word ptr ss:[bx]
+ mov ah,byte ptr -12H[bp]
+ call word ptr -0cH[bp]
+ pop di
+ pop si
+ add si,word ptr 0aH[bp]
+ add di,word ptr cs:MX_BYTESPERLINE
+ dec dx
+ jne L$25
+ inc bx
+ inc bx
+ inc byte ptr -10H[bp]
+ rol byte ptr -14H[bp],1
+ adc word ptr -0aH[bp],0
+ inc word ptr 10H[bp]
+ dec byte ptr -0eH[bp]
+ jne L$24
+L$26:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0eH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXPAN
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MXWAITDISPLAY:BYTE
+ EXTRN MXSTARTADDRESS:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPAN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ax,word ptr 6[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov dx,word ptr 8[bp]
+ shr dx,1
+ shr dx,1
+ add ax,dx
+ push ax
+ call far ptr MXWAITDISPLAY
+ call far ptr MXSTARTADDRESS
+ mov dx,3daH
+ in al,dx
+ mov dx,3c0H
+ mov al,33H
+ out dx,al
+ mov al,byte ptr 8[bp]
+ and al,3
+ shl al,1
+ out dx,al
+ xor ax,ax
+ mov sp,bp
+ pop bp
+ retf 4
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXGETPIXEL
+ PUBLIC MXPUTPIXEL
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPIXEL:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ xor ax,ax
+ mov si,word ptr 8[bp]
+ cmp si,word ptr cs:MX_CLIPX1
+ jl L$1
+ cmp si,word ptr cs:MX_CLIPX2
+ jg L$1
+ mov bx,word ptr 6[bp]
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$1
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$1
+ mov al,4
+ mov ah,byte ptr 8[bp]
+ and ah,3
+ mov dx,3ceH
+ out dx,ax
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+ mov ax,bx
+ mul word ptr cs:MX_BYTESPERLINE
+ shr si,1
+ shr si,1
+ add si,ax
+ mov al,byte ptr [si]
+ xor ah,ah
+L$1:
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXPUTPIXEL:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov si,word ptr 0aH[bp]
+ cmp si,word ptr cs:MX_CLIPX1
+ jl L$2
+ cmp si,word ptr cs:MX_CLIPX2
+ jg L$2
+ mov ax,word ptr 8[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$2
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$2
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+ mul word ptr cs:MX_BYTESPERLINE
+ shr si,1
+ shr si,1
+ add si,ax
+ mov cl,byte ptr 0aH[bp]
+ and cl,3
+ mov ax,102H
+ shl ah,cl
+ mov dx,3c4H
+ out dx,ax
+ mov al,byte ptr 6[bp]
+ mov byte ptr [si],al
+L$2:
+ xor ax,ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 6
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXROWADDRESS
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROWADDRESS:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov dx,3d4H
+ mov al,13H
+ mov ah,byte ptr 6[bp]
+ out dx,ax
+ xor ax,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXROTATEPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROTATEPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,300H
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 8[bp]
+ add bx,bx
+ add bx,word ptr 8[bp]
+ lds si,dword ptr 0aH[bp]
+ push ss
+ pop es
+ lea di,-300H[bp]
+ cld
+ mov ax,word ptr 6[bp]
+ mov dx,ax
+ test ax,ax
+ je L$2
+ jl L$1
+ add ax,ax
+ add dx,ax
+ sub bx,dx
+ add si,bx
+ push si
+ mov cx,dx
+ rep movsb
+ mov es,word ptr 0cH[bp]
+ mov di,si
+ dec di
+ pop si
+ dec si
+ mov cx,bx
+ std
+ rep movsb
+ push ss
+ pop ds
+ lea si,-300H[bp]
+ les di,dword ptr 0aH[bp]
+ mov cx,dx
+ cld
+ rep movsb
+ jmp L$2
+L$1:
+ add ax,ax
+ add dx,ax
+ neg dx
+ sub bx,dx
+ mov cx,dx
+ rep movsb
+ les di,dword ptr 0aH[bp]
+ mov cx,bx
+ rep movsb
+ push ss
+ pop ds
+ lea si,-300H[bp]
+ mov cx,dx
+ rep movsb
+L$2:
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSTARTADDRESS
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTADDRESS:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov bx,word ptr 6[bp]
+ mov dx,3d4H
+ mov al,0cH
+ mov ah,bh
+ cli
+ out dx,ax
+ mov al,0dH
+ mov ah,bl
+ out dx,ax
+ sti
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSETCOLOR
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETCOLOR:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr 0cH[bp]
+ mov dx,3c8H
+ out dx,al
+ inc dx
+ mov al,byte ptr 0aH[bp]
+ out dx,al
+ mov al,byte ptr 8[bp]
+ out dx,al
+ mov al,byte ptr 6[bp]
+ out dx,al
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSTRETCHIMAGE
+ EXTRN SUBCLIPBOX:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ DW offset L$8
+ DW offset L$10
+ DW offset L$12
+ DW offset L$14
+ DW offset L$16
+ DW offset L$19
+MXSTRETCHIMAGE:
+ push bp
+ mov bp,sp
+ sub sp,14H
+ push ds
+ push si
+ push es
+ push di
+ xor dx,dx
+ mov ax,word ptr 0eH[bp]
+ mov bx,word ptr 0aH[bp]
+ div bx
+ mov word ptr -0aH[bp],ax
+ xor ax,ax
+ div bx
+ mov word ptr -0cH[bp],ax
+ xor dx,dx
+ mov ax,word ptr 0cH[bp]
+ mov bx,word ptr 8[bp]
+ div bx
+ mov word ptr -0eH[bp],ax
+ xor ax,ax
+ div bx
+ mov word ptr -10H[bp],ax
+ mov bx,word ptr 12H[bp]
+ mov ax,word ptr 10H[bp]
+ mov cx,word ptr 0aH[bp]
+ mov dx,word ptr 8[bp]
+ call near ptr MX_TEXT:SUBCLIPBOX
+ jae L$2
+ jmp near ptr L$7
+L$2:
+ mov word ptr 0aH[bp],cx
+ mov word ptr 8[bp],dx
+ sub word ptr 12H[bp],bx
+ sub word ptr 10H[bp],ax
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,bx
+ shr di,1
+ shr di,1
+ add di,ax
+ mov word ptr -2[bp],di
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ and bl,3
+ mov byte ptr -6[bp],bl
+ mov cl,bl
+ mov al,11H
+ shl al,cl
+ mov byte ptr -14H[bp],al
+ mov ax,word ptr 10H[bp]
+ test ax,ax
+ je L$3
+ mov bx,ax
+ mul word ptr -10H[bp]
+ mov cx,dx
+ mov ax,bx
+ mul word ptr -0eH[bp]
+ add ax,cx
+ mul word ptr 0eH[bp]
+ add word ptr 14H[bp],ax
+L$3:
+ mov ax,word ptr 12H[bp]
+ test ax,ax
+ je L$4
+ mov bx,ax
+ mul word ptr -0cH[bp]
+ mov cx,dx
+ mov ax,bx
+ mul word ptr -0aH[bp]
+ add ax,cx
+ add word ptr 14H[bp],ax
+L$4:
+ mov ax,word ptr -0eH[bp]
+ mul word ptr 0eH[bp]
+ mov word ptr -0eH[bp],ax
+ mov bx,word ptr 6[bp]
+ mov byte ptr -8[bp],bh
+ xor bh,bh
+ cmp bl,5
+ jbe L$5
+ xor bl,bl
+L$5:
+ shl bx,1
+ mov ax,word ptr cs:L$1[bx]
+ mov word ptr -4[bp],ax
+ mov ds,word ptr 16H[bp]
+ xor ax,ax
+ mov word ptr -12H[bp],ax
+L$6:
+ mov si,word ptr 14H[bp]
+ mov ah,byte ptr -14H[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov ah,byte ptr -6[bp]
+ and ah,3
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov cx,word ptr 8[bp]
+ mov di,word ptr -2[bp]
+ mov ah,byte ptr -8[bp]
+ xor bx,bx
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ call word ptr -4[bp]
+ inc byte ptr -6[bp]
+ rol byte ptr -14H[bp],1
+ adc word ptr -2[bp],0
+ mov dx,word ptr -0cH[bp]
+ mov ax,word ptr -0aH[bp]
+ add word ptr -12H[bp],dx
+ adc word ptr 14H[bp],ax
+ dec word ptr 0aH[bp]
+ jne L$6
+L$7:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 12H
+L$8:
+ mov al,byte ptr [si]
+ mov byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$9
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$8
+ add si,word ptr 0eH[bp]
+ jmp L$8
+L$9:
+ ret
+L$10:
+ mov al,byte ptr [si]
+ and byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$11
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$10
+ add si,word ptr 0eH[bp]
+ jmp L$10
+L$11:
+ ret
+L$12:
+ mov al,byte ptr [si]
+ or byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$13
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$12
+ add si,word ptr 0eH[bp]
+ jmp L$12
+L$13:
+ ret
+L$14:
+ mov al,byte ptr [si]
+ xor byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$15
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$14
+ add si,word ptr 0eH[bp]
+ jmp L$14
+L$15:
+ ret
+L$16:
+ mov al,byte ptr [si]
+ cmp al,ah
+ je L$17
+ mov byte ptr es:[di],al
+L$17:
+ add di,dx
+ dec cx
+ je L$18
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$16
+ add si,word ptr 0eH[bp]
+ jmp L$16
+L$18:
+ ret
+L$19:
+ mov al,byte ptr [si]
+ add byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$20
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$19
+ add si,word ptr 0eH[bp]
+ jmp L$19
+L$20:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSTARTLINE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTLINE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ax,word ptr 6[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ xchg ax,bx
+ mov dx,3daH
+L$1:
+ in al,dx
+ test al,8
+ jne L$1
+ mov dx,3d4H
+ mov al,0cH
+ mov ah,bh
+ cli
+ out dx,ax
+ mov al,0dH
+ mov ah,bl
+ out dx,ax
+ sti
+ mov dx,3daH
+L$2:
+ in al,dx
+ test al,8
+ je L$2
+ xor ax,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MX_SCREENWIDTH
+ PUBLIC MX_SCREENHEIGHT
+ PUBLIC MX_BYTESPERLINE
+ PUBLIC MXSETMODE
+ PUBLIC MXCHANGEMODE
+ PUBLIC MXGETASPECT
+ PUBLIC MXGETSCREENSIZE
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MXSETSYSCLIPREGION:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCREENWIDTH:
+ add byte ptr [bx+si],al
+MX_SCREENHEIGHT:
+ add byte ptr [bx+si],al
+L$1:
+ add byte ptr [bx+si],al
+L$2:
+ add byte ptr [bx+si],al
+MX_BYTESPERLINE:
+ add byte ptr [bx+si],al
+L$3:
+ or word ptr 14H[bx+si],ax
+ add byte ptr [bx],dl
+ jcxz L$4
+L$4:
+ DB 0
+L$5:
+ or word ptr 14H[bx+di],ax
+ add byte ptr [bx],dl
+ jcxz L$6
+L$6:
+ DB 0
+L$7:
+ add byte ptr 1[bx],bl
+ dec di
+ add dl,byte ptr 3[bx+si]
+ add byte ptr [si],54H
+ add ax,1380H
+ sub byte ptr [bx+si],al
+ DB 0
+L$8:
+ add byte ptr 1[bp+di],ch
+ pop cx
+ add bl,byte ptr 3[bp+si]
+ mov es,word ptr [si]
+ pop si
+ add ax,138aH
+ sub ax,0
+ push es
+ mov di,1f07H
+ adc byte ptr -7aefH[bp+di],al
+ adc bl,byte ptr 15H[di]
+ arpl word ptr ds:[0baH],dx
+ DB 0
+L$9:
+ push es
+ DD ds:[7bfH]
+ pushf
+ adc word ptr -70eeH[bp],cx
+ adc ax,1696H
+ mov cx,0
+L$10:
+ push es
+ or ax,3e07H
+ adc dl,ch
+ adc word ptr -20eeH[si],cx
+ adc ax,16e7H
+ push es
+ add byte ptr [bx+si],al
+L$11:
+ add byte ptr 1[si],dh
+ arpl word ptr [bp+si],ax
+ add dx,word ptr fs:6804H[bx]
+ add ax,695H
+ xchg byte ptr [bx],al
+ lock or word ptr 0fH[bx+si],sp
+ xor word ptr [bx+si],dx
+ pop bx
+ adc word ptr 5712H[di],cx
+ adc si,word ptr [bp+si]
+ adc al,0
+ adc ax,1660H
+ adc byte ptr [bx],0e3H
+ add byte ptr [bx+si],al
+L$12:
+ arpl word ptr ds:[500H],ax
+ add byte ptr 1[bx+si],al
+ enter 1a00H,0
+ DW offset L$9
+ DW offset L$5
+ add byte ptr [bx+si],al
+ xor ax,word ptr [bp+di]
+L$13:
+ jcxz L$14
+ DB 0
+L$14:
+ add word ptr [bx+si],ax
+ inc ax
+ add ax,si
+ add byte ptr [bp+si],bl
+ add byte ptr [bp+si],bl
+ DW offset L$5
+ add byte ptr [bx+si],al
+ xor ax,word ptr [bp+di]
+L$15:
+ arpl word ptr ds:[0a00H],ax
+ add byte ptr 1[bx+si],al
+ nop
+ add word ptr [bp+si],bx
+ add byte ptr [bp+si],cl
+ DW offset L$3
+ add byte ptr [bx+si],al
+ xor ax,word ptr [bp+di]
+L$16:
+ jcxz L$17
+ DB 0
+L$17:
+ add al,byte ptr [bx+si]
+ inc ax
+ add ax,sp
+ DD L$18
+L$18:
+ add byte ptr [bp+si],cl
+ add byte ptr [bx+si],al
+ add byte ptr [bp+di],dh
+ DB 3
+L$19:
+ sbb ax,word ptr [eax]
+ adc al,0
+ push 0c801H
+ add byte ptr [bp+si],ch
+ add byte ptr [bp+si],cl
+ DW offset L$5
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$20:
+ out 9,ax
+ add byte ptr [bx+si],cl
+ add byte ptr 1[bx+si],ch
+ lock add byte ptr [bp+si],ch
+ add byte ptr [bp+si],bl
+ DW offset L$5
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$21:
+ sbb ax,word ptr [eax]
+ sub byte ptr [bx+si],al
+ push 9001H
+ add word ptr [bp+si],bp
+ add byte ptr [bp+si],cl
+ DW offset L$3
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$22:
+ out 9,ax
+ add byte ptr [bx+si],dl
+ add byte ptr 1[bx+si],ch
+ loopnz L$23
+ DW offset L$8
+L$23 equ $-1
+ DW offset L$10
+ DW offset L$3
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$24:
+ mov word ptr ds:[0],ax
+ add byte ptr [bx+si],al
+ inc ax
+ add word ptr 1a00H[bx],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],dl
+ add byte ptr [bx+si],al
+ add byte ptr [bp+di],dh
+ DB 3
+L$25:
+ mov word ptr 0,ax
+ add byte ptr [bx+si],al
+ inc ax
+ add word ptr 1a00H[bx],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],cl
+ add byte ptr [bx+si],al
+ add byte ptr [bp+di],dh
+ DB 3
+L$26:
+ cmpsw
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ push 0e001H
+ add word ptr [bp+si],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],dl
+ add byte ptr [bx+si],al
+ add al,bl
+ DB 2
+L$27:
+ cmpsw
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ push 0e001H
+ add word ptr [bp+si],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],cl
+ add byte ptr [bx+si],al
+ add al,bl
+ DB 2
+L$28:
+ out 1,ax
+ add byte ptr [bp+si],al
+ add byte ptr 5801H[bx+si],dl
+ add ch,byte ptr [bp+si]
+ add byte ptr [bx+si],al
+ pop word ptr [bp+si]
+L$29:
+ DW offset L$24
+ DW offset L$12
+ DW offset L$13
+ DW offset L$25
+ DW offset L$15
+ DW offset L$16
+ DW offset L$26
+ DW offset L$19
+ DW offset L$20
+ DW offset L$27
+ DW offset L$21
+ DW offset L$22
+ DW offset L$28
+L$30:
+ mov ax,3
+ int 10H
+ mov word ptr MX_SCREENHEIGHT,0
+ mov word ptr MX_BYTESPERLINE,0
+ ret
+MXSETMODE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov si,word ptr 6[bp]
+ cmp si,0dH
+ jbe L$31
+ jmp near ptr L$36
+L$31:
+ test si,si
+ jne L$32
+ call near ptr L$30
+ jmp near ptr L$36
+L$32:
+ dec si
+ shl si,1
+ mov si,word ptr L$29[si]
+ cld
+ push si
+ mov ax,13H
+ int 10H
+ pop si
+ mov dx,3c4H
+ mov ax,604H
+ out dx,ax
+ mov ax,100H
+ out dx,ax
+ mov dx,3c2H
+ lodsb
+ out dx,al
+ mov dx,3c4H
+ mov ax,300H
+ out dx,ax
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ and al,7fH
+ out dx,al
+ lodsw
+ mov word ptr L$1,ax
+ lodsw
+ mov word ptr L$2,ax
+ lodsw
+ mov word ptr MX_SCREENWIDTH,ax
+ shr ax,1
+ shr ax,1
+ mov word ptr MX_BYTESPERLINE,ax
+ lodsw
+ mov word ptr MX_SCREENHEIGHT,ax
+ mov bx,si
+ mov dx,3d4H
+L$33:
+ mov si,word ptr [bx]
+ inc bx
+ inc bx
+ test si,si
+ je L$35
+L$34:
+ lodsw
+ test ax,ax
+ je L$33
+ out dx,ax
+ jmp L$34
+L$35:
+ push word ptr MX_SCREENWIDTH
+ push word ptr [bx]
+ push cs
+ call near ptr MX_TEXT:MXSETSYSCLIPREGION
+ mov dx,3c4H
+ mov ax,0f02H
+ out dx,ax
+ mov es,word ptr MX_TEXT:MX_VIDEOSEGMENT
+ xor di,di
+ mov cx,8000H
+ xor ax,ax
+ rep stosw
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ or al,80H
+ out dx,al
+L$36:
+ xor ax,ax
+ mov ax,word ptr MX_SCREENWIDTH
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 2
+MXCHANGEMODE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov si,word ptr 6[bp]
+ cmp si,0dH
+ ja L$40
+ test si,si
+ je L$40
+ dec si
+ shl si,1
+ mov si,word ptr L$29[si]
+ cld
+ mov dx,3c4H
+ mov ax,604H
+ out dx,ax
+ mov ax,100H
+ out dx,ax
+ mov dx,3c2H
+ lodsb
+ out dx,al
+ mov dx,3c4H
+ mov ax,300H
+ out dx,ax
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ and al,7fH
+ out dx,al
+ lodsw
+ mov word ptr L$1,ax
+ lodsw
+ mov word ptr L$2,ax
+ lodsw
+ mov word ptr MX_SCREENWIDTH,ax
+ lodsw
+ mov word ptr MX_SCREENHEIGHT,ax
+ mov bx,si
+ mov dx,3d4H
+L$37:
+ mov si,word ptr [bx]
+ inc bx
+ inc bx
+ test si,si
+ je L$39
+L$38:
+ lodsw
+ test ax,ax
+ je L$37
+ cmp al,13H
+ je L$38
+ out dx,ax
+ jmp L$38
+L$39:
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ or al,80H
+ out dx,al
+L$40:
+ xor ax,ax
+ mov ax,word ptr MX_SCREENWIDTH
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 2
+MXGETASPECT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 0aH[bp]
+ mov ax,word ptr cs:L$1
+ mov word ptr [si],ax
+ lds si,dword ptr 6[bp]
+ mov ax,word ptr cs:L$2
+ mov word ptr [si],ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MXGETSCREENSIZE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 0aH[bp]
+ mov ax,word ptr cs:MX_SCREENWIDTH
+ mov word ptr [si],ax
+ lds si,dword ptr 6[bp]
+ mov ax,word ptr cs:MX_SCREENHEIGHT
+ mov word ptr [si],ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSETPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 0aH[bp]
+ mov cx,word ptr 6[bp]
+ mov ax,word ptr 8[bp]
+ mov dx,3c8H
+ out dx,al
+ inc dx
+ cld
+ cli
+L$1:
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ loop L$1
+ sti
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSPLITSCREEN
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSPLITSCREEN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ax,word ptr 6[bp]
+ shl ax,1
+ mov bh,ah
+ mov bl,ah
+ and bx,201H
+ mov cl,4
+ shl bx,cl
+ shl bh,1
+ mov dx,3d4H
+ mov ah,al
+ mov al,18H
+ out dx,ax
+ mov al,7
+ out dx,al
+ inc dx
+ in al,dx
+ dec dx
+ mov ah,al
+ and ah,0efH
+ or ah,bl
+ mov al,7
+ out dx,ax
+ mov al,9
+ out dx,al
+ inc dx
+ in al,dx
+ dec dx
+ mov ah,al
+ and ah,0bfH
+ or ah,bh
+ mov al,9
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXPUTTILE
+ PUBLIC MXTRANSPUTTILE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPUTTILE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ax,word ptr 0aH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,word ptr 0cH[bp]
+ shr di,1
+ shr di,1
+ add di,ax
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ lds si,dword ptr 0eH[bp]
+ shr word ptr 8[bp],1
+ shr word ptr 8[bp],1
+ mov cl,byte ptr 0cH[bp]
+ and cl,3
+ mov ah,11H
+ shl ah,cl
+ mov word ptr 0aH[bp],4
+ mov bx,word ptr cs:MX_BYTESPERLINE
+ sub bx,word ptr 8[bp]
+L$1:
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov word ptr 0cH[bp],di
+ mov dx,word ptr 6[bp]
+L$2:
+ mov cx,word ptr 8[bp]
+ shr cx,1
+ rep movsw
+ rcl cx,1
+ rep movsb
+ add di,bx
+ dec dx
+ jne L$2
+ mov di,word ptr 0cH[bp]
+ rol ah,1
+ adc di,0
+ dec word ptr 0aH[bp]
+ jne L$1
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MXTRANSPUTTILE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ax,word ptr 0aH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,word ptr 0cH[bp]
+ shr di,1
+ shr di,1
+ add di,ax
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ lds si,dword ptr 0eH[bp]
+ shr word ptr 8[bp],1
+ shr word ptr 8[bp],1
+ mov cl,byte ptr 0cH[bp]
+ and cl,3
+ mov ah,11H
+ shl ah,cl
+ mov word ptr 0aH[bp],4
+ mov bx,word ptr cs:MX_BYTESPERLINE
+ sub bx,word ptr 8[bp]
+L$3:
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov word ptr 0cH[bp],di
+ mov dx,word ptr 6[bp]
+L$4:
+ mov cx,word ptr 8[bp]
+ jcxz L$7
+L$5:
+ mov al,byte ptr [si]
+ test al,al
+ je L$6
+ mov byte ptr es:[di],al
+L$6:
+ inc si
+ inc di
+ dec cx
+ jne L$5
+L$7:
+ add di,bx
+ dec dx
+ jne L$4
+ mov di,word ptr 0cH[bp]
+ rol ah,1
+ adc di,0
+ dec word ptr 0aH[bp]
+ jne L$3
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXSETVIRTUALSCREEN
+ PUBLIC MXGETVIRTUALSCREEN
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MXROWADDRESS:BYTE
+ EXTRN MXSETSYSCLIPREGION:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bx+si],al
+L$2:
+ add byte ptr [bx+si],al
+MXSETVIRTUALSCREEN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,1
+ cmp word ptr 8[bp],140H
+ jb L$3
+ push ax
+ mov dx,4
+ xor ax,ax
+ div word ptr 8[bp]
+ cmp word ptr 6[bp],ax
+ pop ax
+ ja L$3
+ mov ax,word ptr 8[bp]
+ and ax,0fff8H
+ mov word ptr L$1,ax
+ shr ax,1
+ shr ax,1
+ mov word ptr MX_TEXT:MX_BYTESPERLINE,ax
+ shr ax,1
+ push ax
+ call far ptr MXROWADDRESS
+ mov ax,word ptr 6[bp]
+ mov word ptr L$2,ax
+ push word ptr 8[bp]
+ push word ptr 6[bp]
+ call far ptr MXSETSYSCLIPREGION
+ xor ax,ax
+L$3:
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXGETVIRTUALSCREEN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr cs:L$1
+ lds si,dword ptr 0aH[bp]
+ mov word ptr [si],ax
+ mov ax,word ptr cs:L$2
+ lds si,dword ptr 6[bp]
+ mov word ptr [si],ax
+ xor ax,ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXWAITDISPLAY
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITDISPLAY:
+ mov dx,3daH
+L$1:
+ in al,dx
+ test al,8
+ jne L$1
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXWRITEMODE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEMODE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov dx,3ceH
+ mov ah,byte ptr 6[bp]
+ and ah,3
+ or ah,40H
+ mov al,5
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXWRITEPLANE
+ PUBLIC MXREADPLANE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEPLANE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ah,byte ptr 6[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MXREADPLANE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov al,4
+ mov ah,byte ptr 6[bp]
+ and ah,3
+ mov dx,3ceH
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+ PUBLIC MXWAITRETRACE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITRETRACE:
+ mov dx,3daH
+L$1:
+ in al,dx
+ test al,8
+ je L$1
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+@echo off\r
+wdis -a MXBB.OBJ > mxbb.asm\r
+wdis -a MXCC.OBJ > mxcc.asm\r
+wdis -a MXCG.OBJ > mxcg.asm\r
+wdis -a MXCL.OBJ > mxcl.asm\r
+wdis -a MXCR.OBJ > mxcl.asm\r
+wdis -a MXFB.OBJ > mxfb.asm\r
+wdis -a MXFP.OBJ > mxfp.asm\r
+wdis -a MXGC.OBJ > mxgc.asm\r
+wdis -a MXGI.OBJ > mxgi.asm\r
+wdis -a MXGM.OBJ > mxgm.asm\r
+wdis -a MXGP.OBJ > mxgp.asm\r
+wdis -a MXGV.OBJ > mxgv.asm\r
+wdis -a MXHL.OBJ > mxhl.asm\r
+wdis -a MXIT.OBJ > mxit.asm\r
+wdis -a MXLL.OBJ > mxll.asm\r
+wdis -a MXLN.OBJ > mxln.asm\r
+wdis -a MXOT.OBJ > mxot.asm\r
+wdis -a MXPB.OBJ > mxpb.asm\r
+wdis -a MXPF.OBJ > mxpf.asm\r
+wdis -a MXPG.OBJ > mxpg.asm\r
+wdis -a MXPI.OBJ > mxpi.asm\r
+wdis -a MXPN.OBJ > mxpn.asm\r
+wdis -a MXPP.OBJ > mxpp.asm\r
+wdis -a MXRA.OBJ > mxra.asm\r
+wdis -a MXRP.OBJ > mxrp.asm\r
+wdis -a MXSA.OBJ > mxsa.asm\r
+wdis -a MXSC.OBJ > mxsc.asm\r
+wdis -a MXSI.OBJ > mxsi.asm\r
+wdis -a MXSL.OBJ > mxsl.asm\r
+wdis -a MXSM.OBJ > mxsm.asm\r
+wdis -a MXSP.OBJ > mxsp.asm\r
+wdis -a MXSS.OBJ > mxss.asm\r
+wdis -a MXTL.OBJ > mxtl.asm\r
+wdis -a MXVS.OBJ > mxvs.asm\r
+wdis -a MXWD.OBJ > mxwd.asm\r
+wdis -a MXWM.OBJ > mxwm.asm\r
+wdis -a MXWP.OBJ > mxwp.asm\r
+wdis -a MXWR.OBJ > mxwr.asm\r
--- /dev/null
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0\r
+ DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1\r
+ DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2\r
+ DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3\r
+ DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4\r
+ DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5\r
+ DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6\r
+ DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7\r
+ DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8\r
+ DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9\r
+ DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10\r
+ DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11\r
+ DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12\r
+ DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13\r
+ DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14\r
+ DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15\r
+ DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16\r
+ DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17\r
+ DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18\r
+ DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19\r
+ DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20\r
+ DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21\r
+ DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22\r
+ DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23\r
+ DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24\r
+ DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25\r
+ DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26\r
+ DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27\r
+ DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28\r
+ DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29\r
+ DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30\r
+ DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; \r
+ DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; !\r
+ DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; "\r
+ DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; #\r
+ DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $\r
+ DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; %\r
+ DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; &\r
+ DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; '\r
+ DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; (\r
+ DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; )\r
+ DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; *\r
+ DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; +\r
+ DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; ,\r
+ DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; -\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; .\r
+ DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; /\r
+ DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0\r
+ DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1\r
+ DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2\r
+ DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3\r
+ DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4\r
+ DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5\r
+ DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6\r
+ DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7\r
+ DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8\r
+ DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9\r
+ DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; :\r
+ DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ;\r
+ DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; <\r
+ DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; =\r
+ DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; >\r
+ DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ?\r
+ DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A\r
+ DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B\r
+ DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C\r
+ DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E\r
+ DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F\r
+ DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G\r
+ DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H\r
+ DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I\r
+ DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J\r
+ DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K\r
+ DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L\r
+ DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M\r
+ DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O\r
+ DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P\r
+ DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q\r
+ DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R\r
+ DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S\r
+ DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T\r
+ DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U\r
+ DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V\r
+ DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W\r
+ DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X\r
+ DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y\r
+ DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z\r
+ DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [\r
+ DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \\r
+ DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ]\r
+ DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _\r
+ DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; `\r
+ DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b\r
+ DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c\r
+ DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d\r
+ DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e\r
+ DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g\r
+ DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h\r
+ DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i\r
+ DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j\r
+ DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k\r
+ DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l\r
+ DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m\r
+ DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n\r
+ DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o\r
+ DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p\r
+ DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q\r
+ DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r\r
+ DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s\r
+ DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t\r
+ DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u\r
+ DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v\r
+ DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w\r
+ DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x\r
+ DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y\r
+ DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z\r
+ DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; {\r
+ DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; |\r
+ DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; }\r
+ DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~\r
+ DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ; \7f\r
+ DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128\r
+ DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129\r
+ DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130\r
+ DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131\r
+ DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132\r
+ DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133\r
+ DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134\r
+ DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135\r
+ DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136\r
+ DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137\r
+ DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138\r
+ DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139\r
+ DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140\r
+ DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141\r
+ DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142\r
+ DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143\r
+ DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144\r
+ DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145\r
+ DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146\r
+ DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147\r
+ DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148\r
+ DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149\r
+ DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150\r
+ DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151\r
+ DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152\r
+ DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153\r
+ DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154\r
+ DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155\r
+ DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156\r
+ DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157\r
+ DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158\r
+ DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159\r
+ DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160\r
+ DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161\r
+ DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162\r
+ DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163\r
+ DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164\r
+ DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165\r
+ DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166\r
+ DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167\r
+ DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168\r
+ DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169\r
+ DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170\r
+ DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171\r
+ DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172\r
+ DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173\r
+ DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174\r
+ DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175\r
+ DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176\r
+ DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177\r
+ DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178\r
+ DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181\r
+ DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182\r
+ DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183\r
+ DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184\r
+ DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185\r
+ DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186\r
+ DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187\r
+ DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188\r
+ DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189\r
+ DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190\r
+ DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194\r
+ DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196\r
+ DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198\r
+ DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199\r
+ DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200\r
+ DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201\r
+ DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202\r
+ DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203\r
+ DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205\r
+ DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206\r
+ DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208\r
+ DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210\r
+ DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211\r
+ DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212\r
+ DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213\r
+ DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214\r
+ DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215\r
+ DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216\r
+ DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217\r
+ DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219\r
+ DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220\r
+ DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221\r
+ DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222\r
+ DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223\r
+ DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224\r
+ DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225\r
+ DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226\r
+ DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227\r
+ DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228\r
+ DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229\r
+ DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230\r
+ DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231\r
+ DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232\r
+ DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233\r
+ DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234\r
+ DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235\r
+ DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236\r
+ DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237\r
+ DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238\r
+ DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239\r
+ DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240\r
+ DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241\r
+ DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242\r
+ DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243\r
+ DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244\r
+ DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245\r
+ DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246\r
+ DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247\r
+ DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248\r
+ DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249\r
+ DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250\r
+ DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251\r
+ DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252\r
+ DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253\r
+ DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254\r
+ DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+!ifdef __LINUX__\r
+REMOVECOMMAND=rm -f\r
+COPYCOMMAND=cp -f\r
+DIRSEP=/\r
+OBJ=o\r
+!else\r
+REMOVECOMMAND=del\r
+COPYCOMMAND=copy /y\r
+DIRSEP=\\r
+OBJ=obj\r
+!endif\r
+LIBINCS = modex.def\r
+\r
+LIBOBJS = mxbb.$(OBJ) mxcc.$(OBJ) mxcg.$(OBJ) mxcl.$(OBJ) mxcr.$(OBJ) mxfb.$(OBJ) mxgc.$(OBJ) mxgi.$(OBJ) mxgm.$(OBJ) mxgp.$(OBJ) mxgv.$(OBJ) mxhl.$(OBJ) mxit.$(OBJ) mxll.$(OBJ) mxln.$(OBJ) mxot.$(OBJ) mxpb.$(OBJ) mxpf.$(OBJ) mxpg.$(OBJ) mxpi.$(OBJ) mxpn.$(OBJ) mxpp.$(OBJ) mxra.$(OBJ) mxrp.$(OBJ) mxsa.$(OBJ) mxsc.$(OBJ) mxsi.$(OBJ) mxsl.$(OBJ) mxsm.$(OBJ) mxsp.$(OBJ) mxss.$(OBJ) mxtl.$(OBJ) mxvs.$(OBJ) mxwd.$(OBJ) mxwm.$(OBJ) mxwp.$(OBJ) mxwr.$(OBJ)\r
+#mxfp.$(OBJ) \r
+#\r
+# ASM compiler\r
+#\r
+ASMC =wasm\r
+ASMO =-mh -0\r
+\r
+#\r
+# PAS compiler\r
+#\r
+#PASC = tpc\r
+#PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = wlib\r
+\r
+# .asm.obj:\r
+# $(ASMC) $(ASMO) $<\r
+\r
+mxbb.$(OBJ): mxbb.asm\r
+ $(ASMC) $(ASMO) mxbb.asm\r
+mxcc.$(OBJ): mxcc.asm\r
+ $(ASMC) $(ASMO) mxcc.asm\r
+mxcg.$(OBJ): mxcg.asm\r
+ $(ASMC) $(ASMO) mxcg.asm\r
+mxcl.$(OBJ): mxcl.asm\r
+ $(ASMC) $(ASMO) mxcl.asm\r
+mxcr.$(OBJ): mxcr.asm\r
+ $(ASMC) $(ASMO) mxcr.asm\r
+mxfb.$(OBJ): mxfb.asm\r
+ $(ASMC) $(ASMO) mxfb.asm\r
+mxfp.$(OBJ): mxfp.asm\r
+ $(ASMC) $(ASMO) mxfp.asm\r
+mxgc.$(OBJ): mxgc.asm\r
+ $(ASMC) $(ASMO) mxgc.asm\r
+mxgi.$(OBJ): mxgi.asm\r
+ $(ASMC) $(ASMO) mxgi.asm\r
+mxgm.$(OBJ): mxgm.asm\r
+ $(ASMC) $(ASMO) mxgm.asm\r
+mxgp.$(OBJ): mxgp.asm\r
+ $(ASMC) $(ASMO) mxgp.asm\r
+mxgv.$(OBJ): mxgv.asm\r
+ $(ASMC) $(ASMO) mxgv.asm\r
+mxhl.$(OBJ): mxhl.asm\r
+ $(ASMC) $(ASMO) mxhl.asm\r
+mxit.$(OBJ): mxit.asm\r
+ $(ASMC) $(ASMO) mxit.asm\r
+mxll.$(OBJ): mxll.asm\r
+ $(ASMC) $(ASMO) mxll.asm\r
+mxln.$(OBJ): mxln.asm\r
+ $(ASMC) $(ASMO) mxln.asm\r
+mxot.$(OBJ): mxot.asm\r
+ $(ASMC) $(ASMO) mxot.asm\r
+mxpb.$(OBJ): mxpb.asm\r
+ $(ASMC) $(ASMO) mxpb.asm\r
+mxpf.$(OBJ): mxpf.asm\r
+ $(ASMC) $(ASMO) mxpf.asm\r
+mxpg.$(OBJ): mxpg.asm\r
+ $(ASMC) $(ASMO) mxpg.asm\r
+mxpi.$(OBJ): mxpi.asm\r
+ $(ASMC) $(ASMO) mxpi.asm\r
+mxpn.$(OBJ): mxpn.asm\r
+ $(ASMC) $(ASMO) mxpn.asm\r
+mxpp.$(OBJ): mxpp.asm\r
+ $(ASMC) $(ASMO) mxpp.asm\r
+mxra.$(OBJ): mxra.asm\r
+ $(ASMC) $(ASMO) mxra.asm\r
+mxrp.$(OBJ): mxrp.asm\r
+ $(ASMC) $(ASMO) mxrp.asm\r
+mxsa.$(OBJ): mxsa.asm\r
+ $(ASMC) $(ASMO) mxsa.asm\r
+mxsc.$(OBJ): mxsc.asm\r
+ $(ASMC) $(ASMO) mxsc.asm\r
+mxsi.$(OBJ): mxsi.asm\r
+ $(ASMC) $(ASMO) mxsi.asm\r
+mxsl.$(OBJ): mxsl.asm\r
+ $(ASMC) $(ASMO) mxsl.asm\r
+mxsm.$(OBJ): mxsm.asm\r
+ $(ASMC) $(ASMO) mxsm.asm\r
+mxsp.$(OBJ): mxsp.asm\r
+ $(ASMC) $(ASMO) mxsp.asm\r
+mxss.$(OBJ): mxss.asm\r
+ $(ASMC) $(ASMO) mxss.asm\r
+mxtl.$(OBJ): mxtl.asm\r
+ $(ASMC) $(ASMO) mxtl.asm\r
+mxvs.$(OBJ): mxvs.asm\r
+ $(ASMC) $(ASMO) mxvs.asm\r
+mxwd.$(OBJ): mxwd.asm\r
+ $(ASMC) $(ASMO) mxwd.asm\r
+mxwm.$(OBJ): mxwm.asm\r
+ $(ASMC) $(ASMO) mxwm.asm\r
+mxwp.$(OBJ): mxwp.asm\r
+ $(ASMC) $(ASMO) mxwp.asm\r
+mxwr.$(OBJ): mxwr.asm\r
+ $(ASMC) $(ASMO) mxwr.asm\r
+\r
+all: $(LIBOBJS) modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+ MXCC.OBJ \\r
+ MXCG.OBJ \\r
+ MXCL.OBJ \\r
+ MXCR.OBJ \\r
+ MXFB.OBJ \\r
+ MXFP.OBJ \\r
+ MXGC.OBJ \\r
+ MXGI.OBJ \\r
+ MXGM.OBJ \\r
+ MXGP.OBJ \\r
+ MXGV.OBJ \\r
+ MXHL.OBJ \\r
+ MXIT.OBJ \\r
+ MXLL.OBJ \\r
+ MXLN.OBJ \\r
+ MXOT.OBJ \\r
+ MXPB.OBJ \\r
+ MXPF.OBJ \\r
+ MXPG.OBJ \\r
+ MXPI.OBJ \\r
+ MXPN.OBJ \\r
+ MXPP.OBJ \\r
+ MXRA.OBJ \\r
+ MXRP.OBJ \\r
+ MXSA.OBJ \\r
+ MXSC.OBJ \\r
+ MXSI.OBJ \\r
+ MXSL.OBJ \\r
+ MXSM.OBJ \\r
+ MXSP.OBJ \\r
+ MXSS.OBJ \\r
+ MXTL.OBJ \\r
+ MXVS.OBJ \\r
+ MXWD.OBJ \\r
+ MXWM.OBJ \\r
+ MXWP.OBJ \\r
+ MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+ $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+# $(PASC) $(PASO) modex\r
+# copy modex.tpu ..\r
+# copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+# $(PASC) /cp $(PASO) modex\r
+# copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+ $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS): modex.def\r
--- /dev/null
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+;JUMPS\r
+;LOCALS\r
+\r
+TRUE EQU 1 ; Boolean constants\r
+FALSE EQU 0\r
+\r
+USE286 = FALSE ; TRUE enables 80286 instructions\r
+USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+ P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+ P386\r
+ USE286 = TRUE\r
+ENDIF\r
+\r
+MXVERSION EQU 0128h ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC EQU 3C2h ; Miscellaneous output\r
+TS EQU 3C4h ; Timing Sequencer index register\r
+GDC EQU 3CEh ; Graphics Data Controller index register\r
+CRTC EQU 3D4h ; CRTC index register\r
+STATUS EQU 3DAh ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET EQU 0\r
+OP_MOVE EQU 0 ; Same as OP_SET\r
+OP_AND EQU 1\r
+OP_OR EQU 2\r
+OP_XOR EQU 3\r
+OP_TRANS EQU 4\r
+OP_ADD EQU 5 ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU 4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.PUSH has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+ IFB <$reg> ;; Is argument blank?\r
+ EXITM ;; Yes, exit\r
+ ELSEIFIDNI <$reg>, <FLAGS> ;; Is argument the keyword "FLAGS"?\r
+ pushf ;; Yes, push flags\r
+ ELSE\r
+ push $reg ;; Push argument\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+; .pop ax, flags, var1\r
+;\r
+.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+ IFNB <r10>\r
+ .ERROR <.POP has more than 10 arguments>\r
+ ENDIF\r
+ IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+ IFNB <$reg> ;; Is argument non-blank?\r
+ IFIDNI <$reg>, <FLAGS> ;; Yes, is it the keyword "FLAGS"?\r
+ popf ;; Yes, pop flags\r
+ ELSE\r
+ pop $reg ;; Pop argument\r
+ ENDIF\r
+ ENDIF\r
+ ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter MACRO localsize\r
+ IF USE286 EQ TRUE\r
+ enter localsize, 0\r
+ ELSE\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, localsize\r
+ ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.leave MACRO argsize\r
+; IF USE286 EQ TRUE\r
+; leave\r
+; ELSE\r
+; mov sp, bp\r
+; pop bp\r
+; ENDIF\r
+; IFNB <argspace>\r
+; ret argsize\r
+; ELSE\r
+; ret\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shr MACRO arg, count\r
+; IF USE286 EQ TRUE\r
+; shr arg, count\r
+; ELSE\r
+; $temp = count\r
+; WHILE $temp GT 0\r
+; shr arg, 1\r
+; $temp = $temp-1\r
+; ENDM\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shl MACRO arg, count\r
+; IF USE286 EQ TRUE\r
+; shl arg, count\r
+; ELSE\r
+; $temp = count\r
+; WHILE $temp GT 0\r
+; shl arg, 1\r
+; $temp = $temp-1\r
+; ENDM\r
+; ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.chk386 MACRO name, jump\r
+; IF USE386 EQ FALSE\r
+; .OUT "Warning: ", <name>, " needs a 386 or better to run!"\r
+; jmp @@jump\r
+; ENDIF\r
+;ENDM\r
--- /dev/null
+/*\r
+ MODEX.H - C/C++ include file for the MODEX library\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_ // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT 0 // 80x25 text\r
+#define MX_320x175 1 // 320x175x256\r
+#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350 4 // 320x350x256\r
+#define MX_320x400 5 // 320x400x256, 2 pages\r
+#define MX_320x480 6 // 320x480x256, 1 page\r
+#define MX_360x175 7 // 360x175x256\r
+#define MX_360x200 8 // 360x200x256, 3 pages\r
+#define MX_360x240 9 // 360x240x256, 2 pages\r
+#define MX_360x350 10 // 360x350x256\r
+#define MX_360x400 11 // 360x400x256, 1 page\r
+#define MX_360x480 12 // 360x480x256, 1 page\r
+#define MX_400x600 13 // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN 0\r
+#define MX_FADEOUT 1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET 0 // No operator\r
+#define OP_AND 1 // And\r
+#define OP_OR 2 // Or\r
+#define OP_XOR 3 // Xor\r
+#define OP_TRANS 4 // Transparent\r
+#define OP_ADD 5 // Additive\r
+#define OP_MOVE 0 // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE unsigned char\r
+#define MXBOOL short int\r
+#define MXSINT short int\r
+#define MXUINT unsigned short int\r
+#define MXAPI far pascal\r
+#define MXPTR void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT MXAPI mxInit( void ); // Returns 0 if successful\r
+void MXAPI mxTerm( void );\r
+MXUINT MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void MXAPI mxChangeMode( MXUINT mode );\r
+void MXAPI mxSetMode( MXUINT mode );\r
+void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void MXAPI mxWriteMode( MXBYTE wm );\r
+void MXAPI mxSplitScreen( MXUINT line );\r
+void MXAPI mxStartAddress( MXUINT sa );\r
+void MXAPI mxStartLine( MXUINT sl );\r
+void MXAPI mxWaitDisplay( void );\r
+void MXAPI mxWaitRetrace( void );\r
+void MXAPI mxWritePlane( MXBYTE wp );\r
+void MXAPI mxReadPlane( MXBYTE rp );\r
+void MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL MXAPI mxGetClip( void );\r
+MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL MXAPI mxSetClip( MXBOOL );\r
+void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef MXBYTE\r
+#undef MXBOOL\r
+#undef MXSINT\r
+#undef MXUINT\r
+#undef MXPTR\r
+#undef MXAPI\r
+\r
+#endif // _MODEX_H_\r
--- /dev/null
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXPT.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
--- /dev/null
+(*\r
+ Turbo Pascal interface to the MODEX library\r
+ Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+ (* Video modes *)\r
+ MX_TEXT = 0;\r
+ MX_320x175 = 1;\r
+ MX_320x200 = 2;\r
+ MX_320x240 = 3;\r
+ MX_320x350 = 4;\r
+ MX_320x400 = 5;\r
+ MX_320x480 = 6;\r
+ MX_360x175 = 7;\r
+ MX_360x200 = 8;\r
+ MX_360x240 = 9;\r
+ MX_360x350 = 10;\r
+ MX_360x400 = 11;\r
+ MX_360x480 = 12;\r
+ MX_400x600 = 13;\r
+\r
+ (* Fade effects *)\r
+ MX_FADEIN = 0;\r
+ MX_FADEOUT = 1;\r
+\r
+ (* Raster ops *)\r
+ OP_SET = 0;\r
+ OP_AND = 1;\r
+ OP_OR = 2;\r
+ OP_XOR = 3;\r
+ OP_TRANS = 4;\r
+ OP_ADD = 5;\r
+ OP_MOVE = 0; (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt; external;\r
+procedure mxChangeMode( Mode: word ); external;\r
+procedure mxCircle; external;\r
+procedure mxColorToGray; external;\r
+procedure mxFadePalette; external;\r
+procedure mxFillBox; external;\r
+procedure mxGammaCorrect; external;\r
+procedure mxGetAspect( var AspectX, AspectY: word ); external;\r
+function mxGetClipRegion; external;\r
+function mxGetClip: boolean; external;\r
+procedure mxGetImage; external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function mxGetPixel( X, Y: word ): byte; external;\r
+procedure mxGetScreenSize( var Width, Height: word ); external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external;\r
+function mxGetVersion: word; external;\r
+procedure mxGetVirtualScreen( var Width, Height: word ); external;\r
+procedure mxInit; external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external;\r
+procedure mxOutChar( X, Y: integer; C: char ); external;\r
+procedure mxOutText( X, Y: integer; S: pointer ); external;\r
+procedure mxPan( X, Y: word ); external;\r
+procedure mxPutImage; external;\r
+procedure mxPutPixel( X, Y: word; C: byte ); external;\r
+procedure mxPutTile; external;\r
+procedure mxReadPlane( Plane: byte ); external;\r
+procedure mxRotatePalette; external;\r
+procedure mxRowAddress( RowAddress: byte ); external;\r
+function mxSetClip( Clip: boolean ): boolean; external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external;\r
+procedure mxSetColor( Index, R, G, B: word ); external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word ); external;\r
+procedure mxSetMode( Mode: word ); external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word ); external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer ); external;\r
+procedure mxSetVirtualScreen( Width, Height: word ); external;\r
+procedure mxSplitScreen( Line: word ); external;\r
+procedure mxStartAddress( StartAddress: word ); external;\r
+procedure mxStartLine; external;\r
+procedure mxStretchImage; external;\r
+procedure mxTerm; external;\r
+procedure mxTransPutTile; external;\r
+procedure mxWaitDisplay; external;\r
+procedure mxWaitRetrace; external;\r
+procedure mxWriteMode( Mode: byte ); external;\r
+procedure mxWritePlane( Plane: byte ); external;\r
+\r
+procedure mxFillPoly; external;\r
+procedure mxGouraudPoly; external;\r
+procedure mxTexturePoly; external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+ Prints a Turbo Pascal string.\r
+ Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+ S := S + #0;\r
+ mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
--- /dev/null
+(*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ MAX_SPRITE = 100;\r
+type\r
+ (* Sprite structure *)\r
+ TSprite = record\r
+ X, Y : integer; (* Sprite coordinates *)\r
+ DX,DY: integer; (* Deltas for sprite movement *)\r
+ W, H : integer; (* Sprite width and height *)\r
+ Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *)\r
+ end;\r
+ (* RGB color structure *)\r
+ TRgb = record\r
+ R, G, B: byte;\r
+ end;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *)\r
+ Palette: array[ byte ] of TRgb; (* Palette *)\r
+ Page : word; (* Page offset *)\r
+ I : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X := Random( 320 ); (* Initialize position with random values *)\r
+ S.Y := Random( 240 );\r
+ S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+ S.DY := Random( 7 )-3;\r
+ S.W := 16; (* Size is fixed in this program *)\r
+ S.H := 16;\r
+ (* The image is a square with a hole inside *)\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); (* Get new position *)\r
+ Inc( S.Y, S.DY );\r
+ (* Check sprite position, change delta if needed *)\r
+ if( S.X > 320 ) then begin\r
+ S.X := 320;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.X < -16 ) then begin\r
+ S.X := -16;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.Y > 240 ) then begin\r
+ S.Y := 240;\r
+ S.DY := -S.DY;\r
+ end;\r
+ if( S.Y < -16 ) then begin\r
+ S.Y := -16;\r
+ S.DY := -S.DY;\r
+ end;\r
+ (* Draw the sprite, note the Page offset added to the *)\r
+ (* Y coordinate of the image *)\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+ (* Initialize library *)\r
+ mxInit;\r
+\r
+ (* Enter graphics mode *)\r
+ mxSetMode( MX_320x240 );\r
+\r
+ (* Print initialization message *)\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ (* Initialize sprites *)\r
+ for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+ (* Draw background *)\r
+ for I:=1 to 192 do begin\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ end;\r
+\r
+ (* Compute and set palette *)\r
+ for I:=1 to 192 do with Palette[I+63] do begin\r
+ R := 0;\r
+ G := 0;\r
+ B := 0;\r
+ if( I < 64 ) then\r
+ R := I shr 1+31\r
+ else if( I < 128 ) then\r
+ G := (I-64) shr 1+31\r
+ else\r
+ B := (I-128) shr 1+31;\r
+ end;\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ (* Main loop *)\r
+ Page := 240;\r
+ while( not KeyPressed ) do begin\r
+ (* Set clip region to current page *)\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ (* Restore background *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ (* Draw sprites *)\r
+ for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+ (* Print message *)\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ (* Flip page *)\r
+ mxStartLine( Page );\r
+ Page := 240-Page;\r
+ (* Animate palette *)\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO02 - Texture mapping and palette rotation\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+ LSIZE = 85;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of T2DPoint;\r
+ Width : word;\r
+ Data : array[ 1..64*64 ] of byte;\r
+ end;\r
+ TQuad = record\r
+ VtxCnt : word;\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+var\r
+ Vtx : array[ 0..7 ] of TPoint;\r
+ XVtx : array[ 0..7 ] of TPoint;\r
+ VVtx : array[ 0..7 ] of T2DPoint;\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Txts : array[ 0..5 ] of TTexture;\r
+ Nrm : array[ 0..5 ] of TPoint;\r
+ XNrm : array[ 0..5 ] of TPoint;\r
+ Page : word;\r
+ Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+ I: word;\r
+begin\r
+ mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+ MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+ mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+ (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+ with Txts[Idx] do begin\r
+ Desc[0].X := $80; Desc[0].Y := $80;\r
+ Desc[1].X := $80; Desc[1].Y := $3F80;\r
+ Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+ Desc[3].X := $3F80; Desc[3].Y := $80;\r
+ Width := 64;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Build vertexes for a cube *)\r
+ with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+ with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+ for I:=0 to 7 do begin (* Make points 16:16 fixed *)\r
+ Vtx[I].X := Vtx[I].X*$10000;\r
+ Vtx[I].Y := Vtx[I].Y*$10000;\r
+ Vtx[I].Z := Vtx[I].Z*$10000;\r
+ end;\r
+ (* Build faces *)\r
+ with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+ with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+ with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+ with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+ with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+ with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+ for I:=0 to 5 do Face[I].Texture := I;\r
+ (* Build textures and palette *)\r
+ Randomize;\r
+ FillChar( Palette, SizeOf(Palette), 0 );\r
+ MakePlasmaPalette( Palette, PAL_RGB );\r
+ mxSetPalette( @Palette, 0, 193 );\r
+ for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *)\r
+ (* Draw cube: backface culling is straighforward in this case, so *)\r
+ (* it can be handled by the polygon filling procedure *)\r
+ for I:=0 to 5 do\r
+ mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *)\r
+ Page := 240-Page;\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 1000; (* Number of points *)\r
+ EDGE = 70; (* Length of cube edge *)\r
+ RADIUS = 90; (* Radius of sphere *)\r
+ WAITCOUNT = 192; (* Frames to wait for non-morphing shapes *)\r
+ MS = 32; (* Number of steps for morphing *)\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+ InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+ InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+ InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+ P3DPointArray = ^T3DPointArray;\r
+var\r
+ CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+ VVtx : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+ Page : word;\r
+ Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+ L: longint;\r
+begin\r
+ L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+ Toggle := A;\r
+ if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+ I: integer;\r
+begin\r
+ New( CubeVtx );\r
+ New( SphereVtx );\r
+ New( Vtx );\r
+ New( XVtx );\r
+ (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+ Randomize;\r
+ for I:=0 to MAXVTX-1 do begin\r
+ with CubeVtx^[I] do begin\r
+ (* Build cube *)\r
+ X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+ Z := Toggle( EDGE*$10000 );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ end;\r
+ with SphereVtx^[I] do begin\r
+ (* Build sphere *)\r
+Retry:\r
+ X := (longint(Random(2*RADIUS))-RADIUS);\r
+ Y := (longint(Random(2*RADIUS))-RADIUS);\r
+ if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+ Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+ case Random(3) of\r
+ 0: Swap( X, Z );\r
+ 1: Swap( Y, Z );\r
+ end;\r
+ X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+ end;\r
+ end;\r
+ (* Initialize morphing *)\r
+ Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+ Status := 0;\r
+ Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+ I: integer;\r
+begin\r
+ (* Fully unoptimized, slowest loop I could think of! *)\r
+ for I:=0 to MAXVTX-1 do begin\r
+ Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+ Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+ Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ C := #0;\r
+ repeat\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 1 );\r
+ Inc( AZ, 2 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw points *)\r
+ for I:=0 to MAXVTX-1 do\r
+ mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+ mxStartLine( Page ); (* Flip pages *)\r
+ Page := 240-Page;\r
+ (* Morph *)\r
+ if( Odd(Status) ) then begin\r
+ Morph;\r
+ Inc( Morph1, Delta1 );\r
+ Inc( Morph2, Delta2 );\r
+ if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+ if( Status = 4 ) then Status := 0;\r
+ end\r
+ else begin\r
+ Dec( Count );\r
+ if( Count < 0 ) then begin\r
+ Inc( Status );\r
+ Count := WAITCOUNT;\r
+ Morph1 := InitMorph1[Status];\r
+ Morph2 := InitMorph2[Status];\r
+ Delta1 := InitDelta1[Status];\r
+ Delta2 := InitDelta2[Status];\r
+ end;\r
+ end;\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO04 - Multiple textures and triple buffering (3 pages)\r
+ (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+ MAXVTX = 256;\r
+ MAXCUB = 2;\r
+ MAXTXT = 2;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+ TxtSunDial: array[ 0..7 ] of word = (\r
+ $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+ TxtSapphire : array[ 0..7 ] of word = (\r
+ $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+ TxtMarble: array[ 0..7 ] of word = (\r
+ $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+ T2DPoint = record\r
+ X, Y: integer;\r
+ end;\r
+ TTexture = record\r
+ Desc : array[ 0..3 ] of record X, Y: word end;\r
+ Width : word;\r
+ Data : pointer;\r
+ end;\r
+ TQuad = record\r
+ Vtx : array[ 0..3 ] of word;\r
+ Texture: word;\r
+ end;\r
+ TCube = record\r
+ Face : array[ 0..5 ] of TQuad;\r
+ Base : integer;\r
+ end;\r
+var\r
+ Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+ VVtx : array[ 0..MAXVTX ] of T2DPoint;\r
+ Cube : array[ 0..MAXCUB ] of TCube;\r
+ ZList : array[ 0..MAXCUB ] of integer;\r
+ VtxCnt : word;\r
+ Txts : array[ 0..MAXTXT ] of TTexture;\r
+ Page : word;\r
+ Palette : array[ byte ] of record R, G, B: byte; end;\r
+ TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+ with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+ Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+ FaceIdx: array[ 0..23 ] of integer = (\r
+ 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+ I, VC: integer;\r
+begin\r
+ VC := VtxCnt;\r
+ C.Base := VC;\r
+ AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+ AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+ AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+ AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+ for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+ for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+ P: ^word;\r
+ I: integer;\r
+begin\r
+ P := @VtxData;\r
+ with Txts[Idx] do begin\r
+ for I:=0 to 3 do begin\r
+ Desc[I].X := P^; Inc( P );\r
+ Desc[I].Y := P^; Inc( P );\r
+ end;\r
+ Width := 129;\r
+ Data := TxtDat1;\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ I: integer;\r
+ V: integer;\r
+ F: file;\r
+ P: array[ 1..768 ] of byte;\r
+begin\r
+ (* Initialize objects *)\r
+ VtxCnt := 0;\r
+ MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *)\r
+ Cube[0].Face[0].Texture := 0;\r
+ V := VtxCnt;\r
+ MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+ tdSetTranslation( Trans );\r
+ tdSetRotation( 32, 32, 00 );\r
+ tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *)\r
+ for I:=V to V+7 do begin\r
+ Vtx[I].X := XVtx[I].X;\r
+ Vtx[I].Y := XVtx[I].Y;\r
+ Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+ end;\r
+ MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+ (* Load texture and palette *)\r
+ Assign( F, 'DEMO04.DAT' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, P, SizeOf(P) );\r
+ mxSetPalette( @P, 0, 256 );\r
+ GetMem( TxtDat1, 63*1024 );\r
+ BlockRead( F, TxtDat1^, 129*286 );\r
+ Close( F );\r
+ TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+ (* Init textures *)\r
+ MakeTexture( 0, TxtSundial );\r
+ MakeTexture( 1, TxtMarble );\r
+ MakeTexture( 2, TxtSapphire );\r
+ Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+ I, J, K: integer;\r
+ ZMax: array[ 0..MAXCUB ] of longint;\r
+ ZI: integer;\r
+ L: longint;\r
+begin\r
+ for I:=0 to MAXCUB do begin\r
+ L := XVtx[Cube[I].Base].Z;\r
+ for J:=1 to 7 do\r
+ if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+ ZMax[I] := L;\r
+ ZList[I] := I;\r
+ end;\r
+ for I:=0 to MAXCUB-1 do begin\r
+ ZI := I;\r
+ for J:=I+1 to MAXCUB do\r
+ if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+ if( ZI <> I ) then begin\r
+ K := ZList[I];\r
+ ZList[I] := ZList[ZI];\r
+ ZList[ZI] := K;\r
+ end;\r
+ end;\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I, J, K: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ AX := 0; AY := 0; AZ := 0;\r
+ tdSetTranslation( Trans );\r
+ tdSetPerspective( 600*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 1 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw objects *)\r
+ SortObjects;\r
+ for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+ for J:=0 to 5 do begin\r
+ K := Face[J].Texture;\r
+ mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+ end;\r
+ end;\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO05 - A Gouraud-shaded rotating torus\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+ MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *)\r
+ MAXVTX2 = 15; RADIUS2 = 30;\r
+ MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+ MAXFACE = MAXVTX;\r
+ Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *)\r
+ Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *)\r
+type\r
+ TQuad = record\r
+ QVtx : array[ 0..3 ] of integer;\r
+ end;\r
+var\r
+ Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *)\r
+ VVtx : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+ Face : array[ 0..MAXFACE ] of TQuad; (* Polys *)\r
+ Culled : array[ 0..MAXFACE ] of integer;\r
+ GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *)\r
+ VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *)\r
+ Page : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+ GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ R, N, X, Y, Z: real;\r
+ I, J, K, V: integer;\r
+begin\r
+ (* Build vertexes *)\r
+ for I:=0 to MAXVTX1 do begin\r
+ K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+ R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+ for J:=0 to MAXVTX2 do begin\r
+ V := I*(MAXVTX2+1)+J; (* Index of current vertex *)\r
+ (* Compute coordinates of current vertex *)\r
+ X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *)\r
+ Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+ Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+ Vtx[V].X := Round( X )*$10000; (* Save coordinates *)\r
+ Vtx[V].Y := Round( Y )*$10000;\r
+ Vtx[V].Z := Round( Z )*$10000;\r
+ (* Compute direction of Gouraud normal thru current vertex *)\r
+ X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+ Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+ N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *)\r
+ GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *)\r
+ GNrm[V].Y := Trunc( Y*$10000/N );\r
+ GNrm[V].Z := Trunc( Z*$10000/N );\r
+ end;\r
+ end;\r
+ (* Generate faces so that depth-sorting is not needed: there are still *)\r
+ (* some *very* little errors, but this is the best I could devise *)\r
+ J := 0;\r
+ K := 0;\r
+ for I:=0 to MAXFACE do with Face[I] do begin\r
+ QVtx[0] := GetVtx( J, K );\r
+ QVtx[1] := GetVtx( J, K+1 );\r
+ QVtx[2] := GetVtx( J+1, K+1 );\r
+ QVtx[3] := GetVtx( J+1, K );\r
+ Inc( K );\r
+ if( K > MAXVTX2 ) then begin\r
+ K := 0;\r
+ Inc( J );\r
+ end;\r
+ end;\r
+{$ifndef ALTPAL}\r
+ for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *)\r
+{$else}\r
+ for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+ for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+ AX, AY, AZ: byte;\r
+ I: word;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240; (* Start with hidden page *)\r
+\r
+ AX := 0;\r
+ AY := 0;\r
+ AZ := 0;\r
+ (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+ tdSetTranslation( Trans );\r
+ tdSetLight( Light );\r
+ tdSetPerspective( 400*$10000, $10000, $10000 );\r
+ (* Main loop, all magic here! *)\r
+ while( not KeyPressed ) do begin\r
+ tdSetRotation( AX, AY, AZ ); (* Set new angles *)\r
+ tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *)\r
+ tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+ tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *)\r
+ tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+ (* Backplane culling is not really needed here! *)\r
+ FillChar( Culled, SizeOf(Culled), 0 );\r
+ tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+ Inc( AX, 1 ); (* Bump angles *)\r
+ Inc( AY, 2 );\r
+ Inc( AZ, 3 );\r
+ mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *)\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+ (* Draw polygons *)\r
+ for I:=0 to MAXFACE do with Face[I] do\r
+ if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+ (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+ 480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO06 - Magnifying glass\r
+ (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ R = 40; (* Lens radius *)\r
+ K : real = 1.8; (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+ TLine = array[ 0..319 ] of byte;\r
+ PLine = ^TLine;\r
+ TScreen = array[ 0..239 ] of PLine;\r
+var\r
+ VScreen: TScreen; (* Virtual screen *)\r
+ BallX : array[ 0..R, 0..R ] of integer;\r
+ BallY : array[ 0..R, 0..R ] of integer;\r
+ Sprite : array[ -R..R, -R..R ] of byte;\r
+ Page : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+ LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+ LR := Sqrt( X*X + Y*Y );\r
+ if( LR = 0 ) then Exit;\r
+ if( LR < R ) then begin\r
+ Z := Sqrt( R*R - LR*LR );\r
+ SinA := LR / R;\r
+ SinB := SinA / K;\r
+ TgB := SinB / Sqrt( 1-SinB*SinB );\r
+ Q := LR - TgB*Z;\r
+ X := Round( X * ( Q/LR ) );\r
+ Y := Round( Y * ( Q/LR ) );\r
+ end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+ F : file;\r
+ Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+ X, Y,\r
+ X2, Y2 : integer;\r
+begin\r
+ (* Load background image *)\r
+ Assign( F, 'demo06.dat' );\r
+ Reset( F, 1 );\r
+ BlockRead( F, Palette, 768 );\r
+ mxSetPalette( @Palette, 0, 256 );\r
+ for Y:=0 to 239 do begin\r
+ New( VScreen[Y] );\r
+ BlockRead( F, VScreen[Y]^, 320 );\r
+ mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+ end;\r
+ Close( F );\r
+ (* Build lens *)\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ X2 := X;\r
+ Y2 := Y;\r
+ GetCoords( X2, Y2 );\r
+ BallX[X, Y] := X2;\r
+ BallY[X, Y] := Y2;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+ X, Y: integer;\r
+begin\r
+ for X:=0 to R do begin\r
+ for Y:=0 to R do begin\r
+ Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+ Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+ end;\r
+ end;\r
+ (* Draw the sprite *)\r
+ mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+ Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*Delta;\r
+ end;\r
+end;\r
+\r
+var\r
+ X, Y, DX, DY: integer;\r
+ C: char;\r
+begin\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ Init;\r
+ Page := 240;\r
+ X := R;\r
+ Y := R;\r
+ Randomize;\r
+ DX := Delta;\r
+ DY := Delta;\r
+\r
+ (* Main loop *)\r
+ repeat\r
+ (* Update video *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ PutLens( X, Y );\r
+ mxCircle( X, Page+Y, R, 0 );\r
+ (* Update lens coordinates *)\r
+ Inc( X, DX );\r
+ Check( X+R >= 319, X, DX, 319-R, -1 );\r
+ Check( X <= R, X, DX, R, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+ Check( Y <= R, Y, DY, R, +1 );\r
+ (* Flip pages: double buffering, avoid wait for display *)\r
+ case Page of\r
+ 0 : begin PortW[$3D4] := $000C; Page := 240; end;\r
+ 240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+ end;\r
+ mxWaitRetrace; (* Wait for hidden page to show *)\r
+ until( KeyPressed );\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+(*\r
+ DEMO07 - Hardware scrolling\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+ (* Change this if scrolling seems jerky (this simple program does *)\r
+ (* not handle vertical retrace/display very well) *)\r
+ STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+ if( Cond ) then begin\r
+ Coord := NewCoord;\r
+ DeltaC := Sign*(Random(3)+2);\r
+ end;\r
+end;\r
+\r
+var\r
+ I, X, Y, DX, DY: integer;\r
+begin\r
+ (* Initialize library and graphics mode *)\r
+ mxInit;\r
+ mxSetMode( MX_320x200 );\r
+ (* Set a 640x400 virtual screen *)\r
+ mxSetVirtualScreen( 640, 400 );\r
+ mxSetClip( TRUE );\r
+\r
+ X := 0;\r
+ Y := 0;\r
+ DX := 1;\r
+ DY := 1;\r
+\r
+ (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+ (* 320x200 windows, while smoothly panning virtual screen *)\r
+ while( not KeyPressed ) do begin\r
+ (* Points *)\r
+ mxSetClipRegion( 0, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxPutPixel( Random(320), Random(200), Random(16) );\r
+ (* Lines *)\r
+ mxSetClipRegion( 0, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+ (* Circles *)\r
+ mxSetClipRegion( 320, 0, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+ (* Boxes *)\r
+ mxSetClipRegion( 320, 200, 320, 200 );\r
+ for I:=1 to STEPS do\r
+ mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+ (* Pan *)\r
+ Inc( X, DX );\r
+ Check( X+320 >= 639, X, DX, 319, -1 );\r
+ Check( X < 0, X, DX, 0, +1 );\r
+ Inc( Y, DY );\r
+ Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+ Check( Y < 0, Y, DY, 0, +1 );\r
+ mxPan( X, Y );\r
+ mxWaitRetrace;\r
+ end;\r
+\r
+ (* Shutdown *)\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT STRUC\r
+ X DD ?\r
+ Y DD ?\r
+ Z DD ?\r
+TPOINT ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT STRUC\r
+ IX DW ?\r
+ IY DW ?\r
+TIMAGEPOINT ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv MACRO arg\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul MACRO arg\r
+ imul arg\r
+ shrd eax, edx, 16\r
+ENDM\r
--- /dev/null
+unit Plasma;\r
+interface\r
+\r
+const\r
+ PAL_RGB = 0;\r
+ PAL_CLOUDS = 1;\r
+ PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+ Color: longint;\r
+begin\r
+ Color := Abs( XA-XB )+Abs( YA-YB );\r
+ Color := Random( Color shl 1 )-Color;\r
+ Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+ if( Color < 1 ) then Color := 1;\r
+ if( Color > 192 ) then Color := 192;\r
+ if( mxGetPixel( X, Y ) = 0 ) then\r
+ mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+ X, Y, Color: integer;\r
+begin\r
+ if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+ X := (X1+X2) shr 1;\r
+ Y := (Y1+Y2) shr 1;\r
+ NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+ NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+ NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+ NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+ Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+ mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+ mxPutPixel( X, Y, Color );\r
+ Divide( X1, Y1, X, Y );\r
+ Divide( X, Y1, X2, Y );\r
+ Divide( X, Y, X2, Y2 );\r
+ Divide( X1, Y, X, Y2 );\r
+ end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+ Dec( W );\r
+ Dec( H );\r
+ mxPutPixel( X, Y, C1 );\r
+ mxPutPixel( X, Y+H, C2 );\r
+ mxPutPixel( X+W, Y+H, C3 );\r
+ mxPutPixel( X+W, Y, C4 );\r
+ Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+ TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+ I: word;\r
+begin\r
+ FillChar( TPal(Palette)[1], 192*3, 0 );\r
+ case What of\r
+ PAL_CLOUDS:\r
+ for I:=1 to 192 do begin\r
+ TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+ TPal(Palette)[I].B := 63;\r
+ end;\r
+ PAL_LANDSCAPE:\r
+ begin\r
+ for I:=0 to 31 do begin\r
+ TPal(Palette)[I+1].R := I;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := I + I shr 1+15;\r
+ end;\r
+ for I:=32 to 63 do begin\r
+ TPal(Palette)[I+1].R := 0;\r
+ TPal(Palette)[I+1].G := I;\r
+ TPal(Palette)[I+1].B := 0;\r
+ end;\r
+ for I:=64 to 191 do begin\r
+ TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+ TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+ end;\r
+ end;\r
+ else\r
+ for I:=1 to 64 do begin\r
+ TPal(Palette)[I].G := I-1;\r
+ TPal(Palette)[I].B := 64-I;\r
+ TPal(Palette)[I+64].R := I-1;\r
+ TPal(Palette)[I+64].G := 64-I;\r
+ TPal(Palette)[I+128].B := I-1;\r
+ TPal(Palette)[I+128].R := 64-I;\r
+ end;\r
+ end;\r
+end;\r
+\r
+end.
\ No newline at end of file
--- /dev/null
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+ DEFVERT = 12; (* Vertex count *)\r
+ DEFREPL = 3; (* Repetition count *)\r
+ DEFQIXS = 2; (* Qixs *)\r
+ FADESPEED = 48;\r
+type\r
+ TPoint = record\r
+ X, Y : integer;\r
+ end;\r
+ TRGB = record\r
+ R, G, B: byte;\r
+ end;\r
+ TQix = record\r
+ Color: integer;\r
+ Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+ Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+ end;\r
+var\r
+ Page : integer;\r
+ MaxX,\r
+ MaxY : word;\r
+ Qix : array[ 0..DEFQIXS-1 ] of TQix;\r
+ Pal : array[ byte ] of TRGB;\r
+\r
+type\r
+ TReal = double;\r
+ TRPoint = record\r
+ X, Y: TReal;\r
+ end;\r
+ TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+ M: TMatrix;\r
+ G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+ C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=1 to Steps do begin\r
+ Pal[Idx+1].R := Pal[Idx].R + DR;\r
+ Pal[Idx+1].G := Pal[Idx].G + DG;\r
+ Pal[Idx+1].B := Pal[Idx].B + DB;\r
+ Inc( Idx );\r
+ end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+ with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+ with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+ BumpPal( 1, 0, 2, -2, 31 );\r
+ BumpPal( 32, 2, -2, 0, 31 );\r
+ BumpPal( 63, -2, 2, 2, 31 );\r
+ BumpPal( 94, 2, 0, -2, 31 );\r
+ BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+ for I:=0 to DEFVERT-1 do begin\r
+ Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+ Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+ Qix.Delta[I].X := Random(5)+1;\r
+ Qix.Delta[I].Y := Random(5)+1;\r
+ end;\r
+ Qix.Color := Color;\r
+\r
+ (* Initialize matrix (Catmull-Rom) *)\r
+ M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+ M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+ M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+ M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+ I, J: integer;\r
+ T, T2, T3: TReal;\r
+ X0, Y0, X, Y: TReal;\r
+ Delta: TReal;\r
+begin\r
+ (* Compute coefficients *)\r
+ for I:=0 to 3 do begin\r
+ C[I].X := 0;\r
+ for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+ C[I].Y := 0;\r
+ for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+ end;\r
+ X0 := C[3].X;\r
+ Y0 := C[3].Y;\r
+ Delta := 1 / N;\r
+ T := 0;\r
+ for I:=1 to N do begin\r
+ T := T + Delta;\r
+ T2 := T*T;\r
+ T3 := T*T2;\r
+ X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+ Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+ mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+ X0 := X;\r
+ Y0 := Y;\r
+ end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+ I, J: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do begin\r
+ mxBezier( Qix, I, Idx, 12 );\r
+ end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Inc( Vert[I,Idx].X, Delta[I].X );\r
+ if( Vert[I,Idx].X < 0 ) then begin\r
+ Vert[I,Idx].X := 0;\r
+ Delta[I].X := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].X > MaxX ) then begin\r
+ Vert[I,Idx].X := MaxX;\r
+ Delta[I].X := -Random( 5 )-1;\r
+ end;\r
+ Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+ if( Vert[I,Idx].Y < 0 ) then begin\r
+ Vert[I,Idx].Y := 0;\r
+ Delta[I].Y := Random( 5 )+1;\r
+ end;\r
+ if( Vert[I,Idx].Y > MaxY ) then begin\r
+ Vert[I,Idx].Y := MaxY;\r
+ Delta[I].Y := -Random( 5 )-1;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+ I: integer;\r
+begin\r
+ for I:=0 to DEFVERT-1 do with Qix do begin\r
+ Vert[I,Dest].X := Vert[I,Src].X;\r
+ Vert[I,Dest].Y := Vert[I,Src].Y;\r
+ end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+ Q, Idx, I, J, P, Count: integer;\r
+begin\r
+ Count := 0;\r
+ P := DEFREPL-1;\r
+ I := 0;\r
+ J := 1;\r
+ repeat\r
+ mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+ mxSetClip( TRUE );\r
+ mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Copy( Qix[Q], I, P );\r
+ Update( Qix[Q], I );\r
+ for Idx:=0 to DEFREPL-1 do begin\r
+ Plot( Qix[Q], Idx );\r
+ end;\r
+ end;\r
+ I := (I+1) mod DEFREPL;\r
+ J := (J+1) mod DEFREPL;\r
+ P := (P+1) mod DEFREPL;\r
+ Inc( Count );\r
+ mxStartLine( Page );\r
+ if( Count >= FADESPEED ) then begin\r
+ for Q:=0 to DEFQIXS-1 do begin\r
+ Inc( Qix[Q].Color );\r
+ if( Qix[Q].Color > 156 ) then\r
+ Qix[Q].Color := 1;\r
+ end;\r
+ Count := 0;\r
+ end;\r
+ Page := 240-Page;\r
+ until( KeyPressed );\r
+end;\r
+\r
+var\r
+ I: integer;\r
+begin\r
+ Randomize;\r
+ mxInit;\r
+ mxSetMode( MX_320x240 );\r
+ mxGetScreenSize( MaxX, MaxY );\r
+ for I:=0 to DEFQIXS-1 do\r
+ Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+ InitPalette;\r
+ mxSetPalette( @Pal, 0, 157 );\r
+ Page := 240;\r
+ Dec( MaxX );\r
+ Dec( MaxY );\r
+ AnimateQix;\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin LABEL DWORD\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+tblCos LABEL DWORD\r
+ DD 16777216\r
+ DD 16772163\r
+ DD 16757007\r
+ DD 16731757\r
+ DD 16696429\r
+ DD 16651044\r
+ DD 16595628\r
+ DD 16530216\r
+ DD 16454846\r
+ DD 16369565\r
+ DD 16274424\r
+ DD 16169479\r
+ DD 16054795\r
+ DD 15930439\r
+ DD 15796488\r
+ DD 15653022\r
+ DD 15500126\r
+ DD 15337895\r
+ DD 15166424\r
+ DD 14985817\r
+ DD 14796184\r
+ DD 14597637\r
+ DD 14390298\r
+ DD 14174291\r
+ DD 13949745\r
+ DD 13716797\r
+ DD 13475586\r
+ DD 13226258\r
+ DD 12968963\r
+ DD 12703856\r
+ DD 12431097\r
+ DD 12150850\r
+ DD 11863283\r
+ DD 11568571\r
+ DD 11266890\r
+ DD 10958422\r
+ DD 10643353\r
+ DD 10321873\r
+ DD 9994176\r
+ DD 9660458\r
+ DD 9320922\r
+ DD 8975771\r
+ DD 8625213\r
+ DD 8269459\r
+ DD 7908725\r
+ DD 7543226\r
+ DD 7173184\r
+ DD 6798821\r
+ DD 6420363\r
+ DD 6038037\r
+ DD 5652074\r
+ DD 5262706\r
+ DD 4870169\r
+ DD 4474698\r
+ DD 4076531\r
+ DD 3675909\r
+ DD 3273072\r
+ DD 2868265\r
+ DD 2461729\r
+ DD 2053710\r
+ DD 1644455\r
+ DD 1234209\r
+ DD 823219\r
+ DD 411733\r
+ DD 0\r
+ DD -411733\r
+ DD -823219\r
+ DD -1234209\r
+ DD -1644455\r
+ DD -2053710\r
+ DD -2461729\r
+ DD -2868265\r
+ DD -3273072\r
+ DD -3675909\r
+ DD -4076531\r
+ DD -4474698\r
+ DD -4870169\r
+ DD -5262706\r
+ DD -5652074\r
+ DD -6038037\r
+ DD -6420363\r
+ DD -6798821\r
+ DD -7173184\r
+ DD -7543226\r
+ DD -7908725\r
+ DD -8269459\r
+ DD -8625213\r
+ DD -8975771\r
+ DD -9320922\r
+ DD -9660458\r
+ DD -9994176\r
+ DD -10321873\r
+ DD -10643353\r
+ DD -10958422\r
+ DD -11266890\r
+ DD -11568571\r
+ DD -11863283\r
+ DD -12150850\r
+ DD -12431097\r
+ DD -12703856\r
+ DD -12968963\r
+ DD -13226258\r
+ DD -13475586\r
+ DD -13716797\r
+ DD -13949745\r
+ DD -14174291\r
+ DD -14390298\r
+ DD -14597637\r
+ DD -14796184\r
+ DD -14985817\r
+ DD -15166424\r
+ DD -15337895\r
+ DD -15500126\r
+ DD -15653022\r
+ DD -15796488\r
+ DD -15930439\r
+ DD -16054795\r
+ DD -16169479\r
+ DD -16274424\r
+ DD -16369565\r
+ DD -16454846\r
+ DD -16530216\r
+ DD -16595628\r
+ DD -16651044\r
+ DD -16696429\r
+ DD -16731757\r
+ DD -16757007\r
+ DD -16772163\r
+ DD -16777216\r
+ DD -16772163\r
+ DD -16757007\r
+ DD -16731757\r
+ DD -16696429\r
+ DD -16651044\r
+ DD -16595628\r
+ DD -16530216\r
+ DD -16454846\r
+ DD -16369565\r
+ DD -16274424\r
+ DD -16169479\r
+ DD -16054795\r
+ DD -15930439\r
+ DD -15796488\r
+ DD -15653022\r
+ DD -15500126\r
+ DD -15337895\r
+ DD -15166424\r
+ DD -14985817\r
+ DD -14796184\r
+ DD -14597637\r
+ DD -14390298\r
+ DD -14174291\r
+ DD -13949745\r
+ DD -13716797\r
+ DD -13475586\r
+ DD -13226258\r
+ DD -12968963\r
+ DD -12703856\r
+ DD -12431097\r
+ DD -12150850\r
+ DD -11863283\r
+ DD -11568571\r
+ DD -11266890\r
+ DD -10958422\r
+ DD -10643353\r
+ DD -10321873\r
+ DD -9994176\r
+ DD -9660458\r
+ DD -9320922\r
+ DD -8975771\r
+ DD -8625213\r
+ DD -8269459\r
+ DD -7908725\r
+ DD -7543226\r
+ DD -7173184\r
+ DD -6798821\r
+ DD -6420363\r
+ DD -6038037\r
+ DD -5652074\r
+ DD -5262706\r
+ DD -4870169\r
+ DD -4474698\r
+ DD -4076531\r
+ DD -3675909\r
+ DD -3273072\r
+ DD -2868265\r
+ DD -2461729\r
+ DD -2053710\r
+ DD -1644455\r
+ DD -1234209\r
+ DD -823219\r
+ DD -411733\r
+ DD 0\r
+ DD 411733\r
+ DD 823219\r
+ DD 1234209\r
+ DD 1644455\r
+ DD 2053710\r
+ DD 2461729\r
+ DD 2868265\r
+ DD 3273072\r
+ DD 3675909\r
+ DD 4076531\r
+ DD 4474698\r
+ DD 4870169\r
+ DD 5262706\r
+ DD 5652074\r
+ DD 6038037\r
+ DD 6420363\r
+ DD 6798821\r
+ DD 7173184\r
+ DD 7543226\r
+ DD 7908725\r
+ DD 8269459\r
+ DD 8625213\r
+ DD 8975771\r
+ DD 9320922\r
+ DD 9660458\r
+ DD 9994176\r
+ DD 10321873\r
+ DD 10643353\r
+ DD 10958422\r
+ DD 11266890\r
+ DD 11568571\r
+ DD 11863283\r
+ DD 12150850\r
+ DD 12431097\r
+ DD 12703856\r
+ DD 12968963\r
+ DD 13226258\r
+ DD 13475586\r
+ DD 13716797\r
+ DD 13949745\r
+ DD 14174291\r
+ DD 14390298\r
+ DD 14597637\r
+ DD 14796184\r
+ DD 14985817\r
+ DD 15166424\r
+ DD 15337895\r
+ DD 15500126\r
+ DD 15653022\r
+ DD 15796488\r
+ DD 15930439\r
+ DD 16054795\r
+ DD 16169479\r
+ DD 16274424\r
+ DD 16369565\r
+ DD 16454846\r
+ DD 16530216\r
+ DD 16595628\r
+ DD 16651044\r
+ DD 16696429\r
+ DD 16731757\r
+ DD 16757007\r
+ DD 16772163\r
--- /dev/null
+COMMENT /\r
+ Fixed-point math functions and 3D transforms\r
+ Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC tdFixedMul\r
+PUBLIC tdGetNormal\r
+PUBLIC tdRotate\r
+PUBLIC tdGetSurfaceLight\r
+PUBLIC tdSetLight\r
+PUBLIC tdSetRotation\r
+PUBLIC tdSetTranslation\r
+PUBLIC tdTransform\r
+PUBLIC tdTransformToImage\r
+PUBLIC tdTransformLight\r
+PUBLIC tdBackPlaneCull\r
+PUBLIC tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA'\r
+ ASSUME ds:MATH_DATA\r
+\r
+INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table\r
+\r
+XRotation TPOINT <> ; 3x3 rotation matrix\r
+YRotation TPOINT <>\r
+ZRotation TPOINT <>\r
+\r
+Translation TPOINT <> ; Translation vector\r
+\r
+Light TPOINT <> ; Light vector\r
+AmbientLight DW 00 ; Ambient light\r
+\r
+XScale DD 10000h ; Scaling factor for X coordinate\r
+YScale DD 10000h ; Scaling factor for Y coordinate\r
+PerspectiveDistance DD 20000000h\r
+\r
+MATH_DATA ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective PROC PASCAL FAR\r
+ ARG Perspective:DWORD, \\r
+ ScaleX:DWORD, \\r
+ ScaleY:DWORD\r
+ USES ds\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov eax, [Perspective]\r
+ mov [PerspectiveDistance], eax\r
+ mov eax, [ScaleX]\r
+ mov [XScale], eax\r
+ mov eax, [ScaleY]\r
+ mov [YScale], eax\r
+\r
+ ret\r
+tdSetPerspective ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+; RX = X-axis rotation angle\r
+; RY = X-axis rotation angle\r
+; RZ = X-axis rotation angle\r
+; Output:\r
+; none\r
+;\r
+tdSetRotation PROC PASCAL FAR\r
+ ARG RX:WORD, \\r
+ RY:WORD, \\r
+ RZ:WORD\r
+ USES ds, si, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ mov bx, [RZ]\r
+ mov si, [RY]\r
+ mov di, [RX]\r
+ shl bx, 2\r
+ shl si, 2\r
+ shl di, 2\r
+\r
+ push ebp ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[si]\r
+ mov [XRotation.Y], edx\r
+\r
+ mov eax, tblSin[si]\r
+ sar eax, 8 ; Convert fixed 8:24 to fixed 16:16\r
+ mov [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si] ; EDX:EAX = fixed 16:48\r
+ shrd eax, edx, 24 ; EAX = fixed 8:24\r
+ imul tblSin[di] ; EDX:EAX = fixed 16:48\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblCos[di]\r
+ add eax, ebp\r
+ adc edx, ecx ; EDX:EAX = fixed 16:48\r
+ neg edx\r
+ mov [YRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblSin[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblCos[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [YRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblSin[di]\r
+ mov [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[di]\r
+ sub eax, ebp\r
+ sbb edx, ecx\r
+ mov [ZRotation.X], edx\r
+\r
+ mov eax, tblSin[bx]\r
+ imul tblSin[si]\r
+ shrd eax, edx, 24\r
+ imul tblCos[di]\r
+ mov ebp, eax\r
+ mov ecx, edx\r
+ mov eax, tblCos[bx]\r
+ imul tblSin[di]\r
+ add eax, ebp\r
+ add edx, ecx\r
+ neg edx\r
+ mov [ZRotation.Y], edx\r
+\r
+ mov eax, tblCos[si]\r
+ imul tblCos[di]\r
+ mov [ZRotation.Z], edx\r
+\r
+ pop ebp ; Restore EBP\r
+\r
+ ret\r
+tdSetRotation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+; TV = pointer to translation vector\r
+; Output:\r
+; none\r
+;\r
+tdSetTranslation PROC PASCAL FAR\r
+ ARG TV:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [TV]\r
+ mov eax, es:[di].X\r
+ mov [Translation.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Translation.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Translation.Z], eax\r
+\r
+ ret\r
+tdSetTranslation ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransform PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ LOCAL Adjust:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+ ALIGN DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ mov ebx, eax\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16)\r
+ mov es:[di].Z, eax\r
+; Get perspective factor\r
+ mov ebx, [PerspectiveDistance]\r
+ sub eax, ebx\r
+ neg eax ; EAX = PD - Z\r
+ xor edx, edx\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx ; EAX = fixed 16:16 result\r
+ mov [Adjust], eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.X]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ add eax, [Translation.Y]\r
+ imul [Adjust]\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdTransform ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TIMAGEPOINT\r
+; Count = number of entries to transform\r
+; DeltaX = translation distance for the X coordinate\r
+; DeltaY = translation distance for the Y coordinate\r
+; Output:\r
+; the maximum Z value\r
+;\r
+tdTransformToImage PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD, \\r
+ DeltaX:WORD, \\r
+ DeltaY:WORD\r
+ LOCAL Adjust:DWORD, \\r
+ Max:DWORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+ mov [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+ mov eax, fs:[si].Z\r
+ cmp eax, [Max]\r
+ jle @@1\r
+ mov [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+ mov ax, WORD PTR fs:[si].X[2]\r
+ add ax, [DeltaX]\r
+ mov es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+ mov ax, WORD PTR fs:[si].Y[2]\r
+ add ax, [DeltaY]\r
+ mov es:[di].IY, ax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TIMAGEPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ mov eax, [Max]\r
+ shld edx, eax, 16\r
+ ret\r
+tdTransformToImage ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+; Light = pointer to light vector\r
+; Output:\r
+; none\r
+;\r
+tdSetLight PROC PASCAL FAR\r
+ ARG L:DWORD\r
+ USES ds, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [L]\r
+ mov eax, es:[di].X\r
+ mov [Light.X], eax\r
+ mov eax, es:[di].Y\r
+ mov [Light.Y], eax\r
+ mov eax, es:[di].Z\r
+ mov [Light.Z], eax\r
+\r
+ ret\r
+tdSetLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+; Normals = pointer to an array of surface normals\r
+; Lights = pointer to an array of integer to be filled with\r
+; light intensity\r
+; Count = number of elements to transform\r
+; Output:\r
+; none\r
+;\r
+tdTransformLight PROC PASCAL FAR\r
+ ARG Normals:DWORD, \\r
+ Lights:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov fs, ax\r
+ ASSUME fs:MATH_DATA\r
+\r
+ lds si, [Normals]\r
+ les di, [Lights]\r
+ ASSUME ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+ mov eax, ds:[si].Z\r
+ imul [Light.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, ds:[si].Y\r
+ imul [Light.Y]\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, ds:[si].X\r
+ imul [Light.X]\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = fixed 32:32 intensity\r
+ add dx, [AmbientLight]\r
+ test dx, dx\r
+ jg @@1\r
+ xor dx, dx ; Return 0 for no light\r
+@@1:\r
+ mov es:[di], dx\r
+ inc di\r
+ inc di\r
+ add si, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ASSUME fs:NOTHING\r
+ ret\r
+tdTransformLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+; Normal = pointer to TPOINT surface normal vector\r
+; Output:\r
+; AX = light intensity (>=0)\r
+; Notes:\r
+; the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight PROC PASCAL FAR\r
+ ARG Normal:DWORD\r
+ USES ds, esi, es, di\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ les di, [Normal]\r
+\r
+; Transform Z coordinate\r
+ mov eax, es:[di].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.Z]\r
+ shrd eax, edx, 16\r
+ mov esi, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, es:[di].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add esi, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, es:[di].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, es:[di].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, es:[di].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ imul [Light.X]\r
+ shrd eax, edx, 16\r
+ add eax, esi\r
+ shr eax, 16\r
+\r
+; Add ambient light\r
+ add ax, [AmbientLight]\r
+ test ax, ax\r
+ jge @@Exit\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ ret\r
+tdGetSurfaceLight ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+; Source = pointer to source array of TPOINT\r
+; Dest = pointer to destination array of TPOINT\r
+; Count = number of entries to transform\r
+; Output:\r
+; none\r
+;\r
+tdRotate PROC PASCAL FAR\r
+ ARG Source:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+\r
+ mov ax, SEG MATH_DATA\r
+ mov ds, ax\r
+ ASSUME ds:MATH_DATA\r
+\r
+ lfs si, [Source]\r
+ les di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+ mov eax, fs:[si].X\r
+ imul [ZRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [ZRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [ZRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+ mov eax, fs:[si].X\r
+ imul [XRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [XRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [XRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+ mov eax, fs:[si].X\r
+ imul [YRotation.X]\r
+ mov ecx, eax\r
+ mov ebx, edx\r
+ mov eax, fs:[si].Y\r
+ imul [YRotation.Y]\r
+ add ecx, eax\r
+ adc ebx, edx\r
+ mov eax, fs:[si].Z\r
+ imul [YRotation.Z]\r
+ add eax, ecx\r
+ adc edx, ebx\r
+ shrd eax, edx, 16\r
+ mov es:[di].Y, eax\r
+\r
+ add si, SIZE TPOINT\r
+ add di, SIZE TPOINT\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdRotate ENDP\r
+\r
+tdFixedMul PROC PASCAL FAR\r
+ ARG F1:DWORD, \\r
+ F2:DWORD\r
+\r
+ mov eax, [F1]\r
+ imul [F2]\r
+ shr eax, 16\r
+\r
+ ret\r
+tdFixedMul ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+ push esi\r
+ push edi\r
+\r
+ add eax, eax\r
+ adc edx, 0\r
+ mov eax, edx ; Just discard the low bits\r
+\r
+ mov esi, eax\r
+ xor edi, edi\r
+ shld edi, esi, 16\r
+ shl esi, 16\r
+@@Loop:\r
+ mov ebx, eax\r
+ mul eax\r
+ add eax, esi\r
+ adc edx, edi\r
+ shrd eax, edx, 1\r
+ shr edx, 1\r
+ div ebx\r
+ cmp eax, ebx\r
+ jne @@Loop\r
+\r
+; Adjust EAX\r
+ shl eax, 8\r
+\r
+ pop edi\r
+ pop esi\r
+ ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+; Dest = pointer to TPOINT (vector) result\r
+; P1, P2, P3 = pointer to TPOINT points on surface\r
+; Output:\r
+; none\r
+; Notes:\r
+; the normal is given by the cross-product between (P3-P1) and\r
+; (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal PROC PASCAL FAR\r
+ ARG Dest:DWORD, \\r
+ P1:DWORD, \\r
+ P2:DWORD, \\r
+ P3:DWORD\r
+ LOCAL V1:TPOINT, \\r
+ V2:TPOINT, \\r
+ N:TPOINT\r
+ USES ds, si, es, di\r
+\r
+; Get vector V1\r
+ lds si, [P1]\r
+ les di, [P3]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V1.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V1.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V1.Z], eax\r
+\r
+; Get vector V2\r
+ les di, [P2]\r
+ mov eax, es:[di].X\r
+ sub eax, ds:[si].X\r
+ mov [V2.X], eax\r
+ mov eax, es:[di].Y\r
+ sub eax, ds:[si].Y\r
+ mov [V2.Y], eax\r
+ mov eax, es:[di].Z\r
+ sub eax, ds:[si].Z\r
+ mov [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+ mov eax, [V1.Z]\r
+ imul [V2.Y]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Y]\r
+ imul [V2.Z]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.X], eax\r
+\r
+ mov eax, [V1.X]\r
+ imul [V2.Z]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.Z]\r
+ imul [V2.X]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Y], eax\r
+\r
+ mov eax, [V1.Y]\r
+ imul [V2.X]\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [V1.X]\r
+ imul [V2.Y]\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ shrd eax, edx, 16\r
+ mov [N.Z], eax\r
+\r
+; Get normal length\r
+ mov eax, [N.X]\r
+ imul eax\r
+ mov ebx, eax\r
+ mov ecx, edx\r
+ mov eax, [N.Y]\r
+ imul eax\r
+ add ebx, eax\r
+ adc ecx, edx\r
+ mov eax, [N.Z]\r
+ imul eax\r
+ add eax, ebx\r
+ adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+ call subSqrt ; EAX = normal length\r
+ mov ebx, eax\r
+\r
+; Adjust vector and save it\r
+ les di, [Dest]\r
+ mov eax, [N.X]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].X, eax\r
+ mov eax, [N.Y]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Y, eax\r
+ mov eax, [N.Z]\r
+ cdq\r
+ shld edx, eax, 16\r
+ shl eax, 16\r
+ idiv ebx\r
+ mov es:[di].Z, eax\r
+\r
+ ret\r
+tdGetNormal ENDP\r
+\r
+TPOLY STRUC\r
+ Vtx DW 4 DUP(?)\r
+TPOLY ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+; Poly = pointer to an array of TPOLY\r
+; Vertex = pointer to an array of TPOINT\r
+; Dest = pointer to an array of integer\r
+; Count = number of polygons to check\r
+; Step = size of TPOLY structure\r
+; Output:\r
+; if the n-th polygon is invisible the n-th entry of the\r
+; Dest array is set to -1, other entries are not modified\r
+; (so it's possible to use the Light array for Dest, because\r
+; the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+ ARG Step:WORD, \\r
+ Poly:DWORD, \\r
+ Vertex:DWORD, \\r
+ Dest:DWORD, \\r
+ Count:WORD\r
+ USES ds, si, es, di, fs\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ds, WORD PTR Vertex[2]\r
+ les di, [Poly]\r
+ mov fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+ mov ax, es:[di].Vtx[2] ; Index of 2nd vertex\r
+ shl ax, 2\r
+ mov bx, ax\r
+ shl ax, 1\r
+ add bx, ax ; BX = index*SIZE TPOINT\r
+ add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex\r
+ mov ax, es:[di].Vtx[4] ; Index of 3rd vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex\r
+ mov ecx, ds:[si].X\r
+ sub ecx, ds:[bx].X ; ECX = V3.X-V2.X\r
+ mov edx, ds:[si].Y\r
+ sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y\r
+ mov ax, es:[di].Vtx[0] ; Index of 1st vertex\r
+ shl ax, 2\r
+ mov si, ax\r
+ shl ax, 1\r
+ add si, ax\r
+ add si, WORD PTR [Vertex] ; SI = offset of 1st vertex\r
+ mov eax, ds:[si].X\r
+ sub eax, ds:[bx].X ; EAX = V1.X-V2.X\r
+ mov esi, ds:[si].Y\r
+ sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y\r
+ imul edx\r
+ mov ebx, eax\r
+ xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+ mov eax, esi\r
+ imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+ sub eax, ebx\r
+ sbb edx, ecx\r
+ jl @@Next ; Polygon is visible\r
+ mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry\r
+ mov WORD PTR fs:[bx], -1 ; Remove polygon\r
+@@Next:\r
+ add WORD PTR [Dest], 2 ; Next entry for dest\r
+ add di, [Step] ; Next polygon\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+ ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT ENDS\r
+END\r
--- /dev/null
+typedef struct {\r
+ long x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT TVECTOR\r
+#define PPOINT PVECTOR\r
+\r
+#define VPTR void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+unit ThreeD;\r
+interface\r
+\r
+type\r
+ TVector = record\r
+ X, Y, Z : longint;\r
+ end;\r
+ TPoint = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight; external;\r
+procedure tdSetRotation( RX, RY, RZ: word ); external;\r
+procedure tdGetNormal; external;\r
+procedure tdSetTranslation( var TV: TVector ); external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate; external;\r
+function tdTransformToImage; external;\r
+procedure tdSetLight( var Light: TVector ); external;\r
+procedure tdSetPerspective; external;\r
+procedure tdTransformLight; external;\r
+function tdFixedMul( F1, F2: longint ): longint; external;\r
+procedure tdBackPlaneCull; external;\r
+{$L THREED}\r
+\r
+end.\r
--- /dev/null
+/*\r
+ DEMO01 - Sprites, page flipping and palette rotation\r
+ Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+uses Crt, Modex;\r
+\r
+#DEFINE MAX_SPRITE 100\r
+type\r
+ (* Sprite structure *)\r
+ TSprite = record\r
+ X, Y : integer; (* Sprite coordinates *)\r
+ DX,DY: integer; (* Deltas for sprite movement *)\r
+ W, H : integer; (* Sprite width and height *)\r
+ Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *)\r
+ end;\r
+ (* RGB color structure *)\r
+ TRgb = record\r
+ R, G, B: byte;\r
+ end;\r
+var\r
+ S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *)\r
+ Palette: array[ byte ] of TRgb; (* Palette *)\r
+ Page : word; (* Page offset *)\r
+ I : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+ I: word;\r
+begin\r
+ S.X := Random( 320 ); (* Initialize position with random values *)\r
+ S.Y := Random( 240 );\r
+ S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+ S.DY := Random( 7 )-3;\r
+ S.W := 16; (* Size is fixed in this program *)\r
+ S.H := 16;\r
+ (* The image is a square with a hole inside *)\r
+ FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+ for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+ Inc( S.X, S.DX ); (* Get new position *)\r
+ Inc( S.Y, S.DY );\r
+ (* Check sprite position, change delta if needed *)\r
+ if( S.X > 320 ) then begin\r
+ S.X := 320;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.X < -16 ) then begin\r
+ S.X := -16;\r
+ S.DX := -S.DX;\r
+ end;\r
+ if( S.Y > 240 ) then begin\r
+ S.Y := 240;\r
+ S.DY := -S.DY;\r
+ end;\r
+ if( S.Y < -16 ) then begin\r
+ S.Y := -16;\r
+ S.DY := -S.DY;\r
+ end;\r
+ (* Draw the sprite, note the Page offset added to the *)\r
+ (* Y coordinate of the image *)\r
+ mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+ (* Initialize library *)\r
+ mxInit;\r
+\r
+ (* Enter graphics mode *)\r
+ mxSetMode( MX_320x240 );\r
+\r
+ (* Print initialization message *)\r
+ mxSetTextColor( 15, OP_TRANS );\r
+ mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+ (* Initialize sprites *)\r
+ for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+ (* Draw background *)\r
+ for I:=1 to 192 do begin\r
+ mxCircle( 160, 480+120, I, I+63 );\r
+ mxCircle( 161, 480+120, I, I+63 );\r
+ end;\r
+\r
+ (* Compute and set palette *)\r
+ for I:=1 to 192 do with Palette[I+63] do begin\r
+ R := 0;\r
+ G := 0;\r
+ B := 0;\r
+ if( I < 64 ) then\r
+ R := I shr 1+31\r
+ else if( I < 128 ) then\r
+ G := (I-64) shr 1+31\r
+ else\r
+ B := (I-128) shr 1+31;\r
+ end;\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+ (* Main loop *)\r
+ Page := 240;\r
+ while( not KeyPressed ) do begin\r
+ (* Set clip region to current page *)\r
+ mxSetClipRegion( 0, Page, 320, 240 );\r
+ mxSetClip( TRUE );\r
+ (* Restore background *)\r
+ mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+ (* Draw sprites *)\r
+ for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+ (* Print message *)\r
+ mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+ (* Flip page *)\r
+ mxStartLine( Page );\r
+ Page := 240-Page;\r
+ (* Animate palette *)\r
+ mxSetPalette( @Palette[64], 64, 192 );\r
+ mxRotatePalette( @Palette[64], 192, 3 );\r
+ end;\r
+\r
+ mxSetMode( MX_TEXT );\r
+ mxTerm;\r
+end.\r
--- /dev/null
+.387
+ PUBLIC MXBITBLT
+ EXTRN SUBHORIZONTALLINEINFO:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXBITBLT:
+ push bp
+ mov bp,sp
+ sub sp,16H
+ push ds
+ push si
+ push es
+ push di
+ cmp word ptr 0cH[bp],0
+ je L$2
+ mov ax,word ptr 10H[bp]
+ and al,3
+ mov dx,word ptr 8[bp]
+ and dl,3
+ mov bx,offset L$10
+ cmp al,dl
+ jne L$1
+ mov bx,offset L$3
+L$1:
+ call bx
+L$2:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+L$3:
+ mov bx,word ptr 8[bp]
+ mov ax,word ptr 6[bp]
+ mov cx,word ptr 0cH[bp]
+ call near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+ mov byte ptr -14H[bp],al
+ mov byte ptr -16H[bp],ah
+ mov word ptr 0cH[bp],cx
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ mov es,ax
+ mov ax,word ptr 0eH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov si,word ptr 10H[bp]
+ shr si,1
+ shr si,1
+ add si,ax
+ mov dx,3ceH
+ mov ax,4105H
+ out dx,ax
+ cld
+ mov ah,byte ptr -14H[bp]
+ or ah,ah
+ je L$5
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ dec ax
+ mov cx,word ptr 0aH[bp]
+ push si
+ push di
+L$4:
+ movsb
+ add si,ax
+ add di,ax
+ dec cx
+ jne L$4
+ pop di
+ pop si
+ inc si
+ inc di
+L$5:
+ mov bx,word ptr 0cH[bp]
+ test bx,bx
+ je L$7
+ mov dx,3c4H
+ mov ax,0f02H
+ out dx,ax
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ sub ax,bx
+ mov dx,word ptr 0aH[bp]
+ push si
+ push di
+L$6:
+ mov cx,bx
+ rep movsb
+ add si,ax
+ add di,ax
+ dec dx
+ jne L$6
+ pop di
+ pop si
+ add si,bx
+ add di,bx
+L$7:
+ mov ah,byte ptr -16H[bp]
+ or ah,ah
+ je L$9
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ dec ax
+ mov cx,word ptr 0aH[bp]
+L$8:
+ movsb
+ add si,ax
+ add di,ax
+ dec cx
+ jne L$8
+L$9:
+ mov dx,3ceH
+ mov ax,4005H
+ out dx,ax
+ ret
+L$10:
+ mov cx,word ptr 0cH[bp]
+ mov bx,cx
+ shr bx,1
+ shr bx,1
+ and cl,3
+ mov al,8
+ shr al,cl
+ mov si,6
+L$11:
+ mov word ptr -8[bp+si],bx
+ shr al,1
+ adc bx,0
+ dec si
+ dec si
+ jge L$11
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ mov es,ax
+ mov ax,word ptr 0eH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov si,word ptr 10H[bp]
+ shr si,1
+ shr si,1
+ add si,ax
+ mov word ptr -0aH[bp],si
+ mov ax,word ptr 6[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,word ptr 8[bp]
+ shr di,1
+ shr di,1
+ add di,ax
+ mov word ptr -0cH[bp],di
+ mov ax,word ptr 10H[bp]
+ and al,3
+ mov byte ptr -10H[bp],al
+ mov cx,word ptr 8[bp]
+ and cl,3
+ mov al,11H
+ shl al,cl
+ mov byte ptr -12H[bp],al
+ cld
+ mov byte ptr -0eH[bp],4
+ lea bx,-8[bp]
+L$12:
+ cmp word ptr ss:[bx],0
+ je L$15
+ mov ah,byte ptr -12H[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov ah,byte ptr -10H[bp]
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov dx,word ptr 0aH[bp]
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ sub ax,word ptr ss:[bx]
+L$13:
+ mov cx,word ptr ss:[bx]
+ shr cx,1
+ rep movsw
+ rcl cx,1
+ rep movsb
+ add si,ax
+ add di,ax
+ dec dx
+ jne L$13
+ inc bx
+ inc bx
+ inc byte ptr -10H[bp]
+ and byte ptr -10H[bp],3
+ jne L$14
+ inc word ptr -0aH[bp]
+L$14:
+ rol byte ptr -12H[bp],1
+ adc word ptr -0cH[bp],0
+ mov si,word ptr -0aH[bp]
+ mov di,word ptr -0cH[bp]
+ dec byte ptr -0eH[bp]
+ jne L$12
+L$15:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC XSUBCLIPLINE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ or al,byte ptr [bx+si]
+L$2:
+ DW offset L$3
+ or al,byte ptr [bx+si]
+ DW offset L$4
+ or word ptr [bx+si],ax
+ DW offset L$5
+ ????
+ inc word ptr [bx+si]
+ add byte ptr [bp+si],cl
+ add byte ptr 0a00H[bx+si],al
+ add byte ptr 900H[bp],dl
+ add byte ptr -100H[si],ch
+ inc word ptr [bx+si]
+ add byte ptr ds:[0c000H],al
+ add byte ptr ds:[0ce00H],al
+ add byte ptr [di],al
+ add ah,bl
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ add bh,bh
+ inc word ptr [bx+si]
+ DB 0
+L$3:
+ DW offset MX_TEXT+0ecH
+ DW offset MX_TEXT+0eeH
+ DW offset MX_TEXT+0f1H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+0f4H
+ DW offset MX_TEXT+0f7H
+ DW offset MX_TEXT+104H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+111H
+ DW offset MX_TEXT+114H
+ DW offset MX_TEXT+121H
+L$4:
+ DW offset MX_TEXT+132H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+135H
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+13bH
+ DW offset MX_TEXT+0eaH
+ DW offset MX_TEXT+148H
+ DW offset L$7
+ DW offset L$10
+ DW offset L$7
+ DW offset L$11
+L$5:
+ DW offset L$14
+ DW offset L$15
+ DW offset L$7
+ DW offset L$7
+ DW offset L$16
+ DW offset L$17
+ DW offset L$7
+ DW offset L$7
+ DW offset L$18
+ DW offset L$19
+ DW offset L$22
+ DW offset L$23
+ DW offset L$24
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$25
+ DW offset L$26
+ DW offset L$27
+ DW offset L$30
+ DW offset L$7
+ DW offset L$31
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$32
+ DW offset L$7
+ DW offset L$33
+ DW offset L$36
+ DW offset L$37
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$7
+ DW offset L$38
+ DW offset L$39
+ DW offset L$43
+ DW offset L$44
+ DW offset L$45
+ DW offset L$7
+ DW offset L$46
+ DW offset L$47
+ DW offset L$48
+ DW offset L$51
+ DW offset L$7
+ DW offset L$52
+ DW offset L$7
+ DW offset L$53
+ DW offset L$7
+ DW offset L$54
+ DW offset L$58
+ DW offset L$59
+ DW offset L$7
+ DW offset L$7
+ DW offset L$60
+ DW offset L$61
+L$6:
+ clc
+ ret
+L$7:
+ stc
+ ret
+ clc
+ ret
+ jmp near ptr L$67
+ jmp near ptr L$68
+ jmp near ptr L$70
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$6
+ jmp near ptr L$70
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$6
+ jmp near ptr L$70
+ jmp near ptr L$69
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$6
+ jmp near ptr L$69
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$6
+ jmp near ptr L$69
+L$8:
+ stc
+ ret
+L$9:
+ clc
+ ret
+ jmp near ptr L$63
+ call near ptr L$63
+ jmp near ptr L$68
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$8
+ jmp near ptr L$70
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$8
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$9
+ jmp near ptr L$68
+L$10:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$8
+ jmp near ptr L$69
+L$11:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$8
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$9
+ jmp near ptr L$68
+L$12:
+ clc
+ ret
+L$13:
+ stc
+ ret
+L$14:
+ jmp near ptr L$64
+L$15:
+ call near ptr L$64
+ jmp near ptr L$67
+L$16:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$13
+ jmp near ptr L$70
+L$17:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$13
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$12
+ jmp near ptr L$67
+L$18:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$13
+ jmp near ptr L$69
+L$19:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$13
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$12
+ jmp near ptr L$67
+L$20:
+ clc
+ ret
+L$21:
+ stc
+ ret
+L$22:
+ jmp near ptr L$66
+L$23:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$21
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$20
+ jmp near ptr L$70
+L$24:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$21
+ jmp near ptr L$68
+L$25:
+ call near ptr L$66
+ jmp near ptr L$69
+L$26:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$21
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$20
+ jmp near ptr L$69
+L$27:
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$21
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$20
+ jmp near ptr L$69
+L$28:
+ clc
+ ret
+L$29:
+ stc
+ ret
+L$30:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$28
+ jmp near ptr L$66
+L$31:
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY1
+ jl L$29
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$28
+ jmp near ptr L$63
+L$32:
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX1
+ jl L$29
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$28
+ jmp near ptr L$63
+L$33:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$29
+ call near ptr L$68
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$29
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$28
+ jmp near ptr L$69
+L$34:
+ clc
+ ret
+L$35:
+ stc
+ ret
+L$36:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$34
+ jmp near ptr L$66
+L$37:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jl L$35
+ call near ptr L$66
+ cmp di,word ptr cs:MX_CLIPX2
+ jle L$34
+ jmp near ptr L$64
+L$38:
+ call near ptr L$69
+ cmp cx,word ptr cs:MX_CLIPX2
+ jg L$35
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$34
+ jmp near ptr L$66
+L$39:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jl L$35
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$35
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$40
+ call near ptr L$69
+L$40:
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$34
+ jmp near ptr L$66
+L$41:
+ clc
+ ret
+L$42:
+ stc
+ ret
+L$43:
+ jmp near ptr L$65
+L$44:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$42
+ jmp near ptr L$67
+L$45:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$42
+ jmp near ptr L$68
+L$46:
+ call near ptr L$65
+ jmp near ptr L$70
+L$47:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$42
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$42
+ jmp near ptr L$70
+L$48:
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$42
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$41
+ jmp near ptr L$70
+L$49:
+ clc
+ ret
+L$50:
+ stc
+ ret
+L$51:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$49
+ jmp near ptr L$65
+L$52:
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$50
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$49
+ jmp near ptr L$63
+L$53:
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX1
+ jl L$50
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$49
+ jmp near ptr L$65
+L$54:
+ call near ptr L$63
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$50
+ call near ptr L$68
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$50
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$55
+ call near ptr L$65
+L$55:
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$49
+ jmp near ptr L$70
+L$56:
+ clc
+ ret
+L$57:
+ stc
+ ret
+L$58:
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$56
+ jmp near ptr L$65
+L$59:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$57
+ call near ptr L$65
+ cmp di,word ptr cs:MX_CLIPX2
+ jle L$56
+ jmp L$64
+L$60:
+ call near ptr L$70
+ cmp cx,word ptr cs:MX_CLIPX2
+ jg L$57
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$56
+ jmp L$65
+L$61:
+ call near ptr L$67
+ cmp si,word ptr cs:MX_CLIPY2
+ jg L$57
+ call near ptr L$64
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$57
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$62
+ call near ptr L$70
+L$62:
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$56
+ jmp L$65
+L$63:
+ mov ax,si
+ sub ax,bx
+ mov dx,word ptr cs:MX_CLIPX1
+ sub dx,di
+ imul dx
+ mov bp,cx
+ sub bp,di
+ idiv bp
+ add bx,ax
+ mov di,word ptr cs:MX_CLIPX1
+ clc
+ ret
+L$64:
+ mov ax,si
+ sub ax,bx
+ mov dx,word ptr cs:MX_CLIPX2
+ sub dx,di
+ imul dx
+ mov bp,cx
+ sub bp,di
+ idiv bp
+ add bx,ax
+ mov di,word ptr cs:MX_CLIPX2
+ clc
+ ret
+L$65:
+ mov ax,cx
+ sub ax,di
+ mov dx,word ptr cs:MX_CLIPY2
+ sub dx,bx
+ imul dx
+ mov bp,si
+ sub bp,bx
+ idiv bp
+ add di,ax
+ mov bx,word ptr cs:MX_CLIPY2
+ clc
+ ret
+L$66:
+ mov ax,cx
+ sub ax,di
+ mov dx,word ptr cs:MX_CLIPY1
+ sub dx,bx
+ imul dx
+ mov bp,si
+ sub bp,bx
+ idiv bp
+ add di,ax
+ mov bx,word ptr cs:MX_CLIPY1
+ clc
+ ret
+L$67:
+ mov ax,bx
+ sub ax,si
+ mov dx,word ptr cs:MX_CLIPX1
+ sub dx,cx
+ imul dx
+ mov bp,di
+ sub bp,cx
+ idiv bp
+ add si,ax
+ mov cx,word ptr cs:MX_CLIPX1
+ clc
+ ret
+L$68:
+ mov ax,bx
+ sub ax,si
+ mov dx,word ptr cs:MX_CLIPX2
+ sub dx,cx
+ imul dx
+ mov bp,di
+ sub bp,cx
+ idiv bp
+ add si,ax
+ mov cx,word ptr cs:MX_CLIPX2
+ clc
+ ret
+L$69:
+ mov ax,di
+ sub ax,cx
+ mov dx,word ptr cs:MX_CLIPY2
+ sub dx,si
+ imul dx
+ mov bp,bx
+ sub bp,si
+ idiv bp
+ add cx,ax
+ mov si,word ptr cs:MX_CLIPY2
+ clc
+ ret
+L$70:
+ mov ax,di
+ sub ax,cx
+ mov dx,word ptr cs:MX_CLIPY1
+ sub dx,si
+ imul dx
+ mov bp,bx
+ sub bp,si
+ idiv bp
+ add cx,ax
+ mov si,word ptr cs:MX_CLIPY1
+ clc
+ ret
+XSUBCLIPLINE:
+ push bp
+ xor si,si
+ cmp dx,word ptr cs:MX_CLIPY2
+ jle L$71
+ or si,8
+ jmp L$72
+L$71:
+ cmp dx,word ptr cs:MX_CLIPY1
+ jge L$72
+ or si,4
+L$72:
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$73
+ or si,2
+ jmp L$74
+L$73:
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$74
+ or si,1
+L$74:
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$75
+ or si,80H
+ jmp L$76
+L$75:
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$76
+ or si,40H
+L$76:
+ cmp ax,word ptr cs:MX_CLIPX2
+ jle L$77
+ or si,20H
+ jmp L$78
+L$77:
+ cmp ax,word ptr cs:MX_CLIPX1
+ jge L$78
+ or si,10H
+L$78:
+ mov di,si
+ and di,0fH
+ and si,0f0H
+ shr si,1
+ shr si,1
+ cmp di,word ptr cs:L$1[si]
+ jg L$79
+ mov si,word ptr cs:L$2[si]
+ shl di,1
+ add si,di
+ mov di,ax
+ mov si,word ptr cs:[si]
+ xchg si,dx
+ call dx
+ mov ax,di
+ mov dx,si
+ pop bp
+ ret
+L$79:
+ pop bp
+ stc
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXCOLORTOGRAY
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCOLORTOGRAY:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 6[bp]
+ jcxz L$2
+ lds si,dword ptr 0cH[bp]
+ les di,dword ptr 8[bp]
+ cld
+ mov bx,4d97H
+L$1:
+ lodsb
+ mul bh
+ mov dx,ax
+ lodsb
+ mul bl
+ add dx,ax
+ lodsb
+ mov ah,1cH
+ mul ah
+ add ax,dx
+ mov al,ah
+ stosw
+ stosb
+ loop L$1
+L$2:
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0aH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXCIRCLE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCIRCLE:
+ push bp
+ mov bp,sp
+ sub sp,2
+ push ds
+ push si
+ push di
+ xor si,si
+ mov di,word ptr 8[bp]
+ mov ax,3
+ sub ax,di
+ sub ax,di
+ mov word ptr -2[bp],ax
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+L$1:
+ cmp si,di
+ jg L$3
+ mov ax,si
+ mov bx,di
+ call near ptr L$4
+ mov ax,si
+ neg ax
+ mov bx,di
+ call near ptr L$4
+ mov ax,si
+ mov bx,di
+ neg bx
+ call near ptr L$4
+ mov ax,si
+ neg ax
+ mov bx,di
+ neg bx
+ call near ptr L$4
+ mov ax,di
+ mov bx,si
+ call near ptr L$4
+ mov ax,di
+ neg ax
+ mov bx,si
+ call near ptr L$4
+ mov ax,di
+ mov bx,si
+ neg bx
+ call near ptr L$4
+ mov ax,di
+ neg ax
+ mov bx,si
+ neg bx
+ call near ptr L$4
+ mov ax,word ptr -2[bp]
+ test ax,ax
+ jl L$2
+ mov ax,di
+ shl ax,1
+ shl ax,1
+ sub ax,4
+ sub word ptr -2[bp],ax
+ dec di
+L$2:
+ mov ax,si
+ shl ax,1
+ shl ax,1
+ add ax,6
+ add word ptr -2[bp],ax
+ inc si
+ jmp L$1
+L$3:
+ xor ax,ax
+ pop di
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+L$4:
+ add bx,word ptr 0cH[bp]
+ add ax,word ptr 0aH[bp]
+ cmp bx,word ptr cs:MX_CLIPX1
+ jl L$5
+ cmp bx,word ptr cs:MX_CLIPX2
+ jg L$5
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$5
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$5
+ mul word ptr cs:MX_BYTESPERLINE
+ mov cx,bx
+ shr bx,1
+ shr bx,1
+ add bx,ax
+ and cl,3
+ mov ax,102H
+ shl ah,cl
+ mov dx,3c4H
+ out dx,ax
+ mov al,byte ptr 6[bp]
+ mov byte ptr [bx],al
+L$5:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MX_CLIPX1
+ PUBLIC MX_CLIPY1
+ PUBLIC MX_CLIPX2
+ PUBLIC MX_CLIPY2
+ PUBLIC MXSETCLIP
+ PUBLIC MXGETCLIP
+ PUBLIC MXSETSYSCLIPREGION
+ PUBLIC MXSETCLIPREGION
+ PUBLIC MXGETCLIPREGION
+ PUBLIC SUBCLIPIMAGE
+ PUBLIC SUBCLIPBOX
+ EXTRN MX_CODESEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_CLIPX1:
+ add byte ptr [bx+si],al
+MX_CLIPY1:
+ add byte ptr [bx+si],al
+MX_CLIPX2:
+ add byte ptr [bx+si],al
+MX_CLIPY2:
+ add byte ptr [bx+si],al
+L$1:
+ add byte ptr [bx+si],al
+L$2:
+ add byte ptr [bx+si],al
+L$3:
+ add byte ptr [bx+si],al
+L$4:
+ add byte ptr [bx+si],al
+L$5:
+ add byte ptr [bx+si],al
+L$6:
+ add byte ptr [bx+si],al
+L$7:
+ add byte ptr [bx+si],al
+L$8:
+ add byte ptr [bx+si],al
+L$9:
+ DB 0
+MXSETCLIP:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr L$5
+ mov bx,word ptr L$6
+ mov cx,word ptr L$7
+ mov dx,word ptr L$8
+ cmp byte ptr 6[bp],1
+ je L$10
+ mov ax,word ptr L$1
+ mov bx,word ptr L$2
+ mov cx,word ptr L$3
+ mov dx,word ptr L$4
+L$10:
+ mov word ptr MX_CLIPX1,ax
+ mov word ptr MX_CLIPY1,bx
+ mov word ptr MX_CLIPX2,cx
+ mov word ptr MX_CLIPY2,dx
+ mov al,byte ptr 6[bp]
+ xchg byte ptr L$9,al
+ xor ah,ah
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 2
+MXGETCLIP:
+ mov al,byte ptr cs:L$9
+ xor ah,ah
+ retf
+MXSETSYSCLIPREGION:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ xor ax,ax
+ mov word ptr L$1,ax
+ mov word ptr L$2,ax
+ mov ax,word ptr 8[bp]
+ dec ax
+ mov word ptr L$3,ax
+ mov ax,word ptr 6[bp]
+ dec ax
+ mov word ptr L$4,ax
+ mov ax,0
+ push ax
+ push cs
+ call near ptr MXSETCLIP
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXSETCLIPREGION:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 0cH[bp]
+ mov word ptr L$5,ax
+ mov ax,word ptr 0aH[bp]
+ mov word ptr L$6,ax
+ mov ax,word ptr 8[bp]
+ add ax,word ptr 0cH[bp]
+ dec ax
+ mov word ptr L$7,ax
+ mov ax,word ptr 6[bp]
+ add ax,word ptr 0aH[bp]
+ dec ax
+ mov word ptr L$8,ax
+ mov al,byte ptr L$9
+ cmp al,1
+ jne L$11
+ push ax
+ push cs
+ call near ptr MXSETCLIP
+L$11:
+ xor ax,ax
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MXGETCLIPREGION:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push es
+ push di
+ mov ax,word ptr cs:L$5
+ les di,dword ptr 12H[bp]
+ mov word ptr es:[di],ax
+ mov ax,word ptr cs:L$6
+ les di,dword ptr 0eH[bp]
+ mov word ptr es:[di],ax
+ mov ax,word ptr cs:L$7
+ sub ax,word ptr cs:L$5
+ inc ax
+ les di,dword ptr 0aH[bp]
+ mov word ptr es:[di],ax
+ mov ax,word ptr cs:L$8
+ sub ax,word ptr cs:L$6
+ inc ax
+ les di,dword ptr 6[bp]
+ mov word ptr es:[di],ax
+ mov al,byte ptr cs:L$9
+ xor ah,ah
+ pop di
+ pop es
+ mov sp,bp
+ pop bp
+ retf 10H
+SUBCLIPIMAGE:
+ xor si,si
+ mov di,word ptr cs:MX_CLIPY1
+ cmp ax,di
+ jge L$12
+ sub di,ax
+ sub dx,di
+ jle L$16
+ mov ax,di
+ mov di,dx
+ mul cx
+ mov si,ax
+ mov dx,di
+ mov ax,word ptr cs:MX_CLIPY1
+L$12:
+ mov di,word ptr cs:MX_CLIPY2
+ cmp ax,di
+ jg L$16
+ inc di
+ sub di,dx
+ sub di,ax
+ jge L$13
+ add dx,di
+L$13:
+ mov di,word ptr cs:MX_CLIPX1
+ cmp bx,di
+ jge L$14
+ sub di,bx
+ sub cx,di
+ jle L$16
+ add si,di
+ mov bx,word ptr cs:MX_CLIPX1
+L$14:
+ mov di,word ptr cs:MX_CLIPX2
+ cmp bx,di
+ jg L$16
+ inc di
+ sub di,bx
+ sub di,cx
+ jge L$15
+ add cx,di
+L$15:
+ clc
+ ret
+L$16:
+ stc
+ ret
+SUBCLIPBOX:
+ mov di,word ptr cs:MX_CLIPY1
+ cmp ax,di
+ jge L$17
+ sub di,ax
+ sub dx,di
+ jle L$21
+ mov ax,word ptr cs:MX_CLIPY1
+L$17:
+ mov di,word ptr cs:MX_CLIPY2
+ cmp ax,di
+ jg L$21
+ inc di
+ sub di,dx
+ sub di,ax
+ jge L$18
+ add dx,di
+L$18:
+ mov di,word ptr cs:MX_CLIPX1
+ cmp bx,di
+ jge L$19
+ sub di,bx
+ sub cx,di
+ jle L$21
+ mov bx,word ptr cs:MX_CLIPX1
+L$19:
+ mov di,word ptr cs:MX_CLIPX2
+ cmp bx,di
+ jg L$21
+ inc di
+ sub di,bx
+ sub di,cx
+ jge L$20
+ add cx,di
+L$20:
+ clc
+ ret
+L$21:
+ stc
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXFILLBOX
+ EXTRN SUBCLIPBOX:BYTE
+ EXTRN SUBHORIZONTALLINEINFO:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ mov ah,al
+ shr cx,1
+ rep stosw
+ rcl cx,1
+ rep stosb
+ ret
+L$2:
+ mov byte ptr [bx],al
+ add bx,dx
+ loop L$2
+ ret
+L$3:
+ mov si,di
+L$4:
+ mov ah,byte ptr [si]
+ mov byte ptr [si],al
+ inc si
+ loop L$4
+ ret
+L$5:
+ mov ah,byte ptr [bx]
+ mov byte ptr [bx],al
+ add bx,dx
+ loop L$5
+ ret
+MXFILLBOX:
+ push bp
+ mov bp,sp
+ sub sp,8
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 10H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov cx,word ptr 0cH[bp]
+ mov dx,word ptr 0aH[bp]
+ call near ptr MX_TEXT:SUBCLIPBOX
+ jae L$6
+ jmp near ptr L$12
+L$6:
+ mov word ptr 0aH[bp],dx
+ call near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+ mov word ptr 0cH[bp],cx
+ mov byte ptr -2[bp],al
+ mov byte ptr -4[bp],ah
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov es,ax
+ mov ds,ax
+ cld
+ mov word ptr -6[bp],offset L$2
+ mov word ptr -8[bp],offset L$1
+ mov ax,word ptr 6[bp]
+ cmp al,3
+ ja L$7
+ cmp al,0
+ je L$7
+ shl al,1
+ shl al,1
+ shl al,1
+ mov ah,al
+ mov al,3
+ mov dx,3ceH
+ out dx,ax
+ mov word ptr -6[bp],offset L$5
+ mov word ptr -8[bp],offset L$3
+L$7:
+ mov ah,byte ptr -2[bp]
+ or ah,ah
+ je L$8
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ mov cx,word ptr 0aH[bp]
+ mov bx,di
+ mov al,byte ptr 8[bp]
+ call word ptr -6[bp]
+ inc di
+L$8:
+ mov cx,word ptr 0cH[bp]
+ jcxz L$10
+ mov dx,3c4H
+ mov ax,0f02H
+ out dx,ax
+ mov al,byte ptr 8[bp]
+ mov bx,di
+ mov dx,word ptr 0aH[bp]
+ push di
+L$9:
+ mov di,bx
+ call word ptr -8[bp]
+ mov cx,word ptr 0cH[bp]
+ add bx,word ptr cs:MX_BYTESPERLINE
+ dec dx
+ jne L$9
+ pop di
+ add di,word ptr 0cH[bp]
+L$10:
+ mov ah,byte ptr -4[bp]
+ or ah,ah
+ je L$11
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ mov cx,word ptr 0aH[bp]
+ mov bx,di
+ mov al,byte ptr 8[bp]
+ call word ptr -6[bp]
+L$11:
+ mov dx,3ceH
+ mov ax,3
+ out dx,ax
+L$12:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXFADEPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+ inc bx
+ outsw
+ jo L$5
+ jb L$4
+ push 2074H
+ sub byte ptr 29H[bp+di],ah
+ and byte ptr [bx+di],dh
+ cmp word ptr [bx+di],di
+ xor ch,byte ptr [di]
+ xor word ptr [bx+di],di
+ cmp word ptr [si],si
+ and byte ptr 52H[bx+di],al
+ push sp
+ dec cx
+ push bx
+ and byte ptr 2eH[bp+di],dh
+ jb L$1
+ insb
+ and byte ptr cs:6cH[bx+di],al
+ insb
+ and byte ptr 69H[bp+si],dh
+ push 7374H
+ and byte ptr 65H[bp+si],dh
+ jae L$7
+ jb L$9
+ DB 65H, 64H, 2eH
+MXFADEPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,60aH
+ push si
+ push di
+ push ds
+ push es
+ mov word ptr -608H[bp],1
+ mov ax,word ptr 10H[bp]
+ and ax,0ff00H
+L$1:
+ je L$2
+ mov cl,8
+ shr ax,cl
+ mov word ptr -608H[bp],ax
+L$2:
+ mov ax,word ptr 10H[bp]
+ and ax,0feH
+ mov cl,1
+ shr ax,cl
+ or ax,ax
+ jne L$3
+ mov ax,30H
+L$3:
+ mov word ptr -60aH[bp],ax
+L$4:
+ inc ax
+ mov byte ptr -606H[bp],al
+ mov byte ptr -604H[bp],1
+ DB 0c6H, 86H, 0feH, 0f9H
+L$5:
+ add byte ptr 0e46H[bp+di],cl
+ cmp ax,100H
+ jb L$6
+ jmp near ptr L$12
+L$6:
+ add ax,word ptr 0cH[bp]
+ cmp ax,100H
+ jbe L$8
+ mov ax,100H
+ sub ax,word ptr 0eH[bp]
+ DB 89H, 46H
+L$7:
+ or al,0bH
+ ????
+ jne L$8
+ jmp near ptr L$12
+L$8:
+ mov cx,word ptr 0cH[bp]
+ mov ax,cx
+ shl ax,1
+ add cx,ax
+ mov ax,ss
+L$9:
+ mov es,ax
+ lea di,-300H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov si,ax
+ shl ax,1
+ add ax,si
+ lds si,dword ptr 12H[bp]
+ add si,ax
+ cld
+ shr cx,1
+ rep movsw
+ rcl cx,1
+ rep movsb
+ test word ptr 10H[bp],1
+ je L$10
+ mov ax,word ptr -60aH[bp]
+ mov byte ptr -602H[bp],al
+ mov byte ptr -604H[bp],0ffH
+ mov ax,ss
+ mov ds,ax
+ mov es,ax
+ lea di,-300H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov cx,word ptr 0cH[bp]
+ call near ptr L$19
+L$10:
+ mov bh,byte ptr 0aH[bp]
+ and bh,3fH
+ mov bl,byte ptr 8[bp]
+ and bl,3fH
+ mov dh,byte ptr 6[bp]
+ and dh,3fH
+ mov dl,byte ptr -602H[bp]
+ mov ax,ss
+ mov ds,ax
+ mov es,ax
+L$11:
+ mov ax,word ptr 0cH[bp]
+ mov cx,word ptr -60aH[bp]
+ lea si,-300H[bp]
+ lea di,-600H[bp]
+ call near ptr L$13
+ push bx
+ push dx
+ lea si,-600H[bp]
+ mov ax,word ptr 0eH[bp]
+ mov bx,word ptr 0cH[bp]
+ mov cx,word ptr -608H[bp]
+ call near ptr L$15
+ pop dx
+ pop bx
+ add dl,byte ptr -604H[bp]
+ dec byte ptr -606H[bp]
+ jne L$11
+L$12:
+ pop es
+ pop ds
+ pop di
+ pop si
+ mov sp,bp
+ pop bp
+ retf 10H
+L$13:
+ cld
+ push bp
+ mov bp,ax
+L$14:
+ lodsb
+ sub al,bh
+ imul dl
+ idiv cl
+ add al,bh
+ stosb
+ lodsb
+ sub al,bl
+ imul dl
+ idiv cl
+ add al,bl
+ stosb
+ lodsb
+ sub al,dh
+ imul dl
+ idiv cl
+ add al,dh
+ stosb
+ dec bp
+ jne L$14
+ pop bp
+ ret
+L$15:
+ mov ah,al
+ mov dx,3daH
+L$16:
+ in al,dx
+ test al,8
+ jne L$16
+L$17:
+ in al,dx
+ test al,8
+ je L$17
+ loop L$16
+ mov cx,bx
+ mov dx,3c8H
+ mov al,ah
+ out dx,al
+ inc dx
+ cld
+ cli
+L$18:
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ loop L$18
+ sti
+ ret
+L$19:
+ mov dx,3c7H
+ out dx,al
+ inc dx
+ inc dx
+ cld
+L$20:
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ loop L$20
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGETCOLOR
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETCOLOR:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr 12H[bp]
+ mov dx,3c7H
+ out dx,al
+ inc dx
+ inc dx
+ lds si,dword ptr 0eH[bp]
+ in al,dx
+ mov byte ptr [si],al
+ lds si,dword ptr 0aH[bp]
+ in al,dx
+ mov byte ptr [si],al
+ lds si,dword ptr 6[bp]
+ in al,dx
+ mov byte ptr [si],al
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0eH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGETIMAGE
+ EXTRN SUBCLIPIMAGE:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETIMAGE:
+ push bp
+ mov bp,sp
+ sub sp,10H
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 0cH[bp]
+ mov ax,word ptr 0aH[bp]
+ mov cx,word ptr 8[bp]
+ mov dx,word ptr 6[bp]
+ call near ptr MX_TEXT:SUBCLIPIMAGE
+ jae L$1
+ jmp near ptr L$7
+L$1:
+ mov word ptr 6[bp],dx
+ add word ptr 0eH[bp],si
+ mul word ptr cs:MX_BYTESPERLINE
+ mov si,bx
+ shr si,1
+ shr si,1
+ add si,ax
+ mov word ptr -0aH[bp],si
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+ and bl,3
+ mov byte ptr -0eH[bp],bl
+ mov bx,cx
+ shr bx,1
+ shr bx,1
+ and cl,3
+ mov al,8
+ shr al,cl
+ mov di,6
+L$2:
+ mov word ptr -8[bp+di],bx
+ shr al,1
+ adc bx,0
+ dec di
+ dec di
+ jge L$2
+ cld
+ mov byte ptr -10H[bp],4
+ lea bx,-8[bp]
+ mov es,word ptr 10H[bp]
+ mov ah,byte ptr -0eH[bp]
+L$3:
+ cmp word ptr ss:[bx],0
+ je L$7
+ mov di,word ptr 0eH[bp]
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov dx,word ptr 6[bp]
+ mov si,word ptr -0aH[bp]
+L$4:
+ push si
+ push di
+ mov cx,word ptr ss:[bx]
+L$5:
+ movsb
+ add di,3
+ dec cx
+ jne L$5
+ pop di
+ pop si
+ add di,word ptr 8[bp]
+ add si,word ptr cs:MX_BYTESPERLINE
+ dec dx
+ jne L$4
+ inc bx
+ inc bx
+ inc ah
+ test ah,4
+ je L$6
+ inc word ptr -0aH[bp]
+ and ah,3
+L$6:
+ inc word ptr 0eH[bp]
+ dec byte ptr -10H[bp]
+ jne L$3
+L$7:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGAMMACORRECT
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bp+si],cl
+ push cs
+ adc word ptr [bp+di],dx
+ adc ax,1817H
+ sbb bl,byte ptr [bp+di]
+ sbb al,1dH
+ pop ds
+ and byte ptr [bx+di],ah
+ and ah,byte ptr [bp+di]
+ and al,25H
+ and ax,2726H
+ sub byte ptr [bx+di],ch
+ sub word ptr [bp+si],bp
+ sub bp,word ptr [si]
+ sub al,2dH
+ das
+ xor byte ptr [bx+si],dh
+ xor word ptr [bx+di],si
+ xor dh,byte ptr [bp+di]
+ xor si,word ptr [si]
+ xor al,35H
+ xor ax,3636H
+ aaa
+ aaa
+ cmp byte ptr [bx+si],bh
+ cmp word ptr [bx+di],di
+ cmp bh,byte ptr [bp+si]
+ cmp di,word ptr [bp+di]
+ cmp al,3cH
+ cmp ax,3e3dH
+ aas
+ aas
+MXGAMMACORRECT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 6[bp]
+ jcxz L$3
+ lds si,dword ptr 0cH[bp]
+ les di,dword ptr 8[bp]
+ mov bx,offset L$1
+ cld
+ mov ax,cx
+ add cx,cx
+ add cx,ax
+L$2:
+ lodsb
+ xlat word ptr cs:[bx]
+ stosb
+ loop L$2
+L$3:
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0aH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGETPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push es
+ push di
+ les di,dword ptr 0aH[bp]
+ mov cx,word ptr 6[bp]
+ mov ax,word ptr 8[bp]
+ mov dx,3c7H
+ out dx,al
+ inc dx
+ inc dx
+ cld
+L$1:
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ in al,dx
+ stosb
+ loop L$1
+ pop di
+ pop es
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGETVERSION
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETVERSION:
+ mov ax,128H
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC SUBHORIZONTALLINEINFO
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bx+si],al
+ add ax,word ptr [bx+si]
+ add al,byte ptr [bx+si]
+ add word ptr [bx+si],ax
+L$2:
+ add byte ptr ds:[80cH],cl
+L$3:
+ add byte ptr [bx+di],al
+ add ax,word ptr [bx]
+L$4:
+ DB 2, 6
+SUBHORIZONTALLINEINFO:
+ DD ds:[0f72eH]
+ add byte ptr -2e05H[bp+di],cl
+ out dx,ax
+ shr di,1
+ add di,ax
+ and bx,3
+ mov al,byte ptr cs:L$2[bx]
+ shl bx,1
+ sub cx,word ptr cs:L$1[bx]
+ jge L$5
+ mov bx,cx
+ inc bx
+ inc bx
+ and al,byte ptr cs:L$4[bx]
+ xor ah,ah
+ xor cx,cx
+ jmp L$6
+L$5:
+ mov bx,cx
+ and bx,3
+ mov ah,byte ptr cs:L$3[bx]
+ shr cx,1
+ shr cx,1
+L$6:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MX_VIDEOSEGMENT
+ PUBLIC MX_CODESEGMENT
+ PUBLIC MXINIT
+ PUBLIC MXTERM
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+ dec bp
+ dec di
+ inc sp
+ inc bp
+ pop ax
+ and byte ptr 69H[si],ch
+ bound si,word ptr 61H[bp+si]
+ jb L$3
+ and byte ptr [di],ch
+ and byte ptr 6fH[bp+di],al
+ jo L$5
+ jb L$2
+ push 2074H
+ sub byte ptr 29H[bp+di],ah
+ and byte ptr [bx+di],dh
+ cmp word ptr [bx+di],di
+ xor ch,byte ptr [di]
+ xor word ptr [bx+di],di
+ cmp word ptr [si],si
+ and byte ptr 6cH[bx+di],al
+ ; The label referred to here is an undefined location
+ jae 0a0H
+ popa
+ outsb
+ ; The label referred to here is an undefined location
+ jb 0a1H
+ and byte ptr 63H[bp+di],dl
+ outsw
+ ; The label referred to here is an undefined location
+ je 0acH
+ DB 69H
+MX_VIDEOSEGMENT:
+ DB 0, 0a0H
+MX_CODESEGMENT:
+ DW MX_TEXT
+MXINIT:
+ push bp
+ mov bp,sp
+ sub sp,6
+ push ds
+ push si
+ push es
+ push di
+ mov word ptr -2[bp],0ffffH
+ mov word ptr -4[bp],0a000H
+ mov word ptr -6[bp],cs
+ mov ax,1686H
+ int 2fH
+ or ax,ax
+ jne L$1
+ mov ax,0aH
+ mov bx,cs
+ int 31H
+ jb L$4
+ mov word ptr -6[bp],ax
+ mov ax,2
+ mov bx,0a000H
+ int 31H
+ jb L$4
+ mov word ptr -4[bp],ax
+L$1:
+ mov ds,word ptr -6[bp]
+ mov word ptr MX_CODESEGMENT,ds
+ DB 8bH, 46H
+L$2:
+ cld
+ mov word ptr MX_VIDEOSEGMENT,ax
+ DB 0c7H, 46H, 0feH
+L$3:
+ add byte ptr [bx+si],al
+L$4:
+ mov ax,word ptr -2[bp]
+ pop di
+ pop es
+L$5:
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf
+MXTERM:
+ xor ax,ax
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXLOADLATCHES
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXLOADLATCHES:
+ push ds
+ push si
+ mov dx,3ceH
+ mov ax,0ff08H
+ out dx,ax
+ mov ax,3
+ out dx,ax
+ mov ax,5
+ out dx,ax
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ mov si,0ffffH
+ mov bh,8
+ mov cx,3
+L$1:
+ mov dx,3ceH
+ mov al,4
+ mov ah,cl
+ out dx,ax
+ mov dx,3c4H
+ mov al,2
+ mov ah,bh
+ out dx,ax
+ mov al,byte ptr [si]
+ push ax
+ mov byte ptr [si],bl
+ mov al,byte ptr [di]
+ shr bh,1
+ loop L$1
+ mov cx,3
+ mov bh,8
+ mov dx,3c4H
+L$2:
+ mov al,2
+ mov ah,bh
+ out dx,ax
+ pop ax
+ mov byte ptr [si],al
+ shr bh,1
+ loop L$2
+ pop si
+ pop ds
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXLINE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ DW offset L$29
+ DW offset L$32
+ DW offset L$35
+ DW offset L$38
+MXLINE:
+ push bp
+ mov bp,sp
+ sub sp,12H
+ push ds
+ push si
+ push di
+ mov ax,word ptr 10H[bp]
+ mov bx,word ptr 0eH[bp]
+ mov cx,word ptr 0cH[bp]
+ mov dx,word ptr 0aH[bp]
+ call near ptr L$8
+ jae L$2
+ jmp near ptr L$7
+L$2:
+ mov si,cx
+ xchg ax,si
+ sub ax,si
+ jge L$3
+ xchg cx,si
+ xchg dx,bx
+ neg ax
+L$3:
+ mov word ptr -2[bp],ax
+ mov cx,word ptr cs:MX_BYTESPERLINE
+ mov ax,dx
+ sub ax,bx
+ jge L$4
+ neg cx
+ neg ax
+L$4:
+ mov word ptr -4[bp],ax
+ mov word ptr -0cH[bp],cx
+ mov ax,bx
+ mul word ptr cs:MX_BYTESPERLINE
+ mov cx,si
+ shr si,1
+ shr si,1
+ add si,ax
+ and cl,3
+ mov ax,1102H
+ shl ah,cl
+ mov byte ptr -12H[bp],ah
+ mov dx,3c4H
+ out dx,ax
+ mov ax,word ptr cs:MX_VIDEOSEGMENT
+ mov ds,ax
+ xor bx,bx
+ mov al,byte ptr 6[bp]
+ cmp al,0
+ je L$5
+ and al,3
+ shl al,1
+ shl al,1
+ shl al,1
+ mov ah,al
+ mov al,3
+ mov dx,3ceH
+ out dx,ax
+ inc bx
+ inc bx
+L$5:
+ mov ax,word ptr -2[bp]
+ mov cx,word ptr -4[bp]
+ cmp ax,cx
+ jae L$6
+ inc bx
+L$6:
+ shl bx,1
+ call word ptr cs:L$1[bx]
+ cmp byte ptr 6[bp],0
+ je L$7
+ mov ax,3
+ mov dx,3ceH
+ out dx,ax
+L$7:
+ xor ax,ax
+ pop di
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+L$8:
+ mov di,ax
+ mov si,dx
+ xor al,al
+ cmp cx,word ptr cs:MX_CLIPX1
+ jge L$9
+ or al,1
+L$9:
+ cmp cx,word ptr cs:MX_CLIPX2
+ jle L$10
+ or al,2
+L$10:
+ cmp si,word ptr cs:MX_CLIPY1
+ jge L$11
+ or al,4
+L$11:
+ cmp si,word ptr cs:MX_CLIPY2
+ jle L$12
+ or al,8
+L$12:
+ mov byte ptr -10H[bp],al
+ xor al,al
+ cmp di,word ptr cs:MX_CLIPX1
+ jge L$13
+ or al,1
+L$13:
+ cmp di,word ptr cs:MX_CLIPX2
+ jle L$14
+ or al,2
+L$14:
+ cmp bx,word ptr cs:MX_CLIPY1
+ jge L$15
+ or al,4
+L$15:
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$16
+ or al,8
+L$16:
+ mov byte ptr -0eH[bp],al
+ mov ah,byte ptr -10H[bp]
+ test ah,al
+ je L$17
+ jmp near ptr L$28
+L$17:
+ or ah,al
+ jne L$18
+ jmp near ptr L$27
+L$18:
+ mov ax,cx
+ sub ax,di
+ mov word ptr -0aH[bp],ax
+ mov ax,si
+ sub ax,bx
+ mov word ptr -0cH[bp],ax
+ mov al,byte ptr -0eH[bp]
+L$19:
+ test al,al
+ jne L$20
+ xchg di,cx
+ xchg si,bx
+ xchg byte ptr -10H[bp],al
+L$20:
+ test al,1
+ je L$21
+ mov ax,word ptr cs:MX_CLIPX1
+ sub ax,di
+ mov di,word ptr cs:MX_CLIPX1
+ jmp L$22
+L$21:
+ test al,2
+ je L$23
+ mov ax,word ptr cs:MX_CLIPX2
+ sub ax,di
+ mov di,word ptr cs:MX_CLIPX2
+L$22:
+ imul word ptr -0cH[bp]
+ idiv word ptr -0aH[bp]
+ add bx,ax
+ mov al,8
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$26
+ mov al,4
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$26
+ xor al,al
+ jmp L$26
+L$23:
+ test al,4
+ je L$24
+ mov ax,word ptr cs:MX_CLIPY1
+ sub ax,bx
+ mov bx,word ptr cs:MX_CLIPY1
+ jmp L$25
+L$24:
+ mov ax,word ptr cs:MX_CLIPY2
+ sub ax,bx
+ mov bx,word ptr cs:MX_CLIPY2
+L$25:
+ imul word ptr -0aH[bp]
+ idiv word ptr -0cH[bp]
+ add di,ax
+ mov al,1
+ cmp di,word ptr cs:MX_CLIPX1
+ jl L$26
+ mov al,2
+ cmp di,word ptr cs:MX_CLIPX2
+ jg L$26
+ xor al,al
+L$26:
+ mov ah,byte ptr -10H[bp]
+ test ah,al
+ jne L$28
+ or ah,al
+ je L$27
+ jmp near ptr L$19
+L$27:
+ mov ax,di
+ mov dx,si
+ clc
+ ret
+L$28:
+ stc
+ ret
+L$29:
+ mov di,ax
+ neg di
+ shl cx,1
+ mov word ptr -6[bp],cx
+ mov cx,ax
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov al,2
+ mov ah,byte ptr -12H[bp]
+ mov bl,byte ptr 8[bp]
+ mov dx,3c4H
+ inc cx
+L$30:
+ mov byte ptr [si],bl
+ dec cx
+ je L$31
+ rol ah,1
+ adc si,0
+ out dx,ax
+ add di,word ptr -6[bp]
+ jl L$30
+ add si,word ptr -0cH[bp]
+ sub di,word ptr -8[bp]
+ jmp L$30
+L$31:
+ ret
+L$32:
+ mov di,cx
+ neg di
+ shl ax,1
+ mov word ptr -6[bp],ax
+ mov ax,cx
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov bl,byte ptr 8[bp]
+ mov ah,byte ptr -12H[bp]
+ mov al,2
+ mov dx,3c4H
+ inc cx
+L$33:
+ mov byte ptr [si],bl
+ dec cx
+ je L$34
+ add si,word ptr -0cH[bp]
+ add di,word ptr -6[bp]
+ jl L$33
+ rol ah,1
+ adc si,0
+ out dx,ax
+ sub di,word ptr -8[bp]
+ jmp L$33
+L$34:
+ ret
+L$35:
+ mov di,ax
+ neg di
+ shl cx,1
+ mov word ptr -6[bp],cx
+ mov cx,ax
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov al,2
+ mov ah,byte ptr -12H[bp]
+ mov bl,byte ptr 8[bp]
+ mov dx,3c4H
+ inc cx
+L$36:
+ mov bh,byte ptr [si]
+ mov byte ptr [si],bl
+ dec cx
+ je L$37
+ rol ah,1
+ adc si,0
+ out dx,ax
+ add di,word ptr -6[bp]
+ jl L$36
+ add si,word ptr -0cH[bp]
+ sub di,word ptr -8[bp]
+ jmp L$36
+L$37:
+ ret
+L$38:
+ mov di,cx
+ neg di
+ shl ax,1
+ mov word ptr -6[bp],ax
+ mov ax,cx
+ shl ax,1
+ mov word ptr -8[bp],ax
+ mov bl,byte ptr 8[bp]
+ mov ah,byte ptr -12H[bp]
+ mov al,2
+ mov dx,3c4H
+ inc cx
+L$39:
+ mov bh,byte ptr [si]
+ mov byte ptr [si],bl
+ dec cx
+ je L$40
+ add si,word ptr -0cH[bp]
+ add di,word ptr -6[bp]
+ jl L$39
+ rol ah,1
+ adc si,0
+ out dx,ax
+ sub di,word ptr -8[bp]
+ jmp L$39
+L$40:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSETFONT
+ PUBLIC MXSETTEXTCOLOR
+ PUBLIC MXOUTCHAR
+ PUBLIC MXOUTTEXT
+ PUBLIC MXSETTEXTSTEP
+ PUBLIC MXGETTEXTSTEP
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MXPUTIMAGE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ; The label referred to here is an undefined location
+ jle 0ffffff8bH
+ movsw
+ and word ptr -7e67H[di],7e7eH
+ call bx
+ call bx
+ out 0ffH,ax
+ jle L$9
+ ????
+ ????
+ ????
+ jl L$7
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],bh
+L$2:
+ jl L$2
+ jl L$8
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],bh
+ adc byte ptr -2[si],dl
+ push sp
+ adc dh,bh
+ adc byte ptr [bx+si],bh
+L$3:
+ jl L$3
+L$4:
+ ????
+ jl L$5
+ inc byte ptr [bx+si]
+ sbb byte ptr [si],bh
+ jle L$11
+ cmp al,18H
+ add bh,bh
+ out 0c3H,ax
+ DB 81H, 81H, 0c3H, 0e7H
+L$5:
+ inc word ptr [bx+si]
+ cmp al,66H
+ inc dx
+ inc dx
+ DB 66H, 3cH
+L$6:
+ add bh,bh
+ ret
+ cwd
+ mov bp,99bdH
+L$7:
+ ret
+ inc word ptr [bx]
+ add ax,word ptr [di]
+ ; The label referred to here is an undefined location
+ js 0ffffffe1H
+ DB 84H
+L$8:
+ test byte ptr 7cH[bx+si],bh
+ add byte ptr 7c82H[bp+si],10H
+ cmp byte ptr [bx+si],dl
+ sbb al,10H
+ sbb al,10H
+ adc byte ptr [bx+si],dl
+ xor byte ptr [bx+si],dh
+ and bh,byte ptr ds:[2222H]
+ pushad
+ cwd
+ pop dx
+ cmp al,0e7H
+ out 3cH,ax
+ pop dx
+ cwd
+ add byte ptr [bx+si],dl
+ xor byte ptr -10H[bx+si],dh
+L$9:
+ jo L$10
+ adc byte ptr [bx+si],al
+ add al,0e0H
+ lock loopnz L$6
+ adc byte ptr [bx+si],38H
+ push sp
+ adc byte ptr [bx+si],dl
+ push sp
+ cmp byte ptr [bx+si],dl
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ add byte ptr [bx+si],cl
+ jle L$4
+ xchg ax,dx
+ jb L$10
+ adc dl,byte ptr [bp+si]
+ add byte ptr [si],bh
+ and bl,byte ptr [bx+si]
+ and al,24H
+ sbb byte ptr 3cH[si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ DB 0, 3eH
+ DD ds:[3eH]
+L$10:
+ add byte ptr [bx+si],bh
+ push sp
+ DB 10H
+L$11:
+ adc byte ptr [bx+si],dl
+ push sp
+ cmp dh,bh
+ add byte ptr [bx+si],dl
+ cmp byte ptr 10H[si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr 38H[si],dl
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],cl
+ add al,0feH
+ add al,8
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],ah
+ inc ax
+ inc byte ptr 20H[bx+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr -380H[bx+si],0
+ add byte ptr [bx+si],al
+ and al,42H
+ inc word ptr 24H[bp+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],bh
+L$12:
+ jl L$12
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ????
+ jl L$15
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ and al,24H
+ add byte ptr [bx+si],al
+ DB 0
+L$13:
+ add byte ptr [bx+si],al
+ and al,24H
+ jle 140H
+ jle 142H
+L$14:
+ and al,0
+ cmp byte ptr 50H[si],dl
+ cmp byte ptr [si],dl
+ push sp
+ cmp byte ptr [bx+si],dl
+ add byte ptr [bp+si],al
+ inc sp
+ or byte ptr [bx+si],dl
+ and byte ptr [bp+si],al
+ cmp byte ptr 38H[si],al
+ pusha
+ xchg ax,sp
+L$15:
+ DB 88H
+L$16:
+ je 138H
+ and byte ptr [bx+si],ah
+ inc ax
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ and byte ptr 40H[bx+si],al
+ inc ax
+ and byte ptr [bx+si],dl
+ add byte ptr 20H[bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],ah
+L$17:
+ inc ax
+ add byte ptr [bx+si],al
+ and al,18H
+ jle L$18
+ and al,0
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ jl L$18
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ and byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cld
+ DB 0
+L$18:
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add al,8
+ adc byte ptr [bx+si],ah
+ inc ax
+L$19:
+ add byte ptr [bx+si],7cH
+ ????
+ DB 8aH, 92H
+L$20:
+ mov byte ptr 0c6H,al
+ DD L$21
+L$21:
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],bh
+ add byte ptr L$13[bx+si],bh
+ add al,18H
+ pusha
+ cmp ah,0
+ js L$14
+ add al,38H
+ add al,84H
+ js L$22
+L$22:
+ sbb al,24H
+ inc sp
+ test dh,bh
+ add al,0eH
+ add ah,bh
+ cmp al,4
+ add al,84H
+ js L$23
+L$23:
+ js L$16
+ cmp al,84H
+ test byte ptr [bx+si],bh
+ cld
+ add al,4
+ or byte ptr [bx+si],dl
+ and byte ptr [bx+si],ah
+ add byte ptr -7cH[bx+si],bh
+ test byte ptr -7cH[bx+si],bh
+ test byte ptr [bx+si],bh
+ js L$17
+ test byte ptr 4[si],bh
+ test byte ptr [bx+si],bh
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],ah
+ or byte ptr [bx+si],dl
+ and byte ptr 20H[bx+si],al
+ adc byte ptr [bx+si],cl
+ add byte ptr [bx+si],al
+ add ah,bh
+ add byte ptr [bx+si],al
+ cld
+ add byte ptr [bx+si],al
+ inc ax
+ and byte ptr [bx+si],dl
+ or byte ptr [bx+si],dl
+ and byte ptr [bx+si],al
+ js L$19
+ add al,8
+ adc byte ptr [bx+si],al
+L$24:
+ adc byte ptr [bx+si],al
+ jl L$20
+ mov dx,0bea6H
+ cmp byte ptr [si],78H
+ test byte ptr -7b04H[si],al
+ test byte ptr -800H[si],al
+ test byte ptr -7b08H[si],al
+ test al,bh
+ add byte ptr -7cH[bx+si],bh
+ add byte ptr -7b80H[bx+si],78H
+ add al,dh
+ mov byte ptr -7b7cH[si],al
+ mov al,dh
+ add ah,bh
+ add byte ptr -7f10H[bx+si],80H
+ cld
+ add ah,bh
+ add byte ptr -7f10H[bx+si],80H
+ add byte ptr [bx+si],78H
+ test byte ptr -7b64H[bx+si],al
+ test byte ptr [bx+si],bh
+ test byte ptr -37cH[si],al
+ test byte ptr 84H[si],al
+ cmp byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ cmp byte ptr [bx+si],al
+ sbb al,8
+ or byte ptr [bx+si],cl
+ mov byte ptr 70H[bx+si],cl
+ test byte ptr -1f70H[bx+si],cl
+ nop
+ mov byte ptr -8000H[si],al
+ add byte ptr -7f80H[bx+si],80H
+ cld
+ add dh,al
+ stosb
+ xchg ax,dx
+ add byte ptr -7d7eH[bp+si],0
+ add dl,0a2H
+ xchg ax,dx
+ mov al,byte ptr 82H[bp]
+ js L$24
+ test byte ptr -7b7cH[si],al
+ js L$25
+L$25:
+ clc
+ test byte ptr -7f08H[si],al
+ add byte ptr 7800H[bx+si],84H
+ test byte ptr -776cH[si],al
+ jbe L$26
+L$26:
+ clc
+ test byte ptr -6f08H[si],al
+ mov byte ptr 7800H[si],al
+ test byte ptr 478H[bx+si],al
+ test byte ptr [bx+si],bh
+ ????
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr -7b7cH[si],al
+ test byte ptr 7884H[si],al
+ add byte ptr -7b7cH[si],al
+ test byte ptr 3048H[si],al
+ add byte ptr -7d7eH[bp+si],al
+ adc byte ptr -3956H[bp+si],0
+ add byte ptr 28H[si],10H
+ sub byte ptr -7eH[si],al
+ add byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add dh,bh
+ add al,8
+ adc byte ptr [bx+si],ah
+ inc ax
+ inc byte ptr [bx+si]
+ js L$32
+ inc ax
+ inc ax
+ inc ax
+ inc ax
+ js L$27
+L$27:
+ add byte ptr 2040H[bx+si],al
+ adc byte ptr [bx+si],cl
+ add al,0
+ js L$29
+ or byte ptr [bx+si],cl
+ or byte ptr [bx+si],cl
+ js L$28
+L$28:
+ adc byte ptr [bx+si],ch
+L$29:
+ inc sp
+ add byte ptr [bx+si],0
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add bh,bh
+ and byte ptr [bx+si],ah
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$30
+L$30:
+ add byte ptr 40H[bx+si],al
+ js L$33
+ inc sp
+ js L$31
+L$31:
+ add byte ptr [bx+si],al
+L$32:
+ cmp al,40H
+ inc ax
+ inc ax
+ cmp al,0
+ add byte ptr [si],al
+ add al,3cH
+ inc sp
+ inc sp
+ cmp al,0
+ add byte ptr [bx+si],al
+ cmp byte ptr 7cH[si],al
+ inc ax
+ cmp al,0
+ add byte ptr [si],cl
+ adc byte ptr [si],bh
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp al,44H
+ inc sp
+ cmp al,4
+ cmp byte ptr [bx+si],al
+ inc ax
+ inc ax
+ js L$35
+ inc sp
+ inc sp
+ add byte ptr [bx+si],al
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add al,0
+ add al,4
+ add al,44H
+ cmp byte ptr [bx+si],al
+L$33:
+ inc ax
+ inc ax
+ push ax
+ pusha
+ push ax
+ dec ax
+ add byte ptr [bx+si],al
+ xor byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add byte ptr 54H[bx+si],ch
+ push sp
+ inc sp
+ inc sp
+ add byte ptr [bx+si],al
+ add byte ptr 44H[bx+si],bh
+ inc sp
+ inc sp
+ inc sp
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bh
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+L$34:
+ js L$42
+ inc sp
+ js L$41
+ inc ax
+ DB 0
+L$35:
+ add byte ptr [si],bh
+ inc sp
+ inc sp
+ cmp al,4
+ add al,0
+ add byte ptr 60H[si],bl
+ inc ax
+ inc ax
+ inc ax
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bh
+L$36:
+ inc ax
+ jl L$38
+ jl L$37
+L$37:
+ add byte ptr [bx+si],dl
+L$38:
+ cmp byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ sbb byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ sub byte ptr [bx+si],dl
+ add byte ptr [bx+si],al
+ add byte ptr 44H[si],al
+L$39:
+ push sp
+ push sp
+ insb
+ add byte ptr [bx+si],al
+ add byte ptr 28H[si],al
+L$40:
+ adc byte ptr [bx+si],ch
+ inc sp
+L$41:
+ DB 0
+L$42:
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp al,4
+ jl L$43
+L$43:
+ add byte ptr 4[si],bh
+ cmp byte ptr 7cH[bx+si],al
+ add byte ptr [bx+si],al
+ or byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dh
+ adc byte ptr [bx+si],dl
+ or byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ and byte ptr [bx+si],dl
+ adc byte ptr [bx+si],bl
+ adc byte ptr [bx+si],dl
+ and byte ptr -68H[si],ah
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],dl
+ sub byte ptr -7eH[si],al
+ cmp dh,0
+ jl L$34
+ add byte ptr 7c80H[bx+si],4
+ jl L$44
+L$44:
+ sub byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ cmp al,0
+ jl L$54
+ jl L$53
+ jl L$45
+L$45:
+ jle L$36
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$46
+L$46:
+ and al,0
+L$47:
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$48
+L$48:
+ js L$49
+L$49:
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$50
+L$50:
+ sbb byte ptr [bx+si],bl
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$51
+L$51:
+ add byte ptr [bx+si],al
+ js L$39
+ cmp byte ptr 8[bx+si],38H
+ jl L$40
+ cmp byte ptr 7cH[si],al
+ inc ax
+ cmp al,0
+ dec ax
+ add byte ptr [bx+si],bh
+ inc sp
+ jl L$55
+ cmp al,0
+ js L$52
+L$52:
+ cmp byte ptr 7cH[si],al
+ inc ax
+L$53:
+ cmp al,0
+L$54:
+ add byte ptr [bx+si],ch
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],ch
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],dh
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ dec ax
+ add byte ptr -7cH[bx+si],bh
+ cld
+ test byte ptr 3000H[si],al
+ xor byte ptr -7cH[bx+si],bh
+ cld
+ test byte ptr 3800H[si],al
+ add ah,bh
+ xor al,80H
+ cld
+ add byte ptr [bx+si],al
+ add byte ptr 8[bp],bh
+ jle L$59
+L$55:
+ jle L$56
+L$56:
+ jle L$47
+ nop
+ cld
+ nop
+ nop
+ sahf
+ add byte ptr -7eH[si],bh
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ sub byte ptr [bx+si],al
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ jo L$57
+L$57:
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ cmp byte ptr [si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ jo L$58
+L$58:
+ inc sp
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ sub byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ cmp al,4
+ jl L$64
+ add byte ptr -7cH[bx+si],bh
+ test byte ptr 78H[si],al
+ dec ax
+ add byte ptr -7b7cH[si],al
+ DB 84H
+L$59:
+ js 4d8H
+ add byte ptr [bx+si],dl
+ cmp byte ptr 40H[bx+si],al
+ inc ax
+ cmp byte ptr [bx+si],dl
+ cmp byte ptr 40H[si],al
+ loopnz L$66
+ inc ax
+ cmp ah,44H
+ jl L$60
+ jl L$61
+ jl L$62
+ add al,dh
+ mov byte ptr -7d09H[bp+si],cl
+ add byte ptr 0c00H[bp+si],12H
+ DB 10H
+L$60:
+ sbb byte ptr [bx+si],dh
+L$61:
+ DB 10H, 90H
+L$62:
+ pusha
+ cmp al,0
+ cmp byte ptr [si],al
+ cmp al,44H
+ jl L$63
+L$63:
+ add byte ptr [bx+si],bl
+ add byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],al
+ DB 1cH
+L$64:
+ add byte ptr [bx+si],bh
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ sbb al,0
+ inc sp
+ inc sp
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ jl L$65
+L$65:
+ js L$67
+ inc sp
+L$66:
+ inc sp
+ inc sp
+ add byte ptr [si],bh
+ inc sp
+ push sp
+ dec sp
+ inc sp
+ add byte ptr [bx+si],bl
+ and al,24H
+ push ds
+ add byte ptr ds:[0],bh
+ sbb al,22H
+ and bl,byte ptr [si]
+ add byte ptr ds:[0],bh
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],ah
+ inc ax
+ inc dx
+ cmp al,0
+ add byte ptr [bx+si],al
+ add ah,bh
+ add byte ptr [bx+si],0
+ add byte ptr [bx+si],al
+ cld
+ add al,4
+ add byte ptr [bx+si],al
+ inc ax
+ inc sp
+ dec ax
+ push di
+ and word ptr 4[bx],ax
+ pop es
+ inc ax
+ inc sp
+ dec ax
+ push dx
+ dec dx
+ pop ds
+ DB 2
+L$67:
+ adc byte ptr [bx+si],al
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+L$68:
+ adc byte ptr [bx+si],al
+ add byte ptr [si],ah
+L$69:
+ dec ax
+ nop
+ dec ax
+ and al,0
+ add byte ptr [bx+si],al
+ dec ax
+ and al,12H
+ and al,48H
+ add byte ptr [bx+si],al
+ and cl,byte ptr -77deH[bx+si]
+ and cl,byte ptr -77deH[bx+si]
+ push bp
+ stosb
+ push bp
+ stosb
+ push bp
+ stosb
+ push bp
+ stosb
+ ????
+ ja L$68
+ out dx,al
+ ????
+ ja L$69
+ out dx,al
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ clc
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb al,bh
+ sbb al,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr ds:[3636H],dh
+ div byte ptr ss:[3636H]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ ????
+ add byte ptr ss:[bx+si],al
+ clc
+ sbb al,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr ds:[0f636H],dh
+ push es
+ div byte ptr ds:[3636H]
+ add byte ptr ss:[bx+si],al
+ inc byte ptr ds:[36f6H]
+ test byte ptr ss:[0feH],0
+ add byte ptr ds:[3636H],dh
+ inc byte ptr ss:[bx+si]
+ add byte ptr [bx+si],al
+ sbb byte ptr [bx+si],bl
+ clc
+ sbb al,bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add al,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb bh,bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add bh,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add bh,bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb bh,bh
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr ds:[3636H],dh
+ aaa
+ aaa
+ xor byte ptr [bx],bh
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bh
+ xor byte ptr [bx],dh
+ test word ptr ss:[bx+si],0ffH
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc word ptr [bx+si]
+ div word ptr ds:[3636H]
+ aaa
+ xor byte ptr [bx],dh
+ add byte ptr ss:[bx+si],al
+ inc word ptr [bx+si]
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ test word ptr ss:[bx+si],36f7H
+ sbb byte ptr ss:[bx+si],bl
+ inc word ptr [bx+si]
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ inc word ptr ss:[bx+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc word ptr [bx+si]
+ call dword ptr [bx+si]
+ sbb byte ptr [bx+si],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ push word ptr ds:[3636H]
+ aas
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bl
+ sbb byte ptr [bx],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bh
+ push word ptr ss:[3636H]
+ sbb byte ptr [bx+si],bl
+ call dword ptr [bx+si]
+ call dword ptr [bx+si]
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ sbb byte ptr [bx+si],bl
+ clc
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx],bl
+ DB 18H
+L$70:
+ sbb byte ptr [bx+si],bl
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ add bh,bh
+ ????
+ ????
+ push ax
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ ????
+ inc word ptr [bx+si]
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr -6cH[bp+si],ah
+ mov byte ptr 62H[si],dl
+ add al,dh
+ mov al,dh
+ mov byte ptr -7f10H[bx+si],cl
+ add al,bh
+ mov byte ptr -7f80H[bx+si],al
+ add byte ptr [bx+si],0
+ cld
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ dec ax
+ add ah,bh
+ test byte ptr 20H[bx+si],al
+ inc ax
+ test ah,bh
+ add byte ptr [si],bh
+ inc ax
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ inc sp
+ inc sp
+ inc sp
+ js L$71
+ inc ax
+ add byte ptr ds:[848H],dh
+ or byte ptr [bx+si],cl
+ or byte ptr [bx+si],al
+ cmp byte ptr [bx+si],dl
+ cmp byte ptr 44H[si],al
+ cmp byte ptr [bx+si],dl
+ cmp byte ptr -7cH[bx+si],bh
+ test ah,bh
+ test byte ptr 78H[si],al
+ js L$70
+ test byte ptr 4848H[si],al
+ int 3
+ add byte ptr 4[bx+si],bh
+ cmp byte ptr 44H[si],al
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ insb
+ xchg ax,dx
+ xchg ax,dx
+ insb
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp al,byte ptr 5aH[si]
+ and bl,byte ptr [si]
+ sbb byte ptr [bx+si],ah
+ inc ax
+ js L$73
+ and byte ptr [bx+si],bl
+L$71:
+ add byte ptr -7cH[bx+si],bh
+ test byte ptr -7b7cH[si],al
+ test byte ptr [bx+si],al
+ add ah,bh
+ add ah,bh
+ add ah,bh
+ add byte ptr [bx+si],al
+ and byte ptr [bx+si],ah
+ clc
+ and byte ptr [bx+si],ah
+ add al,bh
+ add byte ptr [bx+si],ah
+ adc byte ptr [bx+si],cl
+ adc byte ptr [bx+si],ah
+ add byte ptr [si],bh
+ or byte ptr [bx+si],dl
+ and byte ptr [bx+si],dl
+ or byte ptr [bx+si],al
+ jl L$72
+L$72:
+ or al,12H
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ adc byte ptr [bx+si],dl
+ nop
+ pusha
+ add byte ptr [bx+si],dl
+ add byte ptr [si],bh
+L$73:
+ adc byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ xor cl,byte ptr [si]
+ xor cl,byte ptr [si]
+ add byte ptr [bx+si],bh
+ inc sp
+ inc sp
+ cmp byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ sbb byte ptr [bx+si],bl
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],bl
+ add byte ptr [bx+si],al
+ add byte ptr ds:[808H],cl
+ or byte ptr 28H[bx+si],cl
+ sbb byte ptr [bx+si],cl
+ cmp byte ptr [si],ah
+ and al,24H
+ and al,0
+ add byte ptr [bx+si],al
+ cmp al,4
+ cmp al,20H
+ cmp al,0
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ cmp al,3cH
+ cmp al,3cH
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+L$74:
+ DW offset L$1
+L$75:
+ DB 8
+L$76:
+ add byte ptr [bx+si],cl
+ DB 0
+L$77:
+ DW offset L$1
+L$78:
+ DW seg L$1
+L$79:
+ or byte ptr [bx+si],al
+L$80:
+ or byte ptr [bx+si],al
+L$81:
+ or byte ptr [bx+si],al
+L$82:
+ inc word ptr [bx+si]
+L$83:
+ add byte ptr [bx+si],al
+L$84:
+ or byte ptr [bx+si],al
+L$85:
+ add byte ptr [bx+si],al
+MXSETFONT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 0cH[bp]
+ test ax,ax
+ jne L$87
+ mov ax,word ptr 0aH[bp]
+ cmp ax,1
+ jb L$86
+ xor ax,ax
+L$86:
+ shl ax,1
+ shl ax,1
+ mov bx,ax
+ mov ax,word ptr L$74[bx]
+ mov word ptr L$77,ax
+ mov word ptr L$78,cs
+ mov al,byte ptr L$75[bx]
+ xor ah,ah
+ mov word ptr L$79,ax
+ mov word ptr L$84,ax
+ mov dl,byte ptr L$76[bx]
+ xor dh,dh
+ mov word ptr L$80,dx
+ mul dx
+ mov word ptr L$81,ax
+ mov word ptr L$84,ax
+ xor ax,ax
+ mov word ptr L$85,ax
+ jmp L$88
+L$87:
+ mov ax,0ffffH
+ mov bx,word ptr 8[bp]
+ cmp bx,10H
+ ja L$88
+ mov dx,word ptr 6[bp]
+ cmp dx,20H
+ ja L$88
+ mov word ptr L$79,bx
+ mov word ptr L$80,dx
+ mov ax,bx
+ add ax,7
+ shr ax,1
+ shr ax,1
+ shr ax,1
+ mul dx
+ mov word ptr L$81,ax
+ mov ax,word ptr 0aH[bp]
+ mov word ptr L$77,ax
+ mov ax,word ptr 0cH[bp]
+ mov word ptr L$78,ax
+ xor ax,ax
+L$88:
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MXSETTEXTCOLOR:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 8[bp]
+ mov word ptr L$82,ax
+ mov ax,word ptr 6[bp]
+ mov word ptr L$83,ax
+ xor ax,ax
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXOUTCHAR:
+ push bp
+ mov bp,sp
+ sub sp,202H
+ push ds
+ push si
+ push es
+ push di
+ lds si,dword ptr cs:L$77
+ mov al,byte ptr 6[bp]
+ xor ah,ah
+ mul word ptr cs:L$81
+ add si,ax
+ mov ax,ss
+ mov es,ax
+ lea di,-200H[bp]
+ mov dx,word ptr cs:L$82
+ mov ax,word ptr cs:L$80
+ mov word ptr -202H[bp],ax
+L$89:
+ mov cx,word ptr cs:L$79
+ mov bh,byte ptr [si]
+ inc si
+ cmp cx,8
+ jbe L$90
+ mov bl,byte ptr [si]
+ inc si
+L$90:
+ mov al,dl
+ shl bx,1
+ jb L$91
+ mov al,dh
+L$91:
+ mov byte ptr es:[di],al
+ inc di
+ dec cx
+ jne L$90
+ dec word ptr -202H[bp]
+ jne L$89
+ lea ax,-200H[bp]
+ push es
+ push ax
+ push word ptr 0aH[bp]
+ push word ptr 8[bp]
+ push word ptr cs:L$79
+ push word ptr cs:L$80
+ push word ptr cs:L$83
+ push cs
+ call near ptr MX_TEXT:MXPUTIMAGE
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 6
+MXOUTTEXT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 6[bp]
+L$92:
+ mov al,byte ptr [si]
+ test al,al
+ je L$93
+ inc si
+ push word ptr 0cH[bp]
+ push word ptr 0aH[bp]
+ push ax
+ push cs
+ call near ptr MXOUTCHAR
+ mov ax,word ptr cs:L$84
+ add word ptr 0cH[bp],ax
+ mov ax,word ptr cs:L$85
+ add word ptr 0aH[bp],ax
+ dec word ptr -202H[bp]
+ jne L$92
+L$93:
+ xor ax,ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+ retf
+MXSETTEXTSTEP:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr 8[bp]
+ mov word ptr L$84,ax
+ mov ax,word ptr 6[bp]
+ mov word ptr L$85,ax
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXGETTEXTSTEP:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr cs:L$84
+ lds si,dword ptr 0aH[bp]
+ mov word ptr [si],ax
+ mov ax,word ptr cs:L$85
+ lds si,dword ptr 6[bp]
+ mov word ptr [si],ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN PRO\r
+;NOWARN RES ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxOutChar\r
+PUBLIC mxOutText\r
+PUBLIC mxSetFont\r
+PUBLIC mxSetTextColor\r
+PUBLIC mxGetTextStep\r
+PUBLIC mxSetTextStep\r
+\r
+MAX_WIDTH EQU 16 ; Must be <= 16\r
+MAX_HEIGHT EQU 32\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mxPutImage : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default LABEL BYTE\r
+ INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont LABEL WORD\r
+ DW fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth DW 8 ; Font width in pixels\r
+mx_FontHeight DW 8 ; Font height in pixels\r
+mx_FontCharSize DW 8 ; Size in bytes of a font character\r
+mx_FontColor DW 00FFh ; Color: foreground + background*256\r
+mx_FontOp DW OP_MOVE ; Raster op\r
+mx_DeltaX DW 8 ; Horizontal step\r
+mx_DeltaY DW 0 ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+; Font = pointer to font data\r
+; Width = width of font character in pixels\r
+; Height = height of font character in pixels\r
+; Output:\r
+; AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+; word is used to select one of the system fonts.\r
+;\r
+mxSetFont PROC FAR\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,0\r
+ push ds\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, WORD PTR Font[2] ; Get font segment\r
+ test ax, ax ; Null segment?\r
+ jnz @@UserFont ; No, install user font\r
+\r
+; Install system font\r
+ mov ax, WORD PTR Font[0] ; Get font number\r
+ cmp ax, MX_MAXSYSFONT ; Check range\r
+ jb @@SystemFont\r
+ xor ax, ax ; Out of range, use default font\r
+@@SystemFont:\r
+ shl ax, 1\r
+ shl ax, 1\r
+ mov bx, ax\r
+ mov ax, tbl_SystemFont[bx] ; Get font offset\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov WORD PTR mx_FontPtr[2], cs\r
+ mov al, BYTE PTR tbl_SystemFont[bx+2]\r
+ xor ah, ah\r
+ mov [mx_FontWidth], ax\r
+ mov [mx_DeltaX], ax\r
+ mov dl, BYTE PTR tbl_SystemFont[bx+3]\r
+ xor dh, dh\r
+ mov [mx_FontHeight], dx\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov [mx_DeltaX], ax\r
+ xor ax, ax\r
+ mov [mx_DeltaY], ax\r
+ jmp @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+ mov ax, -1 ; Assume an error\r
+ mov bx, [bp+8]\r
+ cmp bx, MAX_WIDTH\r
+ ja @@Exit ; Invalid character width\r
+ mov dx, [bp+4]\r
+ cmp dx, MAX_HEIGHT\r
+ ja @@Exit ; Invalid character height\r
+ mov [mx_FontWidth], bx\r
+ mov [mx_FontHeight], dx\r
+ mov ax, bx\r
+ add ax, 7\r
+ shr ax, 1\r
+ shr ax, 1\r
+ shr ax, 1\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov ax, WORD PTR Font[0]\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov ax, WORD PTR Font[2]\r
+ mov WORD PTR mx_FontPtr[2], ax\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ ;.leave ARG_SIZE\r
+mxSetFont ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+; Color = text color (foreground + background*256)\r
+; Op = raster op\r
+; Output:\r
+; none\r
+;\r
+mxSetTextColor PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [Color]\r
+ mov [mx_FontColor], ax\r
+ mov ax, [Op]\r
+ mov [mx_FontOp], ax\r
+\r
+ xor ax, ax\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetTextColor ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+; X, Y = video coordinates\r
+; C = character to print\r
+; Output:\r
+; none\r
+;\r
+mxOutChar PROC FAR\r
+ ARG C:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \\r
+ Count:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+ lds si, DWORD PTR [mx_FontPtr]\r
+ mov al, [C]\r
+ xor ah, ah\r
+ mul [mx_FontCharSize] ; Offset into font\r
+ add si, ax ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [Image]\r
+ mov dx, [mx_FontColor]\r
+ mov ax, [mx_FontHeight]\r
+ mov [Count], ax\r
+@@HeightLoop:\r
+ mov cx, [mx_FontWidth]\r
+ mov bh, ds:[si]\r
+ inc si ; Get a byte from font data\r
+ cmp cx, 8\r
+ jbe @@WidthLoop ; Ok for width <= 8\r
+ mov bl, ds:[si] ; Get another byte\r
+ inc si\r
+@@WidthLoop:\r
+ mov al, dl ; Assume foreground color\r
+ shl bx, 1 ; Is font bit set?\r
+ jc @@1 ; Yes, foreground is just great\r
+ mov al, dh ; Get background color\r
+@@1:\r
+ mov es:[di], al ; Put pixel into image\r
+ inc di\r
+ dec cx\r
+ jnz @@WidthLoop\r
+ dec [Count]\r
+ jnz @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+ lea ax, [Image]\r
+ push es\r
+ push ax ; Pointer to image\r
+ push [X]\r
+ push [Y] ; Image coordinates\r
+ push [mx_FontWidth]\r
+ push [mx_FontHeight] ; Image size\r
+ push [mx_FontOp] ; Raster op\r
+ call mxPutImage ; Write character\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxOutChar ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+; X, Y = text coordinates\r
+; S = pointer to ASCIIZ string\r
+; Output:\r
+; none\r
+;\r
+mxOutText PROC FAR\r
+ ARG S:DWORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [S]\r
+@@Loop:\r
+ mov al, ds:[si]\r
+ test al, al ; End of string?\r
+ jz @@Exit ; Yes, exit\r
+ inc si\r
+ push [X] ; Display character\r
+ push [Y]\r
+ push ax\r
+ call mxOutChar\r
+ mov ax, [mx_DeltaX]\r
+ add [X], ax ; Bump X coordinate\r
+ mov ax, [mx_DeltaY]\r
+ add [Y], ax ; Bump Y coordinate\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+ ret\r
+mxOutText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = horizontal distance in pixels\r
+; DeltaY = vertical distance in pixels\r
+; Output:\r
+; none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep PROC FAR\r
+ ARG DeltaY:WORD, \\r
+ DeltaX:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [DeltaX]\r
+ mov [mx_DeltaX], ax\r
+ mov ax, [DeltaY]\r
+ mov [mx_DeltaY], ax\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetTextStep ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = pointer to horizontal distance in pixels (integer)\r
+; DeltaY = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+; none\r
+;\r
+mxGetTextStep PROC FAR\r
+ ARG DeltaY:DWORD, \\r
+ DeltaX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [mx_DeltaX]\r
+ lds si, [DeltaX]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_DeltaY]\r
+ lds si, [DeltaY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetTextStep ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
--- /dev/null
+.387
+ PUBLIC MX_SCANBUFFER
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCANBUFFER:
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXFILLPOLY
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MX_SCANBUFFER:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ mov cx,word ptr [si]
+ sub cx,word ptr [bx]
+ jg L$2
+ ret
+L$2:
+ push bp
+ mov ax,word ptr 2[si]
+ mov bx,word ptr 2[bx]
+ sub ax,bx
+ jg L$4
+ jl L$6
+ mov ax,bx
+L$3:
+ mov word ptr es:[di],ax
+ add di,4
+ dec cx
+ jne L$3
+ jmp L$8
+L$4:
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$5:
+ mov word ptr es:[di],ax
+ add di,4
+ add dx,bx
+ adc ax,bp
+ dec cx
+ jne L$5
+ jmp L$8
+L$6:
+ neg ax
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$7:
+ mov word ptr es:[di],ax
+ add di,4
+ sub dx,bx
+ sbb ax,bp
+ dec cx
+ jne L$7
+L$8:
+ pop bp
+ ret
+MXFILLPOLY:
+ push bp
+ mov bp,sp
+ sub sp,1eH
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 10H[bp]
+ cmp cx,3
+ jae L$9
+ jmp near ptr L$36
+L$9:
+ les di,dword ptr 0cH[bp]
+ lds si,dword ptr 8[bp]
+ mov word ptr -16H[bp],7fffH
+ mov word ptr -1aH[bp],8000H
+ mov word ptr -18H[bp],7fffH
+ mov word ptr -1eH[bp],8000H
+ xor dx,dx
+L$10:
+ mov bx,word ptr es:[di]
+ shl bx,1
+ shl bx,1
+ add bx,si
+ mov ax,word ptr [bx]
+ cmp ax,word ptr -16H[bp]
+ jge L$11
+ mov word ptr -16H[bp],ax
+ mov word ptr -0eH[bp],dx
+ mov word ptr -10H[bp],dx
+L$11:
+ cmp ax,word ptr -1aH[bp]
+ jle L$12
+ mov word ptr -1aH[bp],ax
+ mov word ptr -12H[bp],dx
+L$12:
+ mov ax,word ptr 2[bx]
+ cmp ax,word ptr -18H[bp]
+ jge L$13
+ mov word ptr -18H[bp],ax
+L$13:
+ cmp ax,word ptr -1eH[bp]
+ jle L$14
+ mov word ptr -1eH[bp],ax
+L$14:
+ inc di
+ inc dx
+ inc di
+ inc dx
+ dec cx
+ jne L$10
+ mov ax,word ptr -1aH[bp]
+ cmp ax,word ptr cs:MX_CLIPX1
+ jge L$15
+ jmp near ptr L$36
+L$15:
+ mov bx,word ptr -16H[bp]
+ cmp bx,word ptr cs:MX_CLIPX2
+ jle L$16
+ jmp near ptr L$36
+L$16:
+ sub ax,bx
+ jg L$17
+ jmp near ptr L$36
+L$17:
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jge L$18
+ jmp near ptr L$36
+L$18:
+ mov bx,word ptr -18H[bp]
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$19
+ jmp near ptr L$36
+L$19:
+ sub ax,bx
+ jg L$20
+ jmp near ptr L$36
+L$20:
+ dec word ptr 10H[bp]
+ shl word ptr 10H[bp],1
+ mov es,word ptr cs:MX_CODESEGMENT
+ mov ax,offset MX_TEXT:MX_SCANBUFFER
+ mov word ptr -4[bp],ax
+ mov si,word ptr -0eH[bp]
+L$21:
+ lds bx,dword ptr 0cH[bp]
+ mov di,word ptr [bx+si]
+ dec si
+ dec si
+ test si,si
+ jge L$22
+ mov si,word ptr 10H[bp]
+L$22:
+ mov word ptr -0eH[bp],si
+ mov si,word ptr [bx+si]
+ shl di,1
+ shl di,1
+ shl si,1
+ shl si,1
+ lds bx,dword ptr 8[bp]
+ add si,bx
+ add bx,di
+ mov di,word ptr -4[bp]
+ call near ptr L$1
+ mov word ptr -4[bp],di
+ mov si,word ptr -0eH[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$21
+ mov ax,offset MX_TEXT:MX_SCANBUFFER+2
+ mov word ptr -6[bp],ax
+ mov si,word ptr -10H[bp]
+L$23:
+ lds bx,dword ptr 0cH[bp]
+ mov di,word ptr [bx+si]
+ inc si
+ inc si
+ cmp si,word ptr 10H[bp]
+ jbe L$24
+ xor si,si
+L$24:
+ mov word ptr -10H[bp],si
+ mov si,word ptr [bx+si]
+ shl di,1
+ shl di,1
+ shl si,1
+ shl si,1
+ lds bx,dword ptr 8[bp]
+ add si,bx
+ add bx,di
+ mov di,word ptr -6[bp]
+ call near ptr L$1
+ mov word ptr -6[bp],di
+ mov si,word ptr -10H[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$23
+ mov si,offset MX_TEXT:MX_SCANBUFFER
+ mov ax,word ptr -16H[bp]
+ mov cx,word ptr -1aH[bp]
+ sub cx,ax
+ mov bx,word ptr cs:MX_CLIPX1
+ sub bx,ax
+ jle L$25
+ sub cx,bx
+ add ax,bx
+ mov word ptr -16H[bp],ax
+ shl bx,1
+ shl bx,1
+ add si,bx
+L$25:
+ mov bx,ax
+ add bx,cx
+ sub bx,word ptr cs:MX_CLIPX2
+ jle L$26
+ sub cx,bx
+L$26:
+ test cx,cx
+ jg L$27
+ jmp near ptr L$36
+L$27:
+ mov word ptr -8[bp],cx
+ mov word ptr -4[bp],si
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr -18H[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$28
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$28
+ jmp L$32
+L$28:
+ mov di,cx
+ inc di
+ sub si,4
+L$29:
+ dec di
+ je L$32
+ add si,4
+ mov ax,word ptr [si]
+ mov cx,word ptr 2[si]
+ mov dx,word ptr cs:MX_CLIPY2
+ cmp ax,dx
+ jg L$31
+ cmp cx,dx
+ jle L$30
+ mov word ptr 2[si],dx
+ mov bx,cx
+ sub bx,dx
+ sub cx,ax
+ jle L$31
+ mov cx,word ptr 2[si]
+L$30:
+ mov dx,word ptr cs:MX_CLIPY1
+ cmp cx,dx
+ jl L$31
+ sub cx,ax
+ jle L$31
+ cmp ax,dx
+ jge L$29
+ mov word ptr [si],dx
+ sub dx,ax
+ cmp cx,dx
+ ja L$29
+L$31:
+ mov word ptr [si],0ffffH
+ jmp L$29
+L$32:
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ mov si,word ptr -4[bp]
+ mov cl,byte ptr -16H[bp]
+ and cl,3
+ mov al,11H
+ shl al,cl
+ mov byte ptr -2[bp],al
+ shr word ptr -16H[bp],1
+ shr word ptr -16H[bp],1
+L$33:
+ mov ax,word ptr [si]
+ test ax,ax
+ js L$35
+ mov cx,word ptr 2[si]
+ sub cx,ax
+ jle L$35
+ mul word ptr cs:MX_BYTESPERLINE
+ add ax,word ptr -16H[bp]
+ mov di,ax
+ mov ah,byte ptr -2[bp]
+ mov dx,3c4H
+ mov al,2
+ out dx,ax
+ mov ax,word ptr 6[bp]
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ shr cx,1
+ jae L$34
+ mov byte ptr es:[di],al
+ add di,dx
+ jcxz L$35
+L$34:
+ mov byte ptr es:[di],al
+ add di,dx
+ mov byte ptr es:[di],al
+ add di,dx
+ dec cx
+ jne L$34
+L$35:
+ rol byte ptr -2[bp],1
+ adc word ptr -16H[bp],0
+ add si,4
+ dec word ptr -8[bp]
+ jne L$33
+L$36:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGOURAUDPOLY
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MX_SCANBUFFER:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ mov cx,word ptr [si]
+ sub cx,word ptr [bx]
+ jg L$2
+ ret
+L$2:
+ push bp
+ push di
+ push cx
+ push ax
+ push dx
+ mov ax,word ptr 2[si]
+ mov bx,word ptr 2[bx]
+ sub ax,bx
+ jg L$4
+ jl L$6
+ mov ax,bx
+L$3:
+ mov word ptr es:[di],ax
+ add di,8
+ dec cx
+ jne L$3
+ jmp L$8
+L$4:
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$5:
+ mov word ptr es:[di],ax
+ add di,8
+ add dx,bx
+ adc ax,bp
+ dec cx
+ jne L$5
+ jmp L$8
+L$6:
+ neg ax
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$7:
+ mov word ptr es:[di],ax
+ add di,8
+ sub dx,bx
+ sbb ax,bp
+ dec cx
+ jne L$7
+L$8:
+ pop bx
+ pop ax
+ pop cx
+ pop di
+ sub ax,bx
+ jg L$10
+ jl L$12
+ mov ah,bl
+ mov al,80H
+L$9:
+ mov word ptr es:2[di],ax
+ add di,8
+ dec cx
+ jne L$9
+ jmp L$14
+L$10:
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$11:
+ mov byte ptr es:3[di],al
+ mov byte ptr es:2[di],dh
+ add di,8
+ add dx,bx
+ adc ax,bp
+ dec cx
+ jne L$11
+ jmp L$14
+L$12:
+ neg ax
+ cwd
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ xchg ax,bx
+ mov dx,8000H
+L$13:
+ mov byte ptr es:3[di],al
+ mov byte ptr es:2[di],dh
+ add di,8
+ sub dx,bx
+ sbb ax,bp
+ dec cx
+ jne L$13
+L$14:
+ pop bp
+ ret
+L$15:
+ mov ax,word ptr 6[si]
+ mov bx,word ptr 2[si]
+ cmp ah,bh
+ jg L$17
+ jl L$19
+ add ax,dx
+ mov dx,word ptr cs:MX_BYTESPERLINE
+L$16:
+ mov byte ptr es:[di],ah
+ add di,dx
+ dec cx
+ jne L$16
+ ret
+L$17:
+ push bp
+ push si
+ mov si,bx
+ add si,dx
+ sub ax,bx
+ xor dx,dx
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ mov bx,ax
+ mov dx,8000H
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ xchg ax,si
+L$18:
+ mov byte ptr es:[di],ah
+ add dx,bx
+ adc ax,bp
+ add di,si
+ dec cx
+ jne L$18
+ pop si
+ pop bp
+ ret
+L$19:
+ push bp
+ push si
+ mov si,bx
+ add si,dx
+ sub ax,bx
+ neg ax
+ xor dx,dx
+ div cx
+ mov bp,ax
+ xor ax,ax
+ div cx
+ mov bx,ax
+ mov dx,8000H
+ mov ax,word ptr cs:MX_BYTESPERLINE
+ xchg ax,si
+L$20:
+ mov byte ptr es:[di],ah
+ sub dx,bx
+ sbb ax,bp
+ add di,si
+ dec cx
+ jne L$20
+ pop si
+ pop bp
+ ret
+MXGOURAUDPOLY:
+ push bp
+ mov bp,sp
+ sub sp,1eH
+ push ds
+ push si
+ push es
+ push di
+ mov cx,word ptr 14H[bp]
+ cmp cx,3
+ jae L$21
+ jmp near ptr L$47
+L$21:
+ les di,dword ptr 10H[bp]
+ lds si,dword ptr 0cH[bp]
+ mov word ptr -16H[bp],7fffH
+ mov word ptr -1aH[bp],8000H
+ mov word ptr -18H[bp],7fffH
+ mov word ptr -1eH[bp],8000H
+ xor dx,dx
+L$22:
+ mov bx,word ptr es:[di]
+ shl bx,1
+ shl bx,1
+ add bx,si
+ mov ax,word ptr [bx]
+ cmp ax,word ptr -16H[bp]
+ jge L$23
+ mov word ptr -16H[bp],ax
+ mov word ptr -0eH[bp],dx
+ mov word ptr -10H[bp],dx
+L$23:
+ cmp ax,word ptr -1aH[bp]
+ jle L$24
+ mov word ptr -1aH[bp],ax
+ mov word ptr -12H[bp],dx
+L$24:
+ mov ax,word ptr 2[bx]
+ cmp ax,word ptr -18H[bp]
+ jge L$25
+ mov word ptr -18H[bp],ax
+L$25:
+ cmp ax,word ptr -1eH[bp]
+ jle L$26
+ mov word ptr -1eH[bp],ax
+L$26:
+ inc di
+ inc di
+ inc dx
+ inc dx
+ dec cx
+ jne L$22
+ mov ax,word ptr -1aH[bp]
+ cmp ax,word ptr cs:MX_CLIPX1
+ jge L$27
+ jmp near ptr L$47
+L$27:
+ mov bx,word ptr -16H[bp]
+ cmp bx,word ptr cs:MX_CLIPX2
+ jle L$28
+ jmp near ptr L$47
+L$28:
+ sub ax,bx
+ jg L$29
+ jmp near ptr L$47
+L$29:
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jge L$30
+ jmp near ptr L$47
+L$30:
+ mov bx,word ptr -18H[bp]
+ cmp bx,word ptr cs:MX_CLIPY2
+ jle L$31
+ jmp near ptr L$47
+L$31:
+ sub ax,bx
+ jg L$32
+ jmp near ptr L$47
+L$32:
+ dec word ptr 14H[bp]
+ shl word ptr 14H[bp],1
+ mov es,word ptr cs:MX_CODESEGMENT
+ mov ax,offset MX_TEXT:MX_SCANBUFFER
+ mov word ptr -4[bp],ax
+ mov si,word ptr -0eH[bp]
+L$33:
+ lds bx,dword ptr 10H[bp]
+ mov di,word ptr [bx+si]
+ dec si
+ dec si
+ test si,si
+ jge L$34
+ mov si,word ptr 14H[bp]
+L$34:
+ mov word ptr -0eH[bp],si
+ mov si,word ptr [bx+si]
+ lds bx,dword ptr 8[bp]
+ shl di,1
+ shl si,1
+ mov ax,word ptr [bx+si]
+ mov dx,word ptr [bx+di]
+ lds bx,dword ptr 0cH[bp]
+ shl si,1
+ shl di,1
+ add si,bx
+ add bx,di
+ mov di,word ptr -4[bp]
+ call near ptr L$1
+ mov word ptr -4[bp],di
+ mov si,word ptr -0eH[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$33
+ mov ax,offset MX_TEXT:MX_SCANBUFFER+4
+ mov word ptr -6[bp],ax
+ mov si,word ptr -10H[bp]
+L$35:
+ lds bx,dword ptr 10H[bp]
+ mov di,word ptr [bx+si]
+ inc si
+ inc si
+ cmp si,word ptr 14H[bp]
+ jbe L$36
+ xor si,si
+L$36:
+ mov word ptr -10H[bp],si
+ mov si,word ptr [bx+si]
+ lds bx,dword ptr 8[bp]
+ shl di,1
+ shl si,1
+ mov ax,word ptr [bx+si]
+ mov dx,word ptr [bx+di]
+ lds bx,dword ptr 0cH[bp]
+ shl si,1
+ shl di,1
+ add si,bx
+ add bx,di
+ mov di,word ptr -6[bp]
+ call near ptr L$1
+ mov word ptr -6[bp],di
+ mov si,word ptr -10H[bp]
+ cmp si,word ptr -12H[bp]
+ jne L$35
+ mov si,offset MX_TEXT:MX_SCANBUFFER
+ mov ax,word ptr -16H[bp]
+ mov cx,word ptr -1aH[bp]
+ sub cx,ax
+ mov bx,word ptr cs:MX_CLIPX1
+ sub bx,ax
+ jle L$37
+ sub cx,bx
+ add ax,bx
+ mov word ptr -16H[bp],ax
+ shl bx,1
+ shl bx,1
+ shl bx,1
+ add si,bx
+L$37:
+ mov bx,ax
+ add bx,cx
+ sub bx,word ptr cs:MX_CLIPX2
+ jle L$38
+ sub cx,bx
+L$38:
+ test cx,cx
+ jg L$39
+ jmp near ptr L$47
+L$39:
+ mov word ptr -8[bp],cx
+ mov word ptr -4[bp],si
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,word ptr -18H[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$40
+ mov ax,word ptr -1eH[bp]
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$40
+ jmp L$44
+L$40:
+ mov di,cx
+ inc di
+ sub si,8
+L$41:
+ dec di
+ je L$44
+ add si,8
+ mov ax,word ptr [si]
+ mov cx,word ptr 4[si]
+ mov dx,word ptr cs:MX_CLIPY2
+ cmp ax,dx
+ jg L$43
+ cmp cx,dx
+ jle L$42
+ mov word ptr 4[si],dx
+ mov bx,cx
+ sub bx,dx
+ sub cx,ax
+ jle L$43
+ mov ax,word ptr 2[si]
+ sub ax,word ptr 6[si]
+ imul bx
+ idiv cx
+ add word ptr 6[si],ax
+ mov ax,word ptr [si]
+ mov cx,word ptr 4[si]
+L$42:
+ mov dx,word ptr cs:MX_CLIPY1
+ cmp cx,dx
+ jl L$43
+ sub cx,ax
+ jle L$43
+ cmp ax,dx
+ jge L$41
+ mov word ptr [si],dx
+ sub dx,ax
+ cmp cx,dx
+ jbe L$43
+ mov ax,word ptr 6[si]
+ sub ax,word ptr 2[si]
+ imul dx
+ idiv cx
+ add word ptr 2[si],ax
+ jmp L$41
+L$43:
+ mov word ptr [si],0ffffH
+ jmp L$41
+L$44:
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ mov si,word ptr -4[bp]
+ mov cl,byte ptr -16H[bp]
+ and cl,3
+ mov al,11H
+ shl al,cl
+ mov byte ptr -2[bp],al
+ shr word ptr -16H[bp],1
+ shr word ptr -16H[bp],1
+ mov ax,word ptr 6[bp]
+ mov ah,al
+ xor al,al
+ mov word ptr 6[bp],ax
+L$45:
+ mov ax,word ptr [si]
+ test ax,ax
+ js L$46
+ mov cx,word ptr 4[si]
+ sub cx,ax
+ jle L$46
+ mul word ptr cs:MX_BYTESPERLINE
+ add ax,word ptr -16H[bp]
+ mov di,ax
+ mov ah,byte ptr -2[bp]
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov dx,word ptr 6[bp]
+ call near ptr L$15
+L$46:
+ rol byte ptr -2[bp],1
+ adc word ptr -16H[bp],0
+ add si,8
+ dec word ptr -8[bp]
+ jne L$45
+L$47:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 10H
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXPUTIMAGE
+ EXTRN SUBCLIPIMAGE:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ DW offset L$2
+ DW offset L$6
+ DW offset L$10
+ DW offset L$14
+ DW offset L$18
+ DW offset L$20
+L$2:
+ shr cx,1
+ jb L$5
+L$3:
+ movsb
+ add si,3
+ movsb
+ add si,3
+ dec cx
+ jne L$3
+L$4:
+ ret
+L$5:
+ movsb
+ add si,3
+ jcxz L$4
+ jmp L$3
+L$6:
+ shr cx,1
+ jb L$9
+L$7:
+ mov al,byte ptr [si]
+ mov ah,byte ptr 4[si]
+ and word ptr es:[di],ax
+ inc di
+ inc di
+ add si,8
+ dec cx
+ jne L$7
+L$8:
+ ret
+L$9:
+ lodsb
+ and byte ptr es:[di],al
+ inc di
+ add si,3
+ jcxz L$8
+ jmp L$7
+L$10:
+ shr cx,1
+ jb L$13
+L$11:
+ mov al,byte ptr [si]
+ mov ah,byte ptr 4[si]
+ or word ptr es:[di],ax
+ inc di
+ inc di
+ add si,8
+ dec cx
+ jne L$11
+L$12:
+ ret
+L$13:
+ lodsb
+ or byte ptr es:[di],al
+ inc di
+ add si,3
+ jcxz L$12
+ jmp L$11
+L$14:
+ shr cx,1
+ jb L$17
+L$15:
+ mov al,byte ptr [si]
+ mov ah,byte ptr 4[si]
+ xor word ptr es:[di],ax
+ inc di
+ inc di
+ add si,8
+ dec cx
+ jne L$15
+L$16:
+ ret
+L$17:
+ lodsb
+ xor byte ptr es:[di],al
+ inc di
+ add si,3
+ jcxz L$16
+ jmp L$15
+L$18:
+ mov al,byte ptr [si]
+ cmp al,ah
+ je L$19
+ mov byte ptr es:[di],al
+L$19:
+ inc di
+ add si,4
+ dec cx
+ jne L$18
+ ret
+L$20:
+ mov al,byte ptr [si]
+ add byte ptr es:[di],al
+ inc di
+ add si,4
+ dec cx
+ jne L$20
+ ret
+MXPUTIMAGE:
+ push bp
+ mov bp,sp
+ sub sp,14H
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 0eH[bp]
+ mov ax,word ptr 0cH[bp]
+ mov cx,word ptr 0aH[bp]
+ mov dx,word ptr 8[bp]
+ call near ptr MX_TEXT:SUBCLIPIMAGE
+ jae L$21
+ jmp near ptr L$26
+L$21:
+ mov word ptr 8[bp],dx
+ add word ptr 10H[bp],si
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,bx
+ shr di,1
+ shr di,1
+ add di,ax
+ mov word ptr -0aH[bp],di
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ and bl,3
+ mov byte ptr -10H[bp],bl
+ mov bx,cx
+ shr bx,1
+ shr bx,1
+ and cl,3
+ mov al,8
+ shr al,cl
+ mov si,6
+L$22:
+ mov word ptr -8[bp+si],bx
+ shr al,1
+ adc bx,0
+ dec si
+ dec si
+ jge L$22
+ mov cl,byte ptr -10H[bp]
+ mov al,11H
+ shl al,cl
+ mov byte ptr -14H[bp],al
+ mov bx,word ptr 6[bp]
+ mov byte ptr -12H[bp],bh
+ xor bh,bh
+ cmp bl,5
+ jbe L$23
+ xor bl,bl
+L$23:
+ shl bx,1
+ mov ax,word ptr cs:L$1[bx]
+ mov word ptr -0cH[bp],ax
+ cld
+ mov byte ptr -0eH[bp],4
+ lea bx,-8[bp]
+ mov ds,word ptr 12H[bp]
+L$24:
+ cmp word ptr ss:[bx],0
+ je L$26
+ mov si,word ptr 10H[bp]
+ mov ah,byte ptr -14H[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov ah,byte ptr -10H[bp]
+ and ah,3
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov dx,word ptr 8[bp]
+ mov di,word ptr -0aH[bp]
+L$25:
+ push si
+ push di
+ mov cx,word ptr ss:[bx]
+ mov ah,byte ptr -12H[bp]
+ call word ptr -0cH[bp]
+ pop di
+ pop si
+ add si,word ptr 0aH[bp]
+ add di,word ptr cs:MX_BYTESPERLINE
+ dec dx
+ jne L$25
+ inc bx
+ inc bx
+ inc byte ptr -10H[bp]
+ rol byte ptr -14H[bp],1
+ adc word ptr -0aH[bp],0
+ inc word ptr 10H[bp]
+ dec byte ptr -0eH[bp]
+ jne L$24
+L$26:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0eH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXPAN
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MXWAITDISPLAY:BYTE
+ EXTRN MXSTARTADDRESS:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPAN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ax,word ptr 6[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov dx,word ptr 8[bp]
+ shr dx,1
+ shr dx,1
+ add ax,dx
+ push ax
+ call far ptr MXWAITDISPLAY
+ call far ptr MXSTARTADDRESS
+ mov dx,3daH
+ in al,dx
+ mov dx,3c0H
+ mov al,33H
+ out dx,al
+ mov al,byte ptr 8[bp]
+ and al,3
+ shl al,1
+ out dx,al
+ xor ax,ax
+ mov sp,bp
+ pop bp
+ retf 4
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXGETPIXEL
+ PUBLIC MXPUTPIXEL
+ EXTRN MX_CLIPX1:BYTE
+ EXTRN MX_CLIPX2:BYTE
+ EXTRN MX_CLIPY1:BYTE
+ EXTRN MX_CLIPY2:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPIXEL:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ xor ax,ax
+ mov si,word ptr 8[bp]
+ cmp si,word ptr cs:MX_CLIPX1
+ jl L$1
+ cmp si,word ptr cs:MX_CLIPX2
+ jg L$1
+ mov bx,word ptr 6[bp]
+ cmp bx,word ptr cs:MX_CLIPY1
+ jl L$1
+ cmp bx,word ptr cs:MX_CLIPY2
+ jg L$1
+ mov al,4
+ mov ah,byte ptr 8[bp]
+ and ah,3
+ mov dx,3ceH
+ out dx,ax
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+ mov ax,bx
+ mul word ptr cs:MX_BYTESPERLINE
+ shr si,1
+ shr si,1
+ add si,ax
+ mov al,byte ptr [si]
+ xor ah,ah
+L$1:
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXPUTPIXEL:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov si,word ptr 0aH[bp]
+ cmp si,word ptr cs:MX_CLIPX1
+ jl L$2
+ cmp si,word ptr cs:MX_CLIPX2
+ jg L$2
+ mov ax,word ptr 8[bp]
+ cmp ax,word ptr cs:MX_CLIPY1
+ jl L$2
+ cmp ax,word ptr cs:MX_CLIPY2
+ jg L$2
+ mov ds,word ptr cs:MX_VIDEOSEGMENT
+ mul word ptr cs:MX_BYTESPERLINE
+ shr si,1
+ shr si,1
+ add si,ax
+ mov cl,byte ptr 0aH[bp]
+ and cl,3
+ mov ax,102H
+ shl ah,cl
+ mov dx,3c4H
+ out dx,ax
+ mov al,byte ptr 6[bp]
+ mov byte ptr [si],al
+L$2:
+ xor ax,ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 6
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXROWADDRESS
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROWADDRESS:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov dx,3d4H
+ mov al,13H
+ mov ah,byte ptr 6[bp]
+ out dx,ax
+ xor ax,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXROTATEPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROTATEPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,300H
+ push ds
+ push si
+ push es
+ push di
+ mov bx,word ptr 8[bp]
+ add bx,bx
+ add bx,word ptr 8[bp]
+ lds si,dword ptr 0aH[bp]
+ push ss
+ pop es
+ lea di,-300H[bp]
+ cld
+ mov ax,word ptr 6[bp]
+ mov dx,ax
+ test ax,ax
+ je L$2
+ jl L$1
+ add ax,ax
+ add dx,ax
+ sub bx,dx
+ add si,bx
+ push si
+ mov cx,dx
+ rep movsb
+ mov es,word ptr 0cH[bp]
+ mov di,si
+ dec di
+ pop si
+ dec si
+ mov cx,bx
+ std
+ rep movsb
+ push ss
+ pop ds
+ lea si,-300H[bp]
+ les di,dword ptr 0aH[bp]
+ mov cx,dx
+ cld
+ rep movsb
+ jmp L$2
+L$1:
+ add ax,ax
+ add dx,ax
+ neg dx
+ sub bx,dx
+ mov cx,dx
+ rep movsb
+ les di,dword ptr 0aH[bp]
+ mov cx,bx
+ rep movsb
+ push ss
+ pop ds
+ lea si,-300H[bp]
+ mov cx,dx
+ rep movsb
+L$2:
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSTARTADDRESS
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTADDRESS:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov bx,word ptr 6[bp]
+ mov dx,3d4H
+ mov al,0cH
+ mov ah,bh
+ cli
+ out dx,ax
+ mov al,0dH
+ mov ah,bl
+ out dx,ax
+ sti
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSETCOLOR
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETCOLOR:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr 0cH[bp]
+ mov dx,3c8H
+ out dx,al
+ inc dx
+ mov al,byte ptr 0aH[bp]
+ out dx,al
+ mov al,byte ptr 8[bp]
+ out dx,al
+ mov al,byte ptr 6[bp]
+ out dx,al
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSTRETCHIMAGE
+ EXTRN SUBCLIPBOX:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ DW offset L$8
+ DW offset L$10
+ DW offset L$12
+ DW offset L$14
+ DW offset L$16
+ DW offset L$19
+MXSTRETCHIMAGE:
+ push bp
+ mov bp,sp
+ sub sp,14H
+ push ds
+ push si
+ push es
+ push di
+ xor dx,dx
+ mov ax,word ptr 0eH[bp]
+ mov bx,word ptr 0aH[bp]
+ div bx
+ mov word ptr -0aH[bp],ax
+ xor ax,ax
+ div bx
+ mov word ptr -0cH[bp],ax
+ xor dx,dx
+ mov ax,word ptr 0cH[bp]
+ mov bx,word ptr 8[bp]
+ div bx
+ mov word ptr -0eH[bp],ax
+ xor ax,ax
+ div bx
+ mov word ptr -10H[bp],ax
+ mov bx,word ptr 12H[bp]
+ mov ax,word ptr 10H[bp]
+ mov cx,word ptr 0aH[bp]
+ mov dx,word ptr 8[bp]
+ call near ptr MX_TEXT:SUBCLIPBOX
+ jae L$2
+ jmp near ptr L$7
+L$2:
+ mov word ptr 0aH[bp],cx
+ mov word ptr 8[bp],dx
+ sub word ptr 12H[bp],bx
+ sub word ptr 10H[bp],ax
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,bx
+ shr di,1
+ shr di,1
+ add di,ax
+ mov word ptr -2[bp],di
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ and bl,3
+ mov byte ptr -6[bp],bl
+ mov cl,bl
+ mov al,11H
+ shl al,cl
+ mov byte ptr -14H[bp],al
+ mov ax,word ptr 10H[bp]
+ test ax,ax
+ je L$3
+ mov bx,ax
+ mul word ptr -10H[bp]
+ mov cx,dx
+ mov ax,bx
+ mul word ptr -0eH[bp]
+ add ax,cx
+ mul word ptr 0eH[bp]
+ add word ptr 14H[bp],ax
+L$3:
+ mov ax,word ptr 12H[bp]
+ test ax,ax
+ je L$4
+ mov bx,ax
+ mul word ptr -0cH[bp]
+ mov cx,dx
+ mov ax,bx
+ mul word ptr -0aH[bp]
+ add ax,cx
+ add word ptr 14H[bp],ax
+L$4:
+ mov ax,word ptr -0eH[bp]
+ mul word ptr 0eH[bp]
+ mov word ptr -0eH[bp],ax
+ mov bx,word ptr 6[bp]
+ mov byte ptr -8[bp],bh
+ xor bh,bh
+ cmp bl,5
+ jbe L$5
+ xor bl,bl
+L$5:
+ shl bx,1
+ mov ax,word ptr cs:L$1[bx]
+ mov word ptr -4[bp],ax
+ mov ds,word ptr 16H[bp]
+ xor ax,ax
+ mov word ptr -12H[bp],ax
+L$6:
+ mov si,word ptr 14H[bp]
+ mov ah,byte ptr -14H[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov ah,byte ptr -6[bp]
+ and ah,3
+ mov al,4
+ mov dx,3ceH
+ out dx,ax
+ mov cx,word ptr 8[bp]
+ mov di,word ptr -2[bp]
+ mov ah,byte ptr -8[bp]
+ xor bx,bx
+ mov dx,word ptr cs:MX_BYTESPERLINE
+ call word ptr -4[bp]
+ inc byte ptr -6[bp]
+ rol byte ptr -14H[bp],1
+ adc word ptr -2[bp],0
+ mov dx,word ptr -0cH[bp]
+ mov ax,word ptr -0aH[bp]
+ add word ptr -12H[bp],dx
+ adc word ptr 14H[bp],ax
+ dec word ptr 0aH[bp]
+ jne L$6
+L$7:
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 12H
+L$8:
+ mov al,byte ptr [si]
+ mov byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$9
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$8
+ add si,word ptr 0eH[bp]
+ jmp L$8
+L$9:
+ ret
+L$10:
+ mov al,byte ptr [si]
+ and byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$11
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$10
+ add si,word ptr 0eH[bp]
+ jmp L$10
+L$11:
+ ret
+L$12:
+ mov al,byte ptr [si]
+ or byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$13
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$12
+ add si,word ptr 0eH[bp]
+ jmp L$12
+L$13:
+ ret
+L$14:
+ mov al,byte ptr [si]
+ xor byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$15
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$14
+ add si,word ptr 0eH[bp]
+ jmp L$14
+L$15:
+ ret
+L$16:
+ mov al,byte ptr [si]
+ cmp al,ah
+ je L$17
+ mov byte ptr es:[di],al
+L$17:
+ add di,dx
+ dec cx
+ je L$18
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$16
+ add si,word ptr 0eH[bp]
+ jmp L$16
+L$18:
+ ret
+L$19:
+ mov al,byte ptr [si]
+ add byte ptr es:[di],al
+ add di,dx
+ dec cx
+ je L$20
+ add si,word ptr -0eH[bp]
+ add bx,word ptr -10H[bp]
+ jae L$19
+ add si,word ptr 0eH[bp]
+ jmp L$19
+L$20:
+ ret
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSTARTLINE
+ EXTRN MX_BYTESPERLINE:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTLINE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ax,word ptr 6[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ xchg ax,bx
+ mov dx,3daH
+L$1:
+ in al,dx
+ test al,8
+ jne L$1
+ mov dx,3d4H
+ mov al,0cH
+ mov ah,bh
+ cli
+ out dx,ax
+ mov al,0dH
+ mov ah,bl
+ out dx,ax
+ sti
+ mov dx,3daH
+L$2:
+ in al,dx
+ test al,8
+ je L$2
+ xor ax,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MX_SCREENWIDTH
+ PUBLIC MX_SCREENHEIGHT
+ PUBLIC MX_BYTESPERLINE
+ PUBLIC MXSETMODE
+ PUBLIC MXCHANGEMODE
+ PUBLIC MXGETASPECT
+ PUBLIC MXGETSCREENSIZE
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MXSETSYSCLIPREGION:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCREENWIDTH:
+ add byte ptr [bx+si],al
+MX_SCREENHEIGHT:
+ add byte ptr [bx+si],al
+L$1:
+ add byte ptr [bx+si],al
+L$2:
+ add byte ptr [bx+si],al
+MX_BYTESPERLINE:
+ add byte ptr [bx+si],al
+L$3:
+ or word ptr 14H[bx+si],ax
+ add byte ptr [bx],dl
+ jcxz L$4
+L$4:
+ DB 0
+L$5:
+ or word ptr 14H[bx+di],ax
+ add byte ptr [bx],dl
+ jcxz L$6
+L$6:
+ DB 0
+L$7:
+ add byte ptr 1[bx],bl
+ dec di
+ add dl,byte ptr 3[bx+si]
+ add byte ptr [si],54H
+ add ax,1380H
+ sub byte ptr [bx+si],al
+ DB 0
+L$8:
+ add byte ptr 1[bp+di],ch
+ pop cx
+ add bl,byte ptr 3[bp+si]
+ mov es,word ptr [si]
+ pop si
+ add ax,138aH
+ sub ax,0
+ push es
+ mov di,1f07H
+ adc byte ptr -7aefH[bp+di],al
+ adc bl,byte ptr 15H[di]
+ arpl word ptr ds:[0baH],dx
+ DB 0
+L$9:
+ push es
+ DD ds:[7bfH]
+ pushf
+ adc word ptr -70eeH[bp],cx
+ adc ax,1696H
+ mov cx,0
+L$10:
+ push es
+ or ax,3e07H
+ adc dl,ch
+ adc word ptr -20eeH[si],cx
+ adc ax,16e7H
+ push es
+ add byte ptr [bx+si],al
+L$11:
+ add byte ptr 1[si],dh
+ arpl word ptr [bp+si],ax
+ add dx,word ptr fs:6804H[bx]
+ add ax,695H
+ xchg byte ptr [bx],al
+ lock or word ptr 0fH[bx+si],sp
+ xor word ptr [bx+si],dx
+ pop bx
+ adc word ptr 5712H[di],cx
+ adc si,word ptr [bp+si]
+ adc al,0
+ adc ax,1660H
+ adc byte ptr [bx],0e3H
+ add byte ptr [bx+si],al
+L$12:
+ arpl word ptr ds:[500H],ax
+ add byte ptr 1[bx+si],al
+ enter 1a00H,0
+ DW offset L$9
+ DW offset L$5
+ add byte ptr [bx+si],al
+ xor ax,word ptr [bp+di]
+L$13:
+ jcxz L$14
+ DB 0
+L$14:
+ add word ptr [bx+si],ax
+ inc ax
+ add ax,si
+ add byte ptr [bp+si],bl
+ add byte ptr [bp+si],bl
+ DW offset L$5
+ add byte ptr [bx+si],al
+ xor ax,word ptr [bp+di]
+L$15:
+ arpl word ptr ds:[0a00H],ax
+ add byte ptr 1[bx+si],al
+ nop
+ add word ptr [bp+si],bx
+ add byte ptr [bp+si],cl
+ DW offset L$3
+ add byte ptr [bx+si],al
+ xor ax,word ptr [bp+di]
+L$16:
+ jcxz L$17
+ DB 0
+L$17:
+ add al,byte ptr [bx+si]
+ inc ax
+ add ax,sp
+ DD L$18
+L$18:
+ add byte ptr [bp+si],cl
+ add byte ptr [bx+si],al
+ add byte ptr [bp+di],dh
+ DB 3
+L$19:
+ sbb ax,word ptr [eax]
+ adc al,0
+ push 0c801H
+ add byte ptr [bp+si],ch
+ add byte ptr [bp+si],cl
+ DW offset L$5
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$20:
+ out 9,ax
+ add byte ptr [bx+si],cl
+ add byte ptr 1[bx+si],ch
+ lock add byte ptr [bp+si],ch
+ add byte ptr [bp+si],bl
+ DW offset L$5
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$21:
+ sbb ax,word ptr [eax]
+ sub byte ptr [bx+si],al
+ push 9001H
+ add word ptr [bp+si],bp
+ add byte ptr [bp+si],cl
+ DW offset L$3
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$22:
+ out 9,ax
+ add byte ptr [bx+si],dl
+ add byte ptr 1[bx+si],ch
+ loopnz L$23
+ DW offset L$8
+L$23 equ $-1
+ DW offset L$10
+ DW offset L$3
+ add byte ptr [bx+si],al
+ fadd dword ptr [bp+si]
+L$24:
+ mov word ptr ds:[0],ax
+ add byte ptr [bx+si],al
+ inc ax
+ add word ptr 1a00H[bx],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],dl
+ add byte ptr [bx+si],al
+ add byte ptr [bp+di],dh
+ DB 3
+L$25:
+ mov word ptr 0,ax
+ add byte ptr [bx+si],al
+ inc ax
+ add word ptr 1a00H[bx],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],cl
+ add byte ptr [bx+si],al
+ add byte ptr [bp+di],dh
+ DB 3
+L$26:
+ cmpsw
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ push 0e001H
+ add word ptr [bp+si],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],dl
+ add byte ptr [bx+si],al
+ add al,bl
+ DB 2
+L$27:
+ cmpsw
+ add byte ptr [bx+si],al
+ add byte ptr [bx+si],al
+ push 0e001H
+ add word ptr [bp+si],bp
+ add byte ptr [bp+si],bh
+ add byte ptr [bp+si],cl
+ add byte ptr [bx+si],al
+ add al,bl
+ DB 2
+L$28:
+ out 1,ax
+ add byte ptr [bp+si],al
+ add byte ptr 5801H[bx+si],dl
+ add ch,byte ptr [bp+si]
+ add byte ptr [bx+si],al
+ pop word ptr [bp+si]
+L$29:
+ DW offset L$24
+ DW offset L$12
+ DW offset L$13
+ DW offset L$25
+ DW offset L$15
+ DW offset L$16
+ DW offset L$26
+ DW offset L$19
+ DW offset L$20
+ DW offset L$27
+ DW offset L$21
+ DW offset L$22
+ DW offset L$28
+L$30:
+ mov ax,3
+ int 10H
+ mov word ptr MX_SCREENHEIGHT,0
+ mov word ptr MX_BYTESPERLINE,0
+ ret
+MXSETMODE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov si,word ptr 6[bp]
+ cmp si,0dH
+ jbe L$31
+ jmp near ptr L$36
+L$31:
+ test si,si
+ jne L$32
+ call near ptr L$30
+ jmp near ptr L$36
+L$32:
+ dec si
+ shl si,1
+ mov si,word ptr L$29[si]
+ cld
+ push si
+ mov ax,13H
+ int 10H
+ pop si
+ mov dx,3c4H
+ mov ax,604H
+ out dx,ax
+ mov ax,100H
+ out dx,ax
+ mov dx,3c2H
+ lodsb
+ out dx,al
+ mov dx,3c4H
+ mov ax,300H
+ out dx,ax
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ and al,7fH
+ out dx,al
+ lodsw
+ mov word ptr L$1,ax
+ lodsw
+ mov word ptr L$2,ax
+ lodsw
+ mov word ptr MX_SCREENWIDTH,ax
+ shr ax,1
+ shr ax,1
+ mov word ptr MX_BYTESPERLINE,ax
+ lodsw
+ mov word ptr MX_SCREENHEIGHT,ax
+ mov bx,si
+ mov dx,3d4H
+L$33:
+ mov si,word ptr [bx]
+ inc bx
+ inc bx
+ test si,si
+ je L$35
+L$34:
+ lodsw
+ test ax,ax
+ je L$33
+ out dx,ax
+ jmp L$34
+L$35:
+ push word ptr MX_SCREENWIDTH
+ push word ptr [bx]
+ push cs
+ call near ptr MX_TEXT:MXSETSYSCLIPREGION
+ mov dx,3c4H
+ mov ax,0f02H
+ out dx,ax
+ mov es,word ptr MX_TEXT:MX_VIDEOSEGMENT
+ xor di,di
+ mov cx,8000H
+ xor ax,ax
+ rep stosw
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ or al,80H
+ out dx,al
+L$36:
+ xor ax,ax
+ mov ax,word ptr MX_SCREENWIDTH
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 2
+MXCHANGEMODE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov si,word ptr 6[bp]
+ cmp si,0dH
+ ja L$40
+ test si,si
+ je L$40
+ dec si
+ shl si,1
+ mov si,word ptr L$29[si]
+ cld
+ mov dx,3c4H
+ mov ax,604H
+ out dx,ax
+ mov ax,100H
+ out dx,ax
+ mov dx,3c2H
+ lodsb
+ out dx,al
+ mov dx,3c4H
+ mov ax,300H
+ out dx,ax
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ and al,7fH
+ out dx,al
+ lodsw
+ mov word ptr L$1,ax
+ lodsw
+ mov word ptr L$2,ax
+ lodsw
+ mov word ptr MX_SCREENWIDTH,ax
+ lodsw
+ mov word ptr MX_SCREENHEIGHT,ax
+ mov bx,si
+ mov dx,3d4H
+L$37:
+ mov si,word ptr [bx]
+ inc bx
+ inc bx
+ test si,si
+ je L$39
+L$38:
+ lodsw
+ test ax,ax
+ je L$37
+ cmp al,13H
+ je L$38
+ out dx,ax
+ jmp L$38
+L$39:
+ mov dx,3d4H
+ mov al,11H
+ out dx,al
+ inc dx
+ in al,dx
+ or al,80H
+ out dx,al
+L$40:
+ xor ax,ax
+ mov ax,word ptr MX_SCREENWIDTH
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 2
+MXGETASPECT:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 0aH[bp]
+ mov ax,word ptr cs:L$1
+ mov word ptr [si],ax
+ lds si,dword ptr 6[bp]
+ mov ax,word ptr cs:L$2
+ mov word ptr [si],ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MXGETSCREENSIZE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 0aH[bp]
+ mov ax,word ptr cs:MX_SCREENWIDTH
+ mov word ptr [si],ax
+ lds si,dword ptr 6[bp]
+ mov ax,word ptr cs:MX_SCREENHEIGHT
+ mov word ptr [si],ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSETPALETTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETPALETTE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ lds si,dword ptr 0aH[bp]
+ mov cx,word ptr 6[bp]
+ mov ax,word ptr 8[bp]
+ mov dx,3c8H
+ out dx,al
+ inc dx
+ cld
+ cli
+L$1:
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ lodsb
+ out dx,al
+ loop L$1
+ sti
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSPLITSCREEN
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSPLITSCREEN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ax,word ptr 6[bp]
+ shl ax,1
+ mov bh,ah
+ mov bl,ah
+ and bx,201H
+ mov cl,4
+ shl bx,cl
+ shl bh,1
+ mov dx,3d4H
+ mov ah,al
+ mov al,18H
+ out dx,ax
+ mov al,7
+ out dx,al
+ inc dx
+ in al,dx
+ dec dx
+ mov ah,al
+ and ah,0efH
+ or ah,bl
+ mov al,7
+ out dx,ax
+ mov al,9
+ out dx,al
+ inc dx
+ in al,dx
+ dec dx
+ mov ah,al
+ and ah,0bfH
+ or ah,bh
+ mov al,9
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXPUTTILE
+ PUBLIC MXTRANSPUTTILE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MX_VIDEOSEGMENT:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPUTTILE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ax,word ptr 0aH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,word ptr 0cH[bp]
+ shr di,1
+ shr di,1
+ add di,ax
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ lds si,dword ptr 0eH[bp]
+ shr word ptr 8[bp],1
+ shr word ptr 8[bp],1
+ mov cl,byte ptr 0cH[bp]
+ and cl,3
+ mov ah,11H
+ shl ah,cl
+ mov word ptr 0aH[bp],4
+ mov bx,word ptr cs:MX_BYTESPERLINE
+ sub bx,word ptr 8[bp]
+L$1:
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov word ptr 0cH[bp],di
+ mov dx,word ptr 6[bp]
+L$2:
+ mov cx,word ptr 8[bp]
+ shr cx,1
+ rep movsw
+ rcl cx,1
+ rep movsb
+ add di,bx
+ dec dx
+ jne L$2
+ mov di,word ptr 0cH[bp]
+ rol ah,1
+ adc di,0
+ dec word ptr 0aH[bp]
+ jne L$1
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MXTRANSPUTTILE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ push es
+ push di
+ mov ax,word ptr 0aH[bp]
+ mul word ptr cs:MX_BYTESPERLINE
+ mov di,word ptr 0cH[bp]
+ shr di,1
+ shr di,1
+ add di,ax
+ mov es,word ptr cs:MX_VIDEOSEGMENT
+ lds si,dword ptr 0eH[bp]
+ shr word ptr 8[bp],1
+ shr word ptr 8[bp],1
+ mov cl,byte ptr 0cH[bp]
+ and cl,3
+ mov ah,11H
+ shl ah,cl
+ mov word ptr 0aH[bp],4
+ mov bx,word ptr cs:MX_BYTESPERLINE
+ sub bx,word ptr 8[bp]
+L$3:
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov word ptr 0cH[bp],di
+ mov dx,word ptr 6[bp]
+L$4:
+ mov cx,word ptr 8[bp]
+ jcxz L$7
+L$5:
+ mov al,byte ptr [si]
+ test al,al
+ je L$6
+ mov byte ptr es:[di],al
+L$6:
+ inc si
+ inc di
+ dec cx
+ jne L$5
+L$7:
+ add di,bx
+ dec dx
+ jne L$4
+ mov di,word ptr 0cH[bp]
+ rol ah,1
+ adc di,0
+ dec word ptr 0aH[bp]
+ jne L$3
+ xor ax,ax
+ pop di
+ pop es
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 0cH
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXSETVIRTUALSCREEN
+ PUBLIC MXGETVIRTUALSCREEN
+ EXTRN MX_CODESEGMENT:BYTE
+ EXTRN MX_BYTESPERLINE:BYTE
+ EXTRN MXROWADDRESS:BYTE
+ EXTRN MXSETSYSCLIPREGION:BYTE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+ add byte ptr [bx+si],al
+L$2:
+ add byte ptr [bx+si],al
+MXSETVIRTUALSCREEN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ mov ds,word ptr cs:MX_CODESEGMENT
+ mov ax,1
+ cmp word ptr 8[bp],140H
+ jb L$3
+ push ax
+ mov dx,4
+ xor ax,ax
+ div word ptr 8[bp]
+ cmp word ptr 6[bp],ax
+ pop ax
+ ja L$3
+ mov ax,word ptr 8[bp]
+ and ax,0fff8H
+ mov word ptr L$1,ax
+ shr ax,1
+ shr ax,1
+ mov word ptr MX_TEXT:MX_BYTESPERLINE,ax
+ shr ax,1
+ push ax
+ call far ptr MXROWADDRESS
+ mov ax,word ptr 6[bp]
+ mov word ptr L$2,ax
+ push word ptr 8[bp]
+ push word ptr 6[bp]
+ call far ptr MXSETSYSCLIPREGION
+ xor ax,ax
+L$3:
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 4
+MXGETVIRTUALSCREEN:
+ push bp
+ mov bp,sp
+ sub sp,0
+ push ds
+ push si
+ mov ax,word ptr cs:L$1
+ lds si,dword ptr 0aH[bp]
+ mov word ptr [si],ax
+ mov ax,word ptr cs:L$2
+ lds si,dword ptr 6[bp]
+ mov word ptr [si],ax
+ xor ax,ax
+ pop si
+ pop ds
+ mov sp,bp
+ pop bp
+ retf 8
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXWAITDISPLAY
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITDISPLAY:
+ mov dx,3daH
+L$1:
+ in al,dx
+ test al,8
+ jne L$1
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXWRITEMODE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEMODE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov dx,3ceH
+ mov ah,byte ptr 6[bp]
+ and ah,3
+ or ah,40H
+ mov al,5
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXWRITEPLANE
+ PUBLIC MXREADPLANE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEPLANE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov ah,byte ptr 6[bp]
+ and ah,0fH
+ mov al,2
+ mov dx,3c4H
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MXREADPLANE:
+ push bp
+ mov bp,sp
+ sub sp,0
+ mov al,4
+ mov ah,byte ptr 6[bp]
+ and ah,3
+ mov dx,3ceH
+ out dx,ax
+ mov sp,bp
+ pop bp
+ retf 2
+MX_TEXT ENDS
+ END
--- /dev/null
+.387
+ PUBLIC MXWAITRETRACE
+MX_TEXT SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITRETRACE:
+ mov dx,3daH
+L$1:
+ in al,dx
+ test al,8
+ je L$1
+ retf
+MX_TEXT ENDS
+ END
--- /dev/null
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
--- /dev/null
+@echo off\r
+wdis -a MXBB.OBJ > mxbb.asm\r
+wdis -a MXCC.OBJ > mxcc.asm\r
+wdis -a MXCG.OBJ > mxcg.asm\r
+wdis -a MXCL.OBJ > mxcl.asm\r
+wdis -a MXCR.OBJ > mxcl.asm\r
+wdis -a MXFB.OBJ > mxfb.asm\r
+wdis -a MXFP.OBJ > mxfp.asm\r
+wdis -a MXGC.OBJ > mxgc.asm\r
+wdis -a MXGI.OBJ > mxgi.asm\r
+wdis -a MXGM.OBJ > mxgm.asm\r
+wdis -a MXGP.OBJ > mxgp.asm\r
+wdis -a MXGV.OBJ > mxgv.asm\r
+wdis -a MXHL.OBJ > mxhl.asm\r
+wdis -a MXIT.OBJ > mxit.asm\r
+wdis -a MXLL.OBJ > mxll.asm\r
+wdis -a MXLN.OBJ > mxln.asm\r
+wdis -a MXOT.OBJ > mxot.asm\r
+wdis -a MXPB.OBJ > mxpb.asm\r
+wdis -a MXPF.OBJ > mxpf.asm\r
+wdis -a MXPG.OBJ > mxpg.asm\r
+wdis -a MXPI.OBJ > mxpi.asm\r
+wdis -a MXPN.OBJ > mxpn.asm\r
+wdis -a MXPP.OBJ > mxpp.asm\r
+wdis -a MXRA.OBJ > mxra.asm\r
+wdis -a MXRP.OBJ > mxrp.asm\r
+wdis -a MXSA.OBJ > mxsa.asm\r
+wdis -a MXSC.OBJ > mxsc.asm\r
+wdis -a MXSI.OBJ > mxsi.asm\r
+wdis -a MXSL.OBJ > mxsl.asm\r
+wdis -a MXSM.OBJ > mxsm.asm\r
+wdis -a MXSP.OBJ > mxsp.asm\r
+wdis -a MXSS.OBJ > mxss.asm\r
+wdis -a MXTL.OBJ > mxtl.asm\r
+wdis -a MXVS.OBJ > mxvs.asm\r
+wdis -a MXWD.OBJ > mxwd.asm\r
+wdis -a MXWM.OBJ > mxwm.asm\r
+wdis -a MXWP.OBJ > mxwp.asm\r
+wdis -a MXWR.OBJ > mxwr.asm\r
#!/bin/bash
+if [ -z "$*" ]; then
+ pee="wwww"
+ else
+ pee="$*"
+fi
+##echo "$pee"
git add .
-. ./boop.sh "$*"
+. ./boop.sh "$pee"
cp -fp *.exe /var/www/
scp -rp -P 26 *.exe 4ch.mooo.com:/var/www/16/
#if [ -f "*.exe" ]
# -0 8088/8086 class code generation
# -s disable stack overflow checking
+# -zk0u translate kanji to unicode... wwww
+# -zk0 kanji support~
+# -zkl current codepage
+
#%.C
#192x144
#wwww will add these
#!endif
TARGET_OS = dos
-#-zk0u = translate kanji to unicode... wwww
-#-zk0 = kanji support~
-#-zkl = current codepage
#EXMMTESTDIR=16$(DIRSEP)exmmtest$(DIRSEP)
SRC=src$(DIRSEP)
NYANLIB=$(SRCLIB)nyan$(DIRSEP)
#EXMMLIB=$(SRCLIB)exmm$(DIRSEP)
MODEXLIB=$(SRCLIB)modex16$(DIRSEP)
+MODEXLIB_=$(SRCLIB)modex$(DIRSEP)
VGMSNDLIB=$(SRCLIB)vgmsnd$(DIRSEP)
DOSLIB=$(SRCLIB)doslib$(DIRSEP)
WCPULIB=$(SRCLIB)wcpu$(DIRSEP)
+AFLAGS=-mh -0 -d1
16FLAGS=-fh=16.hed
BAKAPIFLAGS=-fh=bakapi.hed
SFLAGS=-sg -st -of+ -zu -zdf -zff -zgf -k55808#60000#32768
DFLAGS=-DTARGET_MSDOS=16 -DMSDOS=1 $(SFLAGS)
ZFLAGS=-zk0 -zq -zc -zp8# -zm
-CFLAGS=$(IFLAGS) -mh -lr -l=dos -wo# -d2##wwww
-OFLAGS=-obmiler -out -oh -ei -zp8 -0 -fpi87 -onac -ol+ -ok####x
+CFLAGS=$(AFLAGS) $(IFLAGS)-lr -l=dos -wo##wwww
+OFLAGS=-obmiler -out -oh -ei -zp8 -fpi87 -onac -ol+ -ok####x
FLAGS=$(CFLAGS) $(OFLAGS) $(DFLAGS) $(ZFLAGS)
+
DOSLIBEXMMOBJ = himemsys.$(OBJ) emm.$(OBJ)
VGMSNDOBJ = vgmSnd.$(OBJ) 16_snd.$(OBJ)
DOSLIBOBJ = adlib.$(OBJ) 8254.$(OBJ) 8259.$(OBJ) dos.$(OBJ) cpu.$(OBJ)
16.exe: 16.$(OBJ) mapread.$(OBJ) jsmn.$(OBJ) $(16LIBOBJS) gfx.lib
wcl $(FLAGS) $(16FLAGS) 16.$(OBJ) mapread.$(OBJ) jsmn.$(OBJ) $(16LIBOBJS) gfx.lib -fm=16.map
-bakapi.exe: bakapi.$(OBJ) $(16LIBOBJS) gfx.lib
- wcl $(FLAGS) $(BAKAPIFLAGS) bakapi.$(OBJ) $(16LIBOBJS) gfx.lib -fm=bakapi.map
+bakapi.exe: bakapi.$(OBJ) $(16LIBOBJS) gfx.lib modex.lib
+ wcl $(FLAGS) $(BAKAPIFLAGS) bakapi.$(OBJ) $(16LIBOBJS) gfx.lib modex.lib -fm=bakapi.map
#
#Test Executables!
#
#memory.$(OBJ): $(EXMMLIB)memory.h $(EXMMLIB)memory.c
# wcl $(FLAGS) $(MFLAGS) -c $(EXMMLIB)memory.c
+c_utils.$(OBJ): $(MODEXLIB_)c_utils.asm
+ wcl -c $(AFLAGS) $(MODEXLIB_)c_utils.asm
+modex.$(OBJ): $(MODEXLIB_)modex.asm
+ wcl -c $(AFLAGS) $(MODEXLIB_)modex.asm
+
#
#other~
#
clean: .symbolic
@$(REMOVECOMMAND) $(EXEC)
@$(REMOVECOMMAND) *.$(OBJ)
- @$(REMOVECOMMAND) *.lib
+ @$(REMOVECOMMAND) 16.lib
+ @$(REMOVECOMMAND) gfx.lib
+ @$(REMOVECOMMAND) doslib.lib
+ @$(REMOVECOMMAND) vgmsnd.lib
@wlib -n 16.lib
@wlib -n gfx.lib
@wlib -n doslib.lib
comp: .symbolic
@upx -9 -qqq $(EXEC)
+ @upx -9 -qqq x-demo.exe
updatelibs: .symbolic
- cd $(JSMNLIB)
- git pull
- cd ../../../
+ @cd $(JSMNLIB)
+ @git pull
+ @cd ../../../
+
+xlib: .symbolic
+ @cd 16/xlib
+ @wmake clean
+ @wmake all
+ @cd ../../
+
+mx: .symbolic
+ @cd 16/xw
+# @wmake clean
+ @wmake all
+ @cd ../../
+
+mx_: .symbolic
+ @cd 16/xw_
+ @wmake -f makefile all
+ @cd ../../
+
what?
-planar function from pcx must be made~
+
+
+test which modex library is faster!
+edit input and switch unecessary words to bytes
+
+
+
+
+planar function from pcx must be made~ ok
font! ok
jis! ...
xdir=1;
ydir=1;
+#ifdef MXLIB
VGAmodeX(1, &gvar);
+#else
+ mxSetMode(3);
+#endif
bakapee.xx = rand()&0%gvar.video.page[0].width;
bakapee.yy = rand()&0%gvar.video.page[0].height;
bakapee.gq = 0;
}
else
{
+ #ifndef MXLIB
+ mxChangeMode(0);
+#else
VGAmodeX(0, &gvar);
+#endif
//modexLeave();
// user imput switch
+ fprintf(stderr, "xx=%d yy=%d\n", bakapee.xx, bakapee.yy);
printf("Enter 1, 2, 3, 4, or 6 to run a screensaver, or enter 0 to quit.\n", getch()); // prompt the user
scanf("%d", &key);
//if(key==3){xx=yy=0;} // crazy screen saver wwww
gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]);
gvar.video.page[0].width += (TILEWH*2);
gvar.video.page[0].height += (TILEWH*2);
+#ifdef MXLIB
VGAmodeX(1, &gvar);
+#else
+ mxChangeMode(3);
+#endif
modexShowPage(&gvar.video.page[0]);
}
}
mx = motion_Left,my = motion_Down;\r
else if (Keyboard[def->downright])\r
mx = motion_Right,my = motion_Down;*/\r
- //if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){\r
+ if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){\r
if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down] && player[playnum].d == 2))// || player[playnum].info.dir == 0)\r
my = motion_Up;\r
if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up] && player[playnum].d == 2))// || player[playnum].info.dir == 4)\r
my = motion_Down;\r
- //}else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){\r
+ }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){\r
if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right] && player[playnum].d == 2))// || player[playnum].info.dir == 1)\r
mx = motion_Left;\r
if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left] && player[playnum].d == 2))// || player[playnum].info.dir == 3)\r
mx = motion_Right;\r
- //}\r
+ }\r
+ //input from player\r
if (inpu.Keyboard[def->button0])\r
buttons += 1 << 0;\r
if (inpu.Keyboard[def->button1])\r
}else pee->sy = 0;
}
-//plot pixel
+//plot pixel or plot tile
void dingpp(page_t *page, bakapee_t *pee)
{
#ifdef TILE
+#ifndef MXLIB
+ //fill_block(pee->xx, pee->yy, pee->xx+TILEWH, pee->yy+TILEWH, pee->coor);
+ mxFillBox(pee->xx, pee->yy, TILEWH, TILEWH, pee->coor, OP_SET);
+#else
modexClearRegion(page, pee->xx, pee->yy, TILEWH, TILEWH, pee->coor);
+#endif
#else
modexputPixel(page, pee->xx, pee->yy, pee->coor);
#endif
\r
#include "src/lib/16_head.h"\r
#include "src/lib/modex16.h"\r
+//#include "src/lib/modex/modex.h"\r
+#include "16/x/modex.h"\r
\r
#define TILEWH 16\r
#define QUADWH TILEWH/2\r
#define LGQ 32\r
#define HGQ 55\r
\r
-//#define TILE\r
+#define TILE\r
+\r
+//which lib?\r
+#define MXLIB\r
\r
typedef struct {\r
word gq;\r
--- /dev/null
+MASM modex,modex,modex,nul
\ No newline at end of file
--- /dev/null
+;=======================================================\r
+;=== C_UTILS.ASM - Asm Utilities for C/C++ ===\r
+;=======================================================\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Huge\r
+; .286\r
+\r
+ ; ==== MACROS ====\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; push R1 ; Save R1\r
+; PUSHx R2, R3, R4;, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; pop R1 ; Restore R1\r
+; POPx R2, R3, R4;, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+\r
+ ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+ xor Register, Register ; Set Register = 0\r
+ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jnz Destination ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jz Destination ; Jump if 0\r
+ENDM\r
+\r
+\r
+ ; ==== General Constants ====\r
+\r
+ False EQU 0\r
+ True EQU -1\r
+ nil EQU 0\r
+\r
+ b EQU BYTE PTR\r
+ w EQU WORD PTR\r
+ d EQU DWORD PTR\r
+ o EQU OFFSET\r
+ f EQU FAR PTR\r
+ s EQU SHORT\r
+ ?x4 EQU <?,?,?,?>\r
+ ?x3 EQU <?,?,?>\r
+ ?x2 EQU <?,?>\r
+ ?x1 EQU <?>\r
+\r
+\r
+ .Data\r
+\r
+ EVEN\r
+\r
+RND_Seed DW 7397, 29447, 802\r
+RND_Mult DW 179, 183, 182\r
+RND_ModV DW 32771, 32779, 32783\r
+\r
+CR_LF DB 13, 10 ; the CRLF data\r
+\r
+ .Code\r
+\r
+;===========================================\r
+;void far pascal dos_print (far char *Text)\r
+;===========================================\r
+;\r
+; - Print Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINT\r
+\r
+DP_Stack STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ DP_Text DD ? ; Far Address of Text to print\r
+DP_Stack ENDS\r
+\r
+\r
+DOS_PRINT PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ mov SI, DX ; DS:SI = String data\r
+\r
+@@DP_Scan_it:\r
+\r
+ cmp b [SI], 0 ; Null Byte found?\r
+ je @@DP_Got_Len ; exit loop if so\r
+\r
+ inc CX ; Len++\r
+ inc SI ; Point to next char\r
+ jmp s @@DP_Scan_it ; check again...\r
+\r
+@@DP_Got_len:\r
+\r
+ jcxz @No_Print ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@No_Print:\r
+ mov AX, SEG DGROUP ; Restore DGroup\r
+ mov DS, AX\r
+\r
+ mov DX, o CR_LF ; Get Addr of CR/LF pair\r
+ mov CX, 2 ; 2 Characters to Write\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+ cld ; Reset Direction Flag\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 4 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT ENDP\r
+\r
+\r
+;===========================================\r
+;void far pascal dos_prints (char far *Text)\r
+;===========================================\r
+;\r
+; Print Text Directly to DOS console\r
+; without a trailing CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINTS\r
+\r
+DOS_PRINTS PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ mov SI, DX ; DS:SI = String data\r
+\r
+@@DPS_Scan_it:\r
+\r
+ cmp b [SI], 0 ; Null Byte found?\r
+ je @@DPS_Got_Len ; exit loop if so\r
+\r
+ inc CX ; Len++\r
+ inc SI ; Point to next char\r
+ jmp s @@DPS_Scan_it ; check again...\r
+\r
+@@DPS_Got_len:\r
+\r
+ jcxz @DPS_Exit ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+ cld ; Reset Direction Flag\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS ENDP\r
+\r
+\r
+;=========================================\r
+;void far pascal set_video_mode (int Mode)\r
+;=========================================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+ PUBLIC SET_VIDEO_MODE\r
+\r
+SVM_Stack STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ SVM_Mode DB ?,? ; Desired Video Mode\r
+SVM_Stack ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR AH ; Function 0\r
+ mov AL, [BP].SVM_Mode ; Get Mode #\r
+\r
+ int 10H ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;===================================\r
+;int far pascal scan_keyboard (void)\r
+;===================================\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+ PUBLIC SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ mov AH, 01H ; Function #1\r
+ INT 16H ; Call Keyboard Driver\r
+ JZ @SK_NO_KEY ; Exit if Zero flag set\r
+\r
+ mov AH, 00H ; Remove Key from Buffer\r
+ INT 16H ; Get Keycode in AX\r
+\r
+ OR AL, AL ; Low Byte Set (Ascii?)\r
+ JZ @SK_Exit ; if not, it's a F-Key\r
+\r
+ CLR AH ; Clear ScanCode if Ascii\r
+ JMP s @SK_Exit ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+ CLR AX ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+ cld ; Reset Direction Flag\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD ENDP\r
+\r
+\r
+;========================================\r
+;int far pascal random_int (int MaxValue)\r
+;========================================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+ PUBLIC RANDOM_INT\r
+\r
+RI_Stack STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ RI_MaxVal DW ? ; Maximum Value to Return + 1\r
+RI_Stack ENDS\r
+\r
+\r
+RANDOM_INT PROC FAR\r
+\r
+ push BP ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR BX ; BX is the data index\r
+ CLR CX ; CX is the accumulator\r
+\r
+REPT 3\r
+ mov AX, RND_Seed[BX] ; load the initial seed\r
+ mul RND_Mult[BX] ; multiply it\r
+ div RND_ModV[BX] ; and obtain the Mod value\r
+ mov RND_Seed[BX], DX ; save that for the next time\r
+\r
+ add CX, DX ; add it into the accumulator\r
+ inc BX\r
+ inc BX ; point to the next set of values\r
+ENDM\r
+\r
+ mov AX, CX ; AX = Random #\r
+ CLR DX ; DX = 0\r
+ div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
+\r
+ mov AX, DX\r
+\r
+ pop BP ; Restore BP\r
+ ret 2 ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT ENDP\r
+\r
+\r
+;==================================\r
+;void far pascal init_random (void)\r
+;==================================\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+ PUBLIC INIT_RANDOM\r
+\r
+INIT_RANDOM PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ mov ES, AX\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+\r
+ xor RND_Seed, AX ; Scramble 1st Seed\r
+\r
+ ret ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM ENDP\r
+\r
+;=========================================\r
+;int far pascal int_sqr (int X, int Round)\r
+;=========================================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the\r
+; nearest integer value by passing 0x80. Passing 0\r
+; return the Integer Portion only. The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus\r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ ISQ_Round DW ? ; Amount to Round Result * 256\r
+ ISQ_X DW ? ; "X"\r
+ISQ_Stack ENDS\r
+\r
+ PUBLIC INT_SQR\r
+\r
+INT_SQR PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Save BP\r
+ push bp\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ xor AX, AX ; {xor eax,eax}\r
+ xor DX, DX ; {xor edx,edx}\r
+ mov DI, [BP].ISQ_X ; {mov edi,x}\r
+\r
+ mov CX, 16 ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl AX, 1 ; {shl eax,1}\r
+ mov BX, AX ; {mov ebx,eax}\r
+ shl BX, 1 ; {shl ebx,1}\r
+ inc BX ; {inc ebx}\r
+ cmp DX, BX ; {cmp edx,ebx}\r
+ jl @ISQ_S\r
+\r
+ sub DX, BX ; {sub edx,ebx}\r
+ inc AX ; {inc eax}\r
+\r
+@ISQ_S:\r
+ loop @ISQ_L\r
+\r
+ add ax, [BP].ISQ_Round ; {add eax,$00008000}\r
+ ; {*round* result in hi word: ie. +0.5}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+\r
+ ;POPx DI, BP ; Restore Registers\r
+ pop di\r
+ pop bp\r
+ ret 4 ; Exit\r
+\r
+INT_SQR ENDP\r
+\r
+;=================================\r
+;int far pascal timer_count (void)\r
+;=================================\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+ PUBLIC TIMER_COUNT\r
+\r
+TIMER_COUNT PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ mov ES, AX\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+ mov DX, ES:[046Eh] ; Get Timer Hi Word\r
+ ret ; Exit & Clean Up Stack\r
+\r
+TIMER_COUNT ENDP\r
+\r
+\r
+ END\r
--- /dev/null
+\r
+#ifndef __C_UTILS_H\r
+#define __C_UTILS_H\r
+\r
+\r
+ /* Misc Constants */\r
+\r
+#define True -1\r
+#define False 0\r
+#define nil 0\r
+\r
+ /* Color Constants */\r
+\r
+#define c_BLACK 0\r
+#define c_BLUE 1\r
+#define c_GREEN 2\r
+#define c_CYAN 3\r
+#define c_RED 4\r
+#define c_PURPLE 5\r
+#define c_BROWN 6\r
+#define c_WHITE 7\r
+#define c_GREY 8\r
+#define c_bBLUE 9\r
+#define c_bGREEN 10\r
+#define c_bCYAN 11\r
+#define c_bRED 12\r
+#define c_bPURPLE 13\r
+#define c_YELLOW 14\r
+#define c_bWHITE 15\r
+#define c_BRIGHT 16\r
+\r
+\r
+#define Ky_F1 0x3B00\r
+#define Ky_F2 0x3C00\r
+#define Ky_F3 0x3D00\r
+#define Ky_F4 0x3E00\r
+#define Ky_F5 0x3F00\r
+#define Ky_F6 0x4000\r
+#define Ky_F7 0x4100\r
+#define Ky_F8 0x4200\r
+#define Ky_F9 0x4300\r
+#define Ky_F10 0x4400\r
+\r
+#define Ky_Up 0x4800\r
+#define Ky_Left 0x4B00\r
+#define Ky_Right 0x4D00\r
+#define Ky_Down 0x5000\r
+#define Ky_SUp 0xC800\r
+#define Ky_SLeft 0xCB00\r
+#define Ky_SRight 0xCD00\r
+#define Ky_SDown 0xD000\r
+\r
+#define Ky_Home 0x4700\r
+#define Ky_End 0x4F00\r
+#define Ky_PgUp 0x4900\r
+#define Ky_PgDn 0x5100\r
+#define Ky_SHome 0xC700\r
+#define Ky_SEnd 0xCF00\r
+#define Ky_SPgUp 0xC900\r
+#define Ky_SPgDn 0xD100\r
+\r
+#define Ky_Ins 0x5200\r
+#define Ky_Del 0x5300\r
+#define Ky_SIns 0xC200\r
+#define Ky_SDel 0xC300\r
+\r
+#define Ky_Tab 0x0009\r
+#define Ky_RvsTab 0x8F00\r
+#define Ky_STab 0x8F00\r
+\r
+#define Ky_BS 0x0008\r
+#define Ky_CR 0x000D\r
+#define Ky_ESC 0x001B\r
+#define Ky_Clr 0x007F\r
+\r
+#define Ky_Plus 0x002D\r
+#define Ky_Minus 0x002B\r
+\r
+#define Ky_AltA 0x1E00\r
+#define Ky_AltB 0x3000\r
+#define Ky_AltC 0x2E00\r
+#define Ky_AltD 0x2000\r
+#define Ky_AltE 0x1200\r
+#define Ky_AltF 0x2100\r
+#define Ky_AltG 0x2200\r
+#define Ky_AltH 0x2300\r
+#define Ky_AltI 0x1700\r
+#define Ky_AltJ 0x2400\r
+#define Ky_AltK 0x2500\r
+#define Ky_AltL 0x2600\r
+#define Ky_AltM 0x3200\r
+#define Ky_AltN 0x3100\r
+#define Ky_AltO 0x1800\r
+#define Ky_AltP 0x1900\r
+#define Ky_AltQ 0x1000\r
+#define Ky_AltR 0x1300\r
+#define Ky_AltS 0x1F00\r
+#define Ky_AltT 0x1400\r
+#define Ky_AltU 0x1600\r
+#define Ky_AltV 0x2F00\r
+#define Ky_AltW 0x1100\r
+#define Ky_AltX 0x2D00\r
+#define Ky_AltY 0x1500\r
+#define Ky_AltZ 0x2C00\r
+\r
+ /* .ASM Functions From C_UTILS.ASM */\r
+\r
+void far pascal dos_print (char far *Text);\r
+void far pascal dos_prints (char far *Text);\r
+void far pascal set_video_mode (int Mode);\r
+int far pascal scan_keyboard (void);\r
+int far pascal random_int (int MaxValue);\r
+void far pascal init_random (void);\r
+int far pascal int_sqr (int X, int Round);\r
+int far pascal timer_count (void);\r
+\r
+#endif\r
--- /dev/null
+Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Page 1 - 1\r
+\r
+\r
+ ;=======================================================\r
+ ;=== C_UTILS.ASM - Asm Utilities for C/C++ ===\r
+ ;=======================================================\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Medium\r
+ .286\r
+\r
+ ; ==== MACROS ====\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+ PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ push R1 ; Save R1\r
+ PUSHx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ ENDM\r
+\r
+ POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ pop R1 ; Restore R1\r
+ POPx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ ENDM\r
+\r
+ ; Macro to Clear a Register to 0\r
+\r
+ CLR MACRO Register\r
+ xor Register, Register ; Set Register = 0\r
+ ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+ LOOPx MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jnz Destination ; Jump if not 0\r
+ ENDM\r
+\r
+ LOOPjz MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jz Destination ; Jump if 0\r
+ ENDM\r
+\r
+\r
+ ; ==== General Constants ====\r
+\r
+ = 0000 False EQU 0\r
+ =-0001 True EQU -1\r
+ = 0000 nil EQU 0\r
+\r
+ = BYTE PTR b EQU BYTE PTR\r
+ = WORD PTR w EQU WORD PTR\r
+ = DWORD PTR d EQU DWORD PTR\r
+ = OFFSET o EQU OFFSET\r
+ = FAR PTR f EQU FAR PTR\r
+ = SHORT s EQU SHORT\r
+ = ?,?,?,? ?x4 EQU <?,?,?,?>\r
+ = ?,?,? ?x3 EQU <?,?,?>\r
+\r
+\r
+ 0000 .Data\r
+\r
+ EVEN\r
+\r
+ 0000 1CE5 7307 0322 RND_Seed DW 7397, 29447, 802\r
+ 0006 00B3 00B7 00B6 RND_Mult DW 179, 183, 182\r
+ 000C 8003 800B 800F RND_ModV DW 32771, 32779, 32783\r
+\r
+ 0012 0D 0A CR_LF DB 13, 10 ; the CRLF data\r
+\r
+ 0000 .Code\r
+\r
+ ;===========================================\r
+ ;void far pascal dos_print (far char *Text)\r
+ ;===========================================\r
+ ;\r
+ ; - Print Text Directly to DOS console w/ CR/LF\r
+ ;\r
+\r
+ PUBLIC DOS_PRINT\r
+\r
+ 0010 DP_Stack STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 00000000 DP_Text DD ? ; Far Address of Text to print\r
+ DP_Stack ENDS\r
+\r
+\r
+ 0000 DOS_PRINT PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0000 55 1 push BP ; Save R1\r
+ 0001 1E 2 push DS ; Save R1\r
+ 0002 56 3 push SI ; Save R1\r
+ 0003 57 4 push DI ; Save R1\r
+ 0004 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ 0006 C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ 0009 33 C9 1 xor CX, CX ; Set Register = 0\r
+ 000B 8B F2 mov SI, DX ; DS:SI = String data\r
+\r
+ 000D @@DP_Scan_it:\r
+ \r
+ 000D 80 3C 00 cmp b [SI], 0 ; Null Byte found?\r
+ 0010 74 04 je @@DP_Got_Len ; exit loop if so\r
+\r
+ 0012 41 inc CX ; Len++\r
+ 0013 46 inc SI ; Point to next char\r
+ 0014 EB F7 jmp s @@DP_Scan_it ; check again...\r
+\r
+ 0016 @@DP_Got_len:\r
+\r
+ 0016 E3 07 jcxz @No_Print ; Don't Print if empty\r
+\r
+ 0018 BB 0001 mov BX, 1 ; 1= DOS Handle for Display\r
+ 001B B4 40 mov AH, 40h ; Write Text Function\r
+ 001D CD 21 int 21h ; Call DOS to do it\r
+\r
+ 001F @No_Print:\r
+ 001F B8 ---- R mov AX, SEG DGROUP ; Restore DGroup\r
+ 0022 8E D8 mov DS, AX\r
+\r
+ 0024 BA 0012 R mov DX, o CR_LF ; Get Addr of CR/LF pair\r
+ 0027 B9 0002 mov CX, 2 ; 2 Characters to Write \r
+ 002A BB 0001 mov BX, 1 ; 1= DOS Handle for Display\r
+\r
+ 002D B4 40 mov AH, 40h ; Write Text Function\r
+ 002F CD 21 int 21h ; Call DOS to do it\r
+\r
+ 0031 FC cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0032 5F 1 pop DI ; Restore R1\r
+ 0033 5E 2 pop SI ; Restore R1\r
+ 0034 1F 3 pop DS ; Restore R1\r
+ 0035 5D 4 pop BP ; Restore R1\r
+ 0036 CA 0004 ret 4 ; Exit & Clean Up Stack\r
+\r
+ 0039 DOS_PRINT ENDP\r
+\r
+\r
+ ;===========================================\r
+ ;void far pascal dos_prints (char far *Text)\r
+ ;===========================================\r
+ ; \r
+ ; Print Text Directly to DOS console \r
+ ; without a trailing CR/LF\r
+ ;\r
+\r
+ PUBLIC DOS_PRINTS\r
+\r
+ 0039 DOS_PRINTS PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0039 55 1 push BP ; Save R1\r
+ 003A 1E 2 push DS ; Save R1\r
+ 003B 56 3 push SI ; Save R1\r
+ 003C 57 4 push DI ; Save R1\r
+ 003D 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ 003F C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ 0042 33 C9 1 xor CX, CX ; Set Register = 0\r
+ 0044 8B F2 mov SI, DX ; DS:SI = String data\r
+\r
+ 0046 @@DPS_Scan_it:\r
+ \r
+ 0046 80 3C 00 cmp b [SI], 0 ; Null Byte found?\r
+ 0049 74 04 je @@DPS_Got_Len ; exit loop if so\r
+\r
+ 004B 41 inc CX ; Len++\r
+ 004C 46 inc SI ; Point to next char\r
+ 004D EB F7 jmp s @@DPS_Scan_it ; check again...\r
+\r
+ 004F @@DPS_Got_len:\r
+\r
+ 004F E3 07 jcxz @DPS_Exit ; Don't Print if empty\r
+\r
+ 0051 BB 0001 mov BX, 1 ; 1= DOS Handle for Display\r
+ 0054 B4 40 mov AH, 40h ; Write Text Function\r
+ 0056 CD 21 int 21h ; Call DOS to do it\r
+\r
+ 0058 @DPS_Exit:\r
+ 0058 FC cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0059 5F 1 pop DI ; Restore R1\r
+ 005A 5E 2 pop SI ; Restore R1\r
+ 005B 1F 3 pop DS ; Restore R1\r
+ 005C 5D 4 pop BP ; Restore R1\r
+ 005D CA 0002 ret 2 ; Exit & Clean Up Stack\r
+\r
+ 0060 DOS_PRINTS ENDP\r
+\r
+\r
+ ;=========================================\r
+ ;void far pascal set_video_mode (int Mode)\r
+ ;=========================================\r
+ ;\r
+ ; Sets the Video Mode through the BIOS\r
+ ;\r
+\r
+ PUBLIC SET_VIDEO_MODE\r
+\r
+ 000E SVM_Stack STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 00 00 SVM_Mode DB ?,? ; Desired Video Mode\r
+ SVM_Stack ENDS\r
+\r
+\r
+ 0060 SET_VIDEO_MODE PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0060 55 1 push BP ; Save R1\r
+ 0061 1E 2 push DS ; Save R1\r
+ 0062 56 3 push SI ; Save R1\r
+ 0063 57 4 push DI ; Save R1\r
+ 0064 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR AH ; Function 0\r
+ 0066 32 E4 1 xor AH, AH ; Set Register = 0\r
+ 0068 8A 46 0C mov AL, [BP].SVM_Mode ; Get Mode #\r
+\r
+ 006B CD 10 int 10H ; Change Video Modes\r
+\r
+ 006D @SVM_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 006D 5F 1 pop DI ; Restore R1\r
+ 006E 5E 2 pop SI ; Restore R1\r
+ 006F 1F 3 pop DS ; Restore R1\r
+ 0070 5D 4 pop BP ; Restore R1\r
+ 0071 CA 0002 ret 2 ; Exit & Clean Up Stack\r
+\r
+ 0074 SET_VIDEO_MODE ENDP\r
+\r
+\r
+ ;===================================\r
+ ;int far pascal scan_keyboard (void)\r
+ ;===================================\r
+ ;\r
+ ; Function to scan keyboard for a pressed key\r
+ ;\r
+\r
+ PUBLIC SCAN_KEYBOARD\r
+\r
+ 0074 SCAN_KEYBOARD PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0074 55 1 push BP ; Save R1\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Page 2 - 1\r
+\r
+\r
+ 0075 1E 2 push DS ; Save R1\r
+ 0076 56 3 push SI ; Save R1\r
+ 0077 57 4 push DI ; Save R1\r
+\r
+ 0078 B4 01 mov AH, 01H ; Function #1\r
+ 007A CD 16 INT 16H ; Call Keyboard Driver\r
+ 007C 74 0C JZ @SK_NO_KEY ; Exit if Zero flag set\r
+\r
+ 007E B4 00 mov AH, 00H ; Remove Key from Buffer\r
+ 0080 CD 16 INT 16H ; Get Keycode in AX\r
+\r
+ 0082 0A C0 OR AL, AL ; Low Byte Set (Ascii?)\r
+ 0084 74 06 JZ @SK_Exit ; if not, it's a F-Key\r
+\r
+ CLR AH ; Clear ScanCode if Ascii\r
+ 0086 32 E4 1 xor AH, AH ; Set Register = 0\r
+ 0088 EB 02 JMP s @SK_Exit ; Return Key in AX\r
+\r
+ 008A @SK_NO_KEY:\r
+ CLR AX ; Return Nil (no Keypress)\r
+ 008A 33 C0 1 xor AX, AX ; Set Register = 0\r
+\r
+ 008C @SK_Exit:\r
+ 008C FC cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 008D 5F 1 pop DI ; Restore R1\r
+ 008E 5E 2 pop SI ; Restore R1\r
+ 008F 1F 3 pop DS ; Restore R1\r
+ 0090 5D 4 pop BP ; Restore R1\r
+ 0091 CB ret ; Exit & Clean Up Stack\r
+\r
+ 0092 SCAN_KEYBOARD ENDP\r
+\r
+\r
+ ;========================================\r
+ ;int far pascal random_int (int MaxValue)\r
+ ;========================================\r
+ ;\r
+ ; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+ ;\r
+\r
+\r
+ PUBLIC RANDOM_INT\r
+\r
+ 0008 RI_Stack STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 RI_MaxVal DW ? ; Maximum Value to Return + 1\r
+ RI_Stack ENDS\r
+\r
+\r
+ 0092 RANDOM_INT PROC FAR\r
+\r
+ 0092 55 push BP ; Preserve Important Registers\r
+ 0093 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR BX ; BX is the data index\r
+ 0095 33 DB 1 xor BX, BX ; Set Register = 0\r
+ CLR CX ; CX is the accumulator\r
+ 0097 33 C9 1 xor CX, CX ; Set Register = 0\r
+\r
+ REPT 3\r
+ mov AX, RND_Seed[BX] ; load the initial seed\r
+ mul RND_Mult[BX] ; multiply it\r
+ div RND_ModV[BX] ; and obtain the Mod value\r
+ mov RND_Seed[BX], DX ; save that for the next time\r
+\r
+ add CX, DX ; add it into the accumulator\r
+ inc BX\r
+ inc BX ; point to the next set of values\r
+ ENDM\r
+ 0099 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed\r
+ 009D F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it\r
+ 00A1 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value\r
+ 00A5 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time\r
+ 00A9 03 CA 1 add CX, DX ; add it into the accumulator\r
+ 00AB 43 1 inc BX\r
+ 00AC 43 1 inc BX ; point to the next set of values\r
+ 00AD 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed\r
+ 00B1 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it\r
+ 00B5 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value\r
+ 00B9 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time\r
+ 00BD 03 CA 1 add CX, DX ; add it into the accumulator\r
+ 00BF 43 1 inc BX\r
+ 00C0 43 1 inc BX ; point to the next set of values\r
+ 00C1 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed\r
+ 00C5 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it\r
+ 00C9 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value\r
+ 00CD 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time\r
+ 00D1 03 CA 1 add CX, DX ; add it into the accumulator\r
+ 00D3 43 1 inc BX\r
+ 00D4 43 1 inc BX ; point to the next set of values\r
+\r
+ 00D5 8B C1 mov AX, CX ; AX = Random #\r
+ CLR DX ; DX = 0\r
+ 00D7 33 D2 1 xor DX, DX ; Set Register = 0\r
+ 00D9 F7 76 06 div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
+\r
+ 00DC 8B C2 mov AX, DX\r
+\r
+ 00DE 5D pop BP ; Restore BP\r
+ 00DF CA 0002 ret 2 ; back to BASIC with AX holding the result\r
+\r
+ 00E2 RANDOM_INT ENDP\r
+\r
+\r
+ ;==================================\r
+ ;void far pascal init_random (void)\r
+ ;==================================\r
+ ;\r
+ ; Scrambles the psuedo-random number sequence\r
+ ; (XOR's the seed value with the timer)\r
+ ;\r
+\r
+ PUBLIC INIT_RANDOM\r
+\r
+ 00E2 INIT_RANDOM PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ 00E2 33 C0 1 xor AX, AX ; Set Register = 0\r
+ 00E4 8E C0 mov ES, AX\r
+ 00E6 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+\r
+ 00EA 31 06 0000 R xor RND_Seed, AX ; Scramble 1st Seed\r
+\r
+ 00EE CB ret ; Exit & Clean Up Stack\r
+\r
+ 00EF INIT_RANDOM ENDP\r
+\r
+ ;=========================================\r
+ ;int far pascal int_sqr (int X, int Round)\r
+ ;=========================================\r
+ ;\r
+ ; Returns the Integer Square Root of (X)\r
+ ; Round allows the return value to be rounded to the \r
+ ; nearest integer value by passing 0x80. Passing 0\r
+ ; return the Integer Portion only. The rounding amound is\r
+ ; a number from 0 to 1 multiplied by 256, thus \r
+ ; 0.5 * 0x100 = 0x80!\r
+ ;\r
+\r
+ 000C ISQ_Stack STRUC\r
+ 0000 0000 0000 DW ?,? ; BP, DI\r
+ 0004 00000000 DD ? ; Caller\r
+ 0008 0000 ISQ_Round DW ? ; Amount to Round Result * 256\r
+ 000A 0000 ISQ_X DW ? ; "X"\r
+ ISQ_Stack ENDS\r
+\r
+ PUBLIC INT_SQR\r
+\r
+ 00EF INT_SQR PROC FAR\r
+\r
+ PUSHx BP, DI ; Save BP\r
+ 00EF 55 1 push BP ; Save R1\r
+ 00F0 57 2 push DI ; Save R1\r
+ 00F1 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ 00F3 33 C0 xor AX, AX ; {xor eax,eax}\r
+ 00F5 33 D2 xor DX, DX ; {xor edx,edx}\r
+ 00F7 8B 7E 0A mov DI, [BP].ISQ_X ; {mov edi,x}\r
+\r
+ 00FA B9 0010 mov CX, 16 ; {mov cx, 32}\r
+\r
+ 00FD @ISQ_L:\r
+\r
+ 00FD D1 E7 shl DI, 1 ; {shl edi,1}\r
+ 00FF D1 D2 rcl DX, 1 ; {rcl edx,1}\r
+ 0101 D1 E7 shl DI, 1 ; {shl edi,1}\r
+ 0103 D1 D2 rcl DX, 1 ; {rcl edx,1}\r
+ 0105 D1 E0 shl AX, 1 ; {shl eax,1}\r
+ 0107 8B D8 mov BX, AX ; {mov ebx,eax}\r
+ 0109 D1 E3 shl BX, 1 ; {shl ebx,1}\r
+ 010B 43 inc BX ; {inc ebx}\r
+ 010C 3B D3 cmp DX, BX ; {cmp edx,ebx}\r
+ 010E 7C 03 jl @ISQ_S\r
+\r
+ 0110 2B D3 sub DX, BX ; {sub edx,ebx}\r
+ 0112 40 inc AX ; {inc eax}\r
+\r
+ 0113 @ISQ_S: \r
+ 0113 E2 E8 loop @ISQ_L\r
+\r
+ 0115 03 46 08 add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
+ ; {*round* result in hi word: ie. +0\r
+ .5}\r
+ 0118 C1 E8 08 shr ax, 8 ; {shr eax,16} {to ax (result)}\r
+\r
+ POPx DI, BP ; Restore Registers \r
+ 011B 5F 1 pop DI ; Restore R1\r
+ 011C 5D 2 pop BP ; Restore R1\r
+ 011D CA 0004 ret 4 ; Exit\r
+\r
+ 0120 INT_SQR ENDP\r
+\r
+ ;=================================\r
+ ;int far pascal timer_count (void)\r
+ ;=================================\r
+ ;\r
+ ; Returns the current timer value as an integer/long integer\r
+ ;\r
+\r
+ PUBLIC TIMER_COUNT\r
+\r
+ 0120 TIMER_COUNT PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ 0120 33 C0 1 xor AX, AX ; Set Register = 0\r
+ 0122 8E C0 mov ES, AX\r
+ 0124 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+ 0128 26: 8B 16 046E mov DX, ES:[046Eh] ; Get Timer Hi Word\r
+ 012D CB ret ; Exit & Clean Up Stack\r
+\r
+ 012E TIMER_COUNT ENDP\r
+\r
+\r
+ END\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 3 - 1\r
+\r
+\r
+\r
+\r
+Macros:\r
+\r
+ N a m e Type\r
+\r
+CLR . . . . . . . . . . . . . . Proc\r
+LOOPjz . . . . . . . . . . . . . Proc\r
+LOOPx . . . . . . . . . . . . . Proc\r
+POPx . . . . . . . . . . . . . . Proc\r
+PUSHx . . . . . . . . . . . . . Proc\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 4 - 1\r
+\r
+\r
+\r
+\r
+Structures and Unions:\r
+\r
+ N a m e Size\r
+ Offset Type\r
+\r
+DP_Stack . . . . . . . . . . . . 0010\r
+ DP_Text . . . . . . . . . . . 000C DWord\r
+ISQ_Stack . . . . . . . . . . . 000C\r
+ ISQ_Round . . . . . . . . . . 0008 Word\r
+ ISQ_X . . . . . . . . . . . . 000A Word\r
+RI_Stack . . . . . . . . . . . . 0008\r
+ RI_MaxVal . . . . . . . . . . 0006 Word\r
+SVM_Stack . . . . . . . . . . . 000E\r
+ SVM_Mode . . . . . . . . . . . 000C Byte\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 5 - 1\r
+\r
+\r
+\r
+\r
+Segments and Groups:\r
+\r
+ N a m e Size Length Align Combine Class\r
+\r
+C_UTILS_TEXT . . . . . . . . . . 16 Bit 012E Word Public 'CODE' \r
+DGROUP . . . . . . . . . . . . . GROUP\r
+_DATA . . . . . . . . . . . . . 16 Bit 0014 Word Public 'DATA' \r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 6 - 1\r
+\r
+\r
+\r
+\r
+Procedures, parameters and locals:\r
+\r
+ N a m e Type Value Attr\r
+\r
+DOS_PRINTS . . . . . . . . . . . P Far 0039 C_UTILS_TEXT Length= 0027 Public\r
+DOS_PRINT . . . . . . . . . . . P Far 0000 C_UTILS_TEXT Length= 0039 Public\r
+INIT_RANDOM . . . . . . . . . . P Far 00E2 C_UTILS_TEXT Length= 000D Public\r
+INT_SQR . . . . . . . . . . . . P Far 00EF C_UTILS_TEXT Length= 0031 Public\r
+RANDOM_INT . . . . . . . . . . . P Far 0092 C_UTILS_TEXT Length= 0050 Public\r
+SCAN_KEYBOARD . . . . . . . . . P Far 0074 C_UTILS_TEXT Length= 001E Public\r
+SET_VIDEO_MODE . . . . . . . . . P Far 0060 C_UTILS_TEXT Length= 0014 Public\r
+TIMER_COUNT . . . . . . . . . . P Far 0120 C_UTILS_TEXT Length= 000E Public\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 7 - 1\r
+\r
+\r
+\r
+\r
+Symbols:\r
+\r
+ N a m e Type Value Attr\r
+\r
+?x3 . . . . . . . . . . . . . . Text ?,?,?\r
+?x4 . . . . . . . . . . . . . . Text ?,?,?,?\r
+@@DPS_Got_len . . . . . . . . . L Near 004F C_UTILS_TEXT \r
+@@DPS_Scan_it . . . . . . . . . L Near 0046 C_UTILS_TEXT \r
+@@DP_Got_len . . . . . . . . . . L Near 0016 C_UTILS_TEXT \r
+@@DP_Scan_it . . . . . . . . . . L Near 000D C_UTILS_TEXT \r
+@CodeSize . . . . . . . . . . . Number 0001h \r
+@DPS_Exit . . . . . . . . . . . L Near 0058 C_UTILS_TEXT \r
+@DataSize . . . . . . . . . . . Number 0000h \r
+@ISQ_L . . . . . . . . . . . . . L Near 00FD C_UTILS_TEXT \r
+@ISQ_S . . . . . . . . . . . . . L Near 0113 C_UTILS_TEXT \r
+@Interface . . . . . . . . . . . Number 0000h \r
+@Model . . . . . . . . . . . . . Number 0004h \r
+@No_Print . . . . . . . . . . . L Near 001F C_UTILS_TEXT \r
+@SK_Exit . . . . . . . . . . . . L Near 008C C_UTILS_TEXT \r
+@SK_NO_KEY . . . . . . . . . . . L Near 008A C_UTILS_TEXT \r
+@SVM_Exit . . . . . . . . . . . L Near 006D C_UTILS_TEXT \r
+@code . . . . . . . . . . . . . Text C_UTILS_TEXT\r
+@data . . . . . . . . . . . . . Text DGROUP\r
+@fardata? . . . . . . . . . . . Text FAR_BSS\r
+@fardata . . . . . . . . . . . . Text FAR_DATA\r
+@stack . . . . . . . . . . . . . Text DGROUP\r
+CR_LF . . . . . . . . . . . . . Byte 0012 _DATA \r
+False . . . . . . . . . . . . . Number 0000h \r
+RND_ModV . . . . . . . . . . . . Word 000C _DATA \r
+RND_Mult . . . . . . . . . . . . Word 0006 _DATA \r
+RND_Seed . . . . . . . . . . . . Word 0000 _DATA \r
+True . . . . . . . . . . . . . . Number -0001h \r
+b . . . . . . . . . . . . . . . Text BYTE PTR\r
+d . . . . . . . . . . . . . . . Text DWORD PTR\r
+f . . . . . . . . . . . . . . . Text FAR PTR\r
+nil . . . . . . . . . . . . . . Number 0000h \r
+o . . . . . . . . . . . . . . . Text OFFSET\r
+s . . . . . . . . . . . . . . . Text SHORT\r
+w . . . . . . . . . . . . . . . Text WORD PTR\r
+\r
+ 0 Warnings\r
+ 0 Errors\r
--- /dev/null
+DEFINT A-Z\r
+DECLARE SUB PRINT.STRING (Text$, Xpos%, Ypos%, Colour%)\r
+DECLARE FUNCTION MakePal$ (Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.FONT (FontFile$, FontNum%)\r
+DECLARE SUB ERROR.OUT (Text$)\r
+\r
+ REM $INCLUDE: 'MODEX.BI'\r
+\r
+ REM $INCLUDE: 'UTILS.BI'\r
+\r
+TYPE FONT\r
+ SetData AS STRING * 1024\r
+END TYPE\r
+\r
+\r
+TYPE VGAPalette\r
+ PalData AS STRING * 768\r
+END TYPE\r
+\r
+\r
+ ' Alternate form of LOAD_DAC_REGISTERS so we can pass an offset into\r
+ ' a String instead of the Address of the String\r
+\r
+DECLARE SUB LOAD.DACS ALIAS "LOAD_DAC_REGISTERS" (BYVAL Addr&, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+\r
+\r
+ '\r
+ 'MODE X DEMO of Multiple Character Sets and Block Color Cycling\r
+ '\r
+ 'By Matt Pritchard\r
+ '\r
+\r
+COMMON SHARED CharSet() AS FONT\r
+\r
+DIM Pal AS VGAPalette\r
+\r
+ REM $DYNAMIC\r
+\r
+DIM SHARED CharSet(0 TO 3) AS FONT\r
+\r
+\r
+ LOAD.FONT "SYSTEM.FNT", 0\r
+ LOAD.FONT "ROM_8x8.FNT", 1\r
+ LOAD.FONT "SPACEAGE.FNT", 2\r
+\r
+\r
+ IF SET.MODEX(Mode320x240) = False THEN\r
+ ERROR.OUT "ERROR SETTING MODE X"\r
+ END IF\r
+\r
+\r
+ A$ = "": B$ = ""\r
+ FOR X = 0 TO 31: A$ = A$ + MakePal$(31 - X, X, 0): NEXT X\r
+ FOR X = 0 TO 31: A$ = A$ + MakePal$(0, 31 - X, X): NEXT X\r
+ FOR X = 0 TO 31: A$ = A$ + MakePal$(X, 0, 31 - X): NEXT X\r
+ \r
+ FOR X = 0 TO 31: B$ = B$ + MakePal$(31 - X, X, X): NEXT X\r
+ FOR X = 0 TO 31: B$ = B$ + MakePal$(X, 31 - X, X): NEXT X\r
+ FOR X = 0 TO 31: B$ = B$ + MakePal$(X, X, 31 - X): NEXT X\r
+\r
+ Black$ = STRING$(192, 0)\r
+ White$ = STRING$(128 * 3, 48)\r
+\r
+ Pal1$ = Black$ + A$ + A$ + B$ + B$ + A$\r
+\r
+ LOAD.DACS SSEGADD(Black$), 64, 127, 1\r
+ LOAD.DACS SSEGADD(Black$), 20, 63, 0\r
+\r
+ LOAD.DACS SSEGADD(White$), 128, 255, 0\r
+\r
+ '*** Background ***\r
+\r
+ FOR X = 0 TO 319\r
+ FOR Y = 0 TO 239\r
+ IF ((X + Y) AND 1) = 1 THEN SET.POINT X, Y, 64 + X \ 5 ELSE SET.POINT X, Y, 20 + Y \ 6\r
+ NEXT Y\r
+ NEXT X\r
+\r
+ '*** Draw Font Displays ***\r
+\r
+ PRINT.STRING "FONT: SYSTEM.FNT", 11, 7, 15\r
+ PRINT.STRING "FONT: ROM_8x8.FNT", 11, 17, 15\r
+ PRINT.STRING "FONT: SPACEAGE.FNT", 11, 27, 15\r
+ PRINT.STRING "PRESS ANY KEY TO CONTINUE", 8, 29, 14\r
+ \r
+\r
+ FOR F = 0 TO 2\r
+ SET.DISPLAY.FONT CharSet(F), 1\r
+ Yp = F * 80 + 10\r
+ FOR Y = 0 TO 96 STEP 32\r
+ FOR X = 0 TO 31\r
+ TGPRINTC 128 + Y + X, X * 10 + 1, Yp, 128 + Y\r
+ NEXT X\r
+ Yp = Yp + 10\r
+ NEXT Y\r
+ NEXT F\r
+\r
+ DO\r
+ LOOP UNTIL SCAN.KEYBOARD\r
+\r
+ Offset = 0\r
+ Restart = 192\r
+ MaxOfs = 192 + 96 * 6\r
+\r
+ Delay = 100\r
+\r
+ Offset2 = 0\r
+ Offset2Dir = 3\r
+ Offset2Min = 192\r
+ Offset2Max = Offset2Min + 192 * 6\r
+\r
+ DO\r
+ LOAD.DACS SSEGADD(Pal1$) + Offset, 64, 127, 1\r
+ Offset = Offset + 3\r
+ IF Offset >= MaxOfs THEN Offset = Restart\r
+ IF Delay THEN\r
+ Delay = Delay - 1\r
+ ELSE\r
+ LOAD.DACS SSEGADD(Pal1$) + Offset2, 20, 60, 0\r
+ IF Offset2 = Offset2Max THEN Offset2Dir = -3\r
+ IF Offset2 = Offset2Min THEN Offset2Dir = 3\r
+ Offset2 = Offset2 + Offset2Dir\r
+ END IF\r
+\r
+ LOOP UNTIL SCAN.KEYBOARD\r
+\r
+ ERROR.OUT "DEMO OVER"\r
+\r
+REM $STATIC\r
+SUB ERROR.OUT (Text$)\r
+\r
+ SET.VIDEO.MODE 3\r
+\r
+ DOS.PRINT Text$\r
+\r
+ END\r
+\r
+END SUB\r
+\r
+SUB LOAD.FONT (FontFile$, FontNum) STATIC\r
+\r
+ IF LEN(DIR$(FontFile$)) = 0 THEN ERROR.OUT "FILE NOT FOUND: " + FontFile$\r
+\r
+ OPEN FontFile$ FOR BINARY AS #1\r
+\r
+ SEEK #1, 1\r
+ GET #1, , CharSet(FontNum)\r
+\r
+ CLOSE #1\r
+\r
+END SUB\r
+\r
+FUNCTION MakePal$ (Red, Green, Blue) STATIC\r
+\r
+ MakePal$ = CHR$(Red) + CHR$(Green) + CHR$(Blue)\r
+\r
+END FUNCTION\r
+\r
+SUB PRINT.STRING (Text$, Xpos, Ypos, Colour)\r
+\r
+ TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos * 8, Ypos * 8, Colour\r
+\r
+END SUB\r
+\r
--- /dev/null
+ECHO ... Building MODEX.QLB for BASIC PDS 7.1\r
+LIB MODEX -+MODEX,,\r
+LIB MODEX -+UTILS,,\r
+DEL MODEX.BAK\r
+LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\BC7\LIB\QBXQLB.LIB;\1a\r
--- /dev/null
+ \r
+ ' ===== SCREEN RESOLUTIONS =====\r
+ \r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
+ \r
+ ' ===== MODE X SETUP ROUTINES =====\r
+ \r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
+ \r
+ ' ===== BASIC GRAPHICS PRIMITIVES =====\r
+ \r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+ \r
+ ' ===== DAC COLOR REGISTER ROUTINES =====\r
+ \r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
+ \r
+ \r
+ ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+ \r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
+ \r
+ ' ===== TEXT DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
+ \r
+ ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+ \r
+ ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+ \r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
--- /dev/null
+'File: TEST6.BAS\r
+'Descp.: A Mode "X" demonstration\r
+'Author: Matt Pritchard\r
+'Date: 14 April, 1993\r
+'\r
+DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%)\r
+DECLARE SUB ERROR.OUT (Message$)\r
+DECLARE FUNCTION GET.KEY% ()\r
+DECLARE SUB LOAD.SHAPES ()\r
+DECLARE SUB PAGE.DEMO ()\r
+DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%)\r
+DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%)\r
+DEFINT A-Z\r
+\r
+\r
+TYPE ShapeType\r
+ ImgData AS STRING * 512\r
+ xWidth AS INTEGER\r
+ yWidth AS INTEGER\r
+END TYPE\r
+\r
+TYPE Sprite\r
+ Xpos AS INTEGER\r
+ Ypos AS INTEGER\r
+ XDir AS INTEGER\r
+ YDir AS INTEGER\r
+ Shape AS INTEGER\r
+END TYPE\r
+\r
+\r
+CONST MaxShapes = 32\r
+\r
+ REM $INCLUDE: 'UTILS.BI'\r
+ REM $INCLUDE: 'MODEX.BI'\r
+\r
+DIM SHARED Img(32) AS ShapeType\r
+COMMON SHARED Img() AS ShapeType\r
+\r
+\r
+ CALL INIT.RANDOM\r
+\r
+ CALL LOAD.SHAPES\r
+\r
+ CALL DEMO.RES(Mode320x200, 320, 200)\r
+ CALL DEMO.RES(Mode320x400, 320, 400)\r
+\r
+ CALL DEMO.RES(Mode360x200, 360, 200)\r
+ CALL DEMO.RES(Mode360x400, 360, 400)\r
+\r
+ CALL DEMO.RES(Mode320x240, 320, 240)\r
+ CALL DEMO.RES(Mode320x480, 320, 480)\r
+\r
+ CALL DEMO.RES(Mode360x240, 360, 240)\r
+ CALL DEMO.RES(Mode360x480, 360, 480)\r
+\r
+ CALL PAGE.DEMO\r
+\r
+ SET.VIDEO.MODE 3\r
+ DOS.PRINT "THIS MODE X DEMO IS FINISHED"\r
+ END\r
+\r
+SUB DEMO.RES (Mode, Xmax, Ymax)\r
+\r
+ IF SET.MODEX%(Mode) = 0 THEN\r
+ ERROR.OUT "Unable to SET_MODEX" + STR$(Mode)\r
+ END IF\r
+\r
+ XCenter = Xmax \ 2\r
+ \r
+ X1 = 10\r
+ Y1 = 10\r
+ X2 = Xmax - 1\r
+ Y2 = Ymax - 1\r
+\r
+ FOR Z = 0 TO 3\r
+ Colr = 31 - Z * 2\r
+ DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr\r
+ DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr\r
+ DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr\r
+ DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr\r
+ NEXT Z\r
+\r
+ XChars = Xmax \ 10\r
+ YChars = Ymax \ 10\r
+\r
+ FOR X = 0 TO XChars - 1\r
+ TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7)\r
+ DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15\r
+ NEXT X\r
+\r
+ FOR Y = 0 TO YChars - 1\r
+ TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7)\r
+ DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15\r
+ NEXT Y\r
+\r
+ ' Draw Lines\r
+\r
+ FOR X = 0 TO 63\r
+ N = 15 + X * .75\r
+ SET.DAC.REGISTER 64 + X, N, N, N\r
+ SET.DAC.REGISTER 128 + X, 0, N, N\r
+\r
+ DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X\r
+ DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X\r
+\r
+ NEXT X\r
+ TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE\r
+\r
+ Y = 60: Gap = 0\r
+ FOR X = 0 TO 9\r
+ FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X\r
+ FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X\r
+ FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X\r
+ Y = Y + Gap + 2\r
+ Gap = Gap + 1\r
+ NEXT X\r
+ TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN\r
+\r
+\r
+ FOR X = 190 TO 250 STEP 2\r
+ FOR Y = 60 TO 122 STEP 2\r
+ SET.POINT X, Y, X + Y + X + Y\r
+ NEXT Y\r
+ NEXT X\r
+\r
+ TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED\r
+\r
+ FOR X = 190 TO 250 STEP 2\r
+ FOR Y = 60 TO 122 STEP 2\r
+ IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
+ ERROR.OUT "READ.PIXEL Failure"\r
+ END IF\r
+ NEXT Y\r
+ NEXT X\r
+\r
+\r
+\r
+ Msg$ = " This is a MODE X demo "\r
+ PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE\r
+ Msg$ = "Screen Resolution is by "\r
+ Xp = XCenter - (LEN(Msg$) * 4)\r
+ PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK\r
+\r
+ PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK\r
+ PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK\r
+\r
+ FOR X = 0 TO 15\r
+ SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3\r
+ DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X\r
+ NEXT X\r
+ TPRINT.TEXT "Press <ANY KEY> to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW\r
+\r
+ X = GET.KEY%\r
+ IF X = KyESC THEN ERROR.OUT "ABORT"\r
+\r
+END SUB\r
+\r
+SUB ERROR.OUT (Message$)\r
+\r
+ SET.VIDEO.MODE 3\r
+ DOS.PRINT Message$\r
+ END\r
+\r
+END SUB\r
+\r
+FUNCTION GET.KEY%\r
+\r
+ DO\r
+ X = SCAN.KEYBOARD\r
+ LOOP UNTIL X\r
+\r
+ GET.KEY% = X\r
+\r
+END FUNCTION\r
+\r
+SUB LOAD.SHAPES\r
+\r
+DIM Grid(1 TO 32, 1 TO 32)\r
+\r
+ FOR Shape = 0 TO MaxShapes - 1\r
+\r
+ FOR Y = 1 TO 32\r
+ FOR X = 1 TO 32\r
+ Grid(X, Y) = 0\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ Style = RANDOM.INT(6)\r
+ Colour = 1 + RANDOM.INT(15)\r
+ \r
+ SELECT CASE Style\r
+\r
+ CASE 0: ' Solid Box\r
+\r
+ DO\r
+ xWidth = 3 + RANDOM.INT(30)\r
+ yWidth = 3 + RANDOM.INT(30)\r
+ LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ Grid(X, Y) = Colour\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 1: ' Hollow Box\r
+\r
+ DO\r
+ xWidth = 5 + RANDOM.INT(28)\r
+ yWidth = 5 + RANDOM.INT(28)\r
+ LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ Grid(X, Y) = Colour\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1)\r
+ HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1)\r
+\r
+ FOR Y = HollowY + 1 TO yWidth - HollowY\r
+ FOR X = HollowX + 1 TO xWidth - HollowX\r
+ Grid(X, Y) = nil\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 2: ' Solid Diamond\r
+\r
+ xWidth = 3 + 2 * RANDOM.INT(10)\r
+ yWidth = xWidth\r
+ Centre = xWidth \ 2\r
+\r
+ FOR Y = 0 TO Centre\r
+ FOR X = 0 TO Y\r
+ Grid(Centre - X + 1, Y + 1) = Colour\r
+ Grid(Centre + X + 1, Y + 1) = Colour\r
+ Grid(Centre - X + 1, yWidth - Y) = Colour\r
+ Grid(Centre + X + 1, yWidth - Y) = Colour\r
+ NEXT X\r
+ NEXT Y\r
+\r
+\r
+ CASE 3: ' Hollow Diamond\r
+\r
+\r
+ xWidth = 3 + 2 * RANDOM.INT(10)\r
+ yWidth = xWidth\r
+ Centre = xWidth \ 2\r
+ sWidth = RANDOM.INT(Centre)\r
+\r
+ FOR Y = 0 TO Centre\r
+ FOR X = 0 TO Y\r
+ IF X + (Centre - Y) >= sWidth THEN\r
+ Grid(Centre - X + 1, Y + 1) = Colour\r
+ Grid(Centre + X + 1, Y + 1) = Colour\r
+ Grid(Centre - X + 1, yWidth - Y) = Colour\r
+ Grid(Centre + X + 1, yWidth - Y) = Colour\r
+ END IF\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 4: ' Ball\r
+\r
+ xWidth = 7 + 2 * RANDOM.INT(8)\r
+ yWidth = xWidth\r
+ Centre = 1 + xWidth \ 2\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+ IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 5: ' Ball\r
+\r
+\r
+ xWidth = 7 + 2 * RANDOM.INT(8)\r
+ yWidth = xWidth\r
+ Centre = 1 + xWidth \ 2\r
+ sWidth = RANDOM.INT(xWidth)\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+ IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ END SELECT\r
+\r
+ Img(Shape).xWidth = xWidth\r
+ Img(Shape).yWidth = yWidth\r
+\r
+ A$ = STRING$(xWidth * yWidth, nil)\r
+\r
+ c = 1\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ MID$(A$, c, 1) = CHR$(Grid(X, Y))\r
+ c = c + 1\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ Img(Shape).ImgData = A$\r
+ \r
+\r
+ NEXT Shape\r
+\r
+END SUB\r
+\r
+SUB PAGE.DEMO\r
+\r
+CONST MaxSprites = 64\r
+\r
+DIM Obj(MaxSprites) AS Sprite\r
+DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1)\r
+DIM LastObjects(1)\r
+\r
+ ScreenX = 360: ScreenY = 240\r
+\r
+ IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN\r
+ ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode)\r
+ END IF\r
+\r
+ SET.ACTIVE.PAGE 0\r
+\r
+ CLEAR.VGA.SCREEN c.BLACK\r
+ \r
+ PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK\r
+\r
+ DRAW.LINE 10, 18, 350, 18, c.YELLOW\r
+ PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK\r
+ PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK\r
+ PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK\r
+ PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK\r
+\r
+ PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK\r
+ PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK\r
+ PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK\r
+\r
+ PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK\r
+ PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK\r
+ PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK\r
+\r
+ PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK\r
+ PRINT.TEXT " SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK\r
+ PRINT.TEXT " SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK\r
+ PRINT.TEXT " PAGE FLIPPING", 190, 50, c.RED, c.BLACK\r
+ PRINT.TEXT " COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK\r
+\r
+\r
+ FOR X = 0 TO 60\r
+ SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X\r
+ SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X\r
+ NEXT X\r
+\r
+ c = 0: DC = 1\r
+ FOR X = 0 TO ScreenX \ 2\r
+ DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50\r
+ DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50\r
+ c = c + DC\r
+ IF c = 0 OR c = 60 THEN DC = -DC\r
+ NEXT X\r
+ \r
+ TPRINT.TEXT "Press <ANY KEY> to Continue", 72, 190, c.bWHITE\r
+ TPRINT.TEXT "< > = Faster < > = Slower", 72, 204, c.bGREEN\r
+ TPRINT.TEXT "< > = Fewer Shapes < > = More Shapes", 32, 218, c.bCYAN\r
+\r
+ TGPRINTC 43, 80, 204, c.YELLOW\r
+ TGPRINTC 45, 200, 204, c.YELLOW\r
+\r
+ TGPRINTC 25, 40, 218, c.YELLOW\r
+ TGPRINTC 24, 200, 218, c.YELLOW\r
+\r
+ COPY.PAGE 0, 1\r
+ COPY.PAGE 0, 2\r
+\r
+ FOR X = 1 TO MaxSprites\r
+ DO\r
+ Obj(X).XDir = RANDOM.INT(7) - 3\r
+ Obj(X).YDir = RANDOM.INT(7) - 3\r
+ LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+\r
+ Obj(X).Shape = X MOD MaxShapes\r
+\r
+ SpriteX = Img(Obj(X).Shape).xWidth\r
+ SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+ Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2)\r
+ Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2)\r
+\r
+ LastX(X, 0) = Obj(X).Xpos\r
+ LastX(X, 1) = Obj(X).Xpos\r
+ LastY(X, 0) = Obj(X).Ypos\r
+ LastY(X, 1) = Obj(X).Ypos\r
+ NEXT X\r
+\r
+ CurrentPage = 0\r
+\r
+ 'View Shift...\r
+\r
+ ViewX = 0\r
+ ViewY = 0\r
+ ViewMax = 3\r
+ ViewCnt = 0\r
+ ViewXD = 1\r
+ ViewYD = 1\r
+\r
+ SetColor = 3: SDir = 1\r
+ PrevColor = 0: PDir = 1\r
+\r
+ VisObjects = MaxSprites \ 2\r
+ LastObjects(0) = 0\r
+ LastObjects(1) = 0\r
+\r
+DRAW.LOOP:\r
+\r
+\r
+ SET.ACTIVE.PAGE CurrentPage\r
+\r
+ ' Erase Old Images\r
+\r
+ FOR X = 1 TO LastObjects(CurrentPage)\r
+ \r
+ X1 = LastX(X, CurrentPage) AND &HFFFC\r
+ Y1 = LastY(X, CurrentPage)\r
+ X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3\r
+ Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1\r
+\r
+ COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1\r
+ \r
+ NEXT X\r
+\r
+ ' Draw new images\r
+\r
+ FOR X = 1 TO VisObjects\r
+\r
+ SpriteX = Img(Obj(X).Shape).xWidth\r
+ SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+ ' Move Sprite\r
+\r
+REDOX:\r
+ NewX = Obj(X).Xpos + Obj(X).XDir\r
+ IF NewX < 0 OR NewX + SpriteX > ScreenX THEN\r
+ Obj(X).XDir = -Obj(X).XDir\r
+ IF RANDOM.INT(20) = 1 THEN\r
+ DO\r
+ Obj(X).XDir = RANDOM.INT(7) - 3\r
+ Obj(X).YDir = RANDOM.INT(7) - 3\r
+ LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+ GOTO REDOX\r
+ END IF\r
+ END IF\r
+ Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir\r
+\r
+REDOY:\r
+ NewY = Obj(X).Ypos + Obj(X).YDir\r
+ IF NewY < 0 OR NewY + SpriteY > ScreenY THEN\r
+ Obj(X).YDir = -Obj(X).YDir\r
+ IF RANDOM.INT(20) = 1 THEN\r
+ DO\r
+ Obj(X).XDir = RANDOM.INT(7) - 3\r
+ Obj(X).YDir = RANDOM.INT(7) - 3\r
+ LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+ GOTO REDOY\r
+ END IF\r
+ END IF\r
+ Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir\r
+\r
+ 'Draw Sprite\r
+\r
+ TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY\r
+\r
+ LastX(X, CurrentPage) = Obj(X).Xpos\r
+ LastY(X, CurrentPage) = Obj(X).Ypos\r
+\r
+ NEXT X\r
+\r
+ LastObjects(CurrentPage) = VisObjects\r
+\r
+ ' Pan Screen Back & Forth\r
+\r
+ ViewCnt = ViewCnt + 1\r
+ IF ViewCnt >= ViewMax THEN\r
+ ViewX = ViewX + ViewXD\r
+ IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD\r
+ IF ViewXD < 0 THEN\r
+ ViewY = ViewY + ViewYD\r
+ IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD\r
+ END IF\r
+ \r
+ SET.WINDOW CurrentPage, ViewX, ViewY\r
+\r
+ ViewCnt = 0\r
+ ELSE\r
+ SET.DISPLAY.PAGE CurrentPage\r
+ END IF\r
+\r
+ ' Cycle Colors\r
+\r
+ SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+ SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor\r
+\r
+ SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+ SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor\r
+\r
+ SetColor = SetColor + SDir\r
+ IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir\r
+\r
+ PrevColor = PrevColor + PDir\r
+ IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir\r
+\r
+ CurrentPage = 1 - CurrentPage\r
+\r
+ Code = SCAN.KEYBOARD\r
+\r
+ IF Code = False THEN GOTO DRAW.LOOP\r
+\r
+ IF Code = KyPlus THEN\r
+ IF ViewMax < 12 THEN ViewMax = ViewMax + 1\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+\r
+ IF Code = KyMinus THEN\r
+ IF ViewMax > 1 THEN ViewMax = ViewMax - 1\r
+ IF ViewCnt >= ViewMax THEN ViewCnt = 0\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+\r
+ IF Code = KyUp THEN\r
+ IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+ \r
+ IF Code = KyDown THEN\r
+ IF VisObjects > 1 THEN VisObjects = VisObjects - 1\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+\r
+\r
+END SUB\r
+\r
+SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB)\r
+\r
+ IF LEN(Text$) = 0 THEN EXIT SUB\r
+\r
+ PRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB\r
+\r
+\r
+END SUB\r
+\r
+SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF)\r
+\r
+ IF LEN(Text$) = 0 THEN EXIT SUB\r
+\r
+ TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF\r
+\r
+END SUB\r
+\r
--- /dev/null
+MASM /DFARSTRINGS utils, utils, utils, nul;
\ No newline at end of file
--- /dev/null
+;=======================================================\r
+;=== UTILS.ASM - Asm Utilities for QuickBasic/BC7 ===\r
+;=======================================================\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Medium\r
+ .286\r
+\r
+ ; ==== MACROS ====\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ push R1 ; Save R1\r
+ PUSHx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ENDM\r
+\r
+POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ pop R1 ; Restore R1\r
+ POPx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ENDM\r
+\r
+ ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+ xor Register, Register ; Set Register = 0\r
+ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jnz Destination ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jz Destination ; Jump if 0\r
+ENDM\r
+\r
+\r
+ ; ==== General Constants ====\r
+\r
+ False EQU 0\r
+ True EQU -1\r
+ nil EQU 0\r
+\r
+ b EQU BYTE PTR\r
+ w EQU WORD PTR\r
+ d EQU DWORD PTR\r
+ o EQU OFFSET\r
+ f EQU FAR PTR\r
+ s EQU SHORT\r
+ ?x4 EQU <?,?,?,?>\r
+ ?x3 EQU <?,?,?>\r
+\r
+\r
+IFDEF FARSTRINGS\r
+\r
+ EXTRN stringaddress:far\r
+ EXTRN stringlength:far\r
+\r
+ENDIF\r
+\r
+\r
+ .Data\r
+\r
+ EVEN\r
+\r
+RND_Seed DW 7397, 29447, 802\r
+RND_Mult DW 179, 183, 182\r
+RND_ModV DW 32771, 32779, 32783\r
+\r
+CR_LF DB 13, 10 ; the CRLF data\r
+\r
+ .Code\r
+\r
+;=================\r
+;DOS_PRINT (Text$)\r
+;=================\r
+;\r
+; Prints Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINT\r
+\r
+DP_Stack STRUC\r
+ DW ?x4 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ DP_Text DW ? ; Address of Text$ Descriptor\r
+DP_Stack ENDS\r
+\r
+\r
+DOS_PRINT PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+ push SI ; Push Addr of BC7 Decriptor Ptr\r
+ call stringaddress ; Get Address + Len of string!!!\r
+ ; DX:AX = Addr CX = Len\r
+ mov DS, DX ; DS = DX = Segment of string\r
+ mov DX, AX ; DX = AX = Offset of String\r
+ELSE\r
+ mov CX, [SI] ; put its length into CX\r
+ mov DX, [SI+02] ; now DS:DX points to the String\r
+ENDIF\r
+\r
+ jcxz @No_Print ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@No_Print:\r
+ mov AX, SEG DGROUP ; Restore DGroup\r
+ mov DS, AX\r
+\r
+ mov DX, o CR_LF ; Get Addr of CR/LF pair\r
+ mov CX, 2 ; 2 Characters to Write \r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+ cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT ENDP\r
+\r
+\r
+;==================\r
+;DOS_PRINTS (Text$)\r
+;==================\r
+; \r
+; Print Text$ Directly to DOS console \r
+; without a trailing CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINTS\r
+\r
+DOS_PRINTS PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+ push SI ; Push Addr of BC7 Decriptor Ptr\r
+ call stringaddress ; Get Address + Len of string!!!\r
+ ; DX:AX = Addr CX = Len\r
+ mov DS, DX ; DS = DX = Segment of string\r
+ mov DX, AX ; DX = AX = Offset of String\r
+ELSE\r
+ mov CX, [SI] ; put its length into CX\r
+ mov DX, [SI+02] ; now DS:DX points to the String\r
+ENDIF\r
+\r
+ jcxz @DPS_Exit ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+ cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS ENDP\r
+\r
+\r
+;======================\r
+;SET_VIDEO_MODE (Mode%) \r
+;======================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+ PUBLIC SET_VIDEO_MODE\r
+\r
+SVM_Stack STRUC\r
+ DW ?x4 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ SVM_Mode DB ?,? ; Desired Video Mode\r
+SVM_Stack ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR AH ; Function 0\r
+ mov AL, [BP].SVM_Mode ; Get Mode #\r
+\r
+ int 10H ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;==============\r
+;SCAN_KEYBOARD%\r
+;==============\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+ PUBLIC SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+\r
+ mov AH, 01H ; Function #1\r
+ int 16H ; Call Keyboard Driver\r
+ jz @SK_NO_KEY ; Exit if Zero flag set\r
+\r
+ mov AH, 00H ; Remove Key from Buffer\r
+ int 16H ; Get Keycode in AX\r
+\r
+ or AL, AL ; Low Byte Set (Ascii?)\r
+ jz @SK_Exit ; if not, it's a F-Key\r
+\r
+ CLR AH ; Clear ScanCode if Ascii\r
+ jmp s @SK_Exit ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+ CLR AX ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+ cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD ENDP\r
+\r
+\r
+;====================\r
+;RANDOM_INT (MaxInt%)\r
+;====================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+ PUBLIC RANDOM_INT\r
+\r
+RI_Stack STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ RI_MaxVal DW ? ; Maximum Value to Return + 1\r
+RI_Stack ENDS\r
+\r
+\r
+RANDOM_INT PROC FAR\r
+\r
+ push BP ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR BX ; BX is the data index\r
+ CLR CX ; CX is the accumulator\r
+\r
+REPT 3\r
+ mov AX, RND_Seed[BX] ; load the initial seed\r
+ mul RND_Mult[BX] ; multiply it\r
+ div RND_ModV[BX] ; and obtain the Mod value\r
+ mov RND_Seed[BX], DX ; save that for the next time\r
+\r
+ add CX, DX ; add it into the accumulator\r
+ inc BX\r
+ inc BX ; point to the next set of values\r
+ENDM\r
+\r
+ mov AX, CX ; AX = Random #\r
+ CLR DX ; DX = 0\r
+ div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
+\r
+ mov AX, DX\r
+\r
+ pop BP ; Restore BP\r
+ ret 2 ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT ENDP\r
+\r
+\r
+;===========\r
+;INIT_RANDOM\r
+;===========\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+ PUBLIC INIT_RANDOM\r
+\r
+INIT_RANDOM PROC FAR\r
+\r
+ clr AX ; Segment = 0000\r
+ mov ES, AX\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+\r
+ xor RND_Seed, AX ; Scramble 1st Seed\r
+\r
+ ret ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM ENDP\r
+\r
+\r
+;====================\r
+;INT_SQR (X%, Round%)\r
+;====================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the \r
+; nearest integer value by passing 0x80. Passing 0\r
+; return the Integer Portion only. The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus \r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ ISQ_Round DW ? ; Amount to Round Result * 256\r
+ ISQ_X DW ? ; "X"\r
+ISQ_Stack ENDS\r
+\r
+ PUBLIC INT_SQR\r
+\r
+INT_SQR PROC FAR\r
+\r
+ PUSHx BP, DI ; Save BP\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ xor AX, AX ; {xor eax,eax}\r
+ xor DX, DX ; {xor edx,edx}\r
+ mov DI, [BP].ISQ_X ; {mov edi,x}\r
+\r
+ mov CX, 16 ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl AX, 1 ; {shl eax,1}\r
+ mov BX, AX ; {mov ebx,eax}\r
+ shl BX, 1 ; {shl ebx,1}\r
+ inc BX ; {inc ebx}\r
+ cmp DX, BX ; {cmp edx,ebx}\r
+ jl @ISQ_S\r
+\r
+ sub DX, BX ; {sub edx,ebx}\r
+ inc AX ; {inc eax}\r
+\r
+@ISQ_S: \r
+ loop @ISQ_L\r
+\r
+ add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
+ ; {*round* result in hi word: ie. +0.5}\r
+ shr ax, 8 ; {shr eax,16} {to ax (result)}\r
+\r
+ POPx DI, BP ; Restore Registers \r
+ ret 4 ; Exit\r
+\r
+INT_SQR ENDP\r
+\r
+\r
+;============\r
+;TIMER_COUNT&\r
+;============\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+\r
+ PUBLIC TIMER_COUNT\r
+\r
+TIMER_COUNT PROC FAR\r
+\r
+ clr AX ; Segment = 0000\r
+ mov ES, AX ; use ES to get at data\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+ mov DX, ES:[046Eh] ; Get Timer Hi Word\r
+ ret ; Exit & Return value in DX:AX\r
+\r
+TIMER_COUNT ENDP\r
+\r
+\r
+ END\r
--- /dev/null
+\r
+ ' Misc Constants\r
+\r
+CONST True = -1, False = 0, nil = 0\r
+\r
+ ' Keyboard Codes: Extended\r
+\r
+CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00\r
+CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400\r
+\r
+CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000\r
+CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000\r
+\r
+CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100\r
+CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100\r
+\r
+CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00\r
+CONST KySIns = &HC200, KySDel = &HC300\r
+\r
+CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000\r
+CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300\r
+CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600\r
+CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900\r
+CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400\r
+CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00\r
+CONST KyAltY = &H1500, KyAltZ = &H2C00\r
+\r
+ ' Keyboard Codes: Ascii\r
+\r
+CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F\r
+CONST KyPlus = 45, KyMinus = 43\r
+\r
+ ' Color Constants\r
+\r
+CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3\r
+CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7\r
+CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11\r
+CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15\r
+CONST c.BRIGHT = 8\r
+\r
+ ' From UTILS.ASM\r
+\r
+DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$)\r
+DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$)\r
+DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%)\r
+DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD"\r
+DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%)\r
+DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM"\r
+DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT"\r
+DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%)\r
+\r
--- /dev/null
+;=======================================================\r
+;=== C_UTILS.ASM - Asm Utilities for C/C++ ===\r
+;=======================================================\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Huge\r
+; .286\r
+\r
+ ; ==== MACROS ====\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; push R1 ; Save R1\r
+; PUSHx R2, R3, R4;, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; pop R1 ; Restore R1\r
+; POPx R2, R3, R4;, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+\r
+ ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+ xor Register, Register ; Set Register = 0\r
+ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jnz Destination ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jz Destination ; Jump if 0\r
+ENDM\r
+\r
+\r
+ ; ==== General Constants ====\r
+\r
+ False EQU 0\r
+ True EQU -1\r
+ nil EQU 0\r
+\r
+ b EQU BYTE PTR\r
+ w EQU WORD PTR\r
+ d EQU DWORD PTR\r
+ o EQU OFFSET\r
+ f EQU FAR PTR\r
+ s EQU SHORT\r
+ ?x4 EQU <?,?,?,?>\r
+ ?x3 EQU <?,?,?>\r
+ ?x2 EQU <?,?>\r
+ ?x1 EQU <?>\r
+\r
+\r
+ .Data\r
+\r
+ EVEN\r
+\r
+RND_Seed DW 7397, 29447, 802\r
+RND_Mult DW 179, 183, 182\r
+RND_ModV DW 32771, 32779, 32783\r
+\r
+CR_LF DB 13, 10 ; the CRLF data\r
+\r
+ .Code\r
+\r
+;===========================================\r
+;void far pascal dos_print (far char *Text)\r
+;===========================================\r
+;\r
+; - Print Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINT\r
+\r
+DP_Stack STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ DP_Text DD ? ; Far Address of Text to print\r
+DP_Stack ENDS\r
+\r
+\r
+DOS_PRINT PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ mov SI, DX ; DS:SI = String data\r
+\r
+@@DP_Scan_it:\r
+\r
+ cmp b [SI], 0 ; Null Byte found?\r
+ je @@DP_Got_Len ; exit loop if so\r
+\r
+ inc CX ; Len++\r
+ inc SI ; Point to next char\r
+ jmp s @@DP_Scan_it ; check again...\r
+\r
+@@DP_Got_len:\r
+\r
+ jcxz @No_Print ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@No_Print:\r
+ mov AX, SEG DGROUP ; Restore DGroup\r
+ mov DS, AX\r
+\r
+ mov DX, o CR_LF ; Get Addr of CR/LF pair\r
+ mov CX, 2 ; 2 Characters to Write\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+ cld ; Reset Direction Flag\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 4 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT ENDP\r
+\r
+\r
+;===========================================\r
+;void far pascal dos_prints (char far *Text)\r
+;===========================================\r
+;\r
+; Print Text Directly to DOS console\r
+; without a trailing CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINTS\r
+\r
+DOS_PRINTS PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ mov SI, DX ; DS:SI = String data\r
+\r
+@@DPS_Scan_it:\r
+\r
+ cmp b [SI], 0 ; Null Byte found?\r
+ je @@DPS_Got_Len ; exit loop if so\r
+\r
+ inc CX ; Len++\r
+ inc SI ; Point to next char\r
+ jmp s @@DPS_Scan_it ; check again...\r
+\r
+@@DPS_Got_len:\r
+\r
+ jcxz @DPS_Exit ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+ cld ; Reset Direction Flag\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS ENDP\r
+\r
+\r
+;=========================================\r
+;void far pascal set_video_mode (int Mode)\r
+;=========================================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+ PUBLIC SET_VIDEO_MODE\r
+\r
+SVM_Stack STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ SVM_Mode DB ?,? ; Desired Video Mode\r
+SVM_Stack ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR AH ; Function 0\r
+ mov AL, [BP].SVM_Mode ; Get Mode #\r
+\r
+ int 10H ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;===================================\r
+;int far pascal scan_keyboard (void)\r
+;===================================\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+ PUBLIC SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ mov AH, 01H ; Function #1\r
+ INT 16H ; Call Keyboard Driver\r
+ JZ @SK_NO_KEY ; Exit if Zero flag set\r
+\r
+ mov AH, 00H ; Remove Key from Buffer\r
+ INT 16H ; Get Keycode in AX\r
+\r
+ OR AL, AL ; Low Byte Set (Ascii?)\r
+ JZ @SK_Exit ; if not, it's a F-Key\r
+\r
+ CLR AH ; Clear ScanCode if Ascii\r
+ JMP s @SK_Exit ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+ CLR AX ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+ cld ; Reset Direction Flag\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD ENDP\r
+\r
+\r
+;========================================\r
+;int far pascal random_int (int MaxValue)\r
+;========================================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+ PUBLIC RANDOM_INT\r
+\r
+RI_Stack STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ RI_MaxVal DW ? ; Maximum Value to Return + 1\r
+RI_Stack ENDS\r
+\r
+\r
+RANDOM_INT PROC FAR\r
+\r
+ push BP ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR BX ; BX is the data index\r
+ CLR CX ; CX is the accumulator\r
+\r
+REPT 3\r
+ mov AX, RND_Seed[BX] ; load the initial seed\r
+ mul RND_Mult[BX] ; multiply it\r
+ div RND_ModV[BX] ; and obtain the Mod value\r
+ mov RND_Seed[BX], DX ; save that for the next time\r
+\r
+ add CX, DX ; add it into the accumulator\r
+ inc BX\r
+ inc BX ; point to the next set of values\r
+ENDM\r
+\r
+ mov AX, CX ; AX = Random #\r
+ CLR DX ; DX = 0\r
+ div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
+\r
+ mov AX, DX\r
+\r
+ pop BP ; Restore BP\r
+ ret 2 ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT ENDP\r
+\r
+\r
+;==================================\r
+;void far pascal init_random (void)\r
+;==================================\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+ PUBLIC INIT_RANDOM\r
+\r
+INIT_RANDOM PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ mov ES, AX\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+\r
+ xor RND_Seed, AX ; Scramble 1st Seed\r
+\r
+ ret ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM ENDP\r
+\r
+;=========================================\r
+;int far pascal int_sqr (int X, int Round)\r
+;=========================================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the\r
+; nearest integer value by passing 0x80. Passing 0\r
+; return the Integer Portion only. The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus\r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ ISQ_Round DW ? ; Amount to Round Result * 256\r
+ ISQ_X DW ? ; "X"\r
+ISQ_Stack ENDS\r
+\r
+ PUBLIC INT_SQR\r
+\r
+INT_SQR PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Save BP\r
+ push bp\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ xor AX, AX ; {xor eax,eax}\r
+ xor DX, DX ; {xor edx,edx}\r
+ mov DI, [BP].ISQ_X ; {mov edi,x}\r
+\r
+ mov CX, 16 ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl AX, 1 ; {shl eax,1}\r
+ mov BX, AX ; {mov ebx,eax}\r
+ shl BX, 1 ; {shl ebx,1}\r
+ inc BX ; {inc ebx}\r
+ cmp DX, BX ; {cmp edx,ebx}\r
+ jl @ISQ_S\r
+\r
+ sub DX, BX ; {sub edx,ebx}\r
+ inc AX ; {inc eax}\r
+\r
+@ISQ_S:\r
+ loop @ISQ_L\r
+\r
+ add ax, [BP].ISQ_Round ; {add eax,$00008000}\r
+ ; {*round* result in hi word: ie. +0.5}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+ shr ax, 1 ; {shr eax,16} {to ax (result)}\r
+\r
+ ;POPx DI, BP ; Restore Registers\r
+ pop di\r
+ pop bp\r
+ ret 4 ; Exit\r
+\r
+INT_SQR ENDP\r
+\r
+;=================================\r
+;int far pascal timer_count (void)\r
+;=================================\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+ PUBLIC TIMER_COUNT\r
+\r
+TIMER_COUNT PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ mov ES, AX\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+ mov DX, ES:[046Eh] ; Get Timer Hi Word\r
+ ret ; Exit & Clean Up Stack\r
+\r
+TIMER_COUNT ENDP\r
+\r
+\r
+ END\r
--- /dev/null
+\r
+#ifndef __C_UTILS_H\r
+#define __C_UTILS_H\r
+\r
+\r
+ /* Misc Constants */\r
+\r
+#define True -1\r
+#define False 0\r
+#define nil 0\r
+\r
+ /* Color Constants */\r
+\r
+#define c_BLACK 0\r
+#define c_BLUE 1\r
+#define c_GREEN 2\r
+#define c_CYAN 3\r
+#define c_RED 4\r
+#define c_PURPLE 5\r
+#define c_BROWN 6\r
+#define c_WHITE 7\r
+#define c_GREY 8\r
+#define c_bBLUE 9\r
+#define c_bGREEN 10\r
+#define c_bCYAN 11\r
+#define c_bRED 12\r
+#define c_bPURPLE 13\r
+#define c_YELLOW 14\r
+#define c_bWHITE 15\r
+#define c_BRIGHT 16\r
+\r
+\r
+#define Ky_F1 0x3B00\r
+#define Ky_F2 0x3C00\r
+#define Ky_F3 0x3D00\r
+#define Ky_F4 0x3E00\r
+#define Ky_F5 0x3F00\r
+#define Ky_F6 0x4000\r
+#define Ky_F7 0x4100\r
+#define Ky_F8 0x4200\r
+#define Ky_F9 0x4300\r
+#define Ky_F10 0x4400\r
+\r
+#define Ky_Up 0x4800\r
+#define Ky_Left 0x4B00\r
+#define Ky_Right 0x4D00\r
+#define Ky_Down 0x5000\r
+#define Ky_SUp 0xC800\r
+#define Ky_SLeft 0xCB00\r
+#define Ky_SRight 0xCD00\r
+#define Ky_SDown 0xD000\r
+\r
+#define Ky_Home 0x4700\r
+#define Ky_End 0x4F00\r
+#define Ky_PgUp 0x4900\r
+#define Ky_PgDn 0x5100\r
+#define Ky_SHome 0xC700\r
+#define Ky_SEnd 0xCF00\r
+#define Ky_SPgUp 0xC900\r
+#define Ky_SPgDn 0xD100\r
+\r
+#define Ky_Ins 0x5200\r
+#define Ky_Del 0x5300\r
+#define Ky_SIns 0xC200\r
+#define Ky_SDel 0xC300\r
+\r
+#define Ky_Tab 0x0009\r
+#define Ky_RvsTab 0x8F00\r
+#define Ky_STab 0x8F00\r
+\r
+#define Ky_BS 0x0008\r
+#define Ky_CR 0x000D\r
+#define Ky_ESC 0x001B\r
+#define Ky_Clr 0x007F\r
+\r
+#define Ky_Plus 0x002D\r
+#define Ky_Minus 0x002B\r
+\r
+#define Ky_AltA 0x1E00\r
+#define Ky_AltB 0x3000\r
+#define Ky_AltC 0x2E00\r
+#define Ky_AltD 0x2000\r
+#define Ky_AltE 0x1200\r
+#define Ky_AltF 0x2100\r
+#define Ky_AltG 0x2200\r
+#define Ky_AltH 0x2300\r
+#define Ky_AltI 0x1700\r
+#define Ky_AltJ 0x2400\r
+#define Ky_AltK 0x2500\r
+#define Ky_AltL 0x2600\r
+#define Ky_AltM 0x3200\r
+#define Ky_AltN 0x3100\r
+#define Ky_AltO 0x1800\r
+#define Ky_AltP 0x1900\r
+#define Ky_AltQ 0x1000\r
+#define Ky_AltR 0x1300\r
+#define Ky_AltS 0x1F00\r
+#define Ky_AltT 0x1400\r
+#define Ky_AltU 0x1600\r
+#define Ky_AltV 0x2F00\r
+#define Ky_AltW 0x1100\r
+#define Ky_AltX 0x2D00\r
+#define Ky_AltY 0x1500\r
+#define Ky_AltZ 0x2C00\r
+\r
+ /* .ASM Functions From C_UTILS.ASM */\r
+\r
+void far pascal dos_print (char far *Text);\r
+void far pascal dos_prints (char far *Text);\r
+void far pascal set_video_mode (int Mode);\r
+int far pascal scan_keyboard (void);\r
+int far pascal random_int (int MaxValue);\r
+void far pascal init_random (void);\r
+int far pascal int_sqr (int X, int Round);\r
+int far pascal timer_count (void);\r
+\r
+#endif\r
--- /dev/null
+Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Page 1 - 1\r
+\r
+\r
+ ;=======================================================\r
+ ;=== C_UTILS.ASM - Asm Utilities for C/C++ ===\r
+ ;=======================================================\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Medium\r
+ .286\r
+\r
+ ; ==== MACROS ====\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+ PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ push R1 ; Save R1\r
+ PUSHx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ ENDM\r
+\r
+ POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ pop R1 ; Restore R1\r
+ POPx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ ENDM\r
+\r
+ ; Macro to Clear a Register to 0\r
+\r
+ CLR MACRO Register\r
+ xor Register, Register ; Set Register = 0\r
+ ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+ LOOPx MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jnz Destination ; Jump if not 0\r
+ ENDM\r
+\r
+ LOOPjz MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jz Destination ; Jump if 0\r
+ ENDM\r
+\r
+\r
+ ; ==== General Constants ====\r
+\r
+ = 0000 False EQU 0\r
+ =-0001 True EQU -1\r
+ = 0000 nil EQU 0\r
+\r
+ = BYTE PTR b EQU BYTE PTR\r
+ = WORD PTR w EQU WORD PTR\r
+ = DWORD PTR d EQU DWORD PTR\r
+ = OFFSET o EQU OFFSET\r
+ = FAR PTR f EQU FAR PTR\r
+ = SHORT s EQU SHORT\r
+ = ?,?,?,? ?x4 EQU <?,?,?,?>\r
+ = ?,?,? ?x3 EQU <?,?,?>\r
+\r
+\r
+ 0000 .Data\r
+\r
+ EVEN\r
+\r
+ 0000 1CE5 7307 0322 RND_Seed DW 7397, 29447, 802\r
+ 0006 00B3 00B7 00B6 RND_Mult DW 179, 183, 182\r
+ 000C 8003 800B 800F RND_ModV DW 32771, 32779, 32783\r
+\r
+ 0012 0D 0A CR_LF DB 13, 10 ; the CRLF data\r
+\r
+ 0000 .Code\r
+\r
+ ;===========================================\r
+ ;void far pascal dos_print (far char *Text)\r
+ ;===========================================\r
+ ;\r
+ ; - Print Text Directly to DOS console w/ CR/LF\r
+ ;\r
+\r
+ PUBLIC DOS_PRINT\r
+\r
+ 0010 DP_Stack STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 00000000 DP_Text DD ? ; Far Address of Text to print\r
+ DP_Stack ENDS\r
+\r
+\r
+ 0000 DOS_PRINT PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0000 55 1 push BP ; Save R1\r
+ 0001 1E 2 push DS ; Save R1\r
+ 0002 56 3 push SI ; Save R1\r
+ 0003 57 4 push DI ; Save R1\r
+ 0004 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ 0006 C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ 0009 33 C9 1 xor CX, CX ; Set Register = 0\r
+ 000B 8B F2 mov SI, DX ; DS:SI = String data\r
+\r
+ 000D @@DP_Scan_it:\r
+ \r
+ 000D 80 3C 00 cmp b [SI], 0 ; Null Byte found?\r
+ 0010 74 04 je @@DP_Got_Len ; exit loop if so\r
+\r
+ 0012 41 inc CX ; Len++\r
+ 0013 46 inc SI ; Point to next char\r
+ 0014 EB F7 jmp s @@DP_Scan_it ; check again...\r
+\r
+ 0016 @@DP_Got_len:\r
+\r
+ 0016 E3 07 jcxz @No_Print ; Don't Print if empty\r
+\r
+ 0018 BB 0001 mov BX, 1 ; 1= DOS Handle for Display\r
+ 001B B4 40 mov AH, 40h ; Write Text Function\r
+ 001D CD 21 int 21h ; Call DOS to do it\r
+\r
+ 001F @No_Print:\r
+ 001F B8 ---- R mov AX, SEG DGROUP ; Restore DGroup\r
+ 0022 8E D8 mov DS, AX\r
+\r
+ 0024 BA 0012 R mov DX, o CR_LF ; Get Addr of CR/LF pair\r
+ 0027 B9 0002 mov CX, 2 ; 2 Characters to Write \r
+ 002A BB 0001 mov BX, 1 ; 1= DOS Handle for Display\r
+\r
+ 002D B4 40 mov AH, 40h ; Write Text Function\r
+ 002F CD 21 int 21h ; Call DOS to do it\r
+\r
+ 0031 FC cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0032 5F 1 pop DI ; Restore R1\r
+ 0033 5E 2 pop SI ; Restore R1\r
+ 0034 1F 3 pop DS ; Restore R1\r
+ 0035 5D 4 pop BP ; Restore R1\r
+ 0036 CA 0004 ret 4 ; Exit & Clean Up Stack\r
+\r
+ 0039 DOS_PRINT ENDP\r
+\r
+\r
+ ;===========================================\r
+ ;void far pascal dos_prints (char far *Text)\r
+ ;===========================================\r
+ ; \r
+ ; Print Text Directly to DOS console \r
+ ; without a trailing CR/LF\r
+ ;\r
+\r
+ PUBLIC DOS_PRINTS\r
+\r
+ 0039 DOS_PRINTS PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0039 55 1 push BP ; Save R1\r
+ 003A 1E 2 push DS ; Save R1\r
+ 003B 56 3 push SI ; Save R1\r
+ 003C 57 4 push DI ; Save R1\r
+ 003D 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ 003F C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+ ; Compute Length of string\r
+\r
+ CLR CX ; Length = 0\r
+ 0042 33 C9 1 xor CX, CX ; Set Register = 0\r
+ 0044 8B F2 mov SI, DX ; DS:SI = String data\r
+\r
+ 0046 @@DPS_Scan_it:\r
+ \r
+ 0046 80 3C 00 cmp b [SI], 0 ; Null Byte found?\r
+ 0049 74 04 je @@DPS_Got_Len ; exit loop if so\r
+\r
+ 004B 41 inc CX ; Len++\r
+ 004C 46 inc SI ; Point to next char\r
+ 004D EB F7 jmp s @@DPS_Scan_it ; check again...\r
+\r
+ 004F @@DPS_Got_len:\r
+\r
+ 004F E3 07 jcxz @DPS_Exit ; Don't Print if empty\r
+\r
+ 0051 BB 0001 mov BX, 1 ; 1= DOS Handle for Display\r
+ 0054 B4 40 mov AH, 40h ; Write Text Function\r
+ 0056 CD 21 int 21h ; Call DOS to do it\r
+\r
+ 0058 @DPS_Exit:\r
+ 0058 FC cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0059 5F 1 pop DI ; Restore R1\r
+ 005A 5E 2 pop SI ; Restore R1\r
+ 005B 1F 3 pop DS ; Restore R1\r
+ 005C 5D 4 pop BP ; Restore R1\r
+ 005D CA 0002 ret 2 ; Exit & Clean Up Stack\r
+\r
+ 0060 DOS_PRINTS ENDP\r
+\r
+\r
+ ;=========================================\r
+ ;void far pascal set_video_mode (int Mode)\r
+ ;=========================================\r
+ ;\r
+ ; Sets the Video Mode through the BIOS\r
+ ;\r
+\r
+ PUBLIC SET_VIDEO_MODE\r
+\r
+ 000E SVM_Stack STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 00 00 SVM_Mode DB ?,? ; Desired Video Mode\r
+ SVM_Stack ENDS\r
+\r
+\r
+ 0060 SET_VIDEO_MODE PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0060 55 1 push BP ; Save R1\r
+ 0061 1E 2 push DS ; Save R1\r
+ 0062 56 3 push SI ; Save R1\r
+ 0063 57 4 push DI ; Save R1\r
+ 0064 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR AH ; Function 0\r
+ 0066 32 E4 1 xor AH, AH ; Set Register = 0\r
+ 0068 8A 46 0C mov AL, [BP].SVM_Mode ; Get Mode #\r
+\r
+ 006B CD 10 int 10H ; Change Video Modes\r
+\r
+ 006D @SVM_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 006D 5F 1 pop DI ; Restore R1\r
+ 006E 5E 2 pop SI ; Restore R1\r
+ 006F 1F 3 pop DS ; Restore R1\r
+ 0070 5D 4 pop BP ; Restore R1\r
+ 0071 CA 0002 ret 2 ; Exit & Clean Up Stack\r
+\r
+ 0074 SET_VIDEO_MODE ENDP\r
+\r
+\r
+ ;===================================\r
+ ;int far pascal scan_keyboard (void)\r
+ ;===================================\r
+ ;\r
+ ; Function to scan keyboard for a pressed key\r
+ ;\r
+\r
+ PUBLIC SCAN_KEYBOARD\r
+\r
+ 0074 SCAN_KEYBOARD PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0074 55 1 push BP ; Save R1\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Page 2 - 1\r
+\r
+\r
+ 0075 1E 2 push DS ; Save R1\r
+ 0076 56 3 push SI ; Save R1\r
+ 0077 57 4 push DI ; Save R1\r
+\r
+ 0078 B4 01 mov AH, 01H ; Function #1\r
+ 007A CD 16 INT 16H ; Call Keyboard Driver\r
+ 007C 74 0C JZ @SK_NO_KEY ; Exit if Zero flag set\r
+\r
+ 007E B4 00 mov AH, 00H ; Remove Key from Buffer\r
+ 0080 CD 16 INT 16H ; Get Keycode in AX\r
+\r
+ 0082 0A C0 OR AL, AL ; Low Byte Set (Ascii?)\r
+ 0084 74 06 JZ @SK_Exit ; if not, it's a F-Key\r
+\r
+ CLR AH ; Clear ScanCode if Ascii\r
+ 0086 32 E4 1 xor AH, AH ; Set Register = 0\r
+ 0088 EB 02 JMP s @SK_Exit ; Return Key in AX\r
+\r
+ 008A @SK_NO_KEY:\r
+ CLR AX ; Return Nil (no Keypress)\r
+ 008A 33 C0 1 xor AX, AX ; Set Register = 0\r
+\r
+ 008C @SK_Exit:\r
+ 008C FC cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 008D 5F 1 pop DI ; Restore R1\r
+ 008E 5E 2 pop SI ; Restore R1\r
+ 008F 1F 3 pop DS ; Restore R1\r
+ 0090 5D 4 pop BP ; Restore R1\r
+ 0091 CB ret ; Exit & Clean Up Stack\r
+\r
+ 0092 SCAN_KEYBOARD ENDP\r
+\r
+\r
+ ;========================================\r
+ ;int far pascal random_int (int MaxValue)\r
+ ;========================================\r
+ ;\r
+ ; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+ ;\r
+\r
+\r
+ PUBLIC RANDOM_INT\r
+\r
+ 0008 RI_Stack STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 RI_MaxVal DW ? ; Maximum Value to Return + 1\r
+ RI_Stack ENDS\r
+\r
+\r
+ 0092 RANDOM_INT PROC FAR\r
+\r
+ 0092 55 push BP ; Preserve Important Registers\r
+ 0093 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR BX ; BX is the data index\r
+ 0095 33 DB 1 xor BX, BX ; Set Register = 0\r
+ CLR CX ; CX is the accumulator\r
+ 0097 33 C9 1 xor CX, CX ; Set Register = 0\r
+\r
+ REPT 3\r
+ mov AX, RND_Seed[BX] ; load the initial seed\r
+ mul RND_Mult[BX] ; multiply it\r
+ div RND_ModV[BX] ; and obtain the Mod value\r
+ mov RND_Seed[BX], DX ; save that for the next time\r
+\r
+ add CX, DX ; add it into the accumulator\r
+ inc BX\r
+ inc BX ; point to the next set of values\r
+ ENDM\r
+ 0099 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed\r
+ 009D F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it\r
+ 00A1 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value\r
+ 00A5 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time\r
+ 00A9 03 CA 1 add CX, DX ; add it into the accumulator\r
+ 00AB 43 1 inc BX\r
+ 00AC 43 1 inc BX ; point to the next set of values\r
+ 00AD 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed\r
+ 00B1 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it\r
+ 00B5 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value\r
+ 00B9 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time\r
+ 00BD 03 CA 1 add CX, DX ; add it into the accumulator\r
+ 00BF 43 1 inc BX\r
+ 00C0 43 1 inc BX ; point to the next set of values\r
+ 00C1 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed\r
+ 00C5 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it\r
+ 00C9 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value\r
+ 00CD 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time\r
+ 00D1 03 CA 1 add CX, DX ; add it into the accumulator\r
+ 00D3 43 1 inc BX\r
+ 00D4 43 1 inc BX ; point to the next set of values\r
+\r
+ 00D5 8B C1 mov AX, CX ; AX = Random #\r
+ CLR DX ; DX = 0\r
+ 00D7 33 D2 1 xor DX, DX ; Set Register = 0\r
+ 00D9 F7 76 06 div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
+\r
+ 00DC 8B C2 mov AX, DX\r
+\r
+ 00DE 5D pop BP ; Restore BP\r
+ 00DF CA 0002 ret 2 ; back to BASIC with AX holding the result\r
+\r
+ 00E2 RANDOM_INT ENDP\r
+\r
+\r
+ ;==================================\r
+ ;void far pascal init_random (void)\r
+ ;==================================\r
+ ;\r
+ ; Scrambles the psuedo-random number sequence\r
+ ; (XOR's the seed value with the timer)\r
+ ;\r
+\r
+ PUBLIC INIT_RANDOM\r
+\r
+ 00E2 INIT_RANDOM PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ 00E2 33 C0 1 xor AX, AX ; Set Register = 0\r
+ 00E4 8E C0 mov ES, AX\r
+ 00E6 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+\r
+ 00EA 31 06 0000 R xor RND_Seed, AX ; Scramble 1st Seed\r
+\r
+ 00EE CB ret ; Exit & Clean Up Stack\r
+\r
+ 00EF INIT_RANDOM ENDP\r
+\r
+ ;=========================================\r
+ ;int far pascal int_sqr (int X, int Round)\r
+ ;=========================================\r
+ ;\r
+ ; Returns the Integer Square Root of (X)\r
+ ; Round allows the return value to be rounded to the \r
+ ; nearest integer value by passing 0x80. Passing 0\r
+ ; return the Integer Portion only. The rounding amound is\r
+ ; a number from 0 to 1 multiplied by 256, thus \r
+ ; 0.5 * 0x100 = 0x80!\r
+ ;\r
+\r
+ 000C ISQ_Stack STRUC\r
+ 0000 0000 0000 DW ?,? ; BP, DI\r
+ 0004 00000000 DD ? ; Caller\r
+ 0008 0000 ISQ_Round DW ? ; Amount to Round Result * 256\r
+ 000A 0000 ISQ_X DW ? ; "X"\r
+ ISQ_Stack ENDS\r
+\r
+ PUBLIC INT_SQR\r
+\r
+ 00EF INT_SQR PROC FAR\r
+\r
+ PUSHx BP, DI ; Save BP\r
+ 00EF 55 1 push BP ; Save R1\r
+ 00F0 57 2 push DI ; Save R1\r
+ 00F1 8B EC mov BP, SP ; Set up Stack Frame\r
+\r
+ 00F3 33 C0 xor AX, AX ; {xor eax,eax}\r
+ 00F5 33 D2 xor DX, DX ; {xor edx,edx}\r
+ 00F7 8B 7E 0A mov DI, [BP].ISQ_X ; {mov edi,x}\r
+\r
+ 00FA B9 0010 mov CX, 16 ; {mov cx, 32}\r
+\r
+ 00FD @ISQ_L:\r
+\r
+ 00FD D1 E7 shl DI, 1 ; {shl edi,1}\r
+ 00FF D1 D2 rcl DX, 1 ; {rcl edx,1}\r
+ 0101 D1 E7 shl DI, 1 ; {shl edi,1}\r
+ 0103 D1 D2 rcl DX, 1 ; {rcl edx,1}\r
+ 0105 D1 E0 shl AX, 1 ; {shl eax,1}\r
+ 0107 8B D8 mov BX, AX ; {mov ebx,eax}\r
+ 0109 D1 E3 shl BX, 1 ; {shl ebx,1}\r
+ 010B 43 inc BX ; {inc ebx}\r
+ 010C 3B D3 cmp DX, BX ; {cmp edx,ebx}\r
+ 010E 7C 03 jl @ISQ_S\r
+\r
+ 0110 2B D3 sub DX, BX ; {sub edx,ebx}\r
+ 0112 40 inc AX ; {inc eax}\r
+\r
+ 0113 @ISQ_S: \r
+ 0113 E2 E8 loop @ISQ_L\r
+\r
+ 0115 03 46 08 add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
+ ; {*round* result in hi word: ie. +0\r
+ .5}\r
+ 0118 C1 E8 08 shr ax, 8 ; {shr eax,16} {to ax (result)}\r
+\r
+ POPx DI, BP ; Restore Registers \r
+ 011B 5F 1 pop DI ; Restore R1\r
+ 011C 5D 2 pop BP ; Restore R1\r
+ 011D CA 0004 ret 4 ; Exit\r
+\r
+ 0120 INT_SQR ENDP\r
+\r
+ ;=================================\r
+ ;int far pascal timer_count (void)\r
+ ;=================================\r
+ ;\r
+ ; Returns the current timer value as an integer/long integer\r
+ ;\r
+\r
+ PUBLIC TIMER_COUNT\r
+\r
+ 0120 TIMER_COUNT PROC FAR\r
+\r
+ CLR AX ; Segment = 0000\r
+ 0120 33 C0 1 xor AX, AX ; Set Register = 0\r
+ 0122 8E C0 mov ES, AX\r
+ 0124 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+ 0128 26: 8B 16 046E mov DX, ES:[046Eh] ; Get Timer Hi Word\r
+ 012D CB ret ; Exit & Clean Up Stack\r
+\r
+ 012E TIMER_COUNT ENDP\r
+\r
+\r
+ END\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 3 - 1\r
+\r
+\r
+\r
+\r
+Macros:\r
+\r
+ N a m e Type\r
+\r
+CLR . . . . . . . . . . . . . . Proc\r
+LOOPjz . . . . . . . . . . . . . Proc\r
+LOOPx . . . . . . . . . . . . . Proc\r
+POPx . . . . . . . . . . . . . . Proc\r
+PUSHx . . . . . . . . . . . . . Proc\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 4 - 1\r
+\r
+\r
+\r
+\r
+Structures and Unions:\r
+\r
+ N a m e Size\r
+ Offset Type\r
+\r
+DP_Stack . . . . . . . . . . . . 0010\r
+ DP_Text . . . . . . . . . . . 000C DWord\r
+ISQ_Stack . . . . . . . . . . . 000C\r
+ ISQ_Round . . . . . . . . . . 0008 Word\r
+ ISQ_X . . . . . . . . . . . . 000A Word\r
+RI_Stack . . . . . . . . . . . . 0008\r
+ RI_MaxVal . . . . . . . . . . 0006 Word\r
+SVM_Stack . . . . . . . . . . . 000E\r
+ SVM_Mode . . . . . . . . . . . 000C Byte\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 5 - 1\r
+\r
+\r
+\r
+\r
+Segments and Groups:\r
+\r
+ N a m e Size Length Align Combine Class\r
+\r
+C_UTILS_TEXT . . . . . . . . . . 16 Bit 012E Word Public 'CODE' \r
+DGROUP . . . . . . . . . . . . . GROUP\r
+_DATA . . . . . . . . . . . . . 16 Bit 0014 Word Public 'DATA' \r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 6 - 1\r
+\r
+\r
+\r
+\r
+Procedures, parameters and locals:\r
+\r
+ N a m e Type Value Attr\r
+\r
+DOS_PRINTS . . . . . . . . . . . P Far 0039 C_UTILS_TEXT Length= 0027 Public\r
+DOS_PRINT . . . . . . . . . . . P Far 0000 C_UTILS_TEXT Length= 0039 Public\r
+INIT_RANDOM . . . . . . . . . . P Far 00E2 C_UTILS_TEXT Length= 000D Public\r
+INT_SQR . . . . . . . . . . . . P Far 00EF C_UTILS_TEXT Length= 0031 Public\r
+RANDOM_INT . . . . . . . . . . . P Far 0092 C_UTILS_TEXT Length= 0050 Public\r
+SCAN_KEYBOARD . . . . . . . . . P Far 0074 C_UTILS_TEXT Length= 001E Public\r
+SET_VIDEO_MODE . . . . . . . . . P Far 0060 C_UTILS_TEXT Length= 0014 Public\r
+TIMER_COUNT . . . . . . . . . . P Far 0120 C_UTILS_TEXT Length= 000E Public\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18\r
+c_utils.asm Symbols 7 - 1\r
+\r
+\r
+\r
+\r
+Symbols:\r
+\r
+ N a m e Type Value Attr\r
+\r
+?x3 . . . . . . . . . . . . . . Text ?,?,?\r
+?x4 . . . . . . . . . . . . . . Text ?,?,?,?\r
+@@DPS_Got_len . . . . . . . . . L Near 004F C_UTILS_TEXT \r
+@@DPS_Scan_it . . . . . . . . . L Near 0046 C_UTILS_TEXT \r
+@@DP_Got_len . . . . . . . . . . L Near 0016 C_UTILS_TEXT \r
+@@DP_Scan_it . . . . . . . . . . L Near 000D C_UTILS_TEXT \r
+@CodeSize . . . . . . . . . . . Number 0001h \r
+@DPS_Exit . . . . . . . . . . . L Near 0058 C_UTILS_TEXT \r
+@DataSize . . . . . . . . . . . Number 0000h \r
+@ISQ_L . . . . . . . . . . . . . L Near 00FD C_UTILS_TEXT \r
+@ISQ_S . . . . . . . . . . . . . L Near 0113 C_UTILS_TEXT \r
+@Interface . . . . . . . . . . . Number 0000h \r
+@Model . . . . . . . . . . . . . Number 0004h \r
+@No_Print . . . . . . . . . . . L Near 001F C_UTILS_TEXT \r
+@SK_Exit . . . . . . . . . . . . L Near 008C C_UTILS_TEXT \r
+@SK_NO_KEY . . . . . . . . . . . L Near 008A C_UTILS_TEXT \r
+@SVM_Exit . . . . . . . . . . . L Near 006D C_UTILS_TEXT \r
+@code . . . . . . . . . . . . . Text C_UTILS_TEXT\r
+@data . . . . . . . . . . . . . Text DGROUP\r
+@fardata? . . . . . . . . . . . Text FAR_BSS\r
+@fardata . . . . . . . . . . . . Text FAR_DATA\r
+@stack . . . . . . . . . . . . . Text DGROUP\r
+CR_LF . . . . . . . . . . . . . Byte 0012 _DATA \r
+False . . . . . . . . . . . . . Number 0000h \r
+RND_ModV . . . . . . . . . . . . Word 000C _DATA \r
+RND_Mult . . . . . . . . . . . . Word 0006 _DATA \r
+RND_Seed . . . . . . . . . . . . Word 0000 _DATA \r
+True . . . . . . . . . . . . . . Number -0001h \r
+b . . . . . . . . . . . . . . . Text BYTE PTR\r
+d . . . . . . . . . . . . . . . Text DWORD PTR\r
+f . . . . . . . . . . . . . . . Text FAR PTR\r
+nil . . . . . . . . . . . . . . Number 0000h \r
+o . . . . . . . . . . . . . . . Text OFFSET\r
+s . . . . . . . . . . . . . . . Text SHORT\r
+w . . . . . . . . . . . . . . . Text WORD PTR\r
+\r
+ 0 Warnings\r
+ 0 Errors\r
--- /dev/null
+!ifdef __LINUX__
+REMOVECOMMAND=rm -f
+COPYCOMMAND=cp -f
+DIRSEP=/
+OBJ=o
+!else
+REMOVECOMMAND=del
+COPYCOMMAND=copy /y
+DIRSEP=\
+OBJ=obj
+!endif
+
+CFLAGS=-d2 -0 -mc
+
+all: x-demo.exe
+
+x-demo.exe: x-demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+ wcl $(CFLAGS) x-demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+x-demo.$(OBJ): x-demo.c
+ wcl -c $(CFLAGS) x-demo.c
+
+c_utils.$(OBJ): c_utils.asm
+ wcl -c $(CFLAGS) c_utils.asm
+modex.$(OBJ): modex.asm
+ wcl -c $(CFLAGS) modex.asm
+
+clean: .symbolic
+ @$(REMOVECOMMAND) x-demo.exe
+ @$(REMOVECOMMAND) *.$(OBJ)
+ @$(REMOVECOMMAND) *.err
--- /dev/null
+;========================================================\r
+; MODEX.ASM - A Complete Mode X Library\r
+;\r
+; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
+; With considerable input from Michael Abrash\r
+;\r
+; The following information is donated to the public domain in\r
+; the hopes that save other programmers much frustration.\r
+;\r
+; If you do use this code in a product, it would be nice if\r
+; you include a line like "Mode X routines by Matt Pritchard"\r
+; in the credits.\r
+;\r
+; =========================================================\r
+;\r
+; All of this code is designed to be assembled with MASM 5.10a\r
+; but TASM 3.0 could be used as well.\r
+;\r
+; The routines contained are designed for use in a MEDIUM model\r
+; program. All Routines are FAR, and is assumed that a DGROUP\r
+; data segment exists and that DS will point to it on entry.\r
+;\r
+; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
+; will not be preserved, while the DS, BP, SI and DI registers\r
+; will be preserved.\r
+;\r
+; Unless specifically noted, All Parameters are assumed to be\r
+; "PASSED BY VALUE". That is, the actual value is placed on\r
+; the stack. When a reference is passed it is assumed to be\r
+; a near pointer to a variable in the DGROUP segment.\r
+;\r
+; Routines that return a single 16-Bit integer value will\r
+; return that value in the AX register.\r
+;\r
+; This code will *NOT* run on an 8086/8088 because 80286+\r
+; specific instructions are used. If you have an 8088/86\r
+; and VGA, you can buy an 80386-40 motherboard for about\r
+; $160 and move into the 90's.\r
+;\r
+; This code is reasonably optimized: Most drawing loops have\r
+; been unrolled once and memory references are minimized by\r
+; keeping stuff in registers when possible.\r
+;\r
+; Error Trapping varies by Routine. No Clipping is performed\r
+; so the caller should verify that all coordinates are valid.\r
+;\r
+; Several Macros are used to simplify common 2 or 3 instruction\r
+; sequences. Several Single letter Text Constants also\r
+; simplify common assembler expressions like "WORD PTR".\r
+;\r
+; ------------------ Mode X Variations ------------------\r
+;\r
+; Mode # Screen Size Max Pages Aspect Ratio (X:Y)\r
+;\r
+; 0 320 x 200 4 Pages 1.2:1\r
+; 1 320 x 400 2 Pages 2.4:1\r
+; 2 360 x 200 3 Pages 1.35:1\r
+; 3 360 x 400 1 Page 2.7:1\r
+; 4 320 x 240 3 Pages 1:1\r
+; 5 320 x 480 1 Page 2:1\r
+; 6 360 x 240 3 Pages 1.125:1\r
+; 7 360 x 480 1 Page 2.25:1\r
+;\r
+; -------------------- The Legal Stuff ------------------\r
+;\r
+; No warranty, either written or implied, is made as to\r
+; the accuracy and usability of this code product. Use\r
+; at your own risk. Batteries not included. Pepperoni\r
+; and extra cheese available for an additional charge.\r
+;\r
+; ----------------------- The Author --------------------\r
+;\r
+; Matt Pritchard is a paid programmer who'd rather be\r
+; writing games. He can be reached at: P.O. Box 140264,\r
+; Irving, TX 75014 USA. Michael Abrash is a living\r
+; god, who now works for Bill Gates (Microsoft).\r
+;\r
+; -------------------- Revision History -----------------\r
+; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
+; SET_MODEX now saves SI\r
+; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and\r
+; READ_DAC_REGISTERS. Expanded CLR Macro\r
+; to handle multiple registers\r
+;\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Huge\r
+ ;.286\r
+\r
+ ; ===== MACROS =====\r
+\r
+ ; Macro to OUT a 16 bit value to an I/O port\r
+\r
+OUT_16 MACRO Register, Value\r
+ IFDIFI <Register>, <DX> ; If DX not setup\r
+ MOV DX, Register ; then Select Register\r
+ ENDIF\r
+ IFDIFI <Value>, <AX> ; If AX not setup\r
+ MOV AX, Value ; then Get Data Value\r
+ ENDIF\r
+ OUT DX, AX ; Set I/O Register(s)\r
+ENDM\r
+\r
+ ; Macro to OUT a 8 bit value to an I/O Port\r
+\r
+OUT_8 MACRO Register, Value\r
+ IFDIFI <Register>, <DX> ; If DX not setup\r
+ MOV DX, Register ; then Select Register\r
+ ENDIF\r
+ IFDIFI <Value>, <AL> ; If AL not Setup\r
+ MOV AL, Value ; then Get Data Value\r
+ ENDIF\r
+ OUT DX, AL ; Set I/O Register\r
+ENDM\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; PUSH R1 ; Save R1\r
+; PUSHx R2, R3, R4, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; POP R1 ; Restore R1\r
+; POPx R2, R3, R4, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+\r
+ ; Macro to Clear Registers to 0\r
+\r
+; CLR MACRO Register, R2, R3, R4;, R5, R6\r
+; IFNB <Register>\r
+; XOR Register, Register ; Set Register = 0\r
+; CLR R2, R3, R4;, R5, R6\r
+; ENDIF\r
+; ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+ DEC Register ; Counter--\r
+ JNZ Destination ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+ DEC Register ; Counter--\r
+ JZ Destination ; Jump if 0\r
+ENDM\r
+\r
+\r
+ ; ===== General Constants =====\r
+\r
+ False EQU 0\r
+ True EQU -1\r
+ nil EQU 0\r
+\r
+ b EQU BYTE PTR\r
+ w EQU WORD PTR\r
+ d EQU DWORD PTR\r
+ o EQU OFFSET\r
+ f EQU FAR PTR\r
+ s EQU SHORT\r
+ ?x1 EQU <?>\r
+\r
+ ; ===== VGA Register Values =====\r
+\r
+ VGA_Segment EQU 0A000h ; Vga Memory Segment\r
+\r
+ ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller\r
+ GC_Index EQU 03CEh ; VGA Graphics Controller\r
+ SC_Index EQU 03C4h ; VGA Sequencer Controller\r
+ SC_Data EQU 03C5h ; VGA Sequencer Data Port\r
+ CRTC_Index EQU 03D4h ; VGA CRT Controller\r
+ CRTC_Data EQU 03D5h ; VGA CRT Controller Data\r
+ MISC_OUTPUT EQU 03C2h ; VGA Misc Register\r
+ INPUT_1 EQU 03DAh ; Input Status #1 Register\r
+\r
+ DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register\r
+ DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register\r
+ PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W\r
+\r
+ PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg\r
+ MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg\r
+ READ_MAP EQU 004h ; GC Index: Read Map Register\r
+ START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi\r
+ START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo\r
+\r
+ MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1\r
+ MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1\r
+ ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes\r
+\r
+ CHAIN4_OFF EQU 00604h ; Chain 4 mode Off\r
+ ASYNC_RESET EQU 00100h ; (A)synchronous Reset\r
+ SEQU_RESTART EQU 00300h ; Sequencer Restart\r
+\r
+ LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches\r
+ LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU\r
+\r
+ VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit\r
+ PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane #\r
+ ALL_PLANES EQU 0Fh ; All Bit Planes Selected\r
+ CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data\r
+\r
+ GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set\r
+ ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer\r
+ ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer\r
+\r
+ ; Constants Specific for these routines\r
+\r
+ NUM_MODES EQU 8 ; # of Mode X Variations\r
+\r
+ ; Specific Mode Data Table format...\r
+\r
+Mode_Data_Table STRUC\r
+ M_MiscR DB ? ; Value of MISC_OUTPUT register\r
+ M_Pages DB ? ; Maximum Possible # of pages\r
+ M_XSize DW ? ; X Size Displayed on screen\r
+ M_YSize DW ? ; Y Size Displayed on screen\r
+ M_XMax DW ? ; Maximum Possible X Size\r
+ M_YMax DW ? ; Maximum Possible Y Size\r
+ M_CRTC DW ? ; Table of CRTC register values\r
+Mode_Data_Table ENDS\r
+\r
+ ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
+\r
+ .DATA?\r
+\r
+SCREEN_WIDTH DW 0 ; Width of a line in Bytes\r
+SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels\r
+\r
+LAST_PAGE DW 0 ; # of Display Pages\r
+PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page\r
+\r
+PAGE_SIZE DW 0 ; Size of Page in Addr Bytes\r
+\r
+DISPLAY_PAGE DW 0 ; Page # currently displayed\r
+ACTIVE_PAGE DW 0 ; Page # currently active\r
+\r
+CURRENT_PAGE DW 0 ; Offset of current Page\r
+CURRENT_SEGMENT DW 0 ; Segment of VGA memory\r
+\r
+CURRENT_XOFFSET DW 0 ; Current Display X Offset\r
+CURRENT_YOFFSET DW 0 ; Current Display Y Offset\r
+\r
+CURRENT_MOFFSET DW 0 ; Current Start Offset\r
+\r
+MAX_XOFFSET DW 0 ; Current Display X Offset\r
+MAX_YOFFSET DW 0 ; Current Display Y Offset\r
+\r
+CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127\r
+CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255\r
+\r
+ .CODE\r
+\r
+ ; ===== DATA TABLES =====\r
+\r
+ ; Data Tables, Put in Code Segment for Easy Access\r
+ ; (Like when all the other Segment Registers are in\r
+ ; use!!) and reduced DGROUP requirements...\r
+\r
+ ; Bit Mask Tables for Left/Right/Character Masks\r
+\r
+Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H\r
+\r
+Right_Clip_Mask DB 01H, 03H, 07H, 0FH\r
+\r
+ ; Bit Patterns for converting character fonts\r
+\r
+Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH\r
+ DB 01H,09H,05H,0DH,03H,0BH,07H,0FH\r
+\r
+ ; CRTC Register Values for Various Configurations\r
+\r
+MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes\r
+ DW 04009H ; Cell Height (1 Scan Line)\r
+ DW 00014H ; Dword Mode off\r
+ DW 0E317H ; turn on Byte Mode\r
+ DW nil ; End of CRTC Data for 400/480 Line Mode\r
+\r
+MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes\r
+ DW 04109H ; Cell Height (2 Scan Lines)\r
+ DW 00014H ; Dword Mode off\r
+ DW 0E317H ; turn on Byte Mode\r
+ DW nil ; End of CRTC Data for 200/240 Line Mode\r
+\r
+MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels\r
+ DW 05F00H ; Horz total\r
+ DW 04F01H ; Horz Displayed\r
+ DW 05002H ; Start Horz Blanking\r
+ DW 08203H ; End Horz Blanking\r
+ DW 05404H ; Start H Sync\r
+ DW 08005H ; End H Sync\r
+ DW nil ; End of CRTC Data for 320 Horz pixels\r
+\r
+MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels\r
+ DW 06B00H ; Horz total\r
+ DW 05901H ; Horz Displayed\r
+ DW 05A02H ; Start Horz Blanking\r
+ DW 08E03H ; End Horz Blanking\r
+ DW 05E04H ; Start H Sync\r
+ DW 08A05H ; End H Sync\r
+ DW nil ; End of CRTC Data for 360 Horz pixels\r
+\r
+MODE_200_Tall:\r
+MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes\r
+ DW 0BF06H ; Vertical Total\r
+ DW 01F07H ; Overflow\r
+ DW 09C10H ; V Sync Start\r
+ DW 08E11H ; V Sync End/Prot Cr0 Cr7\r
+ DW 08F12H ; Vertical Displayed\r
+ DW 09615H ; V Blank Start\r
+ DW 0B916H ; V Blank End\r
+ DW nil ; End of CRTC Data for 200/400 Lines\r
+\r
+MODE_240_Tall:\r
+MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes\r
+ DW 00D06H ; Vertical Total\r
+ DW 03E07H ; Overflow\r
+ DW 0EA10H ; V Sync Start\r
+ DW 08C11H ; V Sync End/Prot Cr0 Cr7\r
+ DW 0DF12H ; Vertical Displayed\r
+ DW 0E715H ; V Blank Start\r
+ DW 00616H ; V Blank End\r
+ DW nil ; End of CRTC Data for 240/480 Lines\r
+\r
+ ; Table of Display Mode Tables\r
+\r
+MODE_TABLE:\r
+ DW o MODE_320x200, o MODE_320x400\r
+ DW o MODE_360x200, o MODE_360x400\r
+ DW o MODE_320x240, o MODE_320x480\r
+ DW o MODE_360x240, o MODE_360x480\r
+\r
+ ; Table of Display Mode Components\r
+\r
+MODE_320x200: ; Data for 320 by 200 Pixels\r
+\r
+ DB 063h ; 400 scan Lines & 25 Mhz Clock\r
+ DB 4 ; Maximum of 4 Pages\r
+ DW 320, 200 ; Displayed Pixels (X,Y)\r
+ DW 1302, 816 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_Wide, o MODE_200_Tall\r
+ DW o MODE_Double_Line, nil\r
+\r
+MODE_320x400: ; Data for 320 by 400 Pixels\r
+\r
+ DB 063h ; 400 scan Lines & 25 Mhz Clock\r
+ DB 2 ; Maximum of 2 Pages\r
+ DW 320, 400 ; Displayed Pixels X,Y\r
+ DW 648, 816 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_Wide, o MODE_400_Tall\r
+ DW o MODE_Single_Line, nil\r
+\r
+MODE_360x240: ; Data for 360 by 240 Pixels\r
+\r
+ DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
+ DB 3 ; Maximum of 3 Pages\r
+ DW 360, 240 ; Displayed Pixels X,Y\r
+ DW 1092, 728 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, o MODE_240_Tall\r
+ DW o MODE_Double_Line , nil\r
+\r
+MODE_360x480: ; Data for 360 by 480 Pixels\r
+\r
+ DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
+ DB 1 ; Only 1 Page Possible\r
+ DW 360, 480 ; Displayed Pixels X,Y\r
+ DW 544, 728 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, o MODE_480_Tall\r
+ DW o MODE_Single_Line , nil\r
+\r
+MODE_320x240: ; Data for 320 by 240 Pixels\r
+\r
+ DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
+ DB 3 ; Maximum of 3 Pages\r
+ DW 320, 240 ; Displayed Pixels X,Y\r
+ DW 1088, 818 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_Wide, o MODE_240_Tall\r
+ DW o MODE_Double_Line, nil\r
+\r
+MODE_320x480: ; Data for 320 by 480 Pixels\r
+\r
+ DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
+ DB 1 ; Only 1 Page Possible\r
+ DW 320, 480 ; Displayed Pixels X,Y\r
+ DW 540, 818 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_WIDE, o MODE_480_Tall\r
+ DW o MODE_Single_Line, nil\r
+\r
+MODE_360x200: ; Data for 360 by 200 Pixels\r
+\r
+ DB 067h ; 400 scan Lines & 28 Mhz Clock\r
+ DB 3 ; Maximum of 3 Pages\r
+ DW 360, 200 ; Displayed Pixels (X,Y)\r
+ DW 1302, 728 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, MODE_200_Tall\r
+ DW o MODE_Double_Line, nil\r
+\r
+MODE_360x400: ; Data for 360 by 400 Pixels\r
+\r
+ DB 067h ; 400 scan Lines & 28 Mhz Clock\r
+ DB 1 ; Maximum of 1 Pages\r
+ DW 360, 400 ; Displayed Pixels X,Y\r
+ DW 648, 816 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, MODE_400_Tall\r
+ DW o MODE_Single_Line, nil\r
+\r
+\r
+ ; ===== MODE X SETUP ROUTINES =====\r
+\r
+;======================================================\r
+;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
+;======================================================\r
+;\r
+; Sets Up the specified version of Mode X. Allows for\r
+; the setup of multiple video pages, and a virtual\r
+; screen which can be larger than the displayed screen\r
+; (which can then be scrolled a pixel at a time)\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+;\r
+; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio\r
+; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio\r
+; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio\r
+; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio\r
+; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio\r
+; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio\r
+; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
+; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio\r
+;\r
+; MaxXpos = The Desired Virtual Screen Width\r
+; MaxYpos = The Desired Virtual Screen Height\r
+; Pages = The Desired # of Video Pages\r
+;\r
+; EXIT: AX = Success Flag: >0 = Failure / 0 = Success\r
+;\r
+\r
+SVM_STACK STRUC\r
+ SVM_Table DW ? ; Offset of Mode Info Table\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ SVM_Pages DW ? ; # of Screen Pages desired\r
+ SVM_Ysize DW ? ; Vertical Screen Size Desired\r
+ SVM_Xsize DW ? ; Horizontal Screen Size Desired\r
+ SVM_Mode DW ? ; Display Resolution Desired\r
+SVM_STACK ENDS\r
+\r
+ PUBLIC SET_VGA_MODEX\r
+\r
+SET_VGA_MODEX PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 2 ; Allocate workspace\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Check Legality of Mode Request....\r
+\r
+ MOV BX, [BP].SVM_Mode ; Get Requested Mode #\r
+ CMP BX, NUM_MODES ; Is it 0..7?\r
+ JAE @SVM_BadModeSetup1 ; If Not, Error out\r
+\r
+ SHL BX, 1 ; Scale BX\r
+ MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
+ MOV [BP].SVM_Table, SI ; Save ptr for later use\r
+\r
+ ; Check # of Requested Display Pages\r
+\r
+ MOV CX, [BP].SVM_Pages ; Get # of Requested Pages\r
+ ;CLR CH ; Set Hi Word = 0!\r
+ mov ch,0 ; Set Hi Word = 0!\r
+ CMP CL, CS:[SI].M_Pages ; Check # Pages for mode\r
+ JA @SVM_BadModeSetup2 ; Report Error if too Many Pages\r
+ JCXZ @SVM_BadModeSetup3 ; Report Error if 0 Pages\r
+\r
+ ; Check Validity of X Size\r
+\r
+ AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0\r
+\r
+ MOV AX, [BP].SVM_XSize ; Get Logical Screen Width\r
+ CMP AX, CS:[SI].M_XSize ; Check against Displayed X\r
+ JB @SVM_BadModeSetup4 ; Report Error if too small\r
+ CMP AX, CS:[SI].M_XMax ; Check against Max X\r
+ JA @SVM_BadModeSetup5 ; Report Error if too big\r
+\r
+ ; Check Validity of Y Size\r
+\r
+ MOV BX, [BP].SVM_YSize ; Get Logical Screen Height\r
+ CMP BX, CS:[SI].M_YSize ; Check against Displayed Y\r
+ JB @SVM_BadModeSetup6 ; Report Error if too small\r
+ CMP BX, CS:[SI].M_YMax ; Check against Max Y\r
+ JA @SVM_BadModeSetup7 ; Report Error if too big\r
+\r
+ ; Enough memory to Fit it all?\r
+\r
+ SHR AX, 1 ; # of Bytes:Line = XSize/4\r
+ SHR AX, 1 ; # of Bytes:Line = XSize/4\r
+ MUL CX ; AX = Bytes/Line * Pages\r
+ MUL BX ; DX:AX = Total VGA mem needed\r
+ JNO @SVM_Continue ; Exit if Total Size > 256K\r
+\r
+ DEC DX ; Was it Exactly 256K???\r
+ OR DX, AX ; (DX = 1, AX = 0000)\r
+ JZ @SVM_Continue ; if so, it's valid...\r
+\r
+ jmp @SVM_Continue;0000\r
+\r
+@SVM_BadModeSetup:\r
+ mov ax,8 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup1:\r
+ mov ax,1 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup2:\r
+ mov ax,2 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup3:\r
+ mov ax,3 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup4:\r
+ mov ax,4 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup5:\r
+ mov ax,5 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup6:\r
+ mov ax,6 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup7:\r
+ mov ax,7 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+\r
+@SVM_Continue:\r
+\r
+ MOV AX, 13H ; Start with Mode 13H\r
+ INT 10H ; Let BIOS Set Mode\r
+\r
+ OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode\r
+ OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset\r
+ OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size\r
+ OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ...\r
+\r
+ OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register\r
+ INC DX ; Point to Data\r
+ IN AL, DX ; Get Value, Bit 7 = Protect\r
+ AND AL, 7FH ; Mask out Write Protect\r
+ OUT DX, AL ; And send it back\r
+\r
+ MOV DX, CRTC_INDEX ; Vga Crtc Registers\r
+ ADD SI, M_CRTC ; SI -> CRTC Parameter Data\r
+\r
+ ; Load Tables of CRTC Parameters from List of Tables\r
+\r
+@SVM_Setup_Table:\r
+\r
+ MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl\r
+ ADD SI, 2 ; Point to next Ptr Entry\r
+ OR DI, DI ; A nil Ptr means that we have\r
+ JZ @SVM_Set_Data ; finished CRTC programming\r
+\r
+@SVM_Setup_CRTC:\r
+ MOV AX, CS:[DI] ; Get CRTC Data from Table\r
+ ADD DI, 2 ; Advance Pointer\r
+ OR AX, AX ; At End of Data Table?\r
+ JZ @SVM_Setup_Table ; If so, Exit & get next Table\r
+\r
+ OUT DX, AX ; Reprogram VGA CRTC reg\r
+ JMP s @SVM_Setup_CRTC ; Process Next Table Entry\r
+\r
+ ; Initialize Page & Scroll info, DI = 0\r
+\r
+@SVM_Set_Data:\r
+ MOV DISPLAY_PAGE, DI ; Display Page = 0\r
+ MOV ACTIVE_PAGE, DI ; Active Page = 0\r
+ MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0\r
+ MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
+ MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
+ MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
+\r
+ MOV AX, VGA_SEGMENT ; Segment for VGA memory\r
+ MOV CURRENT_SEGMENT, AX ; Save for Future LES's\r
+\r
+ ; Set Logical Screen Width, X Scroll and Our Data\r
+\r
+ MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info\r
+ MOV AX, [BP].SVM_Xsize ; Get Display Width\r
+\r
+ MOV CX, AX ; CX = Logical Width\r
+ SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
+ MOV MAX_XOFFSET, CX ; Set Maximum X Scroll\r
+\r
+ SHR AX, 1 ; Bytes = Pixels / 4\r
+ SHR AX, 1 ; Bytes = Pixels / 4\r
+ MOV SCREEN_WIDTH, AX ; Save Width in Pixels\r
+\r
+ SHR AX, 1 ; Offset Value = Bytes / 2\r
+ MOV AH, 13h ; CRTC Offset Register Index\r
+ XCHG AL, AH ; Switch format for OUT\r
+ OUT DX, AX ; Set VGA CRTC Offset Reg\r
+\r
+ ; Setup Data table, Y Scroll, Misc for Other Routines\r
+\r
+ MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height\r
+\r
+ MOV CX, AX ; CX = Logical Height\r
+ SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
+ MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll\r
+\r
+ MOV SCREEN_HEIGHT, AX ; Save Height in Pixels\r
+ MUL SCREEN_WIDTH ; AX = Page Size in Bytes,\r
+ MOV PAGE_SIZE, AX ; Save Page Size\r
+\r
+ MOV CX, [BP].SVM_Pages ; Get # of Pages\r
+ MOV LAST_PAGE, CX ; Save # of Pages\r
+\r
+ mov bx,0 ; Page # = 0\r
+ MOV DX, BX ; Page 0 Offset = 0\r
+\r
+@SVM_Set_Pages:\r
+\r
+ MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset\r
+ ADD BX, 2 ; Page#++\r
+ ADD DX, AX ; Compute Addr of Next Page\r
+ LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set\r
+\r
+ ; Clear VGA Memory\r
+\r
+ OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ LES DI, d CURRENT_PAGE ; -> Start of VGA memory\r
+\r
+ mov ax,0 ; AX = 0\r
+ CLD ; Block Xfer Forwards\r
+ MOV CX, 8000H ; 32K * 4 * 2 = 256K\r
+ REP STOSW ; Clear dat memory!\r
+\r
+ ; Setup Font Pointers\r
+\r
+ MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127\r
+ MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
+ INT 10h ; Call VGA BIOS\r
+\r
+ MOV CHARSET_LOW, BP ; Save Char Set Offset\r
+ MOV CHARSET_LOW+2, ES ; Save Char Set Segment\r
+\r
+ MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255\r
+ MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
+ INT 10h ; Call VGA BIOS\r
+\r
+ MOV CHARSET_HI, BP ; Save Char Set Offset\r
+ MOV CHARSET_HI+2, ES ; Save Char Set Segment\r
+\r
+ MOV AX, True ; Return Success Code\r
+\r
+@SVM_EXIT:\r
+ ADD SP, 2 ; Deallocate workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 8 ; Exit & Clean Up Stack\r
+\r
+SET_VGA_MODEX ENDP\r
+\r
+\r
+;==================\r
+;SET_MODEX% (Mode%)\r
+;==================\r
+;\r
+; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+; (See SET_VGA_MODEX for list)\r
+;\r
+; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+;\r
+\r
+SM_STACK STRUC\r
+ DW ?,? ; BP, SI\r
+ DD ? ; Caller\r
+ SM_Mode DW ? ; Desired Screen Resolution\r
+SM_STACK ENDS\r
+\r
+ PUBLIC SET_MODEX\r
+\r
+SET_MODEX PROC FAR\r
+\r
+ ;PUSHx BP, SI ; Preserve Important registers\r
+ push bp\r
+ push si\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ mov ax,0 ; Assume Failure\r
+ MOV BX, [BP].SM_Mode ; Get Desired Mode #\r
+ CMP BX, NUM_MODES ; Is it a Valid Mode #?\r
+ JAE @SMX_Exit ; If Not, don't Bother\r
+\r
+ PUSH BX ; Push Mode Parameter\r
+\r
+ SHL BX, 1 ; Scale BX to word Index\r
+ MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
+\r
+ PUSH CS:[SI].M_XSize ; Push Default X Size\r
+ PUSH CS:[SI].M_Ysize ; Push Default Y size\r
+ MOV AL, CS:[SI].M_Pages ; Get Default # of Pages\r
+ mov ah,0 ; Hi Byte = 0\r
+ PUSH AX ; Push # Pages\r
+\r
+ CALL f SET_VGA_MODEX ; Set up Mode X!\r
+\r
+@SMX_Exit:\r
+ ;POPx SI, BP ; Restore Registers\r
+ pop si\r
+ pop bp\r
+ RET 2 ; Exit & Clean Up Stack\r
+\r
+SET_MODEX ENDP\r
+\r
+\r
+ ; ===== BASIC GRAPHICS PRIMITIVES =====\r
+\r
+;============================\r
+;CLEAR_VGA_SCREEN (ColorNum%)\r
+;============================\r
+;\r
+; Clears the active display page\r
+;\r
+; ENTRY: ColorNum = Color Value to fill the page with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+CVS_STACK STRUC\r
+ DW ?,? ; DI, BP\r
+ DD ? ; Caller\r
+ CVS_COLOR DB ?,? ; Color to Set Screen to\r
+CVS_STACK ENDS\r
+\r
+ PUBLIC CLEAR_VGA_SCREEN\r
+\r
+CLEAR_VGA_SCREEN PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Preserve Important Registers\r
+ push bp\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AL, [BP].CVS_COLOR ; Get Color\r
+ MOV AH, AL ; Copy for Word Write\r
+ CLD ; Block fill Forwards\r
+\r
+ MOV CX, PAGE_SIZE ; Get Size of Page\r
+ SHR CX, 1 ; Divide by 2 for Words\r
+ REP STOSW ; Block Fill VGA memory\r
+\r
+ ;POPx DI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop bp\r
+ RET 2 ; Exit & Clean Up Stack\r
+\r
+CLEAR_VGA_SCREEN ENDP\r
+\r
+\r
+;===================================\r
+;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
+;===================================\r
+;\r
+; Plots a single Pixel on the active display page\r
+;\r
+; ENTRY: Xpos = X position to plot pixel at\r
+; Ypos = Y position to plot pixel at\r
+; ColorNum = Color to plot pixel with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SP_STACK STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ SETP_Color DB ?,? ; Color of Point to Plot\r
+ SETP_Ypos DW ? ; Y pos of Point to Plot\r
+ SETP_Xpos DW ? ; X pos of Point to Plot\r
+SP_STACK ENDS\r
+\r
+ PUBLIC SET_POINT\r
+\r
+SET_POINT PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Preserve Registers\r
+ push bp\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel\r
+ MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
+\r
+ MOV BX, [BP].SETP_Xpos ; Get Xpos\r
+ MOV CX, BX ; Copy to extract Plane # from\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
+\r
+ MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
+ AND CL, PLANE_BITS ; Get Plane Bits\r
+ SHL AH, CL ; Get Plane Select Value\r
+ OUT_16 SC_Index, AX ; Select Plane\r
+\r
+ MOV AL,[BP].SETP_Color ; Get Pixel Color\r
+ MOV ES:[DI+BX], AL ; Draw Pixel\r
+\r
+ ;POPx DI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop bp\r
+ RET 6 ; Exit and Clean up Stack\r
+\r
+SET_POINT ENDP\r
+\r
+\r
+;==========================\r
+;READ_POINT% (Xpos%, Ypos%)\r
+;==========================\r
+;\r
+; Read the color of a pixel from the Active Display Page\r
+;\r
+; ENTRY: Xpos = X position of pixel to read\r
+; Ypos = Y position of pixel to read\r
+;\r
+; EXIT: AX = Color of Pixel at (Xpos, Ypos)\r
+;\r
+\r
+RP_STACK STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ RP_Ypos DW ? ; Y pos of Point to Read\r
+ RP_Xpos DW ? ; X pos of Point to Read\r
+RP_STACK ENDS\r
+\r
+ PUBLIC READ_POINT\r
+\r
+READ_POINT PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Preserve Registers\r
+ push bp\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, [BP].RP_Ypos ; Get Line # of Pixel\r
+ MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
+\r
+ MOV BX, [BP].RP_Xpos ; Get Xpos\r
+ MOV CX, BX\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
+\r
+ MOV AL, READ_MAP ; GC Read Mask Register\r
+ MOV AH, CL ; Get Xpos\r
+ AND AH, PLANE_BITS ; & mask out Plane #\r
+ OUT_16 GC_INDEX, AX ; Select Plane to read in\r
+\r
+ mov ah,0 ; Clear Return Value Hi byte\r
+ MOV AL, ES:[DI+BX] ; Get Color of Pixel\r
+\r
+ ;POPx DI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop bp\r
+ RET 4 ; Exit and Clean up Stack\r
+\r
+READ_POINT ENDP\r
+\r
+\r
+;======================================================\r
+;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;======================================================\r
+;\r
+; Fills a rectangular block on the active display Page\r
+;\r
+; ENTRY: Xpos1 = Left X position of area to fill\r
+; Ypos1 = Top Y position of area to fill\r
+; Xpos2 = Right X position of area to fill\r
+; Ypos2 = Bottom Y position of area to fill\r
+; ColorNum = Color to fill area with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+FB_STACK STRUC\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ FB_Color DB ?,? ; Fill Color\r
+ FB_Ypos2 DW ? ; Y pos of Lower Right Pixel\r
+ FB_Xpos2 DW ? ; X pos of Lower Right Pixel\r
+ FB_Ypos1 DW ? ; Y pos of Upper Left Pixel\r
+ FB_Xpos1 DW ? ; X pos of Upper Left Pixel\r
+FB_STACK ENDS\r
+\r
+ PUBLIC FILL_BLOCK\r
+\r
+FILL_BLOCK PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ CLD ; Direction Flag = Forward\r
+\r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+\r
+ ; Validate Pixel Coordinates\r
+ ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
+\r
+ MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2?\r
+ MOV BX, [BP].FB_Ypos2 ; BX = Y2\r
+ CMP AX, BX\r
+ JLE @FB_NOSWAP1\r
+\r
+ MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1\r
+ XCHG AX, BX ; on stack for future use\r
+\r
+@FB_NOSWAP1:\r
+ SUB BX, AX ; Get Y width\r
+ INC BX ; Add 1 to avoid 0 value\r
+ MOV [BP].FB_Ypos2, BX ; Save in Ypos2\r
+\r
+ MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line\r
+ ADD DI, AX ; DI = Start of Line Y1\r
+\r
+ MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2\r
+ MOV BX, [BP].FB_Xpos2 ;\r
+ CMP AX, BX\r
+ JLE @FB_NOSWAP2 ; Skip Ahead if Ok\r
+\r
+ MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2\r
+ XCHG AX, BX ; on stack for future use\r
+\r
+ ; All our Input Values are in order, Now determine\r
+ ; How many full "bands" 4 pixels wide (aligned) there\r
+ ; are, and if there are partial bands (<4 pixels) on\r
+ ; the left and right edges.\r
+\r
+@FB_NOSWAP2:\r
+ MOV DX, AX ; DX = X1 (Pixel Position)\r
+ SHR DX, 1 ; DX/4 = Bytes into Line\r
+ SHR DX, 1 ; DX/4 = Bytes into Line\r
+ ADD DI, DX ; DI = Addr of Upper-Left Corner\r
+\r
+ MOV CX, BX ; CX = X2 (Pixel Position)\r
+ SHR CX, 1 ; CX/4 = Bytes into Line\r
+ SHR CX, 1 ; CX/4 = Bytes into Line\r
+\r
+ CMP DX, CX ; Start and end in same band?\r
+ JNE @FB_NORMAL ; if not, check for l & r edges\r
+ JMP @FB_ONE_BAND_ONLY ; if so, then special processing\r
+\r
+@FB_NORMAL:\r
+ SUB CX, DX ; CX = # bands -1\r
+ MOV SI, AX ; SI = PLANE#(X1)\r
+ AND SI, PLANE_BITS ; if Left edge is aligned then\r
+ JZ @FB_L_PLANE_FLUSH ; no special processing..\r
+\r
+ ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
+\r
+ OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
+\r
+ MOV SI, DI ; SI = Copy of Start Addr (UL)\r
+\r
+ MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+ MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+\r
+@FB_LEFT_LOOP:\r
+ MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn\r
+\r
+ MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn\r
+\r
+@FB_LEFT_CONT:\r
+\r
+ INC DI ; Point to Middle (or Right) Block\r
+ DEC CX ; Reset CX instead of JMP @FB_RIGHT\r
+\r
+@FB_L_PLANE_FLUSH:\r
+ INC CX ; Add in Left band to middle block\r
+\r
+ ; DI = Addr of 1st middle Pixel (band) to fill\r
+ ; CX = # of Bands to fill -1\r
+\r
+@FB_RIGHT:\r
+ MOV SI, [BP].FB_Xpos2 ; Get Xpos2\r
+ AND SI, PLANE_BITS ; Get Plane values\r
+ CMP SI, 0003 ; Plane = 3?\r
+ JE @FB_R_EDGE_FLUSH ; Hey, add to middle\r
+\r
+ ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
+\r
+ OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask\r
+\r
+ MOV SI, DI ; Get Addr of Left Edge\r
+ ADD SI, CX ; Add Width-1 (Bands)\r
+ DEC SI ; To point to top of Right Edge\r
+\r
+ MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+ MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+\r
+@FB_RIGHT_LOOP:\r
+ MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn\r
+\r
+ MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn\r
+\r
+@FB_RIGHT_CONT:\r
+\r
+ DEC CX ; Minus 1 for Middle bands\r
+ JZ @FB_EXIT ; Uh.. no Middle bands...\r
+\r
+@FB_R_EDGE_FLUSH:\r
+\r
+ ; DI = Addr of Upper Left block to fill\r
+ ; CX = # of Bands to fill in (width)\r
+\r
+ OUT_8 SC_Data, ALL_PLANES ; Write to All Planes\r
+\r
+ MOV DX, SCREEN_WIDTH ; DX = DI Increment\r
+ SUB DX, CX ; = Screen_Width-# Planes Filled\r
+\r
+ MOV BX, CX ; BX = Quick Refill for CX\r
+ MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+\r
+@FB_MIDDLE_LOOP:\r
+ REP STOSB ; Fill in entire line\r
+\r
+ MOV CX, BX ; Recharge CX (Line Width)\r
+ ADD DI, DX ; Point to start of Next Line\r
+ LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
+\r
+ JMP s @FB_EXIT ; Outa here\r
+\r
+@FB_ONE_BAND_ONLY:\r
+ MOV SI, AX ; Get Left Clip Mask, Save X1\r
+ AND SI, PLANE_BITS ; Mask out Row #\r
+ MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
+ MOV SI, BX ; Get Right Clip Mask, Save X2\r
+ AND SI, PLANE_BITS ; Mask out Row #\r
+ AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
+\r
+ OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
+\r
+ MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+ MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+\r
+@FB_ONE_LOOP:\r
+ MOV ES:[DI], AL ; Fill in Pixels\r
+ ADD DI, BX ; Point to Next Line (Below)\r
+ LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn\r
+\r
+ MOV ES:[DI], AL ; Fill in Pixels\r
+ ADD DI, BX ; Point to Next Line (Below)\r
+ LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn\r
+\r
+@FB_EXIT:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 10 ; Exit and Clean up Stack\r
+\r
+FILL_BLOCK ENDP\r
+\r
+\r
+;=====================================================\r
+;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;=====================================================\r
+;\r
+; Draws a Line on the active display page\r
+;\r
+; ENTRY: Xpos1 = X position of first point on line\r
+; Ypos1 = Y position of first point on line\r
+; Xpos2 = X position of last point on line\r
+; Ypos2 = Y position of last point on line\r
+; ColorNum = Color to draw line with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+DL_STACK STRUC\r
+ DW ?x1 ; DI, SI, BP\r
+ DW ?x1 ; DI, SI, BP\r
+ DW ?x1 ; DI, SI, BP\r
+ DD ? ; Caller\r
+ DL_ColorF DB ?,? ; Line Draw Color\r
+ DL_Ypos2 DW ? ; Y pos of last point\r
+ DL_Xpos2 DW ? ; X pos of last point\r
+ DL_Ypos1 DW ? ; Y pos of first point\r
+ DL_Xpos1 DW ? ; X pos of first point\r
+DL_STACK ENDS\r
+\r
+ PUBLIC DRAW_LINE\r
+\r
+DRAW_LINE PROC FAR\r
+\r
+ ;PUSHx BP, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+ CLD ; Direction Flag = Forward\r
+\r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ MOV CH, [BP].DL_ColorF ; Save Line Color in CH\r
+\r
+ ; Check Line Type\r
+\r
+ MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2?\r
+ MOV DI, [BP].DL_Xpos2 ; DX = X2\r
+ CMP SI, DI ; Is X1 < X2\r
+ JE @DL_VLINE ; If X1=X2, Draw Vertical Line\r
+ JL @DL_NOSWAP1 ; If X1 < X2, don't swap\r
+\r
+ XCHG SI, DI ; X2 IS > X1, SO SWAP THEM\r
+\r
+@DL_NOSWAP1:\r
+\r
+ ; SI = X1, DI = X2\r
+\r
+ MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2?\r
+ CMP AX, [BP].DL_Ypos2 ; Y1 = Y2?\r
+ JE @DL_HORZ ; If so, Draw a Horizontal Line\r
+\r
+ JMP @DL_BREZHAM ; Diagonal line... go do it...\r
+\r
+ ; This Code draws a Horizontal Line in Mode X where:\r
+ ; SI = X1, DI = X2, and AX = Y1/Y2\r
+\r
+@DL_HORZ:\r
+\r
+ MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width\r
+ MOV DX, AX ; CX = Line offset into Page\r
+\r
+ MOV AX, SI ; Get Left edge, Save X1\r
+ AND SI, PLANE_BITS ; Mask out Row #\r
+ MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
+ MOV CX, DI ; Get Right edge, Save X2\r
+ AND DI, PLANE_BITS ; Mask out Row #\r
+ MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
+\r
+ SHR AX, 1 ; Get X1 Byte # (=X1/4)\r
+ SHR CX, 1 ; Get X2 Byte # (=X2/4)\r
+ SHR AX, 1 ; Get X1 Byte # (=X1/4)\r
+ SHR CX, 1 ; Get X2 Byte # (=X2/4)\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ ADD DI, DX ; Point to Start of Line\r
+ ADD DI, AX ; Point to Pixel X1\r
+\r
+ SUB CX, AX ; CX = # Of Bands (-1) to set\r
+ JNZ @DL_LONGLN ; jump if longer than one segment\r
+\r
+ AND BL, BH ; otherwise, merge clip masks\r
+\r
+@DL_LONGLN:\r
+\r
+ OUT_8 SC_Data, BL ; Set the Left Clip Mask\r
+\r
+ MOV AL, [BP].DL_ColorF ; Get Line Color\r
+ MOV BL, AL ; BL = Copy of Line Color\r
+ STOSB ; Set Left (1-4) Pixels\r
+\r
+ JCXZ @DL_EXIT ; Done if only one Line Segment\r
+\r
+ DEC CX ; CX = # of Middle Segments\r
+ JZ @DL_XRSEG ; If no middle segments....\r
+\r
+ ; Draw Middle Segments\r
+\r
+ OUT_8 DX, ALL_PLANES ; Write to ALL Planes\r
+\r
+ MOV AL, BL ; Get Color from BL\r
+ REP STOSB ; Draw Middle (4 Pixel) Segments\r
+\r
+@DL_XRSEG:\r
+ OUT_8 DX, BH ; Select Planes for Right Clip Mask\r
+ MOV AL, BL ; Get Color Value\r
+ STOSB ; Draw Right (1-4) Pixels\r
+\r
+ JMP s @DL_EXIT ; We Are Done...\r
+\r
+\r
+ ; This Code Draws A Vertical Line. On entry:\r
+ ; CH = Line Color, SI & DI = X1\r
+\r
+@DL_VLINE:\r
+\r
+ MOV AX, [BP].DL_Ypos1 ; AX = Y1\r
+ MOV SI, [BP].DL_Ypos2 ; SI = Y2\r
+ CMP AX, SI ; Is Y1 < Y2?\r
+ JLE @DL_NOSWAP2 ; if so, Don't Swap them\r
+\r
+ XCHG AX, SI ; Ok, NOW Y1 < Y2\r
+\r
+@DL_NOSWAP2:\r
+\r
+ SUB SI, AX ; SI = Line Height (Y2-Y1+1)\r
+ INC SI\r
+\r
+ ; AX = Y1, DI = X1, Get offset into Page into AX\r
+\r
+ MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width\r
+ MOV DX, DI ; Copy Xpos into DX\r
+ SHR DI, 1 ; DI = Xpos/4\r
+ SHR DI, 1 ; DI = Xpos/4\r
+ ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ ADD DI, AX ; Point to Pixel X1, Y1\r
+\r
+ ;Select Plane\r
+\r
+ MOV CL, DL ; CL = Save X1\r
+ AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #)\r
+ MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
+ SHL AH, CL ; Change to Correct Plane #\r
+ OUT_16 SC_Index, AX ; Select Plane\r
+\r
+ MOV AL, CH ; Get Saved Color\r
+ MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By\r
+\r
+@DL_VLoop:\r
+ MOV ES:[DI], AL ; Draw Single Pixel\r
+ ADD DI, BX ; Point to Next Line\r
+ LOOPjz SI, @DL_EXIT ; Lines--, Exit if done\r
+\r
+ MOV ES:[DI], AL ; Draw Single Pixel\r
+ ADD DI, BX ; Point to Next Line\r
+ LOOPx SI, @DL_VLoop ; Lines--, Loop until Done\r
+\r
+@DL_EXIT:\r
+\r
+ JMP @DL_EXIT2 ; Done!\r
+\r
+ ; This code Draws a diagonal line in Mode X\r
+\r
+@DL_BREZHAM:\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, [BP].DL_Ypos1 ; get Y1 value\r
+ MOV BX, [BP].DL_Ypos2 ; get Y2 value\r
+ MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos\r
+\r
+ CMP BX, AX ; Y2-Y1 is?\r
+ JNC @DL_DeltaYOK ; if Y2>=Y1 then goto...\r
+\r
+ XCHG BX, AX ; Swap em...\r
+ MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos\r
+\r
+@DL_DeltaYOK:\r
+ MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1\r
+\r
+ ADD DI, AX ; DI -> Start of Line Y1 on Page\r
+ MOV AX, CX ; AX = Xpos (X1)\r
+ SHR AX, 1 ; /4 = Byte Offset into Line\r
+ SHR AX, 1 ; /4 = Byte Offset into Line\r
+ ADD DI, AX ; DI = Starting pos (X1,Y1)\r
+\r
+ MOV AL, 11h ; Staring Mask\r
+ AND CL, PLANE_BITS ; Get Plane #\r
+ SHL AL, CL ; and shift into place\r
+ MOV AH, [BP].DL_ColorF ; Color in Hi Bytes\r
+\r
+ PUSH AX ; Save Mask,Color...\r
+\r
+ MOV AH, AL ; Plane # in AH\r
+ MOV AL, MAP_MASK ; Select Plane Register\r
+ OUT_16 SC_Index, AX ; Select initial plane\r
+\r
+ MOV AX, [BP].DL_Xpos1 ; get X1 value\r
+ MOV BX, [BP].DL_Ypos1 ; get Y1 value\r
+ MOV CX, [BP].DL_Xpos2 ; get X2 value\r
+ MOV DX, [BP].DL_Ypos2 ; get Y2 value\r
+\r
+ MOV BP, SCREEN_WIDTH ; Use BP for Line width to\r
+ ; to avoid extra memory access\r
+\r
+ SUB DX, BX ; figure Delta_Y\r
+ JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1\r
+\r
+ ADD BX, DX ; put Y2 into Y1\r
+ NEG DX ; abs(Delta_Y)\r
+ XCHG AX, CX ; and exchange X1 and X2\r
+\r
+@DL_DeltaYOK2:\r
+ MOV BX, 08000H ; seed for fraction accumulator\r
+\r
+ SUB CX, AX ; figure Delta_X\r
+ JC @DL_DrawLeft ; if negative, go left\r
+\r
+ JMP @DL_DrawRight ; Draw Line that slopes right\r
+\r
+@DL_DrawLeft:\r
+\r
+ NEG CX ; abs(Delta_X)\r
+\r
+ CMP CX, DX ; is Delta_X < Delta_Y?\r
+ JB @DL_SteepLeft ; yes, so go do steep line\r
+ ; (Delta_Y iterations)\r
+\r
+ ; Draw a Shallow line to the left in Mode X\r
+\r
+@DL_ShallowLeft:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
+ SBB DX, 0 ; include carry\r
+ DIV CX ; divide by Delta_X\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_X so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
+\r
+@DL_SLLLoop:\r
+ MOV ES:[DI], AH ; set first pixel, plane data set up\r
+ LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_SLLL2nc ; move down on carry\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLLL2nc:\r
+ DEC DI ; Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator,\r
+ JNC @DL_SLLL3nc ; move down on carry\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLLL3nc: ; Now move left a pixel...\r
+ DEC DI ; Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+ JMP s @DL_SLLLoop ; loop until done\r
+\r
+@DL_SLLExit:\r
+ JMP @DL_EXIT2 ; and exit\r
+\r
+ ; Draw a steep line to the left in Mode X\r
+\r
+@DL_SteepLeft:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ XCHG DX, CX ; Delta_Y switched with Delta_X\r
+ DIV CX ; divide by Delta_Y\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add Fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_Y so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
+\r
+@DL_STLLoop:\r
+\r
+ MOV ES:[DI], AH ; set first pixel\r
+ LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_STLnc2 ; No carry, just move down!\r
+\r
+ DEC DI ; Move Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc2:\r
+ ADD DI, BP ; advance to next line.\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_STLnc3 ; No carry, just move down!\r
+\r
+ DEC DI ; Move Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc3:\r
+ ADD DI, BP ; advance to next line.\r
+ JMP s @DL_STLLoop ; Loop until done\r
+\r
+@DL_STLExit:\r
+ JMP @DL_EXIT2 ; and exit\r
+\r
+ ; Draw a line that goes to the Right...\r
+\r
+@DL_DrawRight:\r
+ CMP CX, DX ; is Delta_X < Delta_Y?\r
+ JB @DL_SteepRight ; yes, so go do steep line\r
+ ; (Delta_Y iterations)\r
+\r
+ ; Draw a Shallow line to the Right in Mode X\r
+\r
+@DL_ShallowRight:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
+ SBB DX, 0 ; include carry\r
+ DIV CX ; divide by Delta_X\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add Fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_X so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
+\r
+@DL_SLRLoop:\r
+ MOV ES:[DI], AH ; set first pixel, mask is set up\r
+ LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_SLR2nc ; don't move down if carry not set\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLR2nc: ; Now move right a pixel...\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_SLR3nc ; don't move down if carry not set\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLR3nc:\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+ JMP s @DL_SLRLoop ; loop till done\r
+\r
+@DL_SLRExit:\r
+ JMP @DL_EXIT2 ; and exit\r
+\r
+ ; Draw a Steep line to the Right in Mode X\r
+\r
+@DL_SteepRight:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ XCHG DX, CX ; Delta_Y switched with Delta_X\r
+ DIV CX ; divide by Delta_Y\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add Fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_Y so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
+\r
+@STRLoop:\r
+ MOV ES:[DI], AH ; set first pixel, mask is set up\r
+ LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @STRnc2 ; if no carry then just go down...\r
+\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@STRnc2:\r
+ ADD DI, BP ; advance to next line.\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @STRnc3 ; if no carry then just go down...\r
+\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@STRnc3:\r
+ ADD DI, BP ; advance to next line.\r
+ JMP s @STRLoop ; loop till done\r
+\r
+@DL_EXIT2:\r
+ ;POPx DI, SI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop bp\r
+ RET 10 ; Exit and Clean up Stack\r
+\r
+DRAW_LINE ENDP\r
+\r
+\r
+ ; ===== DAC COLOR REGISTER ROUTINES =====\r
+\r
+;=================================================\r
+;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
+;=================================================\r
+;\r
+; Sets a single (RGB) Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to modify (0-255)\r
+; Red = The new Red Intensity (0-63)\r
+; Green = The new Green Intensity (0-63)\r
+; Blue = The new Blue Intensity (0-63)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SDR_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SDR_Blue DB ?,? ; Blue Data Value\r
+ SDR_Green DB ?,? ; Green Data Value\r
+ SDR_Red DB ?,? ; Red Data Value\r
+ SDR_Register DB ?,? ; Palette Register #\r
+SDR_STACK ENDS\r
+\r
+ PUBLIC SET_DAC_REGISTER\r
+\r
+SET_DAC_REGISTER PROC FAR\r
+\r
+ PUSH BP ; Save BP\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Select which DAC Register to modify\r
+\r
+ OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register\r
+\r
+ MOV DX, PEL_DATA_REG ; Dac Data Register\r
+ OUT_8 DX, [BP].SDR_Red ; Set Red Intensity\r
+ OUT_8 DX, [BP].SDR_Green ; Set Green Intensity\r
+ OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity\r
+\r
+ POP BP ; Restore Registers\r
+ RET 8 ; Exit & Clean Up Stack\r
+\r
+SET_DAC_REGISTER ENDP\r
+\r
+;====================================================\r
+;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
+;====================================================\r
+;\r
+; Reads the RGB Values of a single Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to read (0-255)\r
+; Red = Offset to Red Variable in DS\r
+; Green = Offset to Green Variable in DS\r
+; Blue = Offset to Blue Variable in DS\r
+;\r
+; EXIT: The values of the integer variables Red,\r
+; Green, and Blue are set to the values\r
+; taken from the specified DAC register.\r
+;\r
+\r
+GDR_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ GDR_Blue DW ? ; Addr of Blue Data Value in DS\r
+ GDR_Green DW ? ; Addr of Green Data Value in DS\r
+ GDR_Red DW ? ; Addr of Red Data Value in DS\r
+ GDR_Register DB ?,? ; Palette Register #\r
+GDR_STACK ENDS\r
+\r
+ PUBLIC GET_DAC_REGISTER\r
+\r
+GET_DAC_REGISTER PROC FAR\r
+\r
+ PUSH BP ; Save BP\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Select which DAC Register to read in\r
+\r
+ OUT_8 DAC_READ_ADDR, [BP].GDR_Register\r
+\r
+ MOV DX, PEL_DATA_REG ; Dac Data Register\r
+ mov ax,0 ; Clear AX\r
+\r
+ IN AL, DX ; Read Red Value\r
+ MOV BX, [BP].GDR_Red ; Get Address of Red%\r
+ MOV [BX], AX ; *Red% = AX\r
+\r
+ IN AL, DX ; Read Green Value\r
+ MOV BX, [BP].GDR_Green ; Get Address of Green%\r
+ MOV [BX], AX ; *Green% = AX\r
+\r
+ IN AL, DX ; Read Blue Value\r
+ MOV BX, [BP].GDR_Blue ; Get Address of Blue%\r
+ MOV [BX], AX ; *Blue% = AX\r
+\r
+ POP BP ; Restore Registers\r
+ RET 8 ; Exit & Clean Up Stack\r
+\r
+GET_DAC_REGISTER ENDP\r
+\r
+\r
+;===========================================================\r
+;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
+;===========================================================\r
+;\r
+; Sets a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData = Far Pointer to Block of palette data\r
+; StartReg = First Register # in range to set (0-255)\r
+; EndReg = Last Register # in Range to set (0-255)\r
+; Sync = Wait for Vertical Retrace Flag (Boolean)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+LDR_STACK STRUC\r
+ DW ?x1 ; BP, DS, SI\r
+ DW ?x1 ; BP, DS, SI\r
+ DW ?x1 ; BP, DS, SI\r
+ DD ? ; Caller\r
+ LDR_Sync DW ? ; Vertical Sync Flag\r
+ LDR_EndReg DB ?,? ; Last Register #\r
+ LDR_StartReg DB ?,? ; First Register #\r
+ LDR_PalData DD ? ; Far Ptr to Palette Data\r
+LDR_STACK ENDS\r
+\r
+ PUBLIC LOAD_DAC_REGISTERS\r
+\r
+LOAD_DAC_REGISTERS PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI ; Save Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag\r
+ or AX, AX ; is Sync Flag = 0?\r
+ jz @LDR_Load ; if so, skip call\r
+\r
+ call f SYNC_DISPLAY ; wait for vsync\r
+\r
+ ; Determine register #'s, size to copy, etc\r
+\r
+@LDR_Load:\r
+\r
+ lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data\r
+ mov DX, DAC_WRITE_ADDR ; DAC register # selector\r
+\r
+ mov ax,0, BX ; Clear for byte loads\r
+ mov AL, [BP].LDR_StartReg ; Get Start Register\r
+ mov BL, [BP].LDR_EndReg ; Get End Register\r
+\r
+ sub BX, AX ; BX = # of DAC registers -1\r
+ inc BX ; BX = # of DAC registers\r
+ mov CX, BX ; CX = # of DAC registers\r
+ add CX, BX ; CX = " " * 2\r
+ add CX, BX ; CX = " " * 3\r
+ cld ; Block OUTs forward\r
+ out DX, AL ; set up correct register #\r
+\r
+ ; Load a block of DAC Registers\r
+\r
+ mov DX, PEL_DATA_REG ; Dac Data Register\r
+\r
+ ;rep outsb ; block set DAC registers\r
+\r
+ ;POPx SI, DS, BP ; Restore Registers\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 10 ; Exit & Clean Up Stack\r
+\r
+LOAD_DAC_REGISTERS ENDP\r
+\r
+\r
+;====================================================\r
+;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
+;====================================================\r
+;\r
+; Reads a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData = Far Pointer to block to store palette data\r
+; StartReg = First Register # in range to read (0-255)\r
+; EndReg = Last Register # in Range to read (0-255)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+RDR_STACK STRUC\r
+ DW ?x1 ; BP, ES, DI\r
+ DW ?x1 ; BP, ES, DI\r
+ DW ?x1 ; BP, ES, DI\r
+ DD ? ; Caller\r
+ RDR_EndReg DB ?,? ; Last Register #\r
+ RDR_StartReg DB ?,? ; First Register #\r
+ RDR_PalData DD ? ; Far Ptr to Palette Data\r
+RDR_STACK ENDS\r
+\r
+ PUBLIC READ_DAC_REGISTERS\r
+\r
+READ_DAC_REGISTERS PROC FAR\r
+\r
+ ;PUSHx BP, ES, DI ; Save Registers\r
+ push bp\r
+ push es\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ ; Determine register #'s, size to copy, etc\r
+\r
+ les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer\r
+ mov DX, DAC_READ_ADDR ; DAC register # selector\r
+\r
+ mov ax,0, BX ; Clear for byte loads\r
+ mov AL, [BP].RDR_StartReg ; Get Start Register\r
+ mov BL, [BP].RDR_EndReg ; Get End Register\r
+\r
+ sub BX, AX ; BX = # of DAC registers -1\r
+ inc BX ; BX = # of DAC registers\r
+ mov CX, BX ; CX = # of DAC registers\r
+ add CX, BX ; CX = " " * 2\r
+ add CX, BX ; CX = " " * 3\r
+ cld ; Block INs forward\r
+\r
+ ; Read a block of DAC Registers\r
+\r
+ out DX, AL ; set up correct register #\r
+ mov DX, PEL_DATA_REG ; Dac Data Register\r
+\r
+ ;rep insb ; block read DAC registers\r
+\r
+ ;POPx DI, ES, BP ; Restore Registers\r
+ pop di\r
+ pop es\r
+ pop bp\r
+ ret 8 ; Exit & Clean Up Stack\r
+\r
+READ_DAC_REGISTERS ENDP\r
+\r
+\r
+ ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+\r
+;=========================\r
+;SET_ACTIVE_PAGE (PageNo%)\r
+;=========================\r
+;\r
+; Sets the active display Page to be used for future drawing\r
+;\r
+; ENTRY: PageNo = Display Page to make active\r
+; (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SAP_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SAP_Page DW ? ; Page # for Drawing\r
+SAP_STACK ENDS\r
+\r
+ PUBLIC SET_ACTIVE_PAGE\r
+\r
+SET_ACTIVE_PAGE PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ MOV BX, [BP].SAP_Page ; Get Desired Page #\r
+ CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ JAE @SAP_Exit ; IF Not, Do Nothing\r
+\r
+ MOV ACTIVE_PAGE, BX ; Set Active Page #\r
+\r
+ SHL BX, 1 ; Scale Page # to Word\r
+ MOV AX, PAGE_ADDR[BX] ; Get offset to Page\r
+\r
+ MOV CURRENT_PAGE, AX ; And set for future LES's\r
+\r
+@SAP_Exit:\r
+ POP BP ; Restore Registers\r
+ RET 2 ; Exit and Clean up Stack\r
+\r
+SET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;================\r
+;GET_ACTIVE_PAGE%\r
+;================\r
+;\r
+; Returns the Video Page # currently used for Drawing\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Video Page used for Drawing\r
+;\r
+\r
+ PUBLIC GET_ACTIVE_PAGE\r
+\r
+GET_ACTIVE_PAGE PROC FAR\r
+\r
+ MOV AX, ACTIVE_PAGE ; Get Active Page #\r
+ RET ; Exit and Clean up Stack\r
+\r
+GET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;===============================\r
+;SET_DISPLAY_PAGE (DisplayPage%)\r
+;===============================\r
+;\r
+; Sets the currently visible display page.\r
+; When called this routine syncronizes the display\r
+; to the vertical blank.\r
+;\r
+; ENTRY: PageNo = Display Page to show on the screen\r
+; (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SDP_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SDP_Page DW ? ; Page # to Display...\r
+SDP_STACK ENDS\r
+\r
+ PUBLIC SET_DISPLAY_PAGE\r
+\r
+SET_DISPLAY_PAGE PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ MOV BX, [BP].SDP_Page ; Get Desired Page #\r
+ CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ JAE @SDP_Exit ; IF Not, Do Nothing\r
+\r
+ MOV DISPLAY_PAGE, BX ; Set Display Page #\r
+\r
+ SHL BX, 1 ; Scale Page # to Word\r
+ MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page\r
+ ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
+\r
+ ; Wait if we are currently in a Vertical Retrace\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+@DP_WAIT0:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; In Display mode yet?\r
+ JNZ @DP_WAIT0 ; If Not, wait for it\r
+\r
+ ; Set the Start Display Address to the new page\r
+\r
+ MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
+\r
+ MOV AL, START_DISP_LO ; Display Start Low Register\r
+ MOV AH, CL ; Low 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr Low\r
+\r
+ MOV AL, START_DISP_HI ; Display Start High Register\r
+ MOV AH, CH ; High 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr High\r
+\r
+ ; Wait for a Vertical Retrace to smooth out things\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+@DP_WAIT1:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ JZ @DP_WAIT1 ; If Not, wait for it\r
+\r
+ ; Now Set Display Starting Address\r
+\r
+\r
+@SDP_Exit:\r
+ POP BP ; Restore Registers\r
+ RET 2 ; Exit and Clean up Stack\r
+\r
+SET_DISPLAY_PAGE ENDP\r
+\r
+\r
+;=================\r
+;GET_DISPLAY_PAGE%\r
+;=================\r
+;\r
+; Returns the Video Page # currently displayed\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Video Page being displayed\r
+;\r
+\r
+ PUBLIC GET_DISPLAY_PAGE\r
+\r
+GET_DISPLAY_PAGE PROC FAR\r
+\r
+ MOV AX, DISPLAY_PAGE ; Get Display Page #\r
+ RET ; Exit & Clean Up Stack\r
+\r
+GET_DISPLAY_PAGE ENDP\r
+\r
+\r
+;=======================================\r
+;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
+;=======================================\r
+;\r
+; Since a Logical Screen can be larger than the Physical\r
+; Screen, Scrolling is possible. This routine sets the\r
+; Upper Left Corner of the Screen to the specified Pixel.\r
+; Also Sets the Display page to simplify combined page\r
+; flipping and scrolling. When called this routine\r
+; syncronizes the display to the vertical blank.\r
+;\r
+; ENTRY: DisplayPage = Display Page to show on the screen\r
+; Xpos = # of pixels to shift screen right\r
+; Ypos = # of lines to shift screen down\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SW_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SW_Ypos DW ? ; Y pos of UL Screen Corner\r
+ SW_Xpos DW ? ; X pos of UL Screen Corner\r
+ SW_Page DW ? ; (new) Display Page\r
+SW_STACK ENDS\r
+\r
+ PUBLIC SET_WINDOW\r
+\r
+SET_WINDOW PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Check if our Scroll Offsets are Valid\r
+\r
+ MOV BX, [BP].SW_Page ; Get Desired Page #\r
+ CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ JAE @SW_Exit ; IF Not, Do Nothing\r
+\r
+ MOV AX, [BP].SW_Ypos ; Get Desired Y Offset\r
+ CMP AX, MAX_YOFFSET ; Is it Within Limits?\r
+ JA @SW_Exit ; if not, exit\r
+\r
+ MOV CX, [BP].SW_Xpos ; Get Desired X Offset\r
+ CMP CX, MAX_XOFFSET ; Is it Within Limits?\r
+ JA @SW_Exit ; if not, exit\r
+\r
+ ; Compute proper Display start address to use\r
+\r
+ MUL SCREEN_WIDTH ; AX = YOffset * Line Width\r
+ SHR CX, 1 ; CX / 4 = Bytes into Line\r
+ SHR CX, 1 ; CX / 4 = Bytes into Line\r
+ ADD AX, CX ; AX = Offset of Upper Left Pixel\r
+\r
+ MOV CURRENT_MOFFSET, AX ; Save Offset Info\r
+\r
+ MOV DISPLAY_PAGE, BX ; Set Current Page #\r
+ SHL BX, 1 ; Scale Page # to Word\r
+ ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page\r
+ MOV BX, AX ; BX = Desired Display Start\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+ ; Wait if we are currently in a Vertical Retrace\r
+\r
+@SW_WAIT0:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; In Display mode yet?\r
+ JNZ @SW_WAIT0 ; If Not, wait for it\r
+\r
+ ; Set the Start Display Address to the new window\r
+\r
+ MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
+ MOV AL, START_DISP_LO ; Display Start Low Register\r
+ MOV AH, BL ; Low 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr Low\r
+\r
+ MOV AL, START_DISP_HI ; Display Start High Register\r
+ MOV AH, BH ; High 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr High\r
+\r
+ ; Wait for a Vertical Retrace to smooth out things\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+@SW_WAIT1:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ JZ @SW_WAIT1 ; If Not, wait for it\r
+\r
+ ; Now Set the Horizontal Pixel Pan values\r
+\r
+ OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register\r
+\r
+ MOV AX, [BP].SW_Xpos ; Get Desired X Offset\r
+ AND AL, 03 ; Get # of Pixels to Pan (0-3)\r
+ SHL AL, 1 ; Shift for 256 Color Mode\r
+ OUT DX, AL ; Fine tune the display!\r
+\r
+@SW_Exit:\r
+ POP BP ; Restore Saved Registers\r
+ RET 6 ; Exit and Clean up Stack\r
+\r
+SET_WINDOW ENDP\r
+\r
+\r
+;=============\r
+;GET_X_OFFSET%\r
+;=============\r
+;\r
+; Returns the X coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Horizontal Scroll Offset\r
+;\r
+\r
+ PUBLIC GET_X_OFFSET\r
+\r
+GET_X_OFFSET PROC FAR\r
+\r
+ MOV AX, CURRENT_XOFFSET ; Get current horz offset\r
+ RET ; Exit & Clean Up Stack\r
+\r
+GET_X_OFFSET ENDP\r
+\r
+\r
+;=============\r
+;GET_Y_OFFSET%\r
+;=============\r
+;\r
+; Returns the Y coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Vertical Scroll Offset\r
+;\r
+\r
+ PUBLIC GET_Y_OFFSET\r
+\r
+GET_Y_OFFSET PROC FAR\r
+\r
+ MOV AX, CURRENT_YOFFSET ; Get current vertical offset\r
+ RET ; Exit & Clean Up Stack\r
+\r
+GET_Y_OFFSET ENDP\r
+\r
+\r
+;============\r
+;SYNC_DISPLAY\r
+;============\r
+;\r
+; Pauses the computer until the next Vertical Retrace starts\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+ PUBLIC SYNC_DISPLAY\r
+\r
+SYNC_DISPLAY PROC FAR\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+ ; Wait for any current retrace to end\r
+\r
+@SD_WAIT0:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; In Display mode yet?\r
+ JNZ @SD_WAIT0 ; If Not, wait for it\r
+\r
+ ; Wait for the start of the next vertical retrace\r
+\r
+@SD_WAIT1:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ JZ @SD_WAIT1 ; If Not, wait for it\r
+\r
+ RET ; Exit & Clean Up Stack\r
+\r
+SYNC_DISPLAY ENDP\r
+\r
+\r
+ ; ===== TEXT DISPLAY ROUTINES =====\r
+\r
+;==================================================\r
+;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;==================================================\r
+;\r
+; Draws an ASCII Text Character using the currently selected\r
+; 8x8 font on the active display page. It would be a simple\r
+; exercise to make this routine process variable height fonts.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+; Xpos = X position to draw Character at\r
+; Ypos = Y position of to draw Character at\r
+; ColorF = Color to draw text character in\r
+; ColorB = Color to set background to\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+GPC_STACK STRUC\r
+ GPC_Width DW ? ; Screen Width-1\r
+ GPC_Lines DB ?,? ; Scan lines to Decode\r
+ GPC_T_SETS DW ? ; Saved Charset Segment\r
+ GPC_T_SETO DW ? ; Saved Charset Offset\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ GPC_ColorB DB ?,? ; Background Color\r
+ GPC_ColorF DB ?,? ; Text Color\r
+ GPC_Ypos DW ? ; Y Position to Print at\r
+ GPC_Xpos DW ? ; X position to Print at\r
+ GPC_Char DB ?,? ; Character to Print\r
+GPC_STACK ENDS\r
+\r
+ PUBLIC GPRINTC\r
+\r
+GPRINTC PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 8 ; Allocate WorkSpace on Stack\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
+ MOV BX, AX ; BX = Screen Width\r
+ DEC BX ; = Screen Width-1\r
+ MOV [BP].GPC_Width, BX ; Save for later use\r
+\r
+ MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width\r
+ ADD DI, AX ; DI -> Start of Line Ypos\r
+\r
+ MOV AX, [BP].GPC_Xpos ; Get Xpos of Character\r
+ MOV CX, AX ; Save Copy of Xpos\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ ADD DI, AX ; DI -> (Xpos, Ypos)\r
+\r
+ ;Get Source ADDR of Character Bit Map & Save\r
+\r
+ MOV AL, [BP].GPC_Char ; Get Character #\r
+ TEST AL, 080h ; Is Hi Bit Set?\r
+ JZ @GPC_LowChar ; Nope, use low char set ptr\r
+\r
+ AND AL, 07Fh ; Mask Out Hi Bit\r
+ MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
+ JMP s @GPC_Set_Char ; Go Setup Character Ptr\r
+\r
+@GPC_LowChar:\r
+\r
+ MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
+\r
+@GPC_Set_Char:\r
+ MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
+\r
+ MOV AH, 0 ; Valid #'s are 0..127\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ ADD BX, AX ; BX = Offset of Selected char\r
+ MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
+\r
+ AND CX, PLANE_BITS ; Get Plane #\r
+ MOV CH, ALL_PLANES ; Get Initial Plane mask\r
+ SHL CH, CL ; And shift into position\r
+ AND CH, ALL_PLANES ; And mask to lower nibble\r
+\r
+ MOV AL, 04 ; 4-Plane # = # of initial\r
+ SUB AL, CL ; shifts to align bit mask\r
+ MOV CL, AL ; Shift Count for SHL\r
+\r
+ ;Get segment of character map\r
+\r
+ OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
+ INC DX ; DX -> SC_Data\r
+\r
+ MOV AL, 08 ; 8 Lines to Process\r
+ MOV [BP].GPC_Lines, AL ; Save on Stack\r
+\r
+ MOV DS, [BP].GPC_T_SETS ; Point to character set\r
+\r
+@GPC_DECODE_CHAR_BYTE:\r
+\r
+ MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
+\r
+ MOV BH, [SI] ; Get Bit Map\r
+ INC SI ; Point to Next Line\r
+ MOV [BP].GPC_T_SETO, SI ; And save new Pointer...\r
+\r
+ mov ax,0 ; Clear AX\r
+\r
+ ;mov bl,0 ; Clear BL\r
+ mov bl,0\r
+ ROL BX, CL ; BL holds left edge bits\r
+ MOV SI, BX ; Use as Table Index\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set\r
+\r
+ MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_LEFT1BITS:\r
+ XOR AL, CH ; Invert mask for Background\r
+ JZ @GPC_NO_LEFT0BITS ; Hey, no need for this\r
+\r
+ MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+ ;Now Do Middle/Last Band\r
+\r
+@GPC_NO_LEFT0BITS:\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set\r
+\r
+ MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE1BITS:\r
+ XOR AL, ALL_PLANES ; Invert mask for Background\r
+ JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
+\r
+ MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE0BITS:\r
+ XOR CH, ALL_PLANES ; Invert Clip Mask\r
+ CMP CL, 4 ; Aligned by 4?\r
+ JZ @GPC_NEXT_LINE ; If so, Exit now..\r
+\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set\r
+\r
+ MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT1BITS:\r
+\r
+ XOR AL, CH ; Invert mask for Background\r
+ JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this\r
+\r
+ MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT0BITS:\r
+ DEC DI ; Adjust for Next Line Advance\r
+\r
+@GPC_NEXT_LINE:\r
+ ADD DI, [BP].GPC_Width ; Point to Next Line\r
+ XOR CH, CHAR_BITS ; Flip the Clip mask back\r
+\r
+ DEC [BP].GPC_Lines ; Count Down Lines\r
+ JZ @GPC_EXIT ; Ok... Done!\r
+\r
+ JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey!\r
+\r
+@GPC_EXIT:\r
+ ADD SP, 08 ; Deallocate stack workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 10 ; Exit and Clean up Stack\r
+\r
+GPRINTC ENDP\r
+\r
+\r
+;==========================================\r
+;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
+;==========================================\r
+;\r
+; Transparently draws an ASCII Text Character using the\r
+; currently selected 8x8 font on the active display page.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+; Xpos = X position to draw Character at\r
+; Ypos = Y position of to draw Character at\r
+; ColorF = Color to draw text character in\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+TGP_STACK STRUC\r
+ TGP_Width DW ? ; Screen Width-1\r
+ TGP_Lines DB ?,? ; Scan lines to Decode\r
+ TGP_T_SETS DW ? ; Saved Charset Segment\r
+ TGP_T_SETO DW ? ; Saved Charset Offset\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ TGP_ColorF DB ?,? ; Text Color\r
+ TGP_Ypos DW ? ; Y Position to Print at\r
+ TGP_Xpos DW ? ; X position to Print at\r
+ TGP_Char DB ?,? ; Character to Print\r
+TGP_STACK ENDS\r
+\r
+ PUBLIC TGPRINTC\r
+\r
+TGPRINTC PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 8 ; Allocate WorkSpace on Stack\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
+ MOV BX, AX ; BX = Screen Width\r
+ DEC BX ; = Screen Width-1\r
+ MOV [BP].TGP_Width, BX ; Save for later use\r
+\r
+ MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width\r
+ ADD DI, AX ; DI -> Start of Line Ypos\r
+\r
+ MOV AX, [BP].TGP_Xpos ; Get Xpos of Character\r
+ MOV CX, AX ; Save Copy of Xpos\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ ADD DI, AX ; DI -> (Xpos, Ypos)\r
+\r
+ ;Get Source ADDR of Character Bit Map & Save\r
+\r
+ MOV AL, [BP].TGP_Char ; Get Character #\r
+ TEST AL, 080h ; Is Hi Bit Set?\r
+ JZ @TGP_LowChar ; Nope, use low char set ptr\r
+\r
+ AND AL, 07Fh ; Mask Out Hi Bit\r
+ MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
+ JMP s @TGP_Set_Char ; Go Setup Character Ptr\r
+\r
+@TGP_LowChar:\r
+\r
+ MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
+\r
+@TGP_Set_Char:\r
+ MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
+\r
+ MOV AH, 0 ; Valid #'s are 0..127\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ ADD BX, AX ; BX = Offset of Selected char\r
+ MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
+\r
+ AND CX, PLANE_BITS ; Get Plane #\r
+ MOV CH, ALL_PLANES ; Get Initial Plane mask\r
+ SHL CH, CL ; And shift into position\r
+ AND CH, ALL_PLANES ; And mask to lower nibble\r
+\r
+ MOV AL, 04 ; 4-Plane # = # of initial\r
+ SUB AL, CL ; shifts to align bit mask\r
+ MOV CL, AL ; Shift Count for SHL\r
+\r
+ ;Get segment of character map\r
+\r
+ OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
+ INC DX ; DX -> SC_Data\r
+\r
+ MOV AL, 08 ; 8 Lines to Process\r
+ MOV [BP].TGP_Lines, AL ; Save on Stack\r
+\r
+ MOV DS, [BP].TGP_T_SETS ; Point to character set\r
+\r
+@TGP_DECODE_CHAR_BYTE:\r
+\r
+ MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
+\r
+ MOV BH, [SI] ; Get Bit Map\r
+ INC SI ; Point to Next Line\r
+ MOV [BP].TGP_T_SETO, SI ; And save new Pointer...\r
+\r
+ MOV AH, [BP].TGP_ColorF ; Get Foreground Color\r
+\r
+ mov bl,0 ; Clear BL\r
+ ROL BX, CL ; BL holds left edge bits\r
+ MOV SI, BX ; Use as Table Index\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set\r
+\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+ ;Now Do Middle/Last Band\r
+\r
+@TGP_NO_LEFT1BITS:\r
+\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set\r
+\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@TGP_NO_MIDDLE1BITS:\r
+ XOR CH, ALL_PLANES ; Invert Clip Mask\r
+ CMP CL, 4 ; Aligned by 4?\r
+ JZ @TGP_NEXT_LINE ; If so, Exit now..\r
+\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set\r
+\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@TGP_NO_RIGHT1BITS:\r
+\r
+ DEC DI ; Adjust for Next Line Advance\r
+\r
+@TGP_NEXT_LINE:\r
+ ADD DI, [BP].TGP_Width ; Point to Next Line\r
+ XOR CH, CHAR_BITS ; Flip the Clip mask back\r
+\r
+ DEC [BP].TGP_Lines ; Count Down Lines\r
+ JZ @TGP_EXIT ; Ok... Done!\r
+\r
+ JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey!\r
+\r
+@TGP_EXIT:\r
+ ADD SP, 08 ; Deallocate stack workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 8 ; Exit and Clean up Stack\r
+\r
+TGPRINTC ENDP\r
+\r
+\r
+;===============================================================\r
+;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;===============================================================\r
+;\r
+; Routine to quickly Print a null terminated ASCII string on the\r
+; active display page up to a maximum length.\r
+;\r
+; ENTRY: String = Far Pointer to ASCII string to print\r
+; MaxLen = # of characters to print if no null found\r
+; Xpos = X position to draw Text at\r
+; Ypos = Y position of to draw Text at\r
+; ColorF = Color to draw text in\r
+; ColorB = Color to set background to\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+PS_STACK STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ PS_ColorB DW ? ; Background Color\r
+ PS_ColorF DW ? ; Text Color\r
+ PS_Ypos DW ? ; Y Position to Print at\r
+ PS_Xpos DW ? ; X position to Print at\r
+ PS_Len DW ? ; Maximum Length of string to print\r
+ PS_Text DW ?,? ; Far Ptr to Text String\r
+PS_STACK ENDS\r
+\r
+ PUBLIC PRINT_STR\r
+\r
+PRINT_STR PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+@PS_Print_It:\r
+\r
+ MOV CX, [BP].PS_Len ; Get Remaining text Length\r
+ JCXZ @PS_Exit ; Exit when out of text\r
+\r
+ LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text\r
+ MOV AL, ES:[DI] ; AL = Text Character\r
+ AND AX, 00FFh ; Clear High Word\r
+ JZ @PS_Exit ; Exit if null character\r
+\r
+ DEC [BP].PS_Len ; Remaining Text length--\r
+ INC [BP].PS_Text ; Point to Next text char\r
+\r
+ ; Set up Call to GPRINTC\r
+\r
+ PUSH AX ; Set Character Parameter\r
+ MOV BX, [BP].PS_Xpos ; Get Xpos\r
+ PUSH BX ; Set Xpos Parameter\r
+ ADD BX, 8 ; Advance 1 Char to Right\r
+ MOV [BP].PS_Xpos, BX ; Save for next time through\r
+\r
+ MOV BX, [BP].PS_Ypos ; Get Ypos\r
+ PUSH BX ; Set Ypos Parameter\r
+\r
+ MOV BX, [BP].PS_ColorF ; Get Text Color\r
+ PUSH BX ; Set ColorF Parameter\r
+\r
+ MOV BX, [BP].PS_ColorB ; Get Background Color\r
+ PUSH BX ; Set ColorB Parameter\r
+\r
+ CALL f GPRINTC ; Print Character!\r
+ JMP s @PS_Print_It ; Process next character\r
+\r
+@PS_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 14 ; Exit and Clean up Stack\r
+\r
+PRINT_STR ENDP\r
+\r
+\r
+;================================================================\r
+;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;================================================================\r
+;\r
+; Routine to quickly transparently Print a null terminated ASCII\r
+; string on the active display page up to a maximum length.\r
+;\r
+; ENTRY: String = Far Pointer to ASCII string to print\r
+; MaxLen = # of characters to print if no null found\r
+; Xpos = X position to draw Text at\r
+; Ypos = Y position of to draw Text at\r
+; ColorF = Color to draw text in\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+TPS_STACK STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ TPS_ColorF DW ? ; Text Color\r
+ TPS_Ypos DW ? ; Y Position to Print at\r
+ TPS_Xpos DW ? ; X position to Print at\r
+ TPS_Len DW ? ; Maximum Length of string to print\r
+ TPS_Text DW ?,? ; Far Ptr to Text String\r
+TPS_STACK ENDS\r
+\r
+ PUBLIC TPRINT_STR\r
+\r
+TPRINT_STR PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+@TPS_Print_It:\r
+\r
+ MOV CX, [BP].TPS_Len ; Get Remaining text Length\r
+ JCXZ @TPS_Exit ; Exit when out of text\r
+\r
+ LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
+ MOV AL, ES:[DI] ; AL = Text Character\r
+ AND AX, 00FFh ; Clear High Word\r
+ JZ @TPS_Exit ; Exit if null character\r
+\r
+ DEC [BP].TPS_Len ; Remaining Text length--\r
+ INC [BP].TPS_Text ; Point to Next text char\r
+\r
+ ; Set up Call to TGPRINTC\r
+\r
+ PUSH AX ; Set Character Parameter\r
+ MOV BX, [BP].TPS_Xpos ; Get Xpos\r
+ PUSH BX ; Set Xpos Parameter\r
+ ADD BX, 8 ; Advance 1 Char to Right\r
+ MOV [BP].TPS_Xpos, BX ; Save for next time through\r
+\r
+ MOV BX, [BP].TPS_Ypos ; Get Ypos\r
+ PUSH BX ; Set Ypos Parameter\r
+\r
+ MOV BX, [BP].TPS_ColorF ; Get Text Color\r
+ PUSH BX ; Set ColorF Parameter\r
+\r
+ CALL f TGPRINTC ; Print Character!\r
+ JMP s @TPS_Print_It ; Process next character\r
+\r
+@TPS_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 12 ; Exit and Clean up Stack\r
+\r
+TPRINT_STR ENDP\r
+\r
+\r
+;===========================================\r
+;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
+;===========================================\r
+;\r
+; Allows the user to specify their own font data for\r
+; wither the lower or upper 128 characters.\r
+;\r
+; ENTRY: FontData = Far Pointer to Font Bitmaps\r
+; FontNumber = Which half of set this is\r
+; = 0, Lower 128 characters\r
+; = 1, Upper 128 characters\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SDF_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SDF_Which DW ? ; Hi Table/Low Table Flag\r
+ SDF_Font DD ? ; Far Ptr to Font Table\r
+SDF_STACK ENDS\r
+\r
+ PUBLIC SET_DISPLAY_FONT\r
+\r
+SET_DISPLAY_FONT PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, [BP].SDF_Font ; Get Far Ptr to Font\r
+\r
+ MOV SI, o CHARSET_LOW ; Assume Lower 128 chars\r
+ TEST [BP].SDF_Which, 1 ; Font #1 selected?\r
+ JZ @SDF_Set_Font ; If not, skip ahead\r
+\r
+ MOV SI, o CHARSET_HI ; Ah, really it's 128-255\r
+\r
+@SDF_Set_Font:\r
+ MOV [SI], DI ; Set Font Pointer Offset\r
+ MOV [SI+2], ES ; Set Font Pointer Segment\r
+\r
+ POP BP ; Restore Registers\r
+ RET 6 ; We are Done.. Outa here\r
+\r
+SET_DISPLAY_FONT ENDP\r
+\r
+\r
+ ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+\r
+;======================================================\r
+;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;======================================================\r
+;\r
+; Draws a variable sized Graphics Bitmap such as a\r
+; picture or an Icon on the current Display Page in\r
+; Mode X. The Bitmap is stored in a linear byte array\r
+; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
+; This is the same linear manner as mode 13h graphics.\r
+;\r
+; ENTRY: Image = Far Pointer to Bitmap Data\r
+; Xpos = X position to Place Upper Left pixel at\r
+; Ypos = Y position to Place Upper Left pixel at\r
+; Width = Width of the Bitmap in Pixels\r
+; Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+DB_STACK STRUC\r
+ DB_LineO DW ? ; Offset to Next Line\r
+ DB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
+ DB_Start DW ? ; Addr of Upper Left Pixel\r
+ DB_PixSkew DW ? ; # of bytes to Adjust EOL\r
+ DB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ DB_Height DW ? ; Height of Bitmap in Pixels\r
+ DB_Width DW ? ; Width of Bitmap in Pixels\r
+ DB_Ypos DW ? ; Y position to Draw Bitmap at\r
+ DB_Xpos DW ? ; X position to Draw Bitmap at\r
+ DB_Image DD ? ; Far Pointer to Graphics Bitmap\r
+DB_STACK ENDS\r
+\r
+ PUBLIC DRAW_BITMAP\r
+\r
+DRAW_BITMAP PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 10 ; Allocate workspace\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ CLD ; Direction Flag = Forward\r
+\r
+ MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
+\r
+ MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos\r
+ MOV CL, BL ; Save Plane # in CL\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+\r
+ ADD DI, AX ; ES:DI -> Start of Line\r
+ ADD DI, BX ; ES:DI -> Upper Left Pixel\r
+ MOV [BP].DB_Start, DI ; Save Starting Addr\r
+\r
+ ; Compute line to line offset\r
+\r
+ MOV BX, [BP].DB_Width ; Get Width of Image\r
+ MOV DX, BX ; Save Copy in DX\r
+ SHR BX, 1 ; /4 = width in bands\r
+ SHR BX, 1 ; /4 = width in bands\r
+ MOV AX, SCREEN_WIDTH ; Get Screen Width\r
+ SUB AX, BX ; - (Bitmap Width/4)\r
+\r
+ MOV [BP].DB_LineO, AX ; Save Line Width offset\r
+ MOV [BP].DB_PixCount, BX ; Minimum # pix to copy\r
+\r
+ AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
+ MOV [BP].DB_PixSkew, DX ; Also End of Line Skew\r
+ MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count\r
+\r
+ AND CX, PLANE_BITS ; CL = Starting Plane #\r
+ MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ SHL AH, CL ; Select correct Plane\r
+ OUT_16 SC_Index, AX ; Select Plane...\r
+ MOV BH, AH ; BH = Saved Plane Mask\r
+ MOV BL, 4 ; BL = Planes to Copy\r
+\r
+@DB_COPY_PLANE:\r
+\r
+ LDS SI, [BP].DB_Image ; DS:SI-> Source Image\r
+ MOV DX, [BP].DB_Height ; # of Lines to Copy\r
+ MOV DI, [BP].DB_Start ; ES:DI-> Dest pos\r
+\r
+@DB_COPY_LINE:\r
+ MOV CX, [BP].DB_PixCount ; Min # to copy\r
+\r
+ TEST CL, 0FCh ; 16+PixWide?\r
+ JZ @DB_COPY_REMAINDER ; Nope...\r
+\r
+ ; Pixel Copy loop has been unrolled to x4\r
+\r
+@DB_COPY_LOOP:\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+\r
+ SUB CL, 4 ; Pixels to Copy=-4\r
+ TEST CL, 0FCh ; 4+ Pixels Left?\r
+ JNZ @DB_COPY_LOOP ; if so, do another block\r
+\r
+@DB_COPY_REMAINDER:\r
+ JCXZ @DB_NEXT_LINE ; Any Pixels left on line\r
+\r
+@DB_COPY2:\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI,3 ; Skip to Next Byte in same plane\r
+ LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done\r
+\r
+@DB_NEXT_LINE:\r
+\r
+ ; any Partial Pixels? (some planes only)\r
+\r
+ OR CX, [BP].DB_SkewFlag ; Get Skew Count\r
+ JZ @DB_NEXT2 ; if no partial pixels\r
+\r
+ MOVSB ; Copy Bitmap Pixel\r
+ DEC DI ; Back up to align\r
+ DEC SI ; Back up to align\r
+\r
+@DB_NEXT2:\r
+ ADD SI, [BP].DB_PixSkew ; Adjust Skew\r
+ ADD DI, [BP].DB_LineO ; Set to Next Display Line\r
+ LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more\r
+\r
+ ; Copy Next Plane....\r
+\r
+ DEC BL ; Planes to Go--\r
+ JZ @DB_Exit ; Hey! We are done\r
+\r
+ ROL BH, 1 ; Next Plane in line...\r
+ OUT_8 SC_Data, BH ; Select Plane\r
+\r
+ CMP AL, 12h ; Carry Set if AL=11h\r
+ ADC [BP].DB_Start, 0 ; Screen Addr =+Carry\r
+ INC w [BP].DB_Image ; Start @ Next Byte\r
+\r
+ SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+ JMP s @DB_COPY_PLANE ; Go Copy the Next Plane\r
+\r
+@DB_Exit:\r
+ ADD SP, 10 ; Deallocate workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 12 ; Exit and Clean up Stack\r
+\r
+DRAW_BITMAP ENDP\r
+\r
+\r
+;=======================================================\r
+;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;=======================================================\r
+;\r
+; Transparently Draws a variable sized Graphics Bitmap\r
+; such as a picture or an Icon on the current Display Page\r
+; in Mode X. Pixels with a value of 0 are not drawn,\r
+; leaving the previous "background" contents intact.\r
+;\r
+; The Bitmap format is the same as for the DRAW_BITMAP function.\r
+;\r
+; ENTRY: Image = Far Pointer to Bitmap Data\r
+; Xpos = X position to Place Upper Left pixel at\r
+; Ypos = Y position to Place Upper Left pixel at\r
+; Width = Width of the Bitmap in Pixels\r
+; Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+TB_STACK STRUC\r
+ TB_LineO DW ? ; Offset to Next Line\r
+ TB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
+ TB_Start DW ? ; Addr of Upper Left Pixel\r
+ TB_PixSkew DW ? ; # of bytes to Adjust EOL\r
+ TB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ TB_Height DW ? ; Height of Bitmap in Pixels\r
+ TB_Width DW ? ; Width of Bitmap in Pixels\r
+ TB_Ypos DW ? ; Y position to Draw Bitmap at\r
+ TB_Xpos DW ? ; X position to Draw Bitmap at\r
+ TB_Image DD ? ; Far Pointer to Graphics Bitmap\r
+TB_STACK ENDS\r
+\r
+ PUBLIC TDRAW_BITMAP\r
+\r
+TDRAW_BITMAP PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 10 ; Allocate workspace\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ CLD ; Direction Flag = Forward\r
+\r
+ MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
+\r
+ MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos\r
+ MOV CL, BL ; Save Plane # in CL\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+\r
+ ADD DI, AX ; ES:DI -> Start of Line\r
+ ADD DI, BX ; ES:DI -> Upper Left Pixel\r
+ MOV [BP].TB_Start, DI ; Save Starting Addr\r
+\r
+ ; Compute line to line offset\r
+\r
+ MOV BX, [BP].TB_Width ; Get Width of Image\r
+ MOV DX, BX ; Save Copy in DX\r
+ SHR BX, 1 ; /4 = width in bands\r
+ SHR BX, 1 ; /4 = width in bands\r
+ MOV AX, SCREEN_WIDTH ; Get Screen Width\r
+ SUB AX, BX ; - (Bitmap Width/4)\r
+\r
+ MOV [BP].TB_LineO, AX ; Save Line Width offset\r
+ MOV [BP].TB_PixCount, BX ; Minimum # pix to copy\r
+\r
+ AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
+ MOV [BP].TB_PixSkew, DX ; Also End of Line Skew\r
+ MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count\r
+\r
+ AND CX, PLANE_BITS ; CL = Starting Plane #\r
+ MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ SHL AH, CL ; Select correct Plane\r
+ OUT_16 SC_Index, AX ; Select Plane...\r
+ MOV BH, AH ; BH = Saved Plane Mask\r
+ MOV BL, 4 ; BL = Planes to Copy\r
+\r
+@TB_COPY_PLANE:\r
+\r
+ LDS SI, [BP].TB_Image ; DS:SI-> Source Image\r
+ MOV DX, [BP].TB_Height ; # of Lines to Copy\r
+ MOV DI, [BP].TB_Start ; ES:DI-> Dest pos\r
+\r
+ ; Here AH is set with the value to be considered\r
+ ; "Transparent". It can be changed!\r
+\r
+ MOV AH, 0 ; Value to Detect 0\r
+\r
+@TB_COPY_LINE:\r
+ MOV CX, [BP].TB_PixCount ; Min # to copy\r
+\r
+ TEST CL, 0FCh ; 16+PixWide?\r
+ JZ @TB_COPY_REMAINDER ; Nope...\r
+\r
+ ; Pixel Copy loop has been unrolled to x4\r
+\r
+@TB_COPY_LOOP:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_01 ; Skip ahead if so\r
+ MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_01:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_02 ; Skip ahead if so\r
+ MOV ES:[DI+1], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_02:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_03 ; Skip ahead if so\r
+ MOV ES:[DI+2], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_03:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_04 ; Skip ahead if so\r
+ MOV ES:[DI+3], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_04:\r
+ ADD DI, 4 ; Adjust Pixel Write Location\r
+ SUB CL, 4 ; Pixels to Copy=-4\r
+ TEST CL, 0FCh ; 4+ Pixels Left?\r
+ JNZ @TB_COPY_LOOP ; if so, do another block\r
+\r
+@TB_COPY_REMAINDER:\r
+ JCXZ @TB_NEXT_LINE ; Any Pixels left on line\r
+\r
+@TB_COPY2:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_05 ; Skip ahead if so\r
+ MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_05:\r
+ INC DI ; Advance Dest Addr\r
+ LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done\r
+\r
+@TB_NEXT_LINE:\r
+\r
+ ; any Partial Pixels? (some planes only)\r
+\r
+ OR CX, [BP].TB_SkewFlag ; Get Skew Count\r
+ JZ @TB_NEXT2 ; if no partial pixels\r
+\r
+ LODSB ; Get Pixel Value in AL\r
+ DEC SI ; Backup to Align\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_NEXT2 ; Skip ahead if so\r
+ MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_NEXT2:\r
+ ADD SI, [BP].TB_PixSkew ; Adjust Skew\r
+ ADD DI, [BP].TB_LineO ; Set to Next Display Line\r
+ LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More\r
+\r
+ ;Copy Next Plane....\r
+\r
+ DEC BL ; Planes to Go--\r
+ JZ @TB_Exit ; Hey! We are done\r
+\r
+ ROL BH, 1 ; Next Plane in line...\r
+ OUT_8 SC_Data, BH ; Select Plane\r
+\r
+ CMP AL, 12h ; Carry Set if AL=11h\r
+ ADC [BP].TB_Start, 0 ; Screen Addr =+Carry\r
+ INC w [BP].TB_Image ; Start @ Next Byte\r
+\r
+ SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+ JMP @TB_COPY_PLANE ; Go Copy the next Plane\r
+\r
+@TB_Exit:\r
+ ADD SP, 10 ; Deallocate workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 12 ; Exit and Clean up Stack\r
+\r
+TDRAW_BITMAP ENDP\r
+\r
+\r
+ ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+\r
+;==================================\r
+;COPY_PAGE (SourcePage%, DestPage%)\r
+;==================================\r
+;\r
+; Duplicate on display page onto another\r
+;\r
+; ENTRY: SourcePage = Display Page # to Duplicate\r
+; DestPage = Display Page # to hold copy\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+CP_STACK STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ CP_DestP DW ? ; Page to hold copied image\r
+ CP_SourceP DW ? ; Page to Make copy from\r
+CP_STACK ENDS\r
+\r
+ PUBLIC COPY_PAGE\r
+\r
+COPY_PAGE PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+ CLD ; Block Xfer Forwards\r
+\r
+ ; Make sure Page #'s are valid\r
+\r
+ MOV AX, [BP].CP_SourceP ; Get Source Page #\r
+ CMP AX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CP_Exit ; if so, abort\r
+\r
+ MOV BX, [BP].CP_DestP ; Get Destination Page #\r
+ CMP BX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CP_Exit ; if so, abort\r
+\r
+ CMP AX, BX ; Pages #'s the same?\r
+ JE @CP_Exit ; if so, abort\r
+\r
+ ; Setup DS:SI and ES:DI to Video Pages\r
+\r
+ SHL BX, 1 ; Scale index to Word\r
+ MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page\r
+\r
+ MOV BX, AX ; Index to Source page\r
+ SHL BX, 1 ; Scale index to Word\r
+ MOV SI, PAGE_ADDR[BX] ; Offset to Source Page\r
+\r
+ MOV CX, PAGE_SIZE ; Get size of Page\r
+ MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
+ MOV ES, AX ; ES:DI -> Dest Page\r
+ MOV DS, AX ; DS:SI -> Source Page\r
+\r
+ ; Setup VGA registers for Mem to Mem copy\r
+\r
+ OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
+ OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes\r
+\r
+ ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
+ ; Screw with the latches which are 8 bits x 4\r
+\r
+ REP MOVSB ; Copy entire Page!\r
+\r
+ ; Reset VGA for normal memory access\r
+\r
+ OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off\r
+\r
+@CP_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 4 ; Exit and Clean up Stack\r
+\r
+COPY_PAGE ENDP\r
+\r
+\r
+;==========================================================================\r
+;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
+;==========================================================================\r
+;\r
+; Copies a Bitmap Image from one Display Page to Another\r
+; This Routine is Limited to copying Images with the same\r
+; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
+; Copying an Image to the Same Page is supported, but results\r
+; may be defined when the when the rectangular areas\r
+; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
+; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
+; No Paramter checking to done to insure that\r
+; X2 >= X1 and Y2 >= Y1. Be Careful...\r
+;\r
+; ENTRY: SourcePage = Display Page # with Source Image\r
+; X1 = Upper Left Xpos of Source Image\r
+; Y1 = Upper Left Ypos of Source Image\r
+; X2 = Lower Right Xpos of Source Image\r
+; Y2 = Lower Right Ypos of Source Image\r
+; DestPage = Display Page # to copy Image to\r
+; DestX1 = Xpos to Copy UL Corner of Image to\r
+; DestY1 = Ypos to Copy UL Corner of Image to\r
+;\r
+; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+;\r
+\r
+CB_STACK STRUC\r
+ CB_Height DW ? ; Height of Image in Lines\r
+ CB_Width DW ? ; Width of Image in "bands"\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ CB_DestY1 DW ? ; Destination Ypos\r
+ CB_DestX1 DW ? ; Destination Xpos\r
+ CB_DestP DW ? ; Page to Copy Bitmap To\r
+ CB_Y2 DW ? ; LR Ypos of Image\r
+ CB_X2 DW ? ; LR Xpos of Image\r
+ CB_Y1 DW ? ; UL Ypos of Image\r
+ CB_X1 DW ? ; UL Xpos of Image\r
+ CB_SourceP DW ? ; Page containing Source Bitmap\r
+CB_STACK ENDS\r
+\r
+ PUBLIC COPY_BITMAP\r
+\r
+COPY_BITMAP PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 4 ; Allocate WorkSpace on Stack\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Prep Registers (and keep jumps short!)\r
+\r
+ MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
+ CLD ; Block Xfer Forwards\r
+\r
+ ; Make sure Parameters are valid\r
+\r
+ MOV BX, [BP].CB_SourceP ; Get Source Page #\r
+ CMP BX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CB_Abort ; if so, abort\r
+\r
+ MOV CX, [BP].CB_DestP ; Get Destination Page #\r
+ CMP CX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CB_Abort ; if so, abort\r
+\r
+ MOV AX, [BP].CB_X1 ; Get Source X1\r
+ XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1\r
+ AND AX, PLANE_BITS ; Check Plane Bits\r
+ JNZ @CB_Abort ; They should cancel out\r
+\r
+ ; Setup for Copy processing\r
+\r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
+\r
+ ; Compute Info About Images, Setup ES:SI & ES:DI\r
+\r
+ MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines\r
+ SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1\r
+ INC AX ; (add 1 since were not 0 based)\r
+ MOV [BP].CB_Height, AX ; Save on Stack for later use\r
+\r
+ MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels\r
+ MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1\r
+ SHR AX, 1 ; Get X2 Band (X2 / 4)\r
+ SHR DX, 1 ; Get X1 Band (X1 / 4)\r
+ SHR AX, 1 ; Get X2 Band (X2 / 4)\r
+ SHR DX, 1 ; Get X1 Band (X1 / 4)\r
+ SUB AX, DX ; AX = # of Bands - 1\r
+ INC AX ; AX = # of Bands\r
+ MOV [BP].CB_Width, AX ; Save on Stack for later use\r
+\r
+ SHL BX, 1 ; Scale Source Page to Word\r
+ MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page\r
+ MOV AX, [BP].CB_Y1 ; Get Source Y1 Line\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
+ ADD SI, AX ; SI = Offset to Line Y1\r
+ MOV AX, [BP].CB_X1 ; Get Source X1\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ ADD SI, AX ; SI = Byte Offset to (X1,Y1)\r
+\r
+ MOV BX, CX ; Dest Page Index to BX\r
+ SHL BX, 1 ; Scale Source Page to Word\r
+ MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page\r
+ MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
+ ADD DI, AX ; DI = Offset to Line Y1\r
+ MOV AX, [BP].CB_DestX1 ; Get Dest X1\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1)\r
+\r
+ MOV CX, [BP].CB_Width ; CX = Width of Image (Bands)\r
+ DEC CX ; CX = 1?\r
+ JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band\r
+\r
+ MOV BX, [BP].CB_X1 ; Get Source X1\r
+ AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?)\r
+ JZ @CB_Check_Right ; if so, check right alignment\r
+ JNZ @CB_Left_Band ; not aligned? well..\r
+\r
+@CB_Abort:\r
+ mov ax,0 ; Return False (Failure)\r
+ JMP @CB_Exit ; and Finish Up\r
+\r
+ ; Copy when Left & Right Clip Masks overlap...\r
+\r
+@CB_Only_One_Band:\r
+ MOV BX, [BP].CB_X1 ; Get Left Clip Mask\r
+ AND BX, PLANE_BITS ; Mask out Row #\r
+ MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask\r
+ MOV BX, [BP].CB_X2 ; Get Right Clip Mask\r
+ AND BX, PLANE_BITS ; Mask out Row #\r
+ AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
+\r
+ OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
+\r
+ MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ mov bx,0 ; BX = Offset into Image\r
+\r
+@CB_One_Loop:\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_One_Done ; Exit Loop if Finished\r
+\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_One_Loop ; Loop until Finished\r
+\r
+@CB_One_Done:\r
+ JMP @CB_Finish ; Outa Here!\r
+\r
+ ; Copy Left Edge of Bitmap\r
+\r
+@CB_Left_Band:\r
+\r
+ OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
+\r
+ MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ mov bx,0 ; BX = Offset into Image\r
+\r
+@CB_Left_Loop:\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished\r
+\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_Left_Loop ; Loop until Finished\r
+\r
+@CB_Left_Done:\r
+ INC DI ; Move Dest Over 1 band\r
+ INC SI ; Move Source Over 1 band\r
+ DEC [BP].CB_Width ; Band Width--\r
+\r
+ ; Determine if Right Edge of Bitmap needs special copy\r
+\r
+@CB_Check_Right:\r
+ MOV BX, [BP].CB_X2 ; Get Source X2\r
+ AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?)\r
+ CMP BL, 03h ; Plane = 3?\r
+ JE @CB_Copy_Middle ; Copy the Middle then!\r
+\r
+ ; Copy Right Edge of Bitmap\r
+\r
+@CB_Right_Band:\r
+\r
+ OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask\r
+\r
+ DEC [BP].CB_Width ; Band Width--\r
+ MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ MOV BX, [BP].CB_Width ; BX = Offset to Right Edge\r
+\r
+@CB_Right_Loop:\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished\r
+\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_Right_Loop ; Loop until Finished\r
+\r
+@CB_Right_Done:\r
+\r
+ ; Copy the Main Block of the Bitmap\r
+\r
+@CB_Copy_Middle:\r
+\r
+ MOV CX, [BP].CB_Width ; Get Width Remaining\r
+ JCXZ @CB_Finish ; Exit if Done\r
+\r
+ OUT_8 SC_Data, ALL_PLANES ; Copy all Planes\r
+\r
+ MOV DX, SCREEN_WIDTH ; Get Width of Screen minus\r
+ SUB DX, CX ; Image width (for Adjustment)\r
+ MOV AX, [BP].CB_Height ; AX = # of Lines to Copy\r
+ MOV BX, CX ; BX = Quick REP reload count\r
+ MOV CX, ES ; Move VGA Segment\r
+ MOV DS, CX ; Into DS\r
+\r
+ ; Actual Copy Loop. REP MOVSB does the work\r
+\r
+@CB_Middle_Copy:\r
+ MOV CX, BX ; Recharge Rep Count\r
+ REP MOVSB ; Move Bands\r
+ LOOPjz AX, @CB_Finish ; Exit Loop if Finished\r
+\r
+ ADD SI, DX ; Adjust DS:SI to Next Line\r
+ ADD DI, DX ; Adjust ES:DI to Next Line\r
+\r
+ MOV CX, BX ; Recharge Rep Count\r
+ REP MOVSB ; Move Bands\r
+\r
+ ADD SI, DX ; Adjust DS:SI to Next Line\r
+ ADD DI, DX ; Adjust ES:DI to Next Line\r
+ LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done\r
+\r
+@CB_Finish:\r
+ OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on\r
+\r
+@CB_Exit:\r
+ ADD SP, 04 ; Deallocate stack workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 16 ; Exit and Clean up Stack\r
+\r
+COPY_BITMAP ENDP\r
+\r
+ END ; End of Code Segment\r
--- /dev/null
+ \r
+ ' ===== SCREEN RESOLUTIONS =====\r
+ \r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
+ \r
+ ' ===== MODE X SETUP ROUTINES =====\r
+ \r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
+ \r
+ ' ===== BASIC GRAPHICS PRIMITIVES =====\r
+ \r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+ \r
+ ' ===== DAC COLOR REGISTER ROUTINES =====\r
+ \r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
+ \r
+ \r
+ ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+ \r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
+ \r
+ ' ===== TEXT DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
+ \r
+ ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+ \r
+ ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+ \r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
--- /dev/null
+\r
+#ifndef __MODEX_H\r
+#define __MODEX_H\r
+\r
+ /* ===== SCREEN RESOLUTIONS ===== */\r
+\r
+#define Mode_320x200 0\r
+#define Mode_320x400 1\r
+#define Mode_360x200 2\r
+#define Mode_360x400 3\r
+#define Mode_320x240 4\r
+#define Mode_320x480 5\r
+#define Mode_360x240 6\r
+#define Mode_360x480 7\r
+\r
+ /* ===== MODE X SETUP ROUTINES ===== */\r
+\r
+int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages);\r
+int far pascal set_modex (int Mode);\r
+\r
+ /* ===== BASIC GRAPHICS PRIMITIVES ===== */\r
+\r
+void far pascal clear_vga_screen (int Color);\r
+void far pascal set_point (int Xpos, int Ypos, int Color);\r
+int far pascal read_point (int Xpos, int Ypos);\r
+void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+ int Color);\r
+void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+ int Color);\r
+\r
+ /* ===== DAC COLOR REGISTER ROUTINES ===== */\r
+\r
+void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue);\r
+void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue);\r
+void far pascal load_dac_registers (char far *PalData, int StartReg,\r
+ int EndReg, int VSync);\r
+void far pascal readd_dac_registers (char far *PalData, int StartReg,\r
+ int EndReg);\r
+\r
+ /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */\r
+\r
+void far pascal set_active_page (int PageNo);\r
+int far pascal get_active_page (void);\r
+void far pascal set_display_page (int PageNo);\r
+int far pascal get_display_page (void);\r
+void far pascal set_window (int DisplayPage, int XOffset, int YOffset);\r
+int far pascal get_x_offset (void);\r
+int far pascal get_y_offset (void);\r
+void far pascal sync_display (void);\r
+\r
+ /* ===== TEXT DISPLAY ROUTINES ===== */\r
+\r
+void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF,\r
+ int ColorB);\r
+void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF);\r
+void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+ int ColorF, int ColorB);\r
+void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+ int ColorF);\r
+void far pascal set_display_font (char far *FontData, int FontNumber);\r
+\r
+ /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */\r
+\r
+void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos,\r
+ int Width, int Height);\r
+void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos,\r
+ int Width, int Height);\r
+\r
+ /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */\r
+\r
+void far pascal copy_page (int SourcePage, int DestPage);\r
+void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2,\r
+ int DestPage, int DestX1, int DestY1);\r
+\r
+\r
+#endif\r
--- /dev/null
+MASM c_utils, c_utils, c_utils, nul;
\ No newline at end of file
--- /dev/null
+#! /bin/bash
+wmake clean;wmake
+cp x-demo.exe ../../../../../
--- /dev/null
+/* X-DEMO.C - a Mode "X" Demo */\r
+/* By Matt Pritchard, 14 Apr, 1993 */\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+\r
+#include "modex.h"\r
+#include "c_utils.h"\r
+\r
+#define MAX_SHAPES 32\r
+#define MAX_SPRITES 64\r
+\r
+ /* routines in this file */\r
+\r
+void demo_res (int, int, int);\r
+int get_key (void);\r
+void error_out (char*);\r
+void load_shapes (void);\r
+int int_sqrt (int, int);\r
+void page_demo (void);\r
+\r
+ /* Structures for Sprites */\r
+\r
+struct Shape\r
+{\r
+ unsigned char Image[512];\r
+ int X_Width;\r
+ int Y_Width;\r
+} Img [MAX_SHAPES];\r
+\r
+struct Sprite\r
+{\r
+ int X_pos;\r
+ int Y_pos;\r
+ int X_Dir;\r
+ int Y_Dir;\r
+ int Shape;\r
+ int Last_X [2];\r
+ int Last_Y [2];\r
+} Obj [MAX_SPRITES];\r
+\r
+\r
+ /* MAIN */\r
+\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+\r
+ /* if (argc > 0)\r
+ {\r
+ while (argc > 0)\r
+ {\r
+ dos_print ("Unknown Argument: ");\r
+ dos_print (makefp argv[argc]);\r
+ argc--;\r
+ }\r
+ return (0);\r
+\r
+ }\r
+ */\r
+\r
+ init_random ();\r
+\r
+ load_shapes ();\r
+\r
+ demo_res ( Mode_320x200, 320, 200 );\r
+ demo_res ( Mode_320x400, 320, 400 );\r
+\r
+ demo_res ( Mode_360x200, 360, 200 );\r
+ demo_res ( Mode_360x400, 360, 400 );\r
+\r
+ demo_res ( Mode_320x240, 320, 240 );\r
+ demo_res ( Mode_320x480, 320, 480 );\r
+\r
+ demo_res ( Mode_360x240, 360, 240 );\r
+ demo_res ( Mode_360x480, 360, 480 );\r
+\r
+ page_demo ();\r
+\r
+ set_video_mode (3);\r
+ dos_print ("This Mode X Demo is Finished");\r
+ return (0);\r
+\r
+}\r
+\r
+\r
+ /* Demonstrate a given resolution */\r
+\r
+\r
+void demo_res (int Screen_Mode, int X_max, int Y_max)\r
+{\r
+\r
+char *Error1 = "Failure while calling SET_MODEX";\r
+char *Error2 = "Failure during READ_PIXEL test";\r
+\r
+char *Abort_Msg = "Demo aborted by User";\r
+\r
+char *Demo_Msg = " This is a MODE X demo ";\r
+char *Scrn_Msg = "Screen Resolution is by ";\r
+char *Cont_Msg = "Press <ANY KEY> to Continue";\r
+\r
+char *Line_Msg = "LINE TEST";\r
+char *Fill_Msg = "FILL TEST";\r
+char *Pixel_Msg = "PIXEL TEST";\r
+\r
+char Text[10];\r
+\r
+int x1, y1, x2, y2 = 0;\r
+int x, y, z = 0;\r
+int X_Center, gap = 0;\r
+\r
+\r
+ if (set_modex (Screen_Mode) == 0)\r
+ {\r
+ error_out (Error1);\r
+ }\r
+\r
+ X_Center = X_max / 2;\r
+\r
+ x1 = 10;\r
+ y1 = 10;\r
+ x2 = X_max - 1;\r
+ y2 = Y_max - 1;\r
+\r
+ for (z = 0; z <= 3; z++)\r
+ {\r
+ y = 31 - z -z;\r
+ draw_line (x1+z, y1+z, x2-z, y1+z, y);\r
+ draw_line (x1+z, y1+z, x1+z, y2-z, y);\r
+ draw_line (x1+z, y2-z, x2-z, y2-z, y);\r
+ draw_line (x2-z, y1+z, x2-z, y2-z, y);\r
+ }\r
+\r
+ for (x = 0; x < (X_max / 10); x++)\r
+ {\r
+ tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) );\r
+ draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE);\r
+ }\r
+\r
+ for (y = 0; y < (Y_max / 10); y++)\r
+ {\r
+ tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) );\r
+ draw_line (0, y*10+9, 3, y*10+9, c_bWHITE);\r
+ }\r
+\r
+ for (x = 0; x <= 63; x++)\r
+ {\r
+ z = 15 + (x * 3 / 4);\r
+ set_dac_register (64+x, z, z, z);\r
+ set_dac_register (128+x, 0, z, z);\r
+\r
+ draw_line (103-x, 60, 40+x, 123, 64+x);\r
+ draw_line (40, 60+x, 103, 123-x, 128+x);\r
+\r
+ }\r
+\r
+ tprint_str (Line_Msg, 9, 37, 130, c_BLUE);\r
+\r
+ y = 60;\r
+ gap = 0;\r
+ for (x = 0; x <= 9; x++)\r
+ {\r
+ fill_block (120, y, 120+x, y+gap, 64+x);\r
+ fill_block (140 - (15-x), y, 150+x, y+gap, 230+x);\r
+ fill_block (170 - (15-x), y, 170, y+gap, 128+x);\r
+ y = y + gap + 2;\r
+ gap++;\r
+ }\r
+\r
+ tprint_str (Fill_Msg, 9, 110, 46, c_GREEN);\r
+\r
+ for (x = 190; x <= 250; x+=2)\r
+ {\r
+ for (y = 60; y <= 122; y+=2)\r
+ {\r
+ z = (x+x+y+y) & 0xff;\r
+ set_point (x, y, z);\r
+ }\r
+ }\r
+\r
+ tprint_str (Pixel_Msg, 10, 182, 130, c_RED);\r
+\r
+ for (x = 190; x <= 250; x+=2)\r
+ {\r
+ for (y = 60; y <= 122; y+=2)\r
+ {\r
+ z = (x+x+y+y) & 0xff;\r
+ if (read_point(x, y) != z)\r
+ {\r
+ error_out (Error2);\r
+ }\r
+ }\r
+ }\r
+\r
+ print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE);\r
+\r
+ x = X_Center - 124;\r
+ print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK);\r
+\r
+ sprintf (Text, "%3d", X_max);\r
+ print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK);\r
+\r
+ sprintf (Text, "%3d", Y_max);\r
+ print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK);\r
+\r
+ for (x = 0; x <= 15; x++)\r
+ {\r
+ set_dac_register (230+x, 63-x*4, 0, 15+x*3);\r
+ draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x);\r
+ }\r
+\r
+ tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW);\r
+\r
+ if (get_key () == Ky_ESC)\r
+ {\r
+ error_out (Abort_Msg);\r
+ }\r
+\r
+ return ;\r
+\r
+}\r
+\r
+\r
+ /* Wait for a Keystroke */\r
+\r
+\r
+int get_key(void)\r
+{\r
+\r
+int c = 0;\r
+\r
+ while (c == 0)\r
+ {\r
+ c = scan_keyboard ();\r
+ }\r
+\r
+ return (c);\r
+\r
+}\r
+\r
+\r
+ /* Error Handling Routine */\r
+\r
+\r
+void error_out (char * text)\r
+{\r
+\r
+ set_video_mode (3);\r
+ dos_print (text);\r
+ exit (EXIT_SUCCESS);\r
+\r
+}\r
+\r
+\r
+ /* Routine to generate random sprites */\r
+\r
+\r
+void load_shapes ()\r
+{\r
+\r
+unsigned char Grid[33][33];\r
+\r
+char *Error1 = "Bad Shape Selected Error";\r
+\r
+int Shape;\r
+int x, y, z;\r
+int Style, Color;\r
+int X_Width, Y_Width, Center, S_Width;\r
+int Hollow_X, Hollow_Y;\r
+\r
+ for (Shape = 0; Shape < MAX_SHAPES; Shape++)\r
+ {\r
+ for (y = 0; y <= 32; y++)\r
+ {\r
+ for (x = 0; x <= 32; x++)\r
+ {\r
+ Grid[x][y] = c_BLACK;\r
+ }\r
+ }\r
+\r
+ Style = random_int (6);\r
+ Color = 1 + random_int (15);\r
+\r
+ switch (Style)\r
+\r
+ {\r
+ /* SOLID BOXES */\r
+\r
+ case 0:\r
+\r
+ {\r
+ do\r
+ {\r
+ X_Width = 3 + random_int(30);\r
+ Y_Width = 3 + random_int(30);\r
+\r
+ } while ( (X_Width * Y_Width) >= 512);\r
+\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ Grid[x][y] = Color;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+ /* HOLLOW BOXES */\r
+\r
+ case 1:\r
+\r
+ {\r
+ do {\r
+ X_Width = 6 + random_int(27);\r
+ Y_Width = 6 + random_int(27);\r
+ } while ( (X_Width * Y_Width) >= 512);\r
+\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ Grid[x][y] = Color;\r
+ }\r
+ }\r
+\r
+ Hollow_X = 1 + random_int ((X_Width / 2) -1);\r
+ Hollow_Y = 1 + random_int ((Y_Width / 2) -1);\r
+\r
+ for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++)\r
+ {\r
+ for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++)\r
+ {\r
+ Grid[x][y] = c_BLACK;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ /* SOLID DIAMOND */\r
+\r
+ case 2:\r
+\r
+ {\r
+\r
+ X_Width = 3 + 2 * random_int(10);\r
+ Y_Width = X_Width;\r
+ Center = X_Width / 2;\r
+\r
+ for (y = 0; y <= Center; y++)\r
+ {\r
+ for (x = 0; x <= y; x++)\r
+ {\r
+ Grid [Center-x+1][y+1] = Color;\r
+ Grid [Center+x+1][y+1] = Color;\r
+ Grid [Center-x+1][Y_Width-y] = Color;\r
+ Grid [Center+x+1][Y_Width-y] = Color;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ /* HOLLOW DIAMOND */\r
+\r
+ case 3:\r
+\r
+ {\r
+\r
+ X_Width = 3 + 2 * random_int(10);\r
+ Y_Width = X_Width;\r
+ Center = X_Width / 2;\r
+ S_Width = random_int (Center);\r
+\r
+ for (y = 0; y <= Center; y++)\r
+ {\r
+ for (x = 0; x <= y; x++)\r
+ {\r
+ if ( x+(Center-y) >= S_Width )\r
+ {\r
+ Grid [Center-x+1][y+1] = Color;\r
+ Grid [Center+x+1][y+1] = Color;\r
+ Grid [Center-x+1][Y_Width-y] = Color;\r
+ Grid [Center+x+1][Y_Width-y] = Color;\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ /* BALL */\r
+\r
+ case 4:\r
+\r
+ {\r
+\r
+ X_Width = 7 + 2 * random_int (8);\r
+ Y_Width = X_Width;\r
+ Center = 1 + X_Width / 2;\r
+\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ z = int_sqrt(Center-x, Center-y);\r
+ if (z < Center)\r
+ {\r
+ Grid[x][y] = 150 + Color * 2 + z * 3;\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ /* HOLLOW BALLS */\r
+\r
+ case 5:\r
+\r
+ {\r
+ X_Width = 7 + 2 * random_int (8);\r
+ Y_Width = X_Width;\r
+ Center = 1 + X_Width / 2;\r
+ S_Width = random_int (X_Width);\r
+\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ z = int_sqrt(Center-x, Center-y);\r
+ if ( (z < Center) && (z >= S_Width) )\r
+ {\r
+ Grid[x][y] = 150 + Color * 2 + z * 3;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ break;\r
+ }\r
+\r
+ default:\r
+\r
+ {\r
+ error_out (Error1);\r
+ break;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ z = 0;\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ Img[Shape].Image[z] = Grid[x][y];\r
+ z++;\r
+ }\r
+ }\r
+\r
+ Img[Shape].X_Width = X_Width;\r
+ Img[Shape].Y_Width = Y_Width;\r
+\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+ /* Quickie Psuedo Integer Square Root Routine */\r
+\r
+\r
+int int_sqrt ( int x, int y )\r
+{\r
+\r
+int Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144};\r
+\r
+int r, d;\r
+\r
+ d = (x * x) + (y * y);\r
+ r = 0;\r
+\r
+ while ( d >= Sqr_Table[r] )\r
+ {\r
+ r++;\r
+ }\r
+\r
+ return (r);\r
+\r
+}\r
+\r
+\r
+ /* The Bit Sprite Demo */\r
+\r
+\r
+void page_demo ()\r
+{\r
+\r
+char *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call";\r
+\r
+int Last_Objects[2], Visible_Objects;\r
+\r
+int Screen_X = 384;\r
+int Screen_Y = 224;\r
+\r
+int x, y, z;\r
+int c, dc;\r
+int x1, y1, x2, y2;\r
+\r
+int Sprite_X, Sprite_Y;\r
+int Current_Page;\r
+int New_X, New_Y;\r
+\r
+int View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD;\r
+int Set_Color, Prev_Color, S_Dir, P_Dir;\r
+\r
+int Demo_Running = True;\r
+int redo, code;\r
+\r
+int pee;\r
+pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3);\r
+ if ( pee > 0)\r
+ {\r
+ set_video_mode (3);\r
+ dos_print (Error1);\r
+ fprintf(stdout, "return value is %d\n", pee);\r
+ //error_out (Error1);\r
+ exit (EXIT_SUCCESS);\r
+ }\r
+\r
+ set_active_page (0);\r
+ clear_vga_screen (c_BLACK);\r
+\r
+ print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK);\r
+\r
+ draw_line (10, 18, 350, 18, c_YELLOW);\r
+ print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK);\r
+ print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK);\r
+ print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK);\r
+ print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK);\r
+\r
+ print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK);\r
+ print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK);\r
+ print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK);\r
+\r
+ print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK);\r
+ print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK);\r
+ print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK);\r
+\r
+ print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK);\r
+ print_str (" SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK);\r
+ print_str (" SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK);\r
+ print_str (" PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK);\r
+ print_str (" COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK);\r
+\r
+ for (x = 0; x <=60; x++)\r
+ {\r
+ set_dac_register (50 + x, 3 + x, 0, 60 - x);\r
+ set_dac_register (150 + x, 3 + x, 0, 60 - x);\r
+ }\r
+\r
+ c = 0;\r
+ dc = 1;\r
+ for (x = 0; x <= (Screen_X / 2); x++)\r
+ {\r
+ draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50);\r
+ draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50);\r
+ c+= dc;\r
+ if ((c == 0) || (c == 60) ) { dc = -dc;}\r
+ }\r
+\r
+ tprint_str ("Press <ANY KEY> to Continue", 99, 72, 190, c_bWHITE);\r
+ tprint_str ("< > = Faster < > = Slower", 99, 72, 204, c_bGREEN);\r
+ tprint_str ("< > = Fewer Shapes < > = More Shapes", 99, 32, 218, c_bCYAN);\r
+\r
+ tgprintc (43, 80, 204, c_YELLOW);\r
+ tgprintc (45, 200, 204, c_YELLOW);\r
+\r
+ tgprintc (25, 40, 218, c_YELLOW);\r
+ tgprintc (24, 200, 218, c_YELLOW);\r
+\r
+ copy_page (0, 1);\r
+ copy_page (0, 2);\r
+\r
+ for (x = 0; x < MAX_SPRITES; x++)\r
+ {\r
+ do {\r
+ Obj[x].X_Dir = random_int(7) - 3;\r
+ Obj[x].Y_Dir = random_int(7) - 3;\r
+ } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+\r
+ Obj[x].Shape = x % MAX_SHAPES;\r
+\r
+ Sprite_X = Img[Obj[x].Shape].X_Width;\r
+ Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+ Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2);\r
+ Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2);\r
+\r
+ Obj[x].Last_X[0] = Obj[x].X_pos;\r
+ Obj[x].Last_X[1] = Obj[x].X_pos;\r
+ Obj[x].Last_Y[0] = Obj[x].Y_pos;\r
+ Obj[x].Last_Y[1] = Obj[x].Y_pos;\r
+\r
+ }\r
+\r
+ Current_Page = 0;\r
+\r
+ View_X = 0;\r
+ View_Y = 0;\r
+ View_Max = 3;\r
+ View_Cnt = 0;\r
+ View_XD = 1;\r
+ View_YD = 1;\r
+\r
+ Set_Color = 3;\r
+ S_Dir = 1;\r
+ Prev_Color = 0;\r
+ P_Dir = 1;\r
+\r
+ Visible_Objects = MAX_SPRITES / 2;\r
+ Last_Objects[0] = 0;\r
+ Last_Objects[1] = 0;\r
+\r
+ while (Demo_Running)\r
+ {\r
+\r
+ set_active_page (Current_Page);\r
+\r
+ /* Erase Old Images */\r
+\r
+ for (x = 0; x <= Last_Objects[Current_Page]; x++)\r
+ {\r
+ z = 2;\r
+ y = Obj[x].Shape;\r
+ x1 = Obj[x].Last_X[Current_Page];\r
+ y1 = Obj[x].Last_Y[Current_Page];\r
+ x2 = x1 + Img[y].X_Width -1;\r
+ y2 = y1 + Img[y].Y_Width -1;\r
+\r
+ x1 = x1 & 0xfffc;\r
+ x2 = x2 | 0x0003;\r
+\r
+ copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1);\r
+ }\r
+\r
+ /* Draw new images */\r
+\r
+ for (x = 0; x <= Visible_Objects; x++)\r
+ {\r
+ Sprite_X = Img[Obj[x].Shape].X_Width;\r
+ Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+ /* Move Sprite */\r
+\r
+ do\r
+ {\r
+ redo = False;\r
+ New_X = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+ if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) )\r
+ {\r
+ Obj[x].X_Dir = -Obj[x].X_Dir;\r
+ if (random_int(20) == 1)\r
+ {\r
+ do\r
+ {\r
+ Obj[x].X_Dir = random_int(7) - 3;\r
+ Obj[x].Y_Dir = random_int(7) - 3;\r
+ } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+ redo = True;\r
+ }\r
+ }\r
+ } while (redo);\r
+ Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+\r
+ do\r
+ {\r
+ redo = False;\r
+ New_Y = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+ if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) )\r
+ {\r
+ Obj[x].Y_Dir = -Obj[x].Y_Dir;\r
+ if (random_int(20) == 1)\r
+ {\r
+ do\r
+ {\r
+ Obj[x].X_Dir = random_int(7) - 3;\r
+ Obj[x].Y_Dir = random_int(7) - 3;\r
+ } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+ redo = True;\r
+ }\r
+ }\r
+ } while (redo);\r
+\r
+ Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+ /* Draw Sprite */\r
+\r
+ tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y);\r
+\r
+ Obj[x].Last_X[Current_Page] = Obj[x].X_pos;\r
+ Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos;\r
+\r
+ }\r
+\r
+ Last_Objects[Current_Page] = Visible_Objects;\r
+\r
+\r
+ /* Pan Screen Back & Forth */\r
+\r
+ View_Cnt++;\r
+ if (View_Cnt >= View_Max)\r
+ {\r
+ View_X+= View_XD;\r
+ if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;}\r
+ if (View_XD < 0)\r
+ {\r
+ View_Y+= View_YD;\r
+ if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;}\r
+ }\r
+\r
+ set_window (Current_Page, View_X, View_Y);\r
+\r
+ View_Cnt = 0;\r
+ }\r
+ else\r
+ {\r
+ set_display_page (Current_Page);\r
+ }\r
+\r
+ /* Cycle Colors */\r
+\r
+ set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+ set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color);\r
+\r
+ set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+ set_dac_register (150 + Set_Color, 63, 63, Set_Color);\r
+\r
+ Set_Color+= S_Dir;\r
+ if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;}\r
+\r
+ Prev_Color+= P_Dir;\r
+ if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;}\r
+\r
+ /* Check for Keystroke */\r
+\r
+ Current_Page = Current_Page ^ 0x01;\r
+\r
+ code = scan_keyboard ();\r
+\r
+ if (code == Ky_ESC) {Demo_Running = False;}\r
+\r
+ if (code == Ky_Plus)\r
+ {\r
+ if (View_Max < 12) {View_Max++;}\r
+ }\r
+\r
+ if (code == Ky_Minus)\r
+ {\r
+ if (View_Max > 1) {View_Max--;}\r
+ if (View_Cnt >= View_Max) {View_Cnt = 0;}\r
+ }\r
+\r
+ if (code == Ky_Up)\r
+ {\r
+ if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;}\r
+ }\r
+\r
+ if (code == Ky_Down)\r
+ {\r
+ if (Visible_Objects > 0) {Visible_Objects--;}\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+{ ModeX Turbo Pascal Demo Program }\r
+{ Converted to Turbo Pascal by Scott Wyatt }\r
+{ Original program written in QuickBasic by Matt Prichard }\r
+{ Released to the Public Domain }\r
+{ }\r
+{ Thanks to Matt Prichard for his *EXCELLENT* ModeX Library }\r
+{ Additional Comments by Matt Pritchard }\r
+\r
+Uses Crt;\r
+\r
+{$L modex2.obj} { This file is the external ModeX Library .OBJ }\r
+{$F+}\r
+\r
+ { Mode Setting Routines }\r
+\r
+Function SET_VGA_MODEX (Mode,MaxXpos,MaxYpos,Pages : integer) : integer; external;\r
+Function SET_MODEX (Mode:integer) : Integer; external;\r
+\r
+ { Graphics Primitives }\r
+\r
+Procedure CLEAR_VGA_SCREEN (Color:integer); external;\r
+Procedure SET_POINT (Xpos,Ypos,Color : integer); external;\r
+Function READ_POINT (Xpos,Ypos:integer) : integer; external;\r
+Procedure FILL_BLOCK (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external;\r
+Procedure DRAW_LINE (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external;\r
+\r
+ { VGA DAC Routines }\r
+\r
+Procedure SET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external;\r
+Procedure GET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external;\r
+\r
+ { Page and Window Control Routines }\r
+\r
+Procedure SET_ACTIVE_PAGE (PageNo:integer); external;\r
+Function GET_ACTIVE_PAGE : integer; external;\r
+Procedure SET_DISPLAY_PAGE (PageNo:integer); external;\r
+Function GET_DISPLAY_PAGE : integer; external;\r
+Procedure SET_WINDOW (DisplayPage,XOffset,YOffset : integer); external;\r
+Function GET_X_OFFSET : integer; external;\r
+Function GET_Y_OFFSET : integer; external;\r
+Procedure SYNC_DISPLAY; external;\r
+\r
+ { Text Display Routines }\r
+\r
+Procedure GPRINTC (CharNum,Xpos,Ypos,ColorF,ColorB:integer); external;\r
+Procedure TGPRINTC ( CharNum,Xpos,Ypos,ColorF : integer); external;\r
+Procedure PRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF,ColorB:integer); external;\r
+Procedure TPRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF:integer); external;\r
+Procedure SET_DISPLAY_FONT (Var FontData;FontNumber:integer); external;\r
+\r
+ { Sprite and VGA memory -> Vga memory Copy Routines }\r
+\r
+Procedure DRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external;\r
+Procedure TDRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external;\r
+Procedure COPY_PAGE (SourcePage,DestPage:integer); external;\r
+Procedure COPY_BITMAP (SourcePage,X1,Y1,X2,Y2,DestPage,DestX1,DestY1:integer); external;\r
+\r
+{$F-}\r
+\r
+\r
+TYPE Sprite = Record\r
+ Xpos : INTEGER;\r
+ Ypos : INTEGER;\r
+ XDir : INTEGER;\r
+ YDir : INTEGER;\r
+ Shape : INTEGER;\r
+ LastX : INTEGER;\r
+ LastY : INTEGER;\r
+ END;\r
+\r
+\r
+CONST MaxShapes = 32;\r
+ Circle_16 : Array[1..16,1..16] of byte =\r
+ (( 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0),\r
+ ( 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0),\r
+ ( 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0),\r
+ ( 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0),\r
+ ( 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0),\r
+ ( 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0),\r
+ ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
+ ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
+ ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
+ ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
+ ( 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0),\r
+ ( 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0),\r
+ ( 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0),\r
+ ( 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0),\r
+ ( 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0),\r
+ ( 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0));\r
+ Square_16 : Array[1..16,1..16] of byte =\r
+ (( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+ ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21));\r
+ Diamond : Array[1..8,1..8] of byte =\r
+ (( 0, 0, 0, 22, 22, 0, 0, 0),\r
+ ( 0, 0, 22, 22, 22, 22, 0, 0),\r
+ ( 0, 22, 22, 0, 0, 22, 22, 0),\r
+ ( 22, 22, 0, 0, 0, 0, 22, 22),\r
+ ( 22, 22, 0, 0, 0, 0, 22, 22),\r
+ ( 0, 22, 22, 0, 0, 22, 22, 0),\r
+ ( 0, 0, 22, 22, 22, 22, 0, 0),\r
+ ( 0, 0, 0, 22, 22, 0, 0, 0));\r
+ Rectangle : Array[1..8,1..3] of byte =\r
+ (( 23, 23, 23),\r
+ ( 23, 23, 23),\r
+ ( 23, 23, 23),\r
+ ( 23, 23, 23),\r
+ ( 23, 23, 23),\r
+ ( 23, 23, 23),\r
+ ( 23, 23, 23),\r
+ ( 23, 23, 23));\r
+\r
+ { Global Variables ? }\r
+\r
+Var\r
+ XCenter,X1,Y1,X2,Y2,Z,Colr,XChars,YChars,X,Y,N,Gap : Integer;\r
+ s : string;\r
+ s1 : Array[1..35] of Char;\r
+ ch : Char;\r
+ obj : Array[1..64] of Sprite;\r
+ ScreenX,ScreenY : Integer;\r
+ c, dc, SpriteX, SpriteY, CurrentPage, LastPage : Integer;\r
+ SetColor, SDir, PrevColor, PDir : Byte;\r
+ XView, YView : Integer;\r
+ XView_Change, YView_Change : Integer;\r
+ Right : Boolean;\r
+ Number_Of_Shapes : Byte;\r
+\r
+\r
+ { Error Handler - Returns to Text Mode & Displays Error }\r
+\r
+Procedure ERROR_OUT(s : string);\r
+ Begin\r
+ asm\r
+ mov ah,0\r
+ mov al,3\r
+ int 10h\r
+ end;\r
+ WriteLn(s);\r
+ Halt(0);\r
+END;\r
+\r
+ { Routine to Print a PASCAL string using Print_Str }\r
+\r
+Procedure Print_Text(s : string; X,Y,BColor,FColor : integer);\r
+Var\r
+ s1 : Array[1..135] of Char;\r
+ i : byte;\r
+Begin\r
+ For i := 1 to Length(s) DO\r
+ s1[i] := s[i];\r
+ Print_Str(s1,Length(s),X,Y,BColor,FColor);\r
+End;\r
+\r
+ { Routine to Transparently Print a PASCAL string using TPrint_Str }\r
+\r
+Procedure TPrint_Text(s : string; X,Y,Color : integer);\r
+Var\r
+ s1 : Array[1..135] of Char;\r
+ i : byte;\r
+Begin\r
+ For i := 1 to Length(s) DO\r
+ s1[i] := s[i];\r
+ TPrint_Str(s1,Length(s),X,Y,Color);\r
+End;\r
+\r
+ { Routines to show test patterns for a given mode }\r
+\r
+Procedure Demo_Res(Mode, Xmax, Ymax : integer);\r
+Begin\r
+\r
+ Str(mode,s);\r
+ If Set_ModeX(Mode) = 0 Then\r
+ Error_Out('Unable to SET_MODEX '+s);\r
+ Clear_VGA_Screen(0);\r
+\r
+ XCenter := Xmax div 2;\r
+ X1 := 10;\r
+ Y1 := 10;\r
+ X2 := Xmax - 1;\r
+ Y2 := Ymax - 1;\r
+\r
+ FOR Z := 0 TO 3 DO\r
+ Begin\r
+ Colr := 31 - Z * 2;\r
+ Draw_Line(X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr);\r
+ Draw_Line(X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr);\r
+ Draw_Line(X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr);\r
+ Draw_Line(X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr);\r
+ End;\r
+\r
+ XChars := Xmax div 10;\r
+ YChars := Ymax div 10;\r
+\r
+ FOR X := 0 TO XChars - 1 DO\r
+ Begin\r
+ TGPRINTC(48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X div 8) MOD 7));\r
+ DRAW_LINE(X * 10 + 9, 0, X * 10 + 9, 3, 15);\r
+ End;\r
+ FOR Y := 0 TO YChars - 1 DO\r
+ Begin\r
+ TGPRINTC(48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y div 10) MOD 7));\r
+ DRAW_LINE(0, Y * 10 + 9, 3, Y * 10 + 9, 15);\r
+ End;\r
+\r
+ { Test Line Drawing }\r
+\r
+ FOR X := 0 TO 63 DO\r
+ Begin\r
+ N := 15 + ((X * 3) div 4);\r
+ SET_DAC_REGISTER(64 + X, N, N, N);\r
+ SET_DAC_REGISTER(128 + X, 0, N, N);\r
+ DRAW_LINE(103 - X, 60, 40 + X, 123, 64 + X);\r
+ DRAW_LINE(40, 60 + X, 103, 123 - X, 128 + X);\r
+ End;\r
+ s := 'Line Test';\r
+ PRINT_Text(s,37,130,1,0);\r
+\r
+ { Test Block Fills }\r
+\r
+ Y := 60;\r
+ Gap := 0;\r
+ FOR X := 0 TO 9 DO\r
+ Begin\r
+ FILL_BLOCK(120, Y, 120 + X, Y + Gap, 64 + X);\r
+ FILL_BLOCK(140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X);\r
+ FILL_BLOCK(170 - (15 - X), Y, 170, Y + Gap, 128 + X);\r
+ Y := Y + Gap + 2;\r
+ Gap := Gap + 1;\r
+ End;\r
+ s := 'Fill Test';\r
+ Print_Text(s,110, 46, 2,0);\r
+\r
+ { Test Pixel Write and Read }\r
+\r
+ FOR X := 190 TO 250 DO\r
+ FOR Y := 60 TO 122 DO\r
+ SET_POINT( X, Y, X + Y + X + Y);\r
+\r
+ s := 'Pixel Test';\r
+ Print_Text(s,182, 130, 3,0);\r
+\r
+ FOR X := 190 TO 250 DO\r
+ FOR Y := 60 TO 122 DO\r
+ IF READ_POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
+ WriteLn('READ_PIXEL Failure');\r
+\r
+ { Display rest of screen }\r
+\r
+ s := ' This is a MODE X demo ';\r
+ Print_Text(s,XCenter - (Length(s) * 4), 20, 3, 1);\r
+ s := 'Screen Resolution is by ';\r
+ X := XCenter - (Length(s) * 4);\r
+ Print_Text(s,X,30,4,0);\r
+ Str(XMax,s);\r
+ Print_Text(s, X + 8 * 21, 30, 8, 0);\r
+ Str(YMax,s);\r
+ Print_Text(s, X + 8 * 28, 30, 15, 0);\r
+\r
+ FOR X := 0 TO 15 DO\r
+ Begin\r
+ SET_DAC_REGISTER( 230 + X, 63 - X * 4, 0, 15 + X * 3);\r
+ DRAW_LINE(30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X);\r
+ End;\r
+ s := 'Press <ANY KEY> to Continue';\r
+ For x := 1 to length(s) DO\r
+ s1[x] := s[x];\r
+ TPrint_Str(s1, length(s), XCenter - (26 * 4), Ymax - 18, 5);\r
+\r
+ Ch := ReadKey;\r
+ IF Ch = #27 Then\r
+ Error_Out('Abort');\r
+\r
+End;\r
+\r
+\r
+ { Initialize Sprites for Sprite Demo }\r
+\r
+Procedure Init_Sprites;\r
+Var i : byte;\r
+Begin\r
+ For i := 1 to 64 DO\r
+ Begin\r
+ Obj[i].XPos := Random(300)+10;\r
+ Obj[i].YPos := Random(200)+20;\r
+ Obj[i].XDir := Random(10)-5;\r
+ Obj[i].YDir := Random(10)-5;\r
+ If (Obj[i].XDir = 0) AND (Obj[i].YDir = 0) Then\r
+ Begin\r
+ Obj[i].XDir := Random(5) + 1;\r
+ Obj[i].YDir := Random(5) + 1;\r
+ End;\r
+ Obj[i].Shape := Random(4)+1;\r
+ Obj[i].LastX := obj[i].XPos;\r
+ Obj[i].LastY := obj[i].YPos;\r
+ End;\r
+End;\r
+\r
+Procedure Set_Sprites(number : byte);\r
+Var i : Byte;\r
+Begin\r
+ For i := 1 to number DO\r
+ Begin\r
+ obj[i].LastX := obj[i].XPos;\r
+ obj[i].LastY := obj[i].YPos;\r
+ obj[i].XPos := obj[i].XPos + obj[i].XDir;\r
+ obj[i].YPos := obj[i].YPos + obj[i].YDir;\r
+ If (obj[i].XPos > 335) OR (obj[i].XPos < 5 ) Then\r
+ obj[i].XDir := -(obj[i].XDir);\r
+ If (obj[i].YPos > 220) OR (obj[i].YPos < 5) Then\r
+ obj[i].YDir := -(obj[i].YDir);\r
+ End;\r
+ For i := 1 to number DO\r
+ Case obj[i].Shape of\r
+ 1 : TDraw_Bitmap(Circle_16,obj[i].XPos,obj[i].YPos,16,16);\r
+ 2 : TDraw_Bitmap(Square_16,obj[i].XPos,obj[i].YPos,16,16);\r
+ 3 : TDraw_Bitmap(Diamond,obj[i].XPos,obj[i].YPos,8,8);\r
+ 4 : TDraw_Bitmap(Rectangle,obj[i].XPos,obj[i].YPos,3,8);\r
+ End;\r
+End;\r
+\r
+Procedure Remove_Sprites(p,number : byte);\r
+Var i : byte;\r
+Begin\r
+ For i := 1 to number DO\r
+ Copy_Bitmap(2,obj[i].LastX,obj[i].LastY,obj[i].LastX+16,obj[i].LastY+16,p,Obj[i].LastX,Obj[i].LastY);\r
+End;\r
+\r
+Procedure Page_Demo;\r
+Begin\r
+ Number_Of_Shapes := 64;\r
+ XView_Change := 1;\r
+ YView_Change := 1;\r
+ XView := 1;\r
+ YView := 1;\r
+ Right := TRUE;\r
+ ScreenX := 360;\r
+ ScreenY := 240;\r
+ PrevColor := 0;\r
+ SetColor := 3;\r
+ SDir := 1;\r
+ PDir := 1;\r
+ Str(0,s);\r
+\r
+ IF SET_VGA_MODEX(0, ScreenX, ScreenY, 3) = 0 THEN\r
+ ERROR_OUT('Unable to SET_VGA_MODEX' + S);\r
+\r
+ SET_ACTIVE_PAGE(0);\r
+ CLEAR_VGA_SCREEN(0);\r
+ PRINT_TEXT('This is a Test of the Following Functions:', 10, 9, 15, 0);\r
+ DRAW_LINE( 10, 18, 350, 18, 4);\r
+ Print_Text('SET_ACTIVE_PAGE', 10, 20, 1, 0);\r
+ Print_Text('SET_DISPLAY_PAGE', 10, 30, 3,0);\r
+ Print_Text('SET_DAC_REGISTER', 10, 40, 3, 0);\r
+ Print_Text('CLEAR_VGA_SCREEN', 10, 50, 13, 0);\r
+ Print_Text('TDRAW_BITMAP', 10, 60, 14, 0);\r
+ Print_Text('COPY_PAGE', 10, 70, 3, 0);\r
+ Print_Text('COPY_BITMAP', 10, 80, 13, 0);\r
+ Print_Text('GPRINTC', 10, 90, 1, 0);\r
+ Print_Text('TGPRINTC', 10, 100, 3, 0);\r
+ Print_Text('SYNC_DISPLAY', 10, 110, 3, 0);\r
+ Print_Text('SET_WINDOW', 10, 120, 14, 0);\r
+ Print_Text('VIRTUAL SCREEN SIZES', 190, 20, 1, 0);\r
+ Print_Text(' SMOOTH SCROLLING', 190, 30, 3, 0);\r
+ Print_Text(' SPRITE ANIMATION', 190, 40, 13, 0);\r
+ Print_Text(' PAGE FLIPPING', 190, 50, 3, 0);\r
+ Print_Text(' COLOR CYCLING', 190, 60, 14, 0);\r
+\r
+ FOR X := 0 TO 60 DO\r
+ Begin\r
+ SET_DAC_REGISTER( 50 + X, 3 + X, 0, 60 - X);\r
+ SET_DAC_REGISTER( 150 + X, 3 + X, 0, 60 - X);\r
+ End;\r
+\r
+ c := 0;\r
+ DC := 1;\r
+ FOR X := 0 TO ScreenX div 2 DO\r
+ Begin\r
+ DRAW_LINE( ScreenX div 2 - 1, ScreenY div 4, X, ScreenY - 1, c + 50);\r
+ DRAW_LINE( ScreenX div 2, ScreenY div 4, ScreenX - X - 1, ScreenY - 1, c + 50);\r
+ c := c + DC;\r
+ IF (c = 0) OR (c = 60) THEN DC := -DC;\r
+ End;\r
+\r
+ TPrint_Text('Press <ESC> to Continue', 82, 190, 15);\r
+ TPrint_Text('<+> = Fewer Shapes <-> = More Shapes', 32, 204, 12);\r
+ COPY_PAGE( 0, 1);\r
+ COPY_PAGE( 0, 2);\r
+\r
+ Ch := #0;\r
+ CurrentPage := 1;\r
+ LastPage := 0;\r
+ Set_Sprites(Number_Of_Shapes);\r
+ For c := 1 to 4 DO\r
+ Set_Dac_Register(19+c,63-(c*10),0,0);\r
+\r
+ While Ch <> #27 DO\r
+ Begin\r
+ Set_Active_Page(currentpage);\r
+ Set_Sprites(Number_Of_Shapes);\r
+ If Right Then\r
+ Begin\r
+ XView := XView + XView_Change;\r
+ If (XView > 38) OR (XView < 2) Then\r
+ Begin\r
+ XView_Change := -(XView_Change);\r
+ Right := FALSE;\r
+ End;\r
+ End\r
+ Else\r
+ Begin\r
+ YView := YView + YView_Change;\r
+ If (YView > 38) OR (YView < 2) Then\r
+ Begin\r
+ YView_Change := -(YView_Change);\r
+ Right := TRUE;\r
+ End;\r
+ End;\r
+\r
+ Set_Window(currentpage,XView,YView);\r
+ Set_Display_Page(currentpage);\r
+ Set_Dac_Register(50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor);\r
+ Set_Dac_Register(50 + SetColor, SetColor, 10, 63 - SetColor);\r
+ Set_Dac_Register(150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor);\r
+ Set_Dac_Register(150 + SetColor, 63, 63, SetColor);\r
+ SetColor := SetColor + SDir;\r
+ IF (SetColor = 60) OR (SetColor = 0) THEN SDir := -SDir;\r
+ PrevColor := PrevColor + PDir;\r
+ IF (PrevColor = 60) OR (PrevColor = 0) THEN PDir := -PDir;\r
+ Remove_Sprites(lastpage,Number_Of_Shapes);\r
+\r
+ If Keypressed Then\r
+ Begin\r
+ Ch := ReadKey;\r
+ Case Ch of\r
+ '-' : If Number_Of_Shapes > 1 Then\r
+ Begin\r
+ c := Number_Of_Shapes;\r
+ Copy_Bitmap(2,obj[c].XPos,obj[c].YPos,obj[c].XPos+16,obj[c].YPos+16,\r
+ currentpage,obj[c].XPos,obj[c].YPos);\r
+ Dec(Number_Of_Shapes);\r
+ End;\r
+ '+' : If Number_Of_Shapes < 64 Then Inc(Number_Of_Shapes);\r
+ End;\r
+ End;\r
+ lastpage := (lastpage+1) MOD 2;\r
+ currentpage := (currentpage+1) MOD 2;\r
+ End;\r
+END;\r
+\r
+ { MAIN ROUTINE - Run Through Demos and Exit }\r
+\r
+Begin\r
+\r
+ Randomize;\r
+ Init_Sprites;\r
+\r
+ Demo_Res(0, 320, 200);\r
+ Demo_Res(1, 320, 400);\r
+ Demo_Res(2, 360, 200);\r
+ Demo_Res(3, 360, 400);\r
+ Demo_Res(4, 320, 240);\r
+ Demo_Res(5, 320, 480);\r
+ Demo_Res(6, 360, 240);\r
+ Demo_Res(7, 360, 480);\r
+ Page_Demo;\r
+\r
+ asm\r
+ mov ah,0\r
+ mov al,3\r
+ int 10h\r
+ end;\r
+ WriteLn('THIS MODE X DEMO IS FINISHED');\r
+\r
+END.
\ No newline at end of file
--- /dev/null
+ECHO ... Building MODEX.QLB for QUICKBASIC 4.5\r
+LIB MODEX -+MODEX,,\r
+LIB MODEX -+UTILS,,\r
+DEL MODEX.BAK\r
+LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\QB45\BQLB45.LIB;\1a\r
--- /dev/null
+ \r
+ ' ===== SCREEN RESOLUTIONS =====\r
+ \r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
+ \r
+ ' ===== MODE X SETUP ROUTINES =====\r
+ \r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
+ \r
+ ' ===== BASIC GRAPHICS PRIMITIVES =====\r
+ \r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+ \r
+ ' ===== DAC COLOR REGISTER ROUTINES =====\r
+ \r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
+ \r
+ \r
+ ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+ \r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
+ \r
+ ' ===== TEXT DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
+ \r
+ ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+ \r
+ ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+ \r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
--- /dev/null
+'File: TEST6A.BAS\r
+'Descp.: A Mode "X" demonstration for Quickbasic 4.5\r
+'Author: Matt Pritchard\r
+'Date: 14 April, 1993\r
+'\r
+DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%)\r
+DECLARE SUB ERROR.OUT (Message$)\r
+DECLARE FUNCTION GET.KEY% ()\r
+DECLARE SUB LOAD.SHAPES ()\r
+DECLARE SUB PAGE.DEMO ()\r
+DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%)\r
+DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%)\r
+DEFINT A-Z\r
+\r
+\r
+TYPE ShapeType\r
+ ImgData AS STRING * 512\r
+ xWidth AS INTEGER\r
+ yWidth AS INTEGER\r
+END TYPE\r
+\r
+TYPE Sprite\r
+ Xpos AS INTEGER\r
+ Ypos AS INTEGER\r
+ XDir AS INTEGER\r
+ YDir AS INTEGER\r
+ Shape AS INTEGER\r
+END TYPE\r
+\r
+\r
+CONST MaxShapes = 32\r
+\r
+ REM $INCLUDE: 'UTILS.BI'\r
+ REM $INCLUDE: 'MODEX.BI'\r
+\r
+DIM SHARED Img(32) AS ShapeType\r
+COMMON SHARED Img() AS ShapeType\r
+\r
+\r
+ CALL INIT.RANDOM\r
+\r
+ CALL LOAD.SHAPES\r
+\r
+ CALL DEMO.RES(Mode320x200, 320, 200)\r
+ CALL DEMO.RES(Mode320x400, 320, 400)\r
+\r
+ CALL DEMO.RES(Mode360x200, 360, 200)\r
+ CALL DEMO.RES(Mode360x400, 360, 400)\r
+\r
+ CALL DEMO.RES(Mode320x240, 320, 240)\r
+ CALL DEMO.RES(Mode320x480, 320, 480)\r
+\r
+ CALL DEMO.RES(Mode360x240, 360, 240)\r
+ CALL DEMO.RES(Mode360x480, 360, 480)\r
+\r
+ CALL PAGE.DEMO\r
+\r
+ SET.VIDEO.MODE 3\r
+ DOS.PRINT "THIS MODE X DEMO IS FINISHED"\r
+ END\r
+\r
+SUB DEMO.RES (Mode, Xmax, Ymax)\r
+\r
+ IF SET.MODEX%(Mode) = 0 THEN\r
+ ERROR.OUT "Unable to SET_MODEX" + STR$(Mode)\r
+ END IF\r
+\r
+ XCenter = Xmax \ 2\r
+ \r
+ X1 = 10\r
+ Y1 = 10\r
+ X2 = Xmax - 1\r
+ Y2 = Ymax - 1\r
+\r
+ FOR Z = 0 TO 3\r
+ Colr = 31 - Z * 2\r
+ DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr\r
+ DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr\r
+ DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr\r
+ DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr\r
+ NEXT Z\r
+\r
+ XChars = Xmax \ 10\r
+ YChars = Ymax \ 10\r
+\r
+ FOR X = 0 TO XChars - 1\r
+ TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7)\r
+ DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15\r
+ NEXT X\r
+\r
+ FOR Y = 0 TO YChars - 1\r
+ TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7)\r
+ DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15\r
+ NEXT Y\r
+\r
+ ' Draw Lines\r
+\r
+ FOR X = 0 TO 63\r
+ N = 15 + X * .75\r
+ SET.DAC.REGISTER 64 + X, N, N, N\r
+ SET.DAC.REGISTER 128 + X, 0, N, N\r
+\r
+ DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X\r
+ DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X\r
+\r
+ NEXT X\r
+ TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE\r
+\r
+ Y = 60: Gap = 0\r
+ FOR X = 0 TO 9\r
+ FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X\r
+ FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X\r
+ FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X\r
+ Y = Y + Gap + 2\r
+ Gap = Gap + 1\r
+ NEXT X\r
+ TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN\r
+\r
+\r
+ FOR X = 190 TO 250 STEP 2\r
+ FOR Y = 60 TO 122 STEP 2\r
+ SET.POINT X, Y, X + Y + X + Y\r
+ NEXT Y\r
+ NEXT X\r
+\r
+ TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED\r
+\r
+ FOR X = 190 TO 250 STEP 2\r
+ FOR Y = 60 TO 122 STEP 2\r
+ IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
+ ERROR.OUT "READ.PIXEL Failure"\r
+ END IF\r
+ NEXT Y\r
+ NEXT X\r
+\r
+\r
+\r
+ Msg$ = " This is a MODE X demo "\r
+ PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE\r
+ Msg$ = "Screen Resolution is by "\r
+ Xp = XCenter - (LEN(Msg$) * 4)\r
+ PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK\r
+\r
+ PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK\r
+ PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK\r
+\r
+ FOR X = 0 TO 15\r
+ SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3\r
+ DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X\r
+ NEXT X\r
+ TPRINT.TEXT "Press <ANY KEY> to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW\r
+\r
+ X = GET.KEY%\r
+ IF X = KyESC THEN ERROR.OUT "ABORT"\r
+\r
+END SUB\r
+\r
+SUB ERROR.OUT (Message$)\r
+\r
+ SET.VIDEO.MODE 3\r
+ DOS.PRINT Message$\r
+ END\r
+\r
+END SUB\r
+\r
+FUNCTION GET.KEY%\r
+\r
+ DO\r
+ X = SCAN.KEYBOARD\r
+ LOOP UNTIL X\r
+\r
+ GET.KEY% = X\r
+\r
+END FUNCTION\r
+\r
+SUB LOAD.SHAPES\r
+\r
+DIM Grid(1 TO 32, 1 TO 32)\r
+\r
+ FOR Shape = 0 TO MaxShapes - 1\r
+\r
+ FOR Y = 1 TO 32\r
+ FOR X = 1 TO 32\r
+ Grid(X, Y) = 0\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ Style = RANDOM.INT(6)\r
+ Colour = 1 + RANDOM.INT(15)\r
+ \r
+ SELECT CASE Style\r
+\r
+ CASE 0: ' Solid Box\r
+\r
+ DO\r
+ xWidth = 3 + RANDOM.INT(30)\r
+ yWidth = 3 + RANDOM.INT(30)\r
+ LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ Grid(X, Y) = Colour\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 1: ' Hollow Box\r
+\r
+ DO\r
+ xWidth = 5 + RANDOM.INT(28)\r
+ yWidth = 5 + RANDOM.INT(28)\r
+ LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ Grid(X, Y) = Colour\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1)\r
+ HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1)\r
+\r
+ FOR Y = HollowY + 1 TO yWidth - HollowY\r
+ FOR X = HollowX + 1 TO xWidth - HollowX\r
+ Grid(X, Y) = nil\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 2: ' Solid Diamond\r
+\r
+ xWidth = 3 + 2 * RANDOM.INT(10)\r
+ yWidth = xWidth\r
+ Centre = xWidth \ 2\r
+\r
+ FOR Y = 0 TO Centre\r
+ FOR X = 0 TO Y\r
+ Grid(Centre - X + 1, Y + 1) = Colour\r
+ Grid(Centre + X + 1, Y + 1) = Colour\r
+ Grid(Centre - X + 1, yWidth - Y) = Colour\r
+ Grid(Centre + X + 1, yWidth - Y) = Colour\r
+ NEXT X\r
+ NEXT Y\r
+\r
+\r
+ CASE 3: ' Hollow Diamond\r
+\r
+\r
+ xWidth = 3 + 2 * RANDOM.INT(10)\r
+ yWidth = xWidth\r
+ Centre = xWidth \ 2\r
+ sWidth = RANDOM.INT(Centre)\r
+\r
+ FOR Y = 0 TO Centre\r
+ FOR X = 0 TO Y\r
+ IF X + (Centre - Y) >= sWidth THEN\r
+ Grid(Centre - X + 1, Y + 1) = Colour\r
+ Grid(Centre + X + 1, Y + 1) = Colour\r
+ Grid(Centre - X + 1, yWidth - Y) = Colour\r
+ Grid(Centre + X + 1, yWidth - Y) = Colour\r
+ END IF\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 4: ' Ball\r
+\r
+ xWidth = 7 + 2 * RANDOM.INT(8)\r
+ yWidth = xWidth\r
+ Centre = 1 + xWidth \ 2\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+ IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ CASE 5: ' Ball\r
+\r
+\r
+ xWidth = 7 + 2 * RANDOM.INT(8)\r
+ yWidth = xWidth\r
+ Centre = 1 + xWidth \ 2\r
+ sWidth = RANDOM.INT(xWidth)\r
+\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+ IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ END SELECT\r
+\r
+ Img(Shape).xWidth = xWidth\r
+ Img(Shape).yWidth = yWidth\r
+\r
+ A$ = STRING$(xWidth * yWidth, nil)\r
+\r
+ c = 1\r
+ FOR Y = 1 TO yWidth\r
+ FOR X = 1 TO xWidth\r
+ MID$(A$, c, 1) = CHR$(Grid(X, Y))\r
+ c = c + 1\r
+ NEXT X\r
+ NEXT Y\r
+\r
+ Img(Shape).ImgData = A$\r
+ \r
+\r
+ NEXT Shape\r
+\r
+END SUB\r
+\r
+SUB PAGE.DEMO\r
+\r
+CONST MaxSprites = 64\r
+\r
+DIM Obj(MaxSprites) AS Sprite\r
+DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1)\r
+DIM LastObjects(1)\r
+\r
+ ScreenX = 360: ScreenY = 240\r
+\r
+ IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN\r
+ ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode)\r
+ END IF\r
+\r
+ SET.ACTIVE.PAGE 0\r
+\r
+ CLEAR.VGA.SCREEN c.BLACK\r
+ \r
+ PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK\r
+\r
+ DRAW.LINE 10, 18, 350, 18, c.YELLOW\r
+ PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK\r
+ PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK\r
+ PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK\r
+ PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK\r
+\r
+ PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK\r
+ PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK\r
+ PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK\r
+\r
+ PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK\r
+ PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK\r
+ PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK\r
+\r
+ PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK\r
+ PRINT.TEXT " SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK\r
+ PRINT.TEXT " SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK\r
+ PRINT.TEXT " PAGE FLIPPING", 190, 50, c.RED, c.BLACK\r
+ PRINT.TEXT " COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK\r
+\r
+\r
+ FOR X = 0 TO 60\r
+ SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X\r
+ SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X\r
+ NEXT X\r
+\r
+ c = 0: DC = 1\r
+ FOR X = 0 TO ScreenX \ 2\r
+ DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50\r
+ DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50\r
+ c = c + DC\r
+ IF c = 0 OR c = 60 THEN DC = -DC\r
+ NEXT X\r
+ \r
+ TPRINT.TEXT "Press <ANY KEY> to Continue", 72, 190, c.bWHITE\r
+ TPRINT.TEXT "< > = Faster < > = Slower", 72, 204, c.bGREEN\r
+ TPRINT.TEXT "< > = Fewer Shapes < > = More Shapes", 32, 218, c.bCYAN\r
+\r
+ TGPRINTC 43, 80, 204, c.YELLOW\r
+ TGPRINTC 45, 200, 204, c.YELLOW\r
+\r
+ TGPRINTC 25, 40, 218, c.YELLOW\r
+ TGPRINTC 24, 200, 218, c.YELLOW\r
+\r
+ COPY.PAGE 0, 1\r
+ COPY.PAGE 0, 2\r
+\r
+ FOR X = 1 TO MaxSprites\r
+ DO\r
+ Obj(X).XDir = RANDOM.INT(7) - 3\r
+ Obj(X).YDir = RANDOM.INT(7) - 3\r
+ LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+\r
+ Obj(X).Shape = X MOD MaxShapes\r
+\r
+ SpriteX = Img(Obj(X).Shape).xWidth\r
+ SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+ Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2)\r
+ Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2)\r
+\r
+ LastX(X, 0) = Obj(X).Xpos\r
+ LastX(X, 1) = Obj(X).Xpos\r
+ LastY(X, 0) = Obj(X).Ypos\r
+ LastY(X, 1) = Obj(X).Ypos\r
+ NEXT X\r
+\r
+ CurrentPage = 0\r
+\r
+ 'View Shift...\r
+\r
+ ViewX = 0\r
+ ViewY = 0\r
+ ViewMax = 3\r
+ ViewCnt = 0\r
+ ViewXD = 1\r
+ ViewYD = 1\r
+\r
+ SetColor = 3: SDir = 1\r
+ PrevColor = 0: PDir = 1\r
+\r
+ VisObjects = MaxSprites \ 2\r
+ LastObjects(0) = 0\r
+ LastObjects(1) = 0\r
+\r
+DRAW.LOOP:\r
+\r
+\r
+ SET.ACTIVE.PAGE CurrentPage\r
+\r
+ ' Erase Old Images\r
+\r
+ FOR X = 1 TO LastObjects(CurrentPage)\r
+ \r
+ X1 = LastX(X, CurrentPage) AND &HFFFC\r
+ Y1 = LastY(X, CurrentPage)\r
+ X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3\r
+ Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1\r
+\r
+ COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1\r
+ \r
+ NEXT X\r
+\r
+ ' Draw new images\r
+\r
+ FOR X = 1 TO VisObjects\r
+\r
+ SpriteX = Img(Obj(X).Shape).xWidth\r
+ SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+ ' Move Sprite\r
+\r
+REDOX:\r
+ NewX = Obj(X).Xpos + Obj(X).XDir\r
+ IF NewX < 0 OR NewX + SpriteX > ScreenX THEN\r
+ Obj(X).XDir = -Obj(X).XDir\r
+ IF RANDOM.INT(20) = 1 THEN\r
+ DO\r
+ Obj(X).XDir = RANDOM.INT(7) - 3\r
+ Obj(X).YDir = RANDOM.INT(7) - 3\r
+ LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+ GOTO REDOX\r
+ END IF\r
+ END IF\r
+ Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir\r
+\r
+REDOY:\r
+ NewY = Obj(X).Ypos + Obj(X).YDir\r
+ IF NewY < 0 OR NewY + SpriteY > ScreenY THEN\r
+ Obj(X).YDir = -Obj(X).YDir\r
+ IF RANDOM.INT(20) = 1 THEN\r
+ DO\r
+ Obj(X).XDir = RANDOM.INT(7) - 3\r
+ Obj(X).YDir = RANDOM.INT(7) - 3\r
+ LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+ GOTO REDOY\r
+ END IF\r
+ END IF\r
+ Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir\r
+\r
+ 'Draw Sprite\r
+\r
+ TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY\r
+\r
+ LastX(X, CurrentPage) = Obj(X).Xpos\r
+ LastY(X, CurrentPage) = Obj(X).Ypos\r
+\r
+ NEXT X\r
+\r
+ LastObjects(CurrentPage) = VisObjects\r
+\r
+ ' Pan Screen Back & Forth\r
+\r
+ ViewCnt = ViewCnt + 1\r
+ IF ViewCnt >= ViewMax THEN\r
+ ViewX = ViewX + ViewXD\r
+ IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD\r
+ IF ViewXD < 0 THEN\r
+ ViewY = ViewY + ViewYD\r
+ IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD\r
+ END IF\r
+ \r
+ SET.WINDOW CurrentPage, ViewX, ViewY\r
+\r
+ ViewCnt = 0\r
+ ELSE\r
+ SET.DISPLAY.PAGE CurrentPage\r
+ END IF\r
+\r
+ ' Cycle Colors\r
+\r
+ SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+ SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor\r
+\r
+ SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+ SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor\r
+\r
+ SetColor = SetColor + SDir\r
+ IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir\r
+\r
+ PrevColor = PrevColor + PDir\r
+ IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir\r
+\r
+ CurrentPage = 1 - CurrentPage\r
+\r
+ Code = SCAN.KEYBOARD\r
+\r
+ IF Code = False THEN GOTO DRAW.LOOP\r
+\r
+ IF Code = KyPlus THEN\r
+ IF ViewMax < 12 THEN ViewMax = ViewMax + 1\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+\r
+ IF Code = KyMinus THEN\r
+ IF ViewMax > 1 THEN ViewMax = ViewMax - 1\r
+ IF ViewCnt >= ViewMax THEN ViewCnt = 0\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+\r
+ IF Code = KyUp THEN\r
+ IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+ \r
+ IF Code = KyDown THEN\r
+ IF VisObjects > 1 THEN VisObjects = VisObjects - 1\r
+ GOTO DRAW.LOOP\r
+ END IF\r
+\r
+\r
+END SUB\r
+\r
+SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB)\r
+\r
+ IF LEN(Text$) = 0 THEN EXIT SUB\r
+ PRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB\r
+\r
+\r
+END SUB\r
+\r
+SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF)\r
+\r
+ IF LEN(Text$) = 0 THEN EXIT SUB\r
+\r
+ TPRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF\r
+\r
+END SUB\r
+\r
--- /dev/null
+MASM utils, utils, utils, nul;
\ No newline at end of file
--- /dev/null
+;=======================================================\r
+;=== UTILS.ASM - Asm Utilities for QuickBasic/BC7 ===\r
+;=======================================================\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Medium\r
+ .286\r
+\r
+ ; ==== MACROS ====\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ push R1 ; Save R1\r
+ PUSHx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ENDM\r
+\r
+POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ pop R1 ; Restore R1\r
+ POPx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ENDM\r
+\r
+ ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+ xor Register, Register ; Set Register = 0\r
+ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jnz Destination ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+ dec Register ; Counter--\r
+ jz Destination ; Jump if 0\r
+ENDM\r
+\r
+\r
+ ; ==== General Constants ====\r
+\r
+ False EQU 0\r
+ True EQU -1\r
+ nil EQU 0\r
+\r
+ b EQU BYTE PTR\r
+ w EQU WORD PTR\r
+ d EQU DWORD PTR\r
+ o EQU OFFSET\r
+ f EQU FAR PTR\r
+ s EQU SHORT\r
+ ?x4 EQU <?,?,?,?>\r
+ ?x3 EQU <?,?,?>\r
+\r
+\r
+IFDEF FARSTRINGS\r
+\r
+ EXTRN stringaddress:far\r
+ EXTRN stringlength:far\r
+\r
+ENDIF\r
+\r
+\r
+ .Data\r
+\r
+ EVEN\r
+\r
+RND_Seed DW 7397, 29447, 802\r
+RND_Mult DW 179, 183, 182\r
+RND_ModV DW 32771, 32779, 32783\r
+\r
+CR_LF DB 13, 10 ; the CRLF data\r
+\r
+ .Code\r
+\r
+;=================\r
+;DOS_PRINT (Text$)\r
+;=================\r
+;\r
+; Prints Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINT\r
+\r
+DP_Stack STRUC\r
+ DW ?x4 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ DP_Text DW ? ; Address of Text$ Descriptor\r
+DP_Stack ENDS\r
+\r
+\r
+DOS_PRINT PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+ push SI ; Push Addr of BC7 Decriptor Ptr\r
+ call stringaddress ; Get Address + Len of string!!!\r
+ ; DX:AX = Addr CX = Len\r
+ mov DS, DX ; DS = DX = Segment of string\r
+ mov DX, AX ; DX = AX = Offset of String\r
+ELSE\r
+ mov CX, [SI] ; put its length into CX\r
+ mov DX, [SI+02] ; now DS:DX points to the String\r
+ENDIF\r
+\r
+ jcxz @No_Print ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@No_Print:\r
+ mov AX, SEG DGROUP ; Restore DGroup\r
+ mov DS, AX\r
+\r
+ mov DX, o CR_LF ; Get Addr of CR/LF pair\r
+ mov CX, 2 ; 2 Characters to Write \r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+ cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT ENDP\r
+\r
+\r
+;==================\r
+;DOS_PRINTS (Text$)\r
+;==================\r
+; \r
+; Print Text$ Directly to DOS console \r
+; without a trailing CR/LF\r
+;\r
+\r
+ PUBLIC DOS_PRINTS\r
+\r
+DOS_PRINTS PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+ push SI ; Push Addr of BC7 Decriptor Ptr\r
+ call stringaddress ; Get Address + Len of string!!!\r
+ ; DX:AX = Addr CX = Len\r
+ mov DS, DX ; DS = DX = Segment of string\r
+ mov DX, AX ; DX = AX = Offset of String\r
+ELSE\r
+ mov CX, [SI] ; put its length into CX\r
+ mov DX, [SI+02] ; now DS:DX points to the String\r
+ENDIF\r
+\r
+ jcxz @DPS_Exit ; Don't Print if empty\r
+\r
+ mov BX, 1 ; 1= DOS Handle for Display\r
+ mov AH, 40h ; Write Text Function\r
+ int 21h ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+ cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS ENDP\r
+\r
+\r
+;======================\r
+;SET_VIDEO_MODE (Mode%) \r
+;======================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+ PUBLIC SET_VIDEO_MODE\r
+\r
+SVM_Stack STRUC\r
+ DW ?x4 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ SVM_Mode DB ?,? ; Desired Video Mode\r
+SVM_Stack ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR AH ; Function 0\r
+ mov AL, [BP].SVM_Mode ; Get Mode #\r
+\r
+ int 10H ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret 2 ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;==============\r
+;SCAN_KEYBOARD%\r
+;==============\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+ PUBLIC SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD PROC FAR\r
+\r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+\r
+ mov AH, 01H ; Function #1\r
+ int 16H ; Call Keyboard Driver\r
+ jz @SK_NO_KEY ; Exit if Zero flag set\r
+\r
+ mov AH, 00H ; Remove Key from Buffer\r
+ int 16H ; Get Keycode in AX\r
+\r
+ or AL, AL ; Low Byte Set (Ascii?)\r
+ jz @SK_Exit ; if not, it's a F-Key\r
+\r
+ CLR AH ; Clear ScanCode if Ascii\r
+ jmp s @SK_Exit ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+ CLR AX ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+ cld ; Reset Direction Flag \r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ ret ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD ENDP\r
+\r
+\r
+;====================\r
+;RANDOM_INT (MaxInt%)\r
+;====================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+ PUBLIC RANDOM_INT\r
+\r
+RI_Stack STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ RI_MaxVal DW ? ; Maximum Value to Return + 1\r
+RI_Stack ENDS\r
+\r
+\r
+RANDOM_INT PROC FAR\r
+\r
+ push BP ; Preserve Important Registers\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ CLR BX ; BX is the data index\r
+ CLR CX ; CX is the accumulator\r
+\r
+REPT 3\r
+ mov AX, RND_Seed[BX] ; load the initial seed\r
+ mul RND_Mult[BX] ; multiply it\r
+ div RND_ModV[BX] ; and obtain the Mod value\r
+ mov RND_Seed[BX], DX ; save that for the next time\r
+\r
+ add CX, DX ; add it into the accumulator\r
+ inc BX\r
+ inc BX ; point to the next set of values\r
+ENDM\r
+\r
+ mov AX, CX ; AX = Random #\r
+ CLR DX ; DX = 0\r
+ div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
+\r
+ mov AX, DX\r
+\r
+ pop BP ; Restore BP\r
+ ret 2 ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT ENDP\r
+\r
+\r
+;===========\r
+;INIT_RANDOM\r
+;===========\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+ PUBLIC INIT_RANDOM\r
+\r
+INIT_RANDOM PROC FAR\r
+\r
+ clr AX ; Segment = 0000\r
+ mov ES, AX\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+\r
+ xor RND_Seed, AX ; Scramble 1st Seed\r
+\r
+ ret ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM ENDP\r
+\r
+\r
+;====================\r
+;INT_SQR (X%, Round%)\r
+;====================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the \r
+; nearest integer value by passing 0x80. Passing 0\r
+; return the Integer Portion only. The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus \r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ ISQ_Round DW ? ; Amount to Round Result * 256\r
+ ISQ_X DW ? ; "X"\r
+ISQ_Stack ENDS\r
+\r
+ PUBLIC INT_SQR\r
+\r
+INT_SQR PROC FAR\r
+\r
+ PUSHx BP, DI ; Save BP\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ xor AX, AX ; {xor eax,eax}\r
+ xor DX, DX ; {xor edx,edx}\r
+ mov DI, [BP].ISQ_X ; {mov edi,x}\r
+\r
+ mov CX, 16 ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl DI, 1 ; {shl edi,1}\r
+ rcl DX, 1 ; {rcl edx,1}\r
+ shl AX, 1 ; {shl eax,1}\r
+ mov BX, AX ; {mov ebx,eax}\r
+ shl BX, 1 ; {shl ebx,1}\r
+ inc BX ; {inc ebx}\r
+ cmp DX, BX ; {cmp edx,ebx}\r
+ jl @ISQ_S\r
+\r
+ sub DX, BX ; {sub edx,ebx}\r
+ inc AX ; {inc eax}\r
+\r
+@ISQ_S: \r
+ loop @ISQ_L\r
+\r
+ add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
+ ; {*round* result in hi word: ie. +0.5}\r
+ shr ax, 8 ; {shr eax,16} {to ax (result)}\r
+\r
+ POPx DI, BP ; Restore Registers \r
+ ret 4 ; Exit\r
+\r
+INT_SQR ENDP\r
+\r
+\r
+;============\r
+;TIMER_COUNT&\r
+;============\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+\r
+ PUBLIC TIMER_COUNT\r
+\r
+TIMER_COUNT PROC FAR\r
+\r
+ clr AX ; Segment = 0000\r
+ mov ES, AX ; use ES to get at data\r
+ mov AX, ES:[046Ch] ; Get Timer Lo Word\r
+ mov DX, ES:[046Eh] ; Get Timer Hi Word\r
+ ret ; Exit & Return value in DX:AX\r
+\r
+TIMER_COUNT ENDP\r
+\r
+\r
+ END\r
--- /dev/null
+\r
+ ' Misc Constants\r
+\r
+CONST True = -1, False = 0, nil = 0\r
+\r
+ ' Keyboard Codes: Extended\r
+\r
+CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00\r
+CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400\r
+\r
+CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000\r
+CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000\r
+\r
+CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100\r
+CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100\r
+\r
+CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00\r
+CONST KySIns = &HC200, KySDel = &HC300\r
+\r
+CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000\r
+CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300\r
+CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600\r
+CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900\r
+CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400\r
+CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00\r
+CONST KyAltY = &H1500, KyAltZ = &H2C00\r
+\r
+ ' Keyboard Codes: Ascii\r
+\r
+CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F\r
+CONST KyPlus = 45, KyMinus = 43\r
+\r
+ ' Color Constants\r
+\r
+CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3\r
+CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7\r
+CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11\r
+CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15\r
+CONST c.BRIGHT = 8\r
+\r
+ ' From UTILS.ASM\r
+\r
+DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$)\r
+DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$)\r
+DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%)\r
+DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD"\r
+DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%)\r
+DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM"\r
+DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT"\r
+DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%)\r
+\r
--- /dev/null
+\r
+CSEDIT - A Simple Font Editor by Matt Pritchard\r
+ \r
+ \r
+CSEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X\r
+Library for VGA Graphics.\r
+ \r
+WHAT YOU NEED TO RUN CSEDIT:\r
+ \r
+ * A Vga Monitor\r
+ * A Microsoft Compatible Mouse\r
+ \r
+ A Mouse is most definitely required, as the keyboard is used for\r
+ nothing except entering file names.\r
+ \r
+FILES NEEDED IN THE CURRENT DIRECTORY:\r
+ \r
+ CSEDIT.EXE - The Font Editor Program\r
+ CHARSETS.CS - The Font Editor's Internal Fonts\r
+ PALETTE.CS - The Font Editor's Palette\r
+ MOUSEIMG.CS - The Font Editor's Mouse Pointer\r
+ \r
+SAMPLE FONT FILE THAT SHOULD BE INCLUDED:\r
+ \r
+ SYSTEM.FNT - The Font used by CSEDIT.EXE\r
+ INVERSE.FNT - An Inverted version of SYSTEM.FNT\r
+ SPACEAGE.FNT - A Futuristic, Tech style font\r
+ ROM_8X8.FNT - The Lower 128 characters from the VGA BIOS Rom\r
+ \r
+WHAT IT EDITS:\r
+ \r
+ 8 by 8 character fonts, 128 characters at a time. 2 fonts at a time.\r
+ \r
+HOW IT WORKS/FEATURES:\r
+ \r
+ CSEDIT allows the user to edit 2 different font groups at a time,\r
+ which may be loaded and saved separately.\r
+ \r
+ A enlarged character grid allows the user to edit individual pixels\r
+ on a selected character.\r
+ \r
+ The Following operations can be performed on a single character or\r
+ simultaneously on a selected block of characters.\r
+ \r
+ * Shift the selected character(s) in any direction\r
+ with or without clipping at the edges.\r
+ * Vertically Flip the selected character(s)\r
+ * Horizontally Flip the selected character(s)\r
+ * Rotate the selected character(s) 90 Degrees Clockwise\r
+ * Rotate the selected character(s) 90 Degrees Counterclockwise\r
+ * Clear the selected character(s)\r
+ * Invert the selected character(s)\r
+ * XOR the selected character(s) with other character(s)\r
+ * AND the selected character(s) with other character(s)\r
+ * OR the selected character(s) with other character(s)\r
+ * Copy the selected character(s) to another position or font.\r
+ \r
+ An UNDO feature allows the reversal of the most recent operation.\r
+ \r
+DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN:\r
+ \r
+ Character Grid: (RED) Box in Upper Left corner of screen. This is\r
+ where you edit an individual character. The Left Button sets the\r
+ pixel the mouse pointer is on, while the Right Button clears that\r
+ pixel.\r
+ \r
+ Scroll Buttons: The Four Scroll Buttons are labeled with directional\r
+ arrows, and arranged in a diamond pattern. Left Clicking on a\r
+ directional button will scroll the currently selected character\r
+ in that direction, with the pixels on the edge rolling off and\r
+ appearing on the other size. Right Clicking will prevent the\r
+ pixels from rolling to the other side.\r
+ \r
+ Vertical Flip Button:\r
+ Horizontal Flip Button: Clicking these buttons will flip the pattern\r
+ of the currently selected character(s) around the indicated axis.\r
+ i.e. the top row will be swapped with the bottom row, etc. or the\r
+ left row column will be swapped with right column, etc.\r
+ depending upon which button you push.\r
+ \r
+ Invert Button: Clicking this button causes all pixels in the selected\r
+ character(s) to flip flop between on and off.\r
+ \r
+ Clear Button: Clicking this button erases the selected characters\r
+ \r
+ Rotate Buttons: Clicking these buttons will rotate the pattern in the\r
+ selected character(s) 90 degrees in the indicated direction.\r
+ \r
+ XOR Button: Clicking this button will let you XOR the currently\r
+ selected character(s) with other character(s) in either font.\r
+ The Button will turn RED, indicating that it is waiting for\r
+ you to click on the desired character (or upper left corner\r
+ of the desired block of characters) in either the Red or Green\r
+ Character Set Displays. Clicking anywhere else will abort this\r
+ process without doing anything. If you click on (any of) the\r
+ selected character(s) the operation is aborted. If a block is\r
+ selected and the character you click on is in a position where\r
+ it can't represent the upper left corner of a block of the same\r
+ size, then the operation is not performed.\r
+ \r
+ AND Button & OR Button: These buttons work just like the XOR Button\r
+ except that the Binary operation performed is either an AND or OR\r
+ depending upon which button you have selected.\r
+ \r
+ COPY Button: This button lets you copy a character or selected block\r
+ of characters to another area in the current font or the other\r
+ font. After clicking, the button turns RED and works much like\r
+ the XOR Button. Clicking on a valid position in either font\r
+ window will copy the selected character(s) to that location.\r
+ \r
+ MODE Button: Clicking this button toggles the editor between BLOCK\r
+ mode and CHARACTER mode. The current mode is displayed on a plate\r
+ at the top of the screen, just to the right of the enlarged\r
+ character grid. In character mode the plate will read "CHAR" and\r
+ the currently selected character is displayed just to the right\r
+ of the plate. In Block mode the plate will read "BLOCK" and the\r
+ enlarged character grid is disabled.\r
+ \r
+ UNDO Button: Clicking this Button will UNDO or reverse the effects of\r
+ the most recent operation.\r
+ \r
+ QUIT Button: Clicking this button will return you to DOS. Any loaded\r
+ fonts are not saved, and no confirmation is given.\r
+ \r
+ \r
+ GREEN FONT AREA: This area displays one of the current fonts which\r
+ can be edited. The characters are display in order from #0 to #127\r
+ from the upper left, going right, then down. The Font Box is 32\r
+ characters wide and 4 characters Tall. When the editor is in\r
+ character mode, just point at and Left Click on the character you\r
+ wish to edit and a Cyan box will appear around that character.\r
+\r
+ * If you Right Click on a character, the last current character,\r
+ which will still appear in the enlarged character grid, will be\r
+ copied onto the character you pointed at, replacing it. This is\r
+ a shortcut for copying characters: You can hold the right button\r
+ down an fill in a large area with a single character pattern.\r
+ When the editor is in Block Mode, you select an area by clicking\r
+ on any corner of the desired block. Then drag the mouse to the\r
+ opposite corner while holding down the left button. A Cyan Box\r
+ will stretch to surround the selected block of characters.\r
+ \r
+ GREEN FONT FILE NAME BOX: This Text Box is used to enter the name\r
+ of a font file to load or the name to save the current Green font\r
+ as. Just click on the Box, and it will change color and a\r
+ flashing cursor will appear. Now you type in a filename or edit\r
+ the existing filename. Press <RETURN> or click outside the text\r
+ box to end editing.\r
+ \r
+ GREEN FONT LOAD BUTTON: Clicking this button will load the font file\r
+ that is named in the Green File name box. If no name is given or\r
+ no such file exists, then nothing will be loaded.\r
+ \r
+ GREEN FONT SAVE BUTTON: Clicking this button will save the current\r
+ font in the Green Font Area under the name given in the File Name\r
+ Box. If a Valid name is not provided, nothing will be saved.\r
+ \r
+ RED FONT AREA: This is just the same as the GREEN FONT AREA; providing\r
+ you with the ability to copy and edit between multiple fonts.\r
+ \r
+ RED FONT FILE NAME BOX: This works just like the GREEN FONT FILE\r
+ NAME BOX.\r
+ \r
+ RED FONT LOAD BUTTON: This works just like the GREEN FONT LOAD BUTTON.\r
+ \r
+ RED FONT SAVE BUTTON: This works just like the GREEN FONT SAVE BUTTON.\r
+ \r
+ Message Bar: At the very bottom of the screen, this Bar will display\r
+ information and messages for various functions.\r
+ \r
+ \r
+FONT FILE FORMAT:\r
+ \r
+ BINARY Image, in order of character. The format is identical to that\r
+ used by the VGA ROM. The Files will be exactly 1024 (128 * 8) bytes\r
+ long.\r
+ \r
+ CHARACTER: 8 Bytes\r
+ \r
+ FONT: Array (0 to 127) of CHARACTER\r
+ \r
+ \r
+COMMENTS, QUESTIONS, BUG REPORTS, etc:\r
+ \r
+ Send the to the Author: Matt Pritchard\r
+ \r
+ Through the 80xxx Fidonet Echo or\r
+ \r
+ Matt Pritchard\r
+ P.O. Box 140264\r
+ Irving, TX 75014\r
+ \r
+CREDITS:\r
+ \r
+ This Font Editor was written in QuickBASIC 4.5\r
+ \r
--- /dev/null
+!ifdef __LINUX__
+REMOVECOMMAND=rm -f
+COPYCOMMAND=cp -f
+DIRSEP=/
+OBJ=o
+!else
+REMOVECOMMAND=del
+COPYCOMMAND=copy /y
+DIRSEP=\
+OBJ=obj
+!endif
+
+CFLAGS=-d2 -0 -mc
+
+all: x_demo.exe
+
+x_demo.exe: x_demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+ wcl $(CFLAGS) x_demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+x_demo.$(OBJ): x_demo.c
+ wcl -c $(CFLAGS) x_demo.c
+
+c_utils.$(OBJ): c_utils.asm
+ wcl -c $(CFLAGS) c_utils.asm
+modex.$(OBJ): modex.asm
+ wcl -c $(CFLAGS) modex.asm
+
+clean: .symbolic
+ @$(REMOVECOMMAND) x-demo.exe
+ @$(REMOVECOMMAND) *.$(OBJ)
+ @$(REMOVECOMMAND) *.err
--- /dev/null
+The following is a FAQ (Frequently Asked Question) summary of \r
+information and assembly routines for Mode "X" Graphics.\r
+\r
+An overview of Mode "X" for the VGA Adaptor:\r
+\r
+1) Mode "X" is a 256 color graphics mode that is available on *ANY* VGA\r
+card with the minimum of 256K video RAM. It is capable of providing\r
+higher resoultions than the only "Official" 256 color mode, mode 13h.\r
+(In quickbasic that is mode 13)\r
+\r
+2) Mode "X" comes in 8 different flavors: 320 or 360 pixels\r
+horizontally, and 200, 240, 400, and 480 pixels vertically.\r
+\r
+3) Since mode X is not supported by the VGA BIOS, there is no built in\r
+support for it. A program must provide its own routines for *ALL*\r
+operations in Mode "X", including setting up the video mode.\r
+\r
+4) Unlike Mode 13h, which has one display page, Mode "X" allows from 1\r
+to 4 video pages, depending upon the resoultion selected. The reason\r
+that Mode 13h has but one page is that it activates a VGA hardware\r
+feature known as CHAIN4, which prevents access to all but 64K of VGA's\r
+video RAM. CHAIN4 is what provides mode 13h's linear addres space.\r
+\r
+5) Unlike Mode 13h, where each 256 color (1-byte) pixel has a unique\r
+address in the E000: segement, in Mode X there are Four (4) Pixels\r
+at each address in E000: segment. The VGA's control registers allow you\r
+to control which of the 4 pixels is currently available at an address.\r
+\r
+6) It is possible to use the VGA's control registers to operate on 2 or\r
+more of the Pixels at the same address at the same time. The CPU can\r
+write one color value, and set up to 4 pixels with that value at the\r
+same time.\r
+\r
+7) Video RAM that is not being used for the current screen display can\r
+be used to store images and patterns. These images and patterns can be\r
+copied to other parts of the Video RAM 4 bytes (32 bits) at a time,\r
+which is much faster than the 8 bits (1 byte) at time that is possible\r
+over the ISA BUS. (16 Bit BUS operations can produce erroneous results)\r
+\r
+If anything is unclear, inadequate, or you just plain want to know more \r
+or have other specific questions, please send me a message.\r
+\r
+\r
+-Matt Pritchard\r
--- /dev/null
+;========================================================\r
+; MODEX.ASM - A Complete Mode X Library\r
+;\r
+; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
+; With considerable input from Michael Abrash\r
+;\r
+; The following information is donated to the public domain in\r
+; the hopes that save other programmers much frustration.\r
+;\r
+; If you do use this code in a product, it would be nice if\r
+; you include a line like "Mode X routines by Matt Pritchard"\r
+; in the credits.\r
+;\r
+; =========================================================\r
+;\r
+; All of this code is designed to be assembled with MASM 5.10a\r
+; but TASM 3.0 could be used as well.\r
+;\r
+; The routines contained are designed for use in a MEDIUM model\r
+; program. All Routines are FAR, and is assumed that a DGROUP\r
+; data segment exists and that DS will point to it on entry.\r
+;\r
+; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
+; will not be preserved, while the DS, BP, SI and DI registers\r
+; will be preserved.\r
+;\r
+; Unless specifically noted, All Parameters are assumed to be\r
+; "PASSED BY VALUE". That is, the actual value is placed on\r
+; the stack. When a reference is passed it is assumed to be\r
+; a near pointer to a variable in the DGROUP segment.\r
+;\r
+; Routines that return a single 16-Bit integer value will\r
+; return that value in the AX register.\r
+;\r
+; This code will *NOT* run on an 8086/8088 because 80286+\r
+; specific instructions are used. If you have an 8088/86\r
+; and VGA, you can buy an 80386-40 motherboard for about\r
+; $160 and move into the 90's.\r
+;\r
+; This code is reasonably optimized: Most drawing loops have\r
+; been unrolled once and memory references are minimized by\r
+; keeping stuff in registers when possible.\r
+;\r
+; Error Trapping varies by Routine. No Clipping is performed\r
+; so the caller should verify that all coordinates are valid.\r
+;\r
+; Several Macros are used to simplify common 2 or 3 instruction\r
+; sequences. Several Single letter Text Constants also\r
+; simplify common assembler expressions like "WORD PTR".\r
+;\r
+; ------------------ Mode X Variations ------------------\r
+;\r
+; Mode # Screen Size Max Pages Aspect Ratio (X:Y)\r
+;\r
+; 0 320 x 200 4 Pages 1.2:1\r
+; 1 320 x 400 2 Pages 2.4:1\r
+; 2 360 x 200 3 Pages 1.35:1\r
+; 3 360 x 400 1 Page 2.7:1\r
+; 4 320 x 240 3 Pages 1:1\r
+; 5 320 x 480 1 Page 2:1\r
+; 6 360 x 240 3 Pages 1.125:1\r
+; 7 360 x 480 1 Page 2.25:1\r
+;\r
+; -------------------- The Legal Stuff ------------------\r
+;\r
+; No warranty, either written or implied, is made as to\r
+; the accuracy and usability of this code product. Use\r
+; at your own risk. Batteries not included. Pepperoni\r
+; and extra cheese available for an additional charge.\r
+;\r
+; ----------------------- The Author --------------------\r
+;\r
+; Matt Pritchard is a paid programmer who'd rather be\r
+; writing games. He can be reached at: P.O. Box 140264,\r
+; Irving, TX 75014 USA. Michael Abrash is a living\r
+; god, who now works for Bill Gates (Microsoft).\r
+;\r
+; -------------------- Revision History -----------------\r
+; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
+; SET_MODEX now saves SI\r
+; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and\r
+; READ_DAC_REGISTERS. Expanded CLR Macro\r
+; to handle multiple registers\r
+;\r
+\r
+ PAGE 255, 132\r
+\r
+ .MODEL Huge\r
+ ;.286\r
+\r
+ ; ===== MACROS =====\r
+\r
+ ; Macro to OUT a 16 bit value to an I/O port\r
+\r
+OUT_16 MACRO Register, Value\r
+ IFDIFI <Register>, <DX> ; If DX not setup\r
+ MOV DX, Register ; then Select Register\r
+ ENDIF\r
+ IFDIFI <Value>, <AX> ; If AX not setup\r
+ MOV AX, Value ; then Get Data Value\r
+ ENDIF\r
+ OUT DX, AX ; Set I/O Register(s)\r
+ENDM\r
+\r
+ ; Macro to OUT a 8 bit value to an I/O Port\r
+\r
+OUT_8 MACRO Register, Value\r
+ IFDIFI <Register>, <DX> ; If DX not setup\r
+ MOV DX, Register ; then Select Register\r
+ ENDIF\r
+ IFDIFI <Value>, <AL> ; If AL not Setup\r
+ MOV AL, Value ; then Get Data Value\r
+ ENDIF\r
+ OUT DX, AL ; Set I/O Register\r
+ENDM\r
+\r
+ ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; PUSH R1 ; Save R1\r
+; PUSHx R2, R3, R4, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+; IFNB <R1>\r
+; POP R1 ; Restore R1\r
+; POPx R2, R3, R4, R5, R6, R7, R8\r
+; ENDIF\r
+; ENDM\r
+\r
+ ; Macro to Clear Registers to 0\r
+\r
+; CLR MACRO Register, R2, R3, R4;, R5, R6\r
+; IFNB <Register>\r
+; XOR Register, Register ; Set Register = 0\r
+; CLR R2, R3, R4;, R5, R6\r
+; ENDIF\r
+; ENDM\r
+\r
+ ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+ DEC Register ; Counter--\r
+ JNZ Destination ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+ DEC Register ; Counter--\r
+ JZ Destination ; Jump if 0\r
+ENDM\r
+\r
+\r
+ ; ===== General Constants =====\r
+\r
+ False EQU 0\r
+ True EQU -1\r
+ nil EQU 0\r
+\r
+ b EQU BYTE PTR\r
+ w EQU WORD PTR\r
+ d EQU DWORD PTR\r
+ o EQU OFFSET\r
+ f EQU FAR PTR\r
+ s EQU SHORT\r
+ ?x1 EQU <?>\r
+\r
+ ; ===== VGA Register Values =====\r
+\r
+ VGA_Segment EQU 0A000h ; Vga Memory Segment\r
+\r
+ ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller\r
+ GC_Index EQU 03CEh ; VGA Graphics Controller\r
+ SC_Index EQU 03C4h ; VGA Sequencer Controller\r
+ SC_Data EQU 03C5h ; VGA Sequencer Data Port\r
+ CRTC_Index EQU 03D4h ; VGA CRT Controller\r
+ CRTC_Data EQU 03D5h ; VGA CRT Controller Data\r
+ MISC_OUTPUT EQU 03C2h ; VGA Misc Register\r
+ INPUT_1 EQU 03DAh ; Input Status #1 Register\r
+\r
+ DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register\r
+ DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register\r
+ PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W\r
+\r
+ PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg\r
+ MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg\r
+ READ_MAP EQU 004h ; GC Index: Read Map Register\r
+ START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi\r
+ START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo\r
+\r
+ MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1\r
+ MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1\r
+ ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes\r
+\r
+ CHAIN4_OFF EQU 00604h ; Chain 4 mode Off\r
+ ASYNC_RESET EQU 00100h ; (A)synchronous Reset\r
+ SEQU_RESTART EQU 00300h ; Sequencer Restart\r
+\r
+ LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches\r
+ LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU\r
+\r
+ VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit\r
+ PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane #\r
+ ALL_PLANES EQU 0Fh ; All Bit Planes Selected\r
+ CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data\r
+\r
+ GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set\r
+ ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer\r
+ ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer\r
+\r
+ ; Constants Specific for these routines\r
+\r
+ NUM_MODES EQU 8 ; # of Mode X Variations\r
+\r
+ ; Specific Mode Data Table format...\r
+\r
+Mode_Data_Table STRUC\r
+ M_MiscR DB ? ; Value of MISC_OUTPUT register\r
+ M_Pages DB ? ; Maximum Possible # of pages\r
+ M_XSize DW ? ; X Size Displayed on screen\r
+ M_YSize DW ? ; Y Size Displayed on screen\r
+ M_XMax DW ? ; Maximum Possible X Size\r
+ M_YMax DW ? ; Maximum Possible Y Size\r
+ M_CRTC DW ? ; Table of CRTC register values\r
+Mode_Data_Table ENDS\r
+\r
+ ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
+\r
+ .DATA?\r
+\r
+SCREEN_WIDTH DW 0 ; Width of a line in Bytes\r
+SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels\r
+\r
+LAST_PAGE DW 0 ; # of Display Pages\r
+PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page\r
+\r
+PAGE_SIZE DW 0 ; Size of Page in Addr Bytes\r
+\r
+DISPLAY_PAGE DW 0 ; Page # currently displayed\r
+ACTIVE_PAGE DW 0 ; Page # currently active\r
+\r
+CURRENT_PAGE DW 0 ; Offset of current Page\r
+CURRENT_SEGMENT DW 0 ; Segment of VGA memory\r
+\r
+CURRENT_XOFFSET DW 0 ; Current Display X Offset\r
+CURRENT_YOFFSET DW 0 ; Current Display Y Offset\r
+\r
+CURRENT_MOFFSET DW 0 ; Current Start Offset\r
+\r
+MAX_XOFFSET DW 0 ; Current Display X Offset\r
+MAX_YOFFSET DW 0 ; Current Display Y Offset\r
+\r
+CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127\r
+CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255\r
+\r
+ .CODE\r
+\r
+ ; ===== DATA TABLES =====\r
+\r
+ ; Data Tables, Put in Code Segment for Easy Access\r
+ ; (Like when all the other Segment Registers are in\r
+ ; use!!) and reduced DGROUP requirements...\r
+\r
+ ; Bit Mask Tables for Left/Right/Character Masks\r
+\r
+Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H\r
+\r
+Right_Clip_Mask DB 01H, 03H, 07H, 0FH\r
+\r
+ ; Bit Patterns for converting character fonts\r
+\r
+Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH\r
+ DB 01H,09H,05H,0DH,03H,0BH,07H,0FH\r
+\r
+ ; CRTC Register Values for Various Configurations\r
+\r
+MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes\r
+ DW 04009H ; Cell Height (1 Scan Line)\r
+ DW 00014H ; Dword Mode off\r
+ DW 0E317H ; turn on Byte Mode\r
+ DW nil ; End of CRTC Data for 400/480 Line Mode\r
+\r
+MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes\r
+ DW 04109H ; Cell Height (2 Scan Lines)\r
+ DW 00014H ; Dword Mode off\r
+ DW 0E317H ; turn on Byte Mode\r
+ DW nil ; End of CRTC Data for 200/240 Line Mode\r
+\r
+MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels\r
+ DW 05F00H ; Horz total\r
+ DW 04F01H ; Horz Displayed\r
+ DW 05002H ; Start Horz Blanking\r
+ DW 08203H ; End Horz Blanking\r
+ DW 05404H ; Start H Sync\r
+ DW 08005H ; End H Sync\r
+ DW nil ; End of CRTC Data for 320 Horz pixels\r
+\r
+MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels\r
+ DW 06B00H ; Horz total\r
+ DW 05901H ; Horz Displayed\r
+ DW 05A02H ; Start Horz Blanking\r
+ DW 08E03H ; End Horz Blanking\r
+ DW 05E04H ; Start H Sync\r
+ DW 08A05H ; End H Sync\r
+ DW nil ; End of CRTC Data for 360 Horz pixels\r
+\r
+MODE_200_Tall:\r
+MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes\r
+ DW 0BF06H ; Vertical Total\r
+ DW 01F07H ; Overflow\r
+ DW 09C10H ; V Sync Start\r
+ DW 08E11H ; V Sync End/Prot Cr0 Cr7\r
+ DW 08F12H ; Vertical Displayed\r
+ DW 09615H ; V Blank Start\r
+ DW 0B916H ; V Blank End\r
+ DW nil ; End of CRTC Data for 200/400 Lines\r
+\r
+MODE_240_Tall:\r
+MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes\r
+ DW 00D06H ; Vertical Total\r
+ DW 03E07H ; Overflow\r
+ DW 0EA10H ; V Sync Start\r
+ DW 08C11H ; V Sync End/Prot Cr0 Cr7\r
+ DW 0DF12H ; Vertical Displayed\r
+ DW 0E715H ; V Blank Start\r
+ DW 00616H ; V Blank End\r
+ DW nil ; End of CRTC Data for 240/480 Lines\r
+\r
+ ; Table of Display Mode Tables\r
+\r
+MODE_TABLE:\r
+ DW o MODE_320x200, o MODE_320x400\r
+ DW o MODE_360x200, o MODE_360x400\r
+ DW o MODE_320x240, o MODE_320x480\r
+ DW o MODE_360x240, o MODE_360x480\r
+\r
+ ; Table of Display Mode Components\r
+\r
+MODE_320x200: ; Data for 320 by 200 Pixels\r
+\r
+ DB 063h ; 400 scan Lines & 25 Mhz Clock\r
+ DB 4 ; Maximum of 4 Pages\r
+ DW 320, 200 ; Displayed Pixels (X,Y)\r
+ DW 1302, 816 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_Wide, o MODE_200_Tall\r
+ DW o MODE_Double_Line, nil\r
+\r
+MODE_320x400: ; Data for 320 by 400 Pixels\r
+\r
+ DB 063h ; 400 scan Lines & 25 Mhz Clock\r
+ DB 2 ; Maximum of 2 Pages\r
+ DW 320, 400 ; Displayed Pixels X,Y\r
+ DW 648, 816 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_Wide, o MODE_400_Tall\r
+ DW o MODE_Single_Line, nil\r
+\r
+MODE_360x240: ; Data for 360 by 240 Pixels\r
+\r
+ DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
+ DB 3 ; Maximum of 3 Pages\r
+ DW 360, 240 ; Displayed Pixels X,Y\r
+ DW 1092, 728 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, o MODE_240_Tall\r
+ DW o MODE_Double_Line , nil\r
+\r
+MODE_360x480: ; Data for 360 by 480 Pixels\r
+\r
+ DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
+ DB 1 ; Only 1 Page Possible\r
+ DW 360, 480 ; Displayed Pixels X,Y\r
+ DW 544, 728 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, o MODE_480_Tall\r
+ DW o MODE_Single_Line , nil\r
+\r
+MODE_320x240: ; Data for 320 by 240 Pixels\r
+\r
+ DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
+ DB 3 ; Maximum of 3 Pages\r
+ DW 320, 240 ; Displayed Pixels X,Y\r
+ DW 1088, 818 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_Wide, o MODE_240_Tall\r
+ DW o MODE_Double_Line, nil\r
+\r
+MODE_320x480: ; Data for 320 by 480 Pixels\r
+\r
+ DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
+ DB 1 ; Only 1 Page Possible\r
+ DW 320, 480 ; Displayed Pixels X,Y\r
+ DW 540, 818 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_320_WIDE, o MODE_480_Tall\r
+ DW o MODE_Single_Line, nil\r
+\r
+MODE_360x200: ; Data for 360 by 200 Pixels\r
+\r
+ DB 067h ; 400 scan Lines & 28 Mhz Clock\r
+ DB 3 ; Maximum of 3 Pages\r
+ DW 360, 200 ; Displayed Pixels (X,Y)\r
+ DW 1302, 728 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, MODE_200_Tall\r
+ DW o MODE_Double_Line, nil\r
+\r
+MODE_360x400: ; Data for 360 by 400 Pixels\r
+\r
+ DB 067h ; 400 scan Lines & 28 Mhz Clock\r
+ DB 1 ; Maximum of 1 Pages\r
+ DW 360, 400 ; Displayed Pixels X,Y\r
+ DW 648, 816 ; Max Possible X and Y Sizes\r
+\r
+ DW o MODE_360_Wide, MODE_400_Tall\r
+ DW o MODE_Single_Line, nil\r
+\r
+\r
+ ; ===== MODE X SETUP ROUTINES =====\r
+\r
+;======================================================\r
+;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
+;======================================================\r
+;\r
+; Sets Up the specified version of Mode X. Allows for\r
+; the setup of multiple video pages, and a virtual\r
+; screen which can be larger than the displayed screen\r
+; (which can then be scrolled a pixel at a time)\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+;\r
+; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio\r
+; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio\r
+; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio\r
+; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio\r
+; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio\r
+; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio\r
+; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
+; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio\r
+;\r
+; MaxXpos = The Desired Virtual Screen Width\r
+; MaxYpos = The Desired Virtual Screen Height\r
+; Pages = The Desired # of Video Pages\r
+;\r
+; EXIT: AX = Success Flag: >0 = Failure / 0 = Success\r
+;\r
+\r
+SVM_STACK STRUC\r
+ SVM_Table DW ? ; Offset of Mode Info Table\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DD ? ; Caller\r
+ SVM_Pages DW ? ; # of Screen Pages desired\r
+ SVM_Ysize DW ? ; Vertical Screen Size Desired\r
+ SVM_Xsize DW ? ; Horizontal Screen Size Desired\r
+ SVM_Mode DW ? ; Display Resolution Desired\r
+SVM_STACK ENDS\r
+\r
+ PUBLIC SET_VGA_MODEX\r
+\r
+SET_VGA_MODEX PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 2 ; Allocate workspace\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Check Legality of Mode Request....\r
+\r
+ MOV BX, [BP].SVM_Mode ; Get Requested Mode #\r
+ CMP BX, NUM_MODES ; Is it 0..7?\r
+ JAE @SVM_BadModeSetup1 ; If Not, Error out\r
+\r
+ SHL BX, 1 ; Scale BX\r
+ MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
+ MOV [BP].SVM_Table, SI ; Save ptr for later use\r
+\r
+ ; Check # of Requested Display Pages\r
+\r
+ MOV CX, [BP].SVM_Pages ; Get # of Requested Pages\r
+ ;CLR CH ; Set Hi Word = 0!\r
+ mov ch,0 ; Set Hi Word = 0!\r
+ CMP CL, CS:[SI].M_Pages ; Check # Pages for mode\r
+ JA @SVM_BadModeSetup2 ; Report Error if too Many Pages\r
+ JCXZ @SVM_BadModeSetup3 ; Report Error if 0 Pages\r
+\r
+ ; Check Validity of X Size\r
+\r
+ AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0\r
+\r
+ MOV AX, [BP].SVM_XSize ; Get Logical Screen Width\r
+ CMP AX, CS:[SI].M_XSize ; Check against Displayed X\r
+ JB @SVM_BadModeSetup4 ; Report Error if too small\r
+ CMP AX, CS:[SI].M_XMax ; Check against Max X\r
+ JA @SVM_BadModeSetup5 ; Report Error if too big\r
+\r
+ ; Check Validity of Y Size\r
+\r
+ MOV BX, [BP].SVM_YSize ; Get Logical Screen Height\r
+ CMP BX, CS:[SI].M_YSize ; Check against Displayed Y\r
+ JB @SVM_BadModeSetup6 ; Report Error if too small\r
+ CMP BX, CS:[SI].M_YMax ; Check against Max Y\r
+ JA @SVM_BadModeSetup7 ; Report Error if too big\r
+\r
+ ; Enough memory to Fit it all?\r
+\r
+ SHR AX, 1 ; # of Bytes:Line = XSize/4\r
+ SHR AX, 1 ; # of Bytes:Line = XSize/4\r
+ MUL CX ; AX = Bytes/Line * Pages\r
+ MUL BX ; DX:AX = Total VGA mem needed\r
+ JNO @SVM_Continue ; Exit if Total Size > 256K\r
+\r
+ DEC DX ; Was it Exactly 256K???\r
+ OR DX, AX ; (DX = 1, AX = 0000)\r
+ JZ @SVM_Continue ; if so, it's valid...\r
+\r
+ jmp @SVM_Continue;0000\r
+\r
+@SVM_BadModeSetup:\r
+ mov ax,8 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup1:\r
+ mov ax,1 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup2:\r
+ mov ax,2 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup3:\r
+ mov ax,3 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup4:\r
+ mov ax,4 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup5:\r
+ mov ax,5 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup6:\r
+ mov ax,6 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+@SVM_BadModeSetup7:\r
+ mov ax,7 ; Return Value = False\r
+ JMP @SVM_Exit ; Normal Exit\r
+\r
+@SVM_Continue:\r
+\r
+ MOV AX, 13H ; Start with Mode 13H\r
+ INT 10H ; Let BIOS Set Mode\r
+\r
+ OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode\r
+ OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset\r
+ OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size\r
+ OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ...\r
+\r
+ OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register\r
+ INC DX ; Point to Data\r
+ IN AL, DX ; Get Value, Bit 7 = Protect\r
+ AND AL, 7FH ; Mask out Write Protect\r
+ OUT DX, AL ; And send it back\r
+\r
+ MOV DX, CRTC_INDEX ; Vga Crtc Registers\r
+ ADD SI, M_CRTC ; SI -> CRTC Parameter Data\r
+\r
+ ; Load Tables of CRTC Parameters from List of Tables\r
+\r
+@SVM_Setup_Table:\r
+\r
+ MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl\r
+ ADD SI, 2 ; Point to next Ptr Entry\r
+ OR DI, DI ; A nil Ptr means that we have\r
+ JZ @SVM_Set_Data ; finished CRTC programming\r
+\r
+@SVM_Setup_CRTC:\r
+ MOV AX, CS:[DI] ; Get CRTC Data from Table\r
+ ADD DI, 2 ; Advance Pointer\r
+ OR AX, AX ; At End of Data Table?\r
+ JZ @SVM_Setup_Table ; If so, Exit & get next Table\r
+\r
+ OUT DX, AX ; Reprogram VGA CRTC reg\r
+ JMP s @SVM_Setup_CRTC ; Process Next Table Entry\r
+\r
+ ; Initialize Page & Scroll info, DI = 0\r
+\r
+@SVM_Set_Data:\r
+ MOV DISPLAY_PAGE, DI ; Display Page = 0\r
+ MOV ACTIVE_PAGE, DI ; Active Page = 0\r
+ MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0\r
+ MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
+ MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
+ MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
+\r
+ MOV AX, VGA_SEGMENT ; Segment for VGA memory\r
+ MOV CURRENT_SEGMENT, AX ; Save for Future LES's\r
+\r
+ ; Set Logical Screen Width, X Scroll and Our Data\r
+\r
+ MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info\r
+ MOV AX, [BP].SVM_Xsize ; Get Display Width\r
+\r
+ MOV CX, AX ; CX = Logical Width\r
+ SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
+ MOV MAX_XOFFSET, CX ; Set Maximum X Scroll\r
+\r
+ SHR AX, 1 ; Bytes = Pixels / 4\r
+ SHR AX, 1 ; Bytes = Pixels / 4\r
+ MOV SCREEN_WIDTH, AX ; Save Width in Pixels\r
+\r
+ SHR AX, 1 ; Offset Value = Bytes / 2\r
+ MOV AH, 13h ; CRTC Offset Register Index\r
+ XCHG AL, AH ; Switch format for OUT\r
+ OUT DX, AX ; Set VGA CRTC Offset Reg\r
+\r
+ ; Setup Data table, Y Scroll, Misc for Other Routines\r
+\r
+ MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height\r
+\r
+ MOV CX, AX ; CX = Logical Height\r
+ SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
+ MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll\r
+\r
+ MOV SCREEN_HEIGHT, AX ; Save Height in Pixels\r
+ MUL SCREEN_WIDTH ; AX = Page Size in Bytes,\r
+ MOV PAGE_SIZE, AX ; Save Page Size\r
+\r
+ MOV CX, [BP].SVM_Pages ; Get # of Pages\r
+ MOV LAST_PAGE, CX ; Save # of Pages\r
+\r
+ mov bx,0 ; Page # = 0\r
+ MOV DX, BX ; Page 0 Offset = 0\r
+\r
+@SVM_Set_Pages:\r
+\r
+ MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset\r
+ ADD BX, 2 ; Page#++\r
+ ADD DX, AX ; Compute Addr of Next Page\r
+ LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set\r
+\r
+ ; Clear VGA Memory\r
+\r
+ OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ LES DI, d CURRENT_PAGE ; -> Start of VGA memory\r
+\r
+ mov ax,0 ; AX = 0\r
+ CLD ; Block Xfer Forwards\r
+ MOV CX, 8000H ; 32K * 4 * 2 = 256K\r
+ REP STOSW ; Clear dat memory!\r
+\r
+ ; Setup Font Pointers\r
+\r
+ MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127\r
+ MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
+ INT 10h ; Call VGA BIOS\r
+\r
+ MOV CHARSET_LOW, BP ; Save Char Set Offset\r
+ MOV CHARSET_LOW+2, ES ; Save Char Set Segment\r
+\r
+ MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255\r
+ MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
+ INT 10h ; Call VGA BIOS\r
+\r
+ MOV CHARSET_HI, BP ; Save Char Set Offset\r
+ MOV CHARSET_HI+2, ES ; Save Char Set Segment\r
+\r
+ MOV AX, True ; Return Success Code\r
+\r
+@SVM_EXIT:\r
+ ADD SP, 2 ; Deallocate workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 8 ; Exit & Clean Up Stack\r
+\r
+SET_VGA_MODEX ENDP\r
+\r
+\r
+;==================\r
+;SET_MODEX% (Mode%)\r
+;==================\r
+;\r
+; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+; (See SET_VGA_MODEX for list)\r
+;\r
+; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+;\r
+\r
+SM_STACK STRUC\r
+ DW ?,? ; BP, SI\r
+ DD ? ; Caller\r
+ SM_Mode DW ? ; Desired Screen Resolution\r
+SM_STACK ENDS\r
+\r
+ PUBLIC SET_MODEX\r
+\r
+SET_MODEX PROC FAR\r
+\r
+ ;PUSHx BP, SI ; Preserve Important registers\r
+ push bp\r
+ push si\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ mov ax,0 ; Assume Failure\r
+ MOV BX, [BP].SM_Mode ; Get Desired Mode #\r
+ CMP BX, NUM_MODES ; Is it a Valid Mode #?\r
+ JAE @SMX_Exit ; If Not, don't Bother\r
+\r
+ PUSH BX ; Push Mode Parameter\r
+\r
+ SHL BX, 1 ; Scale BX to word Index\r
+ MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
+\r
+ PUSH CS:[SI].M_XSize ; Push Default X Size\r
+ PUSH CS:[SI].M_Ysize ; Push Default Y size\r
+ MOV AL, CS:[SI].M_Pages ; Get Default # of Pages\r
+ mov ah,0 ; Hi Byte = 0\r
+ PUSH AX ; Push # Pages\r
+\r
+ CALL f SET_VGA_MODEX ; Set up Mode X!\r
+\r
+@SMX_Exit:\r
+ ;POPx SI, BP ; Restore Registers\r
+ pop si\r
+ pop bp\r
+ RET 2 ; Exit & Clean Up Stack\r
+\r
+SET_MODEX ENDP\r
+\r
+\r
+ ; ===== BASIC GRAPHICS PRIMITIVES =====\r
+\r
+;============================\r
+;CLEAR_VGA_SCREEN (ColorNum%)\r
+;============================\r
+;\r
+; Clears the active display page\r
+;\r
+; ENTRY: ColorNum = Color Value to fill the page with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+CVS_STACK STRUC\r
+ DW ?,? ; DI, BP\r
+ DD ? ; Caller\r
+ CVS_COLOR DB ?,? ; Color to Set Screen to\r
+CVS_STACK ENDS\r
+\r
+ PUBLIC CLEAR_VGA_SCREEN\r
+\r
+CLEAR_VGA_SCREEN PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Preserve Important Registers\r
+ push bp\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AL, [BP].CVS_COLOR ; Get Color\r
+ MOV AH, AL ; Copy for Word Write\r
+ CLD ; Block fill Forwards\r
+\r
+ MOV CX, PAGE_SIZE ; Get Size of Page\r
+ SHR CX, 1 ; Divide by 2 for Words\r
+ REP STOSW ; Block Fill VGA memory\r
+\r
+ ;POPx DI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop bp\r
+ RET 2 ; Exit & Clean Up Stack\r
+\r
+CLEAR_VGA_SCREEN ENDP\r
+\r
+\r
+;===================================\r
+;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
+;===================================\r
+;\r
+; Plots a single Pixel on the active display page\r
+;\r
+; ENTRY: Xpos = X position to plot pixel at\r
+; Ypos = Y position to plot pixel at\r
+; ColorNum = Color to plot pixel with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SP_STACK STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ SETP_Color DB ?,? ; Color of Point to Plot\r
+ SETP_Ypos DW ? ; Y pos of Point to Plot\r
+ SETP_Xpos DW ? ; X pos of Point to Plot\r
+SP_STACK ENDS\r
+\r
+ PUBLIC SET_POINT\r
+\r
+SET_POINT PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Preserve Registers\r
+ push bp\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel\r
+ MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
+\r
+ MOV BX, [BP].SETP_Xpos ; Get Xpos\r
+ MOV CX, BX ; Copy to extract Plane # from\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
+\r
+ MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
+ AND CL, PLANE_BITS ; Get Plane Bits\r
+ SHL AH, CL ; Get Plane Select Value\r
+ OUT_16 SC_Index, AX ; Select Plane\r
+\r
+ MOV AL,[BP].SETP_Color ; Get Pixel Color\r
+ MOV ES:[DI+BX], AL ; Draw Pixel\r
+\r
+ ;POPx DI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop bp\r
+ RET 6 ; Exit and Clean up Stack\r
+\r
+SET_POINT ENDP\r
+\r
+\r
+;==========================\r
+;READ_POINT% (Xpos%, Ypos%)\r
+;==========================\r
+;\r
+; Read the color of a pixel from the Active Display Page\r
+;\r
+; ENTRY: Xpos = X position of pixel to read\r
+; Ypos = Y position of pixel to read\r
+;\r
+; EXIT: AX = Color of Pixel at (Xpos, Ypos)\r
+;\r
+\r
+RP_STACK STRUC\r
+ DW ?,? ; BP, DI\r
+ DD ? ; Caller\r
+ RP_Ypos DW ? ; Y pos of Point to Read\r
+ RP_Xpos DW ? ; X pos of Point to Read\r
+RP_STACK ENDS\r
+\r
+ PUBLIC READ_POINT\r
+\r
+READ_POINT PROC FAR\r
+\r
+ ;PUSHx BP, DI ; Preserve Registers\r
+ push bp\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, [BP].RP_Ypos ; Get Line # of Pixel\r
+ MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
+\r
+ MOV BX, [BP].RP_Xpos ; Get Xpos\r
+ MOV CX, BX\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ SHR BX, 1 ; X offset (Bytes) = Xpos/4\r
+ ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
+\r
+ MOV AL, READ_MAP ; GC Read Mask Register\r
+ MOV AH, CL ; Get Xpos\r
+ AND AH, PLANE_BITS ; & mask out Plane #\r
+ OUT_16 GC_INDEX, AX ; Select Plane to read in\r
+\r
+ mov ah,0 ; Clear Return Value Hi byte\r
+ MOV AL, ES:[DI+BX] ; Get Color of Pixel\r
+\r
+ ;POPx DI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop bp\r
+ RET 4 ; Exit and Clean up Stack\r
+\r
+READ_POINT ENDP\r
+\r
+\r
+;======================================================\r
+;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;======================================================\r
+;\r
+; Fills a rectangular block on the active display Page\r
+;\r
+; ENTRY: Xpos1 = Left X position of area to fill\r
+; Ypos1 = Top Y position of area to fill\r
+; Xpos2 = Right X position of area to fill\r
+; Ypos2 = Bottom Y position of area to fill\r
+; ColorNum = Color to fill area with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+FB_STACK STRUC\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ FB_Color DB ?,? ; Fill Color\r
+ FB_Ypos2 DW ? ; Y pos of Lower Right Pixel\r
+ FB_Xpos2 DW ? ; X pos of Lower Right Pixel\r
+ FB_Ypos1 DW ? ; Y pos of Upper Left Pixel\r
+ FB_Xpos1 DW ? ; X pos of Upper Left Pixel\r
+FB_STACK ENDS\r
+\r
+ PUBLIC FILL_BLOCK\r
+\r
+FILL_BLOCK PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ CLD ; Direction Flag = Forward\r
+\r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+\r
+ ; Validate Pixel Coordinates\r
+ ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
+\r
+ MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2?\r
+ MOV BX, [BP].FB_Ypos2 ; BX = Y2\r
+ CMP AX, BX\r
+ JLE @FB_NOSWAP1\r
+\r
+ MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1\r
+ XCHG AX, BX ; on stack for future use\r
+\r
+@FB_NOSWAP1:\r
+ SUB BX, AX ; Get Y width\r
+ INC BX ; Add 1 to avoid 0 value\r
+ MOV [BP].FB_Ypos2, BX ; Save in Ypos2\r
+\r
+ MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line\r
+ ADD DI, AX ; DI = Start of Line Y1\r
+\r
+ MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2\r
+ MOV BX, [BP].FB_Xpos2 ;\r
+ CMP AX, BX\r
+ JLE @FB_NOSWAP2 ; Skip Ahead if Ok\r
+\r
+ MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2\r
+ XCHG AX, BX ; on stack for future use\r
+\r
+ ; All our Input Values are in order, Now determine\r
+ ; How many full "bands" 4 pixels wide (aligned) there\r
+ ; are, and if there are partial bands (<4 pixels) on\r
+ ; the left and right edges.\r
+\r
+@FB_NOSWAP2:\r
+ MOV DX, AX ; DX = X1 (Pixel Position)\r
+ SHR DX, 1 ; DX/4 = Bytes into Line\r
+ SHR DX, 1 ; DX/4 = Bytes into Line\r
+ ADD DI, DX ; DI = Addr of Upper-Left Corner\r
+\r
+ MOV CX, BX ; CX = X2 (Pixel Position)\r
+ SHR CX, 1 ; CX/4 = Bytes into Line\r
+ SHR CX, 1 ; CX/4 = Bytes into Line\r
+\r
+ CMP DX, CX ; Start and end in same band?\r
+ JNE @FB_NORMAL ; if not, check for l & r edges\r
+ JMP @FB_ONE_BAND_ONLY ; if so, then special processing\r
+\r
+@FB_NORMAL:\r
+ SUB CX, DX ; CX = # bands -1\r
+ MOV SI, AX ; SI = PLANE#(X1)\r
+ AND SI, PLANE_BITS ; if Left edge is aligned then\r
+ JZ @FB_L_PLANE_FLUSH ; no special processing..\r
+\r
+ ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
+\r
+ OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
+\r
+ MOV SI, DI ; SI = Copy of Start Addr (UL)\r
+\r
+ MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+ MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+\r
+@FB_LEFT_LOOP:\r
+ MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn\r
+\r
+ MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn\r
+\r
+@FB_LEFT_CONT:\r
+\r
+ INC DI ; Point to Middle (or Right) Block\r
+ DEC CX ; Reset CX instead of JMP @FB_RIGHT\r
+\r
+@FB_L_PLANE_FLUSH:\r
+ INC CX ; Add in Left band to middle block\r
+\r
+ ; DI = Addr of 1st middle Pixel (band) to fill\r
+ ; CX = # of Bands to fill -1\r
+\r
+@FB_RIGHT:\r
+ MOV SI, [BP].FB_Xpos2 ; Get Xpos2\r
+ AND SI, PLANE_BITS ; Get Plane values\r
+ CMP SI, 0003 ; Plane = 3?\r
+ JE @FB_R_EDGE_FLUSH ; Hey, add to middle\r
+\r
+ ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
+\r
+ OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask\r
+\r
+ MOV SI, DI ; Get Addr of Left Edge\r
+ ADD SI, CX ; Add Width-1 (Bands)\r
+ DEC SI ; To point to top of Right Edge\r
+\r
+ MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+ MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+\r
+@FB_RIGHT_LOOP:\r
+ MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn\r
+\r
+ MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
+ ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn\r
+\r
+@FB_RIGHT_CONT:\r
+\r
+ DEC CX ; Minus 1 for Middle bands\r
+ JZ @FB_EXIT ; Uh.. no Middle bands...\r
+\r
+@FB_R_EDGE_FLUSH:\r
+\r
+ ; DI = Addr of Upper Left block to fill\r
+ ; CX = # of Bands to fill in (width)\r
+\r
+ OUT_8 SC_Data, ALL_PLANES ; Write to All Planes\r
+\r
+ MOV DX, SCREEN_WIDTH ; DX = DI Increment\r
+ SUB DX, CX ; = Screen_Width-# Planes Filled\r
+\r
+ MOV BX, CX ; BX = Quick Refill for CX\r
+ MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+\r
+@FB_MIDDLE_LOOP:\r
+ REP STOSB ; Fill in entire line\r
+\r
+ MOV CX, BX ; Recharge CX (Line Width)\r
+ ADD DI, DX ; Point to start of Next Line\r
+ LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
+\r
+ JMP s @FB_EXIT ; Outa here\r
+\r
+@FB_ONE_BAND_ONLY:\r
+ MOV SI, AX ; Get Left Clip Mask, Save X1\r
+ AND SI, PLANE_BITS ; Mask out Row #\r
+ MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
+ MOV SI, BX ; Get Right Clip Mask, Save X2\r
+ AND SI, PLANE_BITS ; Mask out Row #\r
+ AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
+\r
+ OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
+\r
+ MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ MOV AL, [BP].FB_Color ; Get Fill Color\r
+ MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+\r
+@FB_ONE_LOOP:\r
+ MOV ES:[DI], AL ; Fill in Pixels\r
+ ADD DI, BX ; Point to Next Line (Below)\r
+ LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn\r
+\r
+ MOV ES:[DI], AL ; Fill in Pixels\r
+ ADD DI, BX ; Point to Next Line (Below)\r
+ LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn\r
+\r
+@FB_EXIT:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 10 ; Exit and Clean up Stack\r
+\r
+FILL_BLOCK ENDP\r
+\r
+\r
+;=====================================================\r
+;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;=====================================================\r
+;\r
+; Draws a Line on the active display page\r
+;\r
+; ENTRY: Xpos1 = X position of first point on line\r
+; Ypos1 = Y position of first point on line\r
+; Xpos2 = X position of last point on line\r
+; Ypos2 = Y position of last point on line\r
+; ColorNum = Color to draw line with\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+DL_STACK STRUC\r
+ DW ?x1 ; DI, SI, BP\r
+ DW ?x1 ; DI, SI, BP\r
+ DW ?x1 ; DI, SI, BP\r
+ DD ? ; Caller\r
+ DL_ColorF DB ?,? ; Line Draw Color\r
+ DL_Ypos2 DW ? ; Y pos of last point\r
+ DL_Xpos2 DW ? ; X pos of last point\r
+ DL_Ypos1 DW ? ; Y pos of first point\r
+ DL_Xpos1 DW ? ; X pos of first point\r
+DL_STACK ENDS\r
+\r
+ PUBLIC DRAW_LINE\r
+\r
+DRAW_LINE PROC FAR\r
+\r
+ ;PUSHx BP, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+ CLD ; Direction Flag = Forward\r
+\r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ MOV CH, [BP].DL_ColorF ; Save Line Color in CH\r
+\r
+ ; Check Line Type\r
+\r
+ MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2?\r
+ MOV DI, [BP].DL_Xpos2 ; DX = X2\r
+ CMP SI, DI ; Is X1 < X2\r
+ JE @DL_VLINE ; If X1=X2, Draw Vertical Line\r
+ JL @DL_NOSWAP1 ; If X1 < X2, don't swap\r
+\r
+ XCHG SI, DI ; X2 IS > X1, SO SWAP THEM\r
+\r
+@DL_NOSWAP1:\r
+\r
+ ; SI = X1, DI = X2\r
+\r
+ MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2?\r
+ CMP AX, [BP].DL_Ypos2 ; Y1 = Y2?\r
+ JE @DL_HORZ ; If so, Draw a Horizontal Line\r
+\r
+ JMP @DL_BREZHAM ; Diagonal line... go do it...\r
+\r
+ ; This Code draws a Horizontal Line in Mode X where:\r
+ ; SI = X1, DI = X2, and AX = Y1/Y2\r
+\r
+@DL_HORZ:\r
+\r
+ MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width\r
+ MOV DX, AX ; CX = Line offset into Page\r
+\r
+ MOV AX, SI ; Get Left edge, Save X1\r
+ AND SI, PLANE_BITS ; Mask out Row #\r
+ MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
+ MOV CX, DI ; Get Right edge, Save X2\r
+ AND DI, PLANE_BITS ; Mask out Row #\r
+ MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
+\r
+ SHR AX, 1 ; Get X1 Byte # (=X1/4)\r
+ SHR CX, 1 ; Get X2 Byte # (=X2/4)\r
+ SHR AX, 1 ; Get X1 Byte # (=X1/4)\r
+ SHR CX, 1 ; Get X2 Byte # (=X2/4)\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ ADD DI, DX ; Point to Start of Line\r
+ ADD DI, AX ; Point to Pixel X1\r
+\r
+ SUB CX, AX ; CX = # Of Bands (-1) to set\r
+ JNZ @DL_LONGLN ; jump if longer than one segment\r
+\r
+ AND BL, BH ; otherwise, merge clip masks\r
+\r
+@DL_LONGLN:\r
+\r
+ OUT_8 SC_Data, BL ; Set the Left Clip Mask\r
+\r
+ MOV AL, [BP].DL_ColorF ; Get Line Color\r
+ MOV BL, AL ; BL = Copy of Line Color\r
+ STOSB ; Set Left (1-4) Pixels\r
+\r
+ JCXZ @DL_EXIT ; Done if only one Line Segment\r
+\r
+ DEC CX ; CX = # of Middle Segments\r
+ JZ @DL_XRSEG ; If no middle segments....\r
+\r
+ ; Draw Middle Segments\r
+\r
+ OUT_8 DX, ALL_PLANES ; Write to ALL Planes\r
+\r
+ MOV AL, BL ; Get Color from BL\r
+ REP STOSB ; Draw Middle (4 Pixel) Segments\r
+\r
+@DL_XRSEG:\r
+ OUT_8 DX, BH ; Select Planes for Right Clip Mask\r
+ MOV AL, BL ; Get Color Value\r
+ STOSB ; Draw Right (1-4) Pixels\r
+\r
+ JMP s @DL_EXIT ; We Are Done...\r
+\r
+\r
+ ; This Code Draws A Vertical Line. On entry:\r
+ ; CH = Line Color, SI & DI = X1\r
+\r
+@DL_VLINE:\r
+\r
+ MOV AX, [BP].DL_Ypos1 ; AX = Y1\r
+ MOV SI, [BP].DL_Ypos2 ; SI = Y2\r
+ CMP AX, SI ; Is Y1 < Y2?\r
+ JLE @DL_NOSWAP2 ; if so, Don't Swap them\r
+\r
+ XCHG AX, SI ; Ok, NOW Y1 < Y2\r
+\r
+@DL_NOSWAP2:\r
+\r
+ SUB SI, AX ; SI = Line Height (Y2-Y1+1)\r
+ INC SI\r
+\r
+ ; AX = Y1, DI = X1, Get offset into Page into AX\r
+\r
+ MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width\r
+ MOV DX, DI ; Copy Xpos into DX\r
+ SHR DI, 1 ; DI = Xpos/4\r
+ SHR DI, 1 ; DI = Xpos/4\r
+ ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ ADD DI, AX ; Point to Pixel X1, Y1\r
+\r
+ ;Select Plane\r
+\r
+ MOV CL, DL ; CL = Save X1\r
+ AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #)\r
+ MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
+ SHL AH, CL ; Change to Correct Plane #\r
+ OUT_16 SC_Index, AX ; Select Plane\r
+\r
+ MOV AL, CH ; Get Saved Color\r
+ MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By\r
+\r
+@DL_VLoop:\r
+ MOV ES:[DI], AL ; Draw Single Pixel\r
+ ADD DI, BX ; Point to Next Line\r
+ LOOPjz SI, @DL_EXIT ; Lines--, Exit if done\r
+\r
+ MOV ES:[DI], AL ; Draw Single Pixel\r
+ ADD DI, BX ; Point to Next Line\r
+ LOOPx SI, @DL_VLoop ; Lines--, Loop until Done\r
+\r
+@DL_EXIT:\r
+\r
+ JMP @DL_EXIT2 ; Done!\r
+\r
+ ; This code Draws a diagonal line in Mode X\r
+\r
+@DL_BREZHAM:\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, [BP].DL_Ypos1 ; get Y1 value\r
+ MOV BX, [BP].DL_Ypos2 ; get Y2 value\r
+ MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos\r
+\r
+ CMP BX, AX ; Y2-Y1 is?\r
+ JNC @DL_DeltaYOK ; if Y2>=Y1 then goto...\r
+\r
+ XCHG BX, AX ; Swap em...\r
+ MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos\r
+\r
+@DL_DeltaYOK:\r
+ MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1\r
+\r
+ ADD DI, AX ; DI -> Start of Line Y1 on Page\r
+ MOV AX, CX ; AX = Xpos (X1)\r
+ SHR AX, 1 ; /4 = Byte Offset into Line\r
+ SHR AX, 1 ; /4 = Byte Offset into Line\r
+ ADD DI, AX ; DI = Starting pos (X1,Y1)\r
+\r
+ MOV AL, 11h ; Staring Mask\r
+ AND CL, PLANE_BITS ; Get Plane #\r
+ SHL AL, CL ; and shift into place\r
+ MOV AH, [BP].DL_ColorF ; Color in Hi Bytes\r
+\r
+ PUSH AX ; Save Mask,Color...\r
+\r
+ MOV AH, AL ; Plane # in AH\r
+ MOV AL, MAP_MASK ; Select Plane Register\r
+ OUT_16 SC_Index, AX ; Select initial plane\r
+\r
+ MOV AX, [BP].DL_Xpos1 ; get X1 value\r
+ MOV BX, [BP].DL_Ypos1 ; get Y1 value\r
+ MOV CX, [BP].DL_Xpos2 ; get X2 value\r
+ MOV DX, [BP].DL_Ypos2 ; get Y2 value\r
+\r
+ MOV BP, SCREEN_WIDTH ; Use BP for Line width to\r
+ ; to avoid extra memory access\r
+\r
+ SUB DX, BX ; figure Delta_Y\r
+ JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1\r
+\r
+ ADD BX, DX ; put Y2 into Y1\r
+ NEG DX ; abs(Delta_Y)\r
+ XCHG AX, CX ; and exchange X1 and X2\r
+\r
+@DL_DeltaYOK2:\r
+ MOV BX, 08000H ; seed for fraction accumulator\r
+\r
+ SUB CX, AX ; figure Delta_X\r
+ JC @DL_DrawLeft ; if negative, go left\r
+\r
+ JMP @DL_DrawRight ; Draw Line that slopes right\r
+\r
+@DL_DrawLeft:\r
+\r
+ NEG CX ; abs(Delta_X)\r
+\r
+ CMP CX, DX ; is Delta_X < Delta_Y?\r
+ JB @DL_SteepLeft ; yes, so go do steep line\r
+ ; (Delta_Y iterations)\r
+\r
+ ; Draw a Shallow line to the left in Mode X\r
+\r
+@DL_ShallowLeft:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
+ SBB DX, 0 ; include carry\r
+ DIV CX ; divide by Delta_X\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_X so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
+\r
+@DL_SLLLoop:\r
+ MOV ES:[DI], AH ; set first pixel, plane data set up\r
+ LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_SLLL2nc ; move down on carry\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLLL2nc:\r
+ DEC DI ; Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator,\r
+ JNC @DL_SLLL3nc ; move down on carry\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLLL3nc: ; Now move left a pixel...\r
+ DEC DI ; Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+ JMP s @DL_SLLLoop ; loop until done\r
+\r
+@DL_SLLExit:\r
+ JMP @DL_EXIT2 ; and exit\r
+\r
+ ; Draw a steep line to the left in Mode X\r
+\r
+@DL_SteepLeft:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ XCHG DX, CX ; Delta_Y switched with Delta_X\r
+ DIV CX ; divide by Delta_Y\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add Fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_Y so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
+\r
+@DL_STLLoop:\r
+\r
+ MOV ES:[DI], AH ; set first pixel\r
+ LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_STLnc2 ; No carry, just move down!\r
+\r
+ DEC DI ; Move Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc2:\r
+ ADD DI, BP ; advance to next line.\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_STLnc3 ; No carry, just move down!\r
+\r
+ DEC DI ; Move Left one addr\r
+ ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc3:\r
+ ADD DI, BP ; advance to next line.\r
+ JMP s @DL_STLLoop ; Loop until done\r
+\r
+@DL_STLExit:\r
+ JMP @DL_EXIT2 ; and exit\r
+\r
+ ; Draw a line that goes to the Right...\r
+\r
+@DL_DrawRight:\r
+ CMP CX, DX ; is Delta_X < Delta_Y?\r
+ JB @DL_SteepRight ; yes, so go do steep line\r
+ ; (Delta_Y iterations)\r
+\r
+ ; Draw a Shallow line to the Right in Mode X\r
+\r
+@DL_ShallowRight:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
+ SBB DX, 0 ; include carry\r
+ DIV CX ; divide by Delta_X\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add Fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_X so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
+\r
+@DL_SLRLoop:\r
+ MOV ES:[DI], AH ; set first pixel, mask is set up\r
+ LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_SLR2nc ; don't move down if carry not set\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLR2nc: ; Now move right a pixel...\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @DL_SLR3nc ; don't move down if carry not set\r
+\r
+ ADD DI, BP ; Move Down one line...\r
+\r
+@DL_SLR3nc:\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+ JMP s @DL_SLRLoop ; loop till done\r
+\r
+@DL_SLRExit:\r
+ JMP @DL_EXIT2 ; and exit\r
+\r
+ ; Draw a Steep line to the Right in Mode X\r
+\r
+@DL_SteepRight:\r
+ mov ax,0 ; zero low word of Delta_Y * 10000h\r
+ XCHG DX, CX ; Delta_Y switched with Delta_X\r
+ DIV CX ; divide by Delta_Y\r
+\r
+ MOV SI, BX ; SI = Accumulator\r
+ MOV BX, AX ; BX = Add Fraction\r
+ POP AX ; Get Color, Bit mask\r
+ MOV DX, SC_Data ; Sequence controller data register\r
+ INC CX ; Inc Delta_Y so we can unroll loop\r
+\r
+ ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
+\r
+@STRLoop:\r
+ MOV ES:[DI], AH ; set first pixel, mask is set up\r
+ LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @STRnc2 ; if no carry then just go down...\r
+\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@STRnc2:\r
+ ADD DI, BP ; advance to next line.\r
+\r
+ MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
+\r
+ ADD SI, BX ; add numerator to accumulator\r
+ JNC @STRnc3 ; if no carry then just go down...\r
+\r
+ ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ OUT DX, AL ; Set up New Bit Plane mask\r
+\r
+@STRnc3:\r
+ ADD DI, BP ; advance to next line.\r
+ JMP s @STRLoop ; loop till done\r
+\r
+@DL_EXIT2:\r
+ ;POPx DI, SI, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop bp\r
+ RET 10 ; Exit and Clean up Stack\r
+\r
+DRAW_LINE ENDP\r
+\r
+\r
+ ; ===== DAC COLOR REGISTER ROUTINES =====\r
+\r
+;=================================================\r
+;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
+;=================================================\r
+;\r
+; Sets a single (RGB) Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to modify (0-255)\r
+; Red = The new Red Intensity (0-63)\r
+; Green = The new Green Intensity (0-63)\r
+; Blue = The new Blue Intensity (0-63)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SDR_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SDR_Blue DB ?,? ; Blue Data Value\r
+ SDR_Green DB ?,? ; Green Data Value\r
+ SDR_Red DB ?,? ; Red Data Value\r
+ SDR_Register DB ?,? ; Palette Register #\r
+SDR_STACK ENDS\r
+\r
+ PUBLIC SET_DAC_REGISTER\r
+\r
+SET_DAC_REGISTER PROC FAR\r
+\r
+ PUSH BP ; Save BP\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Select which DAC Register to modify\r
+\r
+ OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register\r
+\r
+ MOV DX, PEL_DATA_REG ; Dac Data Register\r
+ OUT_8 DX, [BP].SDR_Red ; Set Red Intensity\r
+ OUT_8 DX, [BP].SDR_Green ; Set Green Intensity\r
+ OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity\r
+\r
+ POP BP ; Restore Registers\r
+ RET 8 ; Exit & Clean Up Stack\r
+\r
+SET_DAC_REGISTER ENDP\r
+\r
+;====================================================\r
+;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
+;====================================================\r
+;\r
+; Reads the RGB Values of a single Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to read (0-255)\r
+; Red = Offset to Red Variable in DS\r
+; Green = Offset to Green Variable in DS\r
+; Blue = Offset to Blue Variable in DS\r
+;\r
+; EXIT: The values of the integer variables Red,\r
+; Green, and Blue are set to the values\r
+; taken from the specified DAC register.\r
+;\r
+\r
+GDR_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ GDR_Blue DW ? ; Addr of Blue Data Value in DS\r
+ GDR_Green DW ? ; Addr of Green Data Value in DS\r
+ GDR_Red DW ? ; Addr of Red Data Value in DS\r
+ GDR_Register DB ?,? ; Palette Register #\r
+GDR_STACK ENDS\r
+\r
+ PUBLIC GET_DAC_REGISTER\r
+\r
+GET_DAC_REGISTER PROC FAR\r
+\r
+ PUSH BP ; Save BP\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Select which DAC Register to read in\r
+\r
+ OUT_8 DAC_READ_ADDR, [BP].GDR_Register\r
+\r
+ MOV DX, PEL_DATA_REG ; Dac Data Register\r
+ mov ax,0 ; Clear AX\r
+\r
+ IN AL, DX ; Read Red Value\r
+ MOV BX, [BP].GDR_Red ; Get Address of Red%\r
+ MOV [BX], AX ; *Red% = AX\r
+\r
+ IN AL, DX ; Read Green Value\r
+ MOV BX, [BP].GDR_Green ; Get Address of Green%\r
+ MOV [BX], AX ; *Green% = AX\r
+\r
+ IN AL, DX ; Read Blue Value\r
+ MOV BX, [BP].GDR_Blue ; Get Address of Blue%\r
+ MOV [BX], AX ; *Blue% = AX\r
+\r
+ POP BP ; Restore Registers\r
+ RET 8 ; Exit & Clean Up Stack\r
+\r
+GET_DAC_REGISTER ENDP\r
+\r
+\r
+;===========================================================\r
+;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
+;===========================================================\r
+;\r
+; Sets a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData = Far Pointer to Block of palette data\r
+; StartReg = First Register # in range to set (0-255)\r
+; EndReg = Last Register # in Range to set (0-255)\r
+; Sync = Wait for Vertical Retrace Flag (Boolean)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+LDR_STACK STRUC\r
+ DW ?x1 ; BP, DS, SI\r
+ DW ?x1 ; BP, DS, SI\r
+ DW ?x1 ; BP, DS, SI\r
+ DD ? ; Caller\r
+ LDR_Sync DW ? ; Vertical Sync Flag\r
+ LDR_EndReg DB ?,? ; Last Register #\r
+ LDR_StartReg DB ?,? ; First Register #\r
+ LDR_PalData DD ? ; Far Ptr to Palette Data\r
+LDR_STACK ENDS\r
+\r
+ PUBLIC LOAD_DAC_REGISTERS\r
+\r
+LOAD_DAC_REGISTERS PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI ; Save Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag\r
+ or AX, AX ; is Sync Flag = 0?\r
+ jz @LDR_Load ; if so, skip call\r
+\r
+ call f SYNC_DISPLAY ; wait for vsync\r
+\r
+ ; Determine register #'s, size to copy, etc\r
+\r
+@LDR_Load:\r
+\r
+ lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data\r
+ mov DX, DAC_WRITE_ADDR ; DAC register # selector\r
+\r
+ mov ax,0, BX ; Clear for byte loads\r
+ mov AL, [BP].LDR_StartReg ; Get Start Register\r
+ mov BL, [BP].LDR_EndReg ; Get End Register\r
+\r
+ sub BX, AX ; BX = # of DAC registers -1\r
+ inc BX ; BX = # of DAC registers\r
+ mov CX, BX ; CX = # of DAC registers\r
+ add CX, BX ; CX = " " * 2\r
+ add CX, BX ; CX = " " * 3\r
+ cld ; Block OUTs forward\r
+ out DX, AL ; set up correct register #\r
+\r
+ ; Load a block of DAC Registers\r
+\r
+ mov DX, PEL_DATA_REG ; Dac Data Register\r
+\r
+ ;rep outsb ; block set DAC registers\r
+\r
+ ;POPx SI, DS, BP ; Restore Registers\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret 10 ; Exit & Clean Up Stack\r
+\r
+LOAD_DAC_REGISTERS ENDP\r
+\r
+\r
+;====================================================\r
+;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
+;====================================================\r
+;\r
+; Reads a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData = Far Pointer to block to store palette data\r
+; StartReg = First Register # in range to read (0-255)\r
+; EndReg = Last Register # in Range to read (0-255)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+RDR_STACK STRUC\r
+ DW ?x1 ; BP, ES, DI\r
+ DW ?x1 ; BP, ES, DI\r
+ DW ?x1 ; BP, ES, DI\r
+ DD ? ; Caller\r
+ RDR_EndReg DB ?,? ; Last Register #\r
+ RDR_StartReg DB ?,? ; First Register #\r
+ RDR_PalData DD ? ; Far Ptr to Palette Data\r
+RDR_STACK ENDS\r
+\r
+ PUBLIC READ_DAC_REGISTERS\r
+\r
+READ_DAC_REGISTERS PROC FAR\r
+\r
+ ;PUSHx BP, ES, DI ; Save Registers\r
+ push bp\r
+ push es\r
+ push di\r
+ mov BP, SP ; Set up Stack Frame\r
+\r
+ ; Determine register #'s, size to copy, etc\r
+\r
+ les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer\r
+ mov DX, DAC_READ_ADDR ; DAC register # selector\r
+\r
+ mov ax,0, BX ; Clear for byte loads\r
+ mov AL, [BP].RDR_StartReg ; Get Start Register\r
+ mov BL, [BP].RDR_EndReg ; Get End Register\r
+\r
+ sub BX, AX ; BX = # of DAC registers -1\r
+ inc BX ; BX = # of DAC registers\r
+ mov CX, BX ; CX = # of DAC registers\r
+ add CX, BX ; CX = " " * 2\r
+ add CX, BX ; CX = " " * 3\r
+ cld ; Block INs forward\r
+\r
+ ; Read a block of DAC Registers\r
+\r
+ out DX, AL ; set up correct register #\r
+ mov DX, PEL_DATA_REG ; Dac Data Register\r
+\r
+ ;rep insb ; block read DAC registers\r
+\r
+ ;POPx DI, ES, BP ; Restore Registers\r
+ pop di\r
+ pop es\r
+ pop bp\r
+ ret 8 ; Exit & Clean Up Stack\r
+\r
+READ_DAC_REGISTERS ENDP\r
+\r
+\r
+ ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+\r
+;=========================\r
+;SET_ACTIVE_PAGE (PageNo%)\r
+;=========================\r
+;\r
+; Sets the active display Page to be used for future drawing\r
+;\r
+; ENTRY: PageNo = Display Page to make active\r
+; (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SAP_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SAP_Page DW ? ; Page # for Drawing\r
+SAP_STACK ENDS\r
+\r
+ PUBLIC SET_ACTIVE_PAGE\r
+\r
+SET_ACTIVE_PAGE PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ MOV BX, [BP].SAP_Page ; Get Desired Page #\r
+ CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ JAE @SAP_Exit ; IF Not, Do Nothing\r
+\r
+ MOV ACTIVE_PAGE, BX ; Set Active Page #\r
+\r
+ SHL BX, 1 ; Scale Page # to Word\r
+ MOV AX, PAGE_ADDR[BX] ; Get offset to Page\r
+\r
+ MOV CURRENT_PAGE, AX ; And set for future LES's\r
+\r
+@SAP_Exit:\r
+ POP BP ; Restore Registers\r
+ RET 2 ; Exit and Clean up Stack\r
+\r
+SET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;================\r
+;GET_ACTIVE_PAGE%\r
+;================\r
+;\r
+; Returns the Video Page # currently used for Drawing\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Video Page used for Drawing\r
+;\r
+\r
+ PUBLIC GET_ACTIVE_PAGE\r
+\r
+GET_ACTIVE_PAGE PROC FAR\r
+\r
+ MOV AX, ACTIVE_PAGE ; Get Active Page #\r
+ RET ; Exit and Clean up Stack\r
+\r
+GET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;===============================\r
+;SET_DISPLAY_PAGE (DisplayPage%)\r
+;===============================\r
+;\r
+; Sets the currently visible display page.\r
+; When called this routine syncronizes the display\r
+; to the vertical blank.\r
+;\r
+; ENTRY: PageNo = Display Page to show on the screen\r
+; (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SDP_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SDP_Page DW ? ; Page # to Display...\r
+SDP_STACK ENDS\r
+\r
+ PUBLIC SET_DISPLAY_PAGE\r
+\r
+SET_DISPLAY_PAGE PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ MOV BX, [BP].SDP_Page ; Get Desired Page #\r
+ CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ JAE @SDP_Exit ; IF Not, Do Nothing\r
+\r
+ MOV DISPLAY_PAGE, BX ; Set Display Page #\r
+\r
+ SHL BX, 1 ; Scale Page # to Word\r
+ MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page\r
+ ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
+\r
+ ; Wait if we are currently in a Vertical Retrace\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+@DP_WAIT0:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; In Display mode yet?\r
+ JNZ @DP_WAIT0 ; If Not, wait for it\r
+\r
+ ; Set the Start Display Address to the new page\r
+\r
+ MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
+\r
+ MOV AL, START_DISP_LO ; Display Start Low Register\r
+ MOV AH, CL ; Low 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr Low\r
+\r
+ MOV AL, START_DISP_HI ; Display Start High Register\r
+ MOV AH, CH ; High 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr High\r
+\r
+ ; Wait for a Vertical Retrace to smooth out things\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+@DP_WAIT1:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ JZ @DP_WAIT1 ; If Not, wait for it\r
+\r
+ ; Now Set Display Starting Address\r
+\r
+\r
+@SDP_Exit:\r
+ POP BP ; Restore Registers\r
+ RET 2 ; Exit and Clean up Stack\r
+\r
+SET_DISPLAY_PAGE ENDP\r
+\r
+\r
+;=================\r
+;GET_DISPLAY_PAGE%\r
+;=================\r
+;\r
+; Returns the Video Page # currently displayed\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Video Page being displayed\r
+;\r
+\r
+ PUBLIC GET_DISPLAY_PAGE\r
+\r
+GET_DISPLAY_PAGE PROC FAR\r
+\r
+ MOV AX, DISPLAY_PAGE ; Get Display Page #\r
+ RET ; Exit & Clean Up Stack\r
+\r
+GET_DISPLAY_PAGE ENDP\r
+\r
+\r
+;=======================================\r
+;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
+;=======================================\r
+;\r
+; Since a Logical Screen can be larger than the Physical\r
+; Screen, Scrolling is possible. This routine sets the\r
+; Upper Left Corner of the Screen to the specified Pixel.\r
+; Also Sets the Display page to simplify combined page\r
+; flipping and scrolling. When called this routine\r
+; syncronizes the display to the vertical blank.\r
+;\r
+; ENTRY: DisplayPage = Display Page to show on the screen\r
+; Xpos = # of pixels to shift screen right\r
+; Ypos = # of lines to shift screen down\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SW_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SW_Ypos DW ? ; Y pos of UL Screen Corner\r
+ SW_Xpos DW ? ; X pos of UL Screen Corner\r
+ SW_Page DW ? ; (new) Display Page\r
+SW_STACK ENDS\r
+\r
+ PUBLIC SET_WINDOW\r
+\r
+SET_WINDOW PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Check if our Scroll Offsets are Valid\r
+\r
+ MOV BX, [BP].SW_Page ; Get Desired Page #\r
+ CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ JAE @SW_Exit ; IF Not, Do Nothing\r
+\r
+ MOV AX, [BP].SW_Ypos ; Get Desired Y Offset\r
+ CMP AX, MAX_YOFFSET ; Is it Within Limits?\r
+ JA @SW_Exit ; if not, exit\r
+\r
+ MOV CX, [BP].SW_Xpos ; Get Desired X Offset\r
+ CMP CX, MAX_XOFFSET ; Is it Within Limits?\r
+ JA @SW_Exit ; if not, exit\r
+\r
+ ; Compute proper Display start address to use\r
+\r
+ MUL SCREEN_WIDTH ; AX = YOffset * Line Width\r
+ SHR CX, 1 ; CX / 4 = Bytes into Line\r
+ SHR CX, 1 ; CX / 4 = Bytes into Line\r
+ ADD AX, CX ; AX = Offset of Upper Left Pixel\r
+\r
+ MOV CURRENT_MOFFSET, AX ; Save Offset Info\r
+\r
+ MOV DISPLAY_PAGE, BX ; Set Current Page #\r
+ SHL BX, 1 ; Scale Page # to Word\r
+ ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page\r
+ MOV BX, AX ; BX = Desired Display Start\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+ ; Wait if we are currently in a Vertical Retrace\r
+\r
+@SW_WAIT0:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; In Display mode yet?\r
+ JNZ @SW_WAIT0 ; If Not, wait for it\r
+\r
+ ; Set the Start Display Address to the new window\r
+\r
+ MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
+ MOV AL, START_DISP_LO ; Display Start Low Register\r
+ MOV AH, BL ; Low 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr Low\r
+\r
+ MOV AL, START_DISP_HI ; Display Start High Register\r
+ MOV AH, BH ; High 8 Bits of Start Addr\r
+ OUT DX, AX ; Set Display Addr High\r
+\r
+ ; Wait for a Vertical Retrace to smooth out things\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+@SW_WAIT1:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ JZ @SW_WAIT1 ; If Not, wait for it\r
+\r
+ ; Now Set the Horizontal Pixel Pan values\r
+\r
+ OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register\r
+\r
+ MOV AX, [BP].SW_Xpos ; Get Desired X Offset\r
+ AND AL, 03 ; Get # of Pixels to Pan (0-3)\r
+ SHL AL, 1 ; Shift for 256 Color Mode\r
+ OUT DX, AL ; Fine tune the display!\r
+\r
+@SW_Exit:\r
+ POP BP ; Restore Saved Registers\r
+ RET 6 ; Exit and Clean up Stack\r
+\r
+SET_WINDOW ENDP\r
+\r
+\r
+;=============\r
+;GET_X_OFFSET%\r
+;=============\r
+;\r
+; Returns the X coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Horizontal Scroll Offset\r
+;\r
+\r
+ PUBLIC GET_X_OFFSET\r
+\r
+GET_X_OFFSET PROC FAR\r
+\r
+ MOV AX, CURRENT_XOFFSET ; Get current horz offset\r
+ RET ; Exit & Clean Up Stack\r
+\r
+GET_X_OFFSET ENDP\r
+\r
+\r
+;=============\r
+;GET_Y_OFFSET%\r
+;=============\r
+;\r
+; Returns the Y coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: AX = Current Vertical Scroll Offset\r
+;\r
+\r
+ PUBLIC GET_Y_OFFSET\r
+\r
+GET_Y_OFFSET PROC FAR\r
+\r
+ MOV AX, CURRENT_YOFFSET ; Get current vertical offset\r
+ RET ; Exit & Clean Up Stack\r
+\r
+GET_Y_OFFSET ENDP\r
+\r
+\r
+;============\r
+;SYNC_DISPLAY\r
+;============\r
+;\r
+; Pauses the computer until the next Vertical Retrace starts\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+ PUBLIC SYNC_DISPLAY\r
+\r
+SYNC_DISPLAY PROC FAR\r
+\r
+ MOV DX, INPUT_1 ; Input Status #1 Register\r
+\r
+ ; Wait for any current retrace to end\r
+\r
+@SD_WAIT0:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; In Display mode yet?\r
+ JNZ @SD_WAIT0 ; If Not, wait for it\r
+\r
+ ; Wait for the start of the next vertical retrace\r
+\r
+@SD_WAIT1:\r
+ IN AL, DX ; Get VGA status\r
+ AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ JZ @SD_WAIT1 ; If Not, wait for it\r
+\r
+ RET ; Exit & Clean Up Stack\r
+\r
+SYNC_DISPLAY ENDP\r
+\r
+\r
+ ; ===== TEXT DISPLAY ROUTINES =====\r
+\r
+;==================================================\r
+;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;==================================================\r
+;\r
+; Draws an ASCII Text Character using the currently selected\r
+; 8x8 font on the active display page. It would be a simple\r
+; exercise to make this routine process variable height fonts.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+; Xpos = X position to draw Character at\r
+; Ypos = Y position of to draw Character at\r
+; ColorF = Color to draw text character in\r
+; ColorB = Color to set background to\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+GPC_STACK STRUC\r
+ GPC_Width DW ? ; Screen Width-1\r
+ GPC_Lines DB ?,? ; Scan lines to Decode\r
+ GPC_T_SETS DW ? ; Saved Charset Segment\r
+ GPC_T_SETO DW ? ; Saved Charset Offset\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ GPC_ColorB DB ?,? ; Background Color\r
+ GPC_ColorF DB ?,? ; Text Color\r
+ GPC_Ypos DW ? ; Y Position to Print at\r
+ GPC_Xpos DW ? ; X position to Print at\r
+ GPC_Char DB ?,? ; Character to Print\r
+GPC_STACK ENDS\r
+\r
+ PUBLIC GPRINTC\r
+\r
+GPRINTC PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 8 ; Allocate WorkSpace on Stack\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
+ MOV BX, AX ; BX = Screen Width\r
+ DEC BX ; = Screen Width-1\r
+ MOV [BP].GPC_Width, BX ; Save for later use\r
+\r
+ MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width\r
+ ADD DI, AX ; DI -> Start of Line Ypos\r
+\r
+ MOV AX, [BP].GPC_Xpos ; Get Xpos of Character\r
+ MOV CX, AX ; Save Copy of Xpos\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ ADD DI, AX ; DI -> (Xpos, Ypos)\r
+\r
+ ;Get Source ADDR of Character Bit Map & Save\r
+\r
+ MOV AL, [BP].GPC_Char ; Get Character #\r
+ TEST AL, 080h ; Is Hi Bit Set?\r
+ JZ @GPC_LowChar ; Nope, use low char set ptr\r
+\r
+ AND AL, 07Fh ; Mask Out Hi Bit\r
+ MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
+ JMP s @GPC_Set_Char ; Go Setup Character Ptr\r
+\r
+@GPC_LowChar:\r
+\r
+ MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
+\r
+@GPC_Set_Char:\r
+ MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
+\r
+ MOV AH, 0 ; Valid #'s are 0..127\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ ADD BX, AX ; BX = Offset of Selected char\r
+ MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
+\r
+ AND CX, PLANE_BITS ; Get Plane #\r
+ MOV CH, ALL_PLANES ; Get Initial Plane mask\r
+ SHL CH, CL ; And shift into position\r
+ AND CH, ALL_PLANES ; And mask to lower nibble\r
+\r
+ MOV AL, 04 ; 4-Plane # = # of initial\r
+ SUB AL, CL ; shifts to align bit mask\r
+ MOV CL, AL ; Shift Count for SHL\r
+\r
+ ;Get segment of character map\r
+\r
+ OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
+ INC DX ; DX -> SC_Data\r
+\r
+ MOV AL, 08 ; 8 Lines to Process\r
+ MOV [BP].GPC_Lines, AL ; Save on Stack\r
+\r
+ MOV DS, [BP].GPC_T_SETS ; Point to character set\r
+\r
+@GPC_DECODE_CHAR_BYTE:\r
+\r
+ MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
+\r
+ MOV BH, [SI] ; Get Bit Map\r
+ INC SI ; Point to Next Line\r
+ MOV [BP].GPC_T_SETO, SI ; And save new Pointer...\r
+\r
+ mov ax,0 ; Clear AX\r
+\r
+ ;mov bl,0 ; Clear BL\r
+ mov bl,0\r
+ ROL BX, CL ; BL holds left edge bits\r
+ MOV SI, BX ; Use as Table Index\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set\r
+\r
+ MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_LEFT1BITS:\r
+ XOR AL, CH ; Invert mask for Background\r
+ JZ @GPC_NO_LEFT0BITS ; Hey, no need for this\r
+\r
+ MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+ ;Now Do Middle/Last Band\r
+\r
+@GPC_NO_LEFT0BITS:\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set\r
+\r
+ MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE1BITS:\r
+ XOR AL, ALL_PLANES ; Invert mask for Background\r
+ JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
+\r
+ MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE0BITS:\r
+ XOR CH, ALL_PLANES ; Invert Clip Mask\r
+ CMP CL, 4 ; Aligned by 4?\r
+ JZ @GPC_NEXT_LINE ; If so, Exit now..\r
+\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set\r
+\r
+ MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT1BITS:\r
+\r
+ XOR AL, CH ; Invert mask for Background\r
+ JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this\r
+\r
+ MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT0BITS:\r
+ DEC DI ; Adjust for Next Line Advance\r
+\r
+@GPC_NEXT_LINE:\r
+ ADD DI, [BP].GPC_Width ; Point to Next Line\r
+ XOR CH, CHAR_BITS ; Flip the Clip mask back\r
+\r
+ DEC [BP].GPC_Lines ; Count Down Lines\r
+ JZ @GPC_EXIT ; Ok... Done!\r
+\r
+ JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey!\r
+\r
+@GPC_EXIT:\r
+ ADD SP, 08 ; Deallocate stack workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 10 ; Exit and Clean up Stack\r
+\r
+GPRINTC ENDP\r
+\r
+\r
+;==========================================\r
+;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
+;==========================================\r
+;\r
+; Transparently draws an ASCII Text Character using the\r
+; currently selected 8x8 font on the active display page.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+; Xpos = X position to draw Character at\r
+; Ypos = Y position of to draw Character at\r
+; ColorF = Color to draw text character in\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+TGP_STACK STRUC\r
+ TGP_Width DW ? ; Screen Width-1\r
+ TGP_Lines DB ?,? ; Scan lines to Decode\r
+ TGP_T_SETS DW ? ; Saved Charset Segment\r
+ TGP_T_SETO DW ? ; Saved Charset Offset\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ TGP_ColorF DB ?,? ; Text Color\r
+ TGP_Ypos DW ? ; Y Position to Print at\r
+ TGP_Xpos DW ? ; X position to Print at\r
+ TGP_Char DB ?,? ; Character to Print\r
+TGP_STACK ENDS\r
+\r
+ PUBLIC TGPRINTC\r
+\r
+TGPRINTC PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 8 ; Allocate WorkSpace on Stack\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+\r
+ MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
+ MOV BX, AX ; BX = Screen Width\r
+ DEC BX ; = Screen Width-1\r
+ MOV [BP].TGP_Width, BX ; Save for later use\r
+\r
+ MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width\r
+ ADD DI, AX ; DI -> Start of Line Ypos\r
+\r
+ MOV AX, [BP].TGP_Xpos ; Get Xpos of Character\r
+ MOV CX, AX ; Save Copy of Xpos\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ SHR AX, 1 ; Bytes into Line = Xpos/4\r
+ ADD DI, AX ; DI -> (Xpos, Ypos)\r
+\r
+ ;Get Source ADDR of Character Bit Map & Save\r
+\r
+ MOV AL, [BP].TGP_Char ; Get Character #\r
+ TEST AL, 080h ; Is Hi Bit Set?\r
+ JZ @TGP_LowChar ; Nope, use low char set ptr\r
+\r
+ AND AL, 07Fh ; Mask Out Hi Bit\r
+ MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
+ JMP s @TGP_Set_Char ; Go Setup Character Ptr\r
+\r
+@TGP_LowChar:\r
+\r
+ MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
+ MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
+\r
+@TGP_Set_Char:\r
+ MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
+\r
+ MOV AH, 0 ; Valid #'s are 0..127\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ SHL AX, 1 ; * 8 Bytes Per Bitmap\r
+ ADD BX, AX ; BX = Offset of Selected char\r
+ MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
+\r
+ AND CX, PLANE_BITS ; Get Plane #\r
+ MOV CH, ALL_PLANES ; Get Initial Plane mask\r
+ SHL CH, CL ; And shift into position\r
+ AND CH, ALL_PLANES ; And mask to lower nibble\r
+\r
+ MOV AL, 04 ; 4-Plane # = # of initial\r
+ SUB AL, CL ; shifts to align bit mask\r
+ MOV CL, AL ; Shift Count for SHL\r
+\r
+ ;Get segment of character map\r
+\r
+ OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
+ INC DX ; DX -> SC_Data\r
+\r
+ MOV AL, 08 ; 8 Lines to Process\r
+ MOV [BP].TGP_Lines, AL ; Save on Stack\r
+\r
+ MOV DS, [BP].TGP_T_SETS ; Point to character set\r
+\r
+@TGP_DECODE_CHAR_BYTE:\r
+\r
+ MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
+\r
+ MOV BH, [SI] ; Get Bit Map\r
+ INC SI ; Point to Next Line\r
+ MOV [BP].TGP_T_SETO, SI ; And save new Pointer...\r
+\r
+ MOV AH, [BP].TGP_ColorF ; Get Foreground Color\r
+\r
+ mov bl,0 ; Clear BL\r
+ ROL BX, CL ; BL holds left edge bits\r
+ MOV SI, BX ; Use as Table Index\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set\r
+\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+ ;Now Do Middle/Last Band\r
+\r
+@TGP_NO_LEFT1BITS:\r
+\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set\r
+\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@TGP_NO_MIDDLE1BITS:\r
+ XOR CH, ALL_PLANES ; Invert Clip Mask\r
+ CMP CL, 4 ; Aligned by 4?\r
+ JZ @TGP_NEXT_LINE ; If so, Exit now..\r
+\r
+ INC DI ; Point to next Byte\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+ ROL BX, 1 ; Shift 4 bits\r
+\r
+ MOV SI, BX ; Make Lookup Pointer\r
+ AND SI, CHAR_BITS ; Get Low Bits\r
+ MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set\r
+\r
+ OUT DX, AL ; Set up Screen Mask\r
+ MOV ES:[DI], AH ; Write Foreground color\r
+\r
+@TGP_NO_RIGHT1BITS:\r
+\r
+ DEC DI ; Adjust for Next Line Advance\r
+\r
+@TGP_NEXT_LINE:\r
+ ADD DI, [BP].TGP_Width ; Point to Next Line\r
+ XOR CH, CHAR_BITS ; Flip the Clip mask back\r
+\r
+ DEC [BP].TGP_Lines ; Count Down Lines\r
+ JZ @TGP_EXIT ; Ok... Done!\r
+\r
+ JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey!\r
+\r
+@TGP_EXIT:\r
+ ADD SP, 08 ; Deallocate stack workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 8 ; Exit and Clean up Stack\r
+\r
+TGPRINTC ENDP\r
+\r
+\r
+;===============================================================\r
+;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;===============================================================\r
+;\r
+; Routine to quickly Print a null terminated ASCII string on the\r
+; active display page up to a maximum length.\r
+;\r
+; ENTRY: String = Far Pointer to ASCII string to print\r
+; MaxLen = # of characters to print if no null found\r
+; Xpos = X position to draw Text at\r
+; Ypos = Y position of to draw Text at\r
+; ColorF = Color to draw text in\r
+; ColorB = Color to set background to\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+PS_STACK STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ PS_ColorB DW ? ; Background Color\r
+ PS_ColorF DW ? ; Text Color\r
+ PS_Ypos DW ? ; Y Position to Print at\r
+ PS_Xpos DW ? ; X position to Print at\r
+ PS_Len DW ? ; Maximum Length of string to print\r
+ PS_Text DW ?,? ; Far Ptr to Text String\r
+PS_STACK ENDS\r
+\r
+ PUBLIC PRINT_STR\r
+\r
+PRINT_STR PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+@PS_Print_It:\r
+\r
+ MOV CX, [BP].PS_Len ; Get Remaining text Length\r
+ JCXZ @PS_Exit ; Exit when out of text\r
+\r
+ LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text\r
+ MOV AL, ES:[DI] ; AL = Text Character\r
+ AND AX, 00FFh ; Clear High Word\r
+ JZ @PS_Exit ; Exit if null character\r
+\r
+ DEC [BP].PS_Len ; Remaining Text length--\r
+ INC [BP].PS_Text ; Point to Next text char\r
+\r
+ ; Set up Call to GPRINTC\r
+\r
+ PUSH AX ; Set Character Parameter\r
+ MOV BX, [BP].PS_Xpos ; Get Xpos\r
+ PUSH BX ; Set Xpos Parameter\r
+ ADD BX, 8 ; Advance 1 Char to Right\r
+ MOV [BP].PS_Xpos, BX ; Save for next time through\r
+\r
+ MOV BX, [BP].PS_Ypos ; Get Ypos\r
+ PUSH BX ; Set Ypos Parameter\r
+\r
+ MOV BX, [BP].PS_ColorF ; Get Text Color\r
+ PUSH BX ; Set ColorF Parameter\r
+\r
+ MOV BX, [BP].PS_ColorB ; Get Background Color\r
+ PUSH BX ; Set ColorB Parameter\r
+\r
+ CALL f GPRINTC ; Print Character!\r
+ JMP s @PS_Print_It ; Process next character\r
+\r
+@PS_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 14 ; Exit and Clean up Stack\r
+\r
+PRINT_STR ENDP\r
+\r
+\r
+;================================================================\r
+;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;================================================================\r
+;\r
+; Routine to quickly transparently Print a null terminated ASCII\r
+; string on the active display page up to a maximum length.\r
+;\r
+; ENTRY: String = Far Pointer to ASCII string to print\r
+; MaxLen = # of characters to print if no null found\r
+; Xpos = X position to draw Text at\r
+; Ypos = Y position of to draw Text at\r
+; ColorF = Color to draw text in\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+TPS_STACK STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ TPS_ColorF DW ? ; Text Color\r
+ TPS_Ypos DW ? ; Y Position to Print at\r
+ TPS_Xpos DW ? ; X position to Print at\r
+ TPS_Len DW ? ; Maximum Length of string to print\r
+ TPS_Text DW ?,? ; Far Ptr to Text String\r
+TPS_STACK ENDS\r
+\r
+ PUBLIC TPRINT_STR\r
+\r
+TPRINT_STR PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+@TPS_Print_It:\r
+\r
+ MOV CX, [BP].TPS_Len ; Get Remaining text Length\r
+ JCXZ @TPS_Exit ; Exit when out of text\r
+\r
+ LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
+ MOV AL, ES:[DI] ; AL = Text Character\r
+ AND AX, 00FFh ; Clear High Word\r
+ JZ @TPS_Exit ; Exit if null character\r
+\r
+ DEC [BP].TPS_Len ; Remaining Text length--\r
+ INC [BP].TPS_Text ; Point to Next text char\r
+\r
+ ; Set up Call to TGPRINTC\r
+\r
+ PUSH AX ; Set Character Parameter\r
+ MOV BX, [BP].TPS_Xpos ; Get Xpos\r
+ PUSH BX ; Set Xpos Parameter\r
+ ADD BX, 8 ; Advance 1 Char to Right\r
+ MOV [BP].TPS_Xpos, BX ; Save for next time through\r
+\r
+ MOV BX, [BP].TPS_Ypos ; Get Ypos\r
+ PUSH BX ; Set Ypos Parameter\r
+\r
+ MOV BX, [BP].TPS_ColorF ; Get Text Color\r
+ PUSH BX ; Set ColorF Parameter\r
+\r
+ CALL f TGPRINTC ; Print Character!\r
+ JMP s @TPS_Print_It ; Process next character\r
+\r
+@TPS_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 12 ; Exit and Clean up Stack\r
+\r
+TPRINT_STR ENDP\r
+\r
+\r
+;===========================================\r
+;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
+;===========================================\r
+;\r
+; Allows the user to specify their own font data for\r
+; wither the lower or upper 128 characters.\r
+;\r
+; ENTRY: FontData = Far Pointer to Font Bitmaps\r
+; FontNumber = Which half of set this is\r
+; = 0, Lower 128 characters\r
+; = 1, Upper 128 characters\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+SDF_STACK STRUC\r
+ DW ? ; BP\r
+ DD ? ; Caller\r
+ SDF_Which DW ? ; Hi Table/Low Table Flag\r
+ SDF_Font DD ? ; Far Ptr to Font Table\r
+SDF_STACK ENDS\r
+\r
+ PUBLIC SET_DISPLAY_FONT\r
+\r
+SET_DISPLAY_FONT PROC FAR\r
+\r
+ PUSH BP ; Preserve Registers\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, [BP].SDF_Font ; Get Far Ptr to Font\r
+\r
+ MOV SI, o CHARSET_LOW ; Assume Lower 128 chars\r
+ TEST [BP].SDF_Which, 1 ; Font #1 selected?\r
+ JZ @SDF_Set_Font ; If not, skip ahead\r
+\r
+ MOV SI, o CHARSET_HI ; Ah, really it's 128-255\r
+\r
+@SDF_Set_Font:\r
+ MOV [SI], DI ; Set Font Pointer Offset\r
+ MOV [SI+2], ES ; Set Font Pointer Segment\r
+\r
+ POP BP ; Restore Registers\r
+ RET 6 ; We are Done.. Outa here\r
+\r
+SET_DISPLAY_FONT ENDP\r
+\r
+\r
+ ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+\r
+;======================================================\r
+;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;======================================================\r
+;\r
+; Draws a variable sized Graphics Bitmap such as a\r
+; picture or an Icon on the current Display Page in\r
+; Mode X. The Bitmap is stored in a linear byte array\r
+; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
+; This is the same linear manner as mode 13h graphics.\r
+;\r
+; ENTRY: Image = Far Pointer to Bitmap Data\r
+; Xpos = X position to Place Upper Left pixel at\r
+; Ypos = Y position to Place Upper Left pixel at\r
+; Width = Width of the Bitmap in Pixels\r
+; Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+DB_STACK STRUC\r
+ DB_LineO DW ? ; Offset to Next Line\r
+ DB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
+ DB_Start DW ? ; Addr of Upper Left Pixel\r
+ DB_PixSkew DW ? ; # of bytes to Adjust EOL\r
+ DB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ DB_Height DW ? ; Height of Bitmap in Pixels\r
+ DB_Width DW ? ; Width of Bitmap in Pixels\r
+ DB_Ypos DW ? ; Y position to Draw Bitmap at\r
+ DB_Xpos DW ? ; X position to Draw Bitmap at\r
+ DB_Image DD ? ; Far Pointer to Graphics Bitmap\r
+DB_STACK ENDS\r
+\r
+ PUBLIC DRAW_BITMAP\r
+\r
+DRAW_BITMAP PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 10 ; Allocate workspace\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ CLD ; Direction Flag = Forward\r
+\r
+ MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
+\r
+ MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos\r
+ MOV CL, BL ; Save Plane # in CL\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+\r
+ ADD DI, AX ; ES:DI -> Start of Line\r
+ ADD DI, BX ; ES:DI -> Upper Left Pixel\r
+ MOV [BP].DB_Start, DI ; Save Starting Addr\r
+\r
+ ; Compute line to line offset\r
+\r
+ MOV BX, [BP].DB_Width ; Get Width of Image\r
+ MOV DX, BX ; Save Copy in DX\r
+ SHR BX, 1 ; /4 = width in bands\r
+ SHR BX, 1 ; /4 = width in bands\r
+ MOV AX, SCREEN_WIDTH ; Get Screen Width\r
+ SUB AX, BX ; - (Bitmap Width/4)\r
+\r
+ MOV [BP].DB_LineO, AX ; Save Line Width offset\r
+ MOV [BP].DB_PixCount, BX ; Minimum # pix to copy\r
+\r
+ AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
+ MOV [BP].DB_PixSkew, DX ; Also End of Line Skew\r
+ MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count\r
+\r
+ AND CX, PLANE_BITS ; CL = Starting Plane #\r
+ MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ SHL AH, CL ; Select correct Plane\r
+ OUT_16 SC_Index, AX ; Select Plane...\r
+ MOV BH, AH ; BH = Saved Plane Mask\r
+ MOV BL, 4 ; BL = Planes to Copy\r
+\r
+@DB_COPY_PLANE:\r
+\r
+ LDS SI, [BP].DB_Image ; DS:SI-> Source Image\r
+ MOV DX, [BP].DB_Height ; # of Lines to Copy\r
+ MOV DI, [BP].DB_Start ; ES:DI-> Dest pos\r
+\r
+@DB_COPY_LINE:\r
+ MOV CX, [BP].DB_PixCount ; Min # to copy\r
+\r
+ TEST CL, 0FCh ; 16+PixWide?\r
+ JZ @DB_COPY_REMAINDER ; Nope...\r
+\r
+ ; Pixel Copy loop has been unrolled to x4\r
+\r
+@DB_COPY_LOOP:\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+\r
+ SUB CL, 4 ; Pixels to Copy=-4\r
+ TEST CL, 0FCh ; 4+ Pixels Left?\r
+ JNZ @DB_COPY_LOOP ; if so, do another block\r
+\r
+@DB_COPY_REMAINDER:\r
+ JCXZ @DB_NEXT_LINE ; Any Pixels left on line\r
+\r
+@DB_COPY2:\r
+ MOVSB ; Copy Bitmap Pixel\r
+ ADD SI,3 ; Skip to Next Byte in same plane\r
+ LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done\r
+\r
+@DB_NEXT_LINE:\r
+\r
+ ; any Partial Pixels? (some planes only)\r
+\r
+ OR CX, [BP].DB_SkewFlag ; Get Skew Count\r
+ JZ @DB_NEXT2 ; if no partial pixels\r
+\r
+ MOVSB ; Copy Bitmap Pixel\r
+ DEC DI ; Back up to align\r
+ DEC SI ; Back up to align\r
+\r
+@DB_NEXT2:\r
+ ADD SI, [BP].DB_PixSkew ; Adjust Skew\r
+ ADD DI, [BP].DB_LineO ; Set to Next Display Line\r
+ LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more\r
+\r
+ ; Copy Next Plane....\r
+\r
+ DEC BL ; Planes to Go--\r
+ JZ @DB_Exit ; Hey! We are done\r
+\r
+ ROL BH, 1 ; Next Plane in line...\r
+ OUT_8 SC_Data, BH ; Select Plane\r
+\r
+ CMP AL, 12h ; Carry Set if AL=11h\r
+ ADC [BP].DB_Start, 0 ; Screen Addr =+Carry\r
+ INC w [BP].DB_Image ; Start @ Next Byte\r
+\r
+ SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+ JMP s @DB_COPY_PLANE ; Go Copy the Next Plane\r
+\r
+@DB_Exit:\r
+ ADD SP, 10 ; Deallocate workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 12 ; Exit and Clean up Stack\r
+\r
+DRAW_BITMAP ENDP\r
+\r
+\r
+;=======================================================\r
+;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;=======================================================\r
+;\r
+; Transparently Draws a variable sized Graphics Bitmap\r
+; such as a picture or an Icon on the current Display Page\r
+; in Mode X. Pixels with a value of 0 are not drawn,\r
+; leaving the previous "background" contents intact.\r
+;\r
+; The Bitmap format is the same as for the DRAW_BITMAP function.\r
+;\r
+; ENTRY: Image = Far Pointer to Bitmap Data\r
+; Xpos = X position to Place Upper Left pixel at\r
+; Ypos = Y position to Place Upper Left pixel at\r
+; Width = Width of the Bitmap in Pixels\r
+; Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+TB_STACK STRUC\r
+ TB_LineO DW ? ; Offset to Next Line\r
+ TB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
+ TB_Start DW ? ; Addr of Upper Left Pixel\r
+ TB_PixSkew DW ? ; # of bytes to Adjust EOL\r
+ TB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ TB_Height DW ? ; Height of Bitmap in Pixels\r
+ TB_Width DW ? ; Width of Bitmap in Pixels\r
+ TB_Ypos DW ? ; Y position to Draw Bitmap at\r
+ TB_Xpos DW ? ; X position to Draw Bitmap at\r
+ TB_Image DD ? ; Far Pointer to Graphics Bitmap\r
+TB_STACK ENDS\r
+\r
+ PUBLIC TDRAW_BITMAP\r
+\r
+TDRAW_BITMAP PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 10 ; Allocate workspace\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ CLD ; Direction Flag = Forward\r
+\r
+ MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
+\r
+ MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos\r
+ MOV CL, BL ; Save Plane # in CL\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+ SHR BX, 1 ; Xpos/4 = Offset Into Line\r
+\r
+ ADD DI, AX ; ES:DI -> Start of Line\r
+ ADD DI, BX ; ES:DI -> Upper Left Pixel\r
+ MOV [BP].TB_Start, DI ; Save Starting Addr\r
+\r
+ ; Compute line to line offset\r
+\r
+ MOV BX, [BP].TB_Width ; Get Width of Image\r
+ MOV DX, BX ; Save Copy in DX\r
+ SHR BX, 1 ; /4 = width in bands\r
+ SHR BX, 1 ; /4 = width in bands\r
+ MOV AX, SCREEN_WIDTH ; Get Screen Width\r
+ SUB AX, BX ; - (Bitmap Width/4)\r
+\r
+ MOV [BP].TB_LineO, AX ; Save Line Width offset\r
+ MOV [BP].TB_PixCount, BX ; Minimum # pix to copy\r
+\r
+ AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
+ MOV [BP].TB_PixSkew, DX ; Also End of Line Skew\r
+ MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count\r
+\r
+ AND CX, PLANE_BITS ; CL = Starting Plane #\r
+ MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ SHL AH, CL ; Select correct Plane\r
+ OUT_16 SC_Index, AX ; Select Plane...\r
+ MOV BH, AH ; BH = Saved Plane Mask\r
+ MOV BL, 4 ; BL = Planes to Copy\r
+\r
+@TB_COPY_PLANE:\r
+\r
+ LDS SI, [BP].TB_Image ; DS:SI-> Source Image\r
+ MOV DX, [BP].TB_Height ; # of Lines to Copy\r
+ MOV DI, [BP].TB_Start ; ES:DI-> Dest pos\r
+\r
+ ; Here AH is set with the value to be considered\r
+ ; "Transparent". It can be changed!\r
+\r
+ MOV AH, 0 ; Value to Detect 0\r
+\r
+@TB_COPY_LINE:\r
+ MOV CX, [BP].TB_PixCount ; Min # to copy\r
+\r
+ TEST CL, 0FCh ; 16+PixWide?\r
+ JZ @TB_COPY_REMAINDER ; Nope...\r
+\r
+ ; Pixel Copy loop has been unrolled to x4\r
+\r
+@TB_COPY_LOOP:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_01 ; Skip ahead if so\r
+ MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_01:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_02 ; Skip ahead if so\r
+ MOV ES:[DI+1], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_02:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_03 ; Skip ahead if so\r
+ MOV ES:[DI+2], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_03:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_04 ; Skip ahead if so\r
+ MOV ES:[DI+3], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_04:\r
+ ADD DI, 4 ; Adjust Pixel Write Location\r
+ SUB CL, 4 ; Pixels to Copy=-4\r
+ TEST CL, 0FCh ; 4+ Pixels Left?\r
+ JNZ @TB_COPY_LOOP ; if so, do another block\r
+\r
+@TB_COPY_REMAINDER:\r
+ JCXZ @TB_NEXT_LINE ; Any Pixels left on line\r
+\r
+@TB_COPY2:\r
+ LODSB ; Get Pixel Value in AL\r
+ ADD SI, 3 ; Skip to Next Byte in same plane\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_SKIP_05 ; Skip ahead if so\r
+ MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_05:\r
+ INC DI ; Advance Dest Addr\r
+ LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done\r
+\r
+@TB_NEXT_LINE:\r
+\r
+ ; any Partial Pixels? (some planes only)\r
+\r
+ OR CX, [BP].TB_SkewFlag ; Get Skew Count\r
+ JZ @TB_NEXT2 ; if no partial pixels\r
+\r
+ LODSB ; Get Pixel Value in AL\r
+ DEC SI ; Backup to Align\r
+ CMP AL, AH ; It is "Transparent"?\r
+ JE @TB_NEXT2 ; Skip ahead if so\r
+ MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+\r
+@TB_NEXT2:\r
+ ADD SI, [BP].TB_PixSkew ; Adjust Skew\r
+ ADD DI, [BP].TB_LineO ; Set to Next Display Line\r
+ LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More\r
+\r
+ ;Copy Next Plane....\r
+\r
+ DEC BL ; Planes to Go--\r
+ JZ @TB_Exit ; Hey! We are done\r
+\r
+ ROL BH, 1 ; Next Plane in line...\r
+ OUT_8 SC_Data, BH ; Select Plane\r
+\r
+ CMP AL, 12h ; Carry Set if AL=11h\r
+ ADC [BP].TB_Start, 0 ; Screen Addr =+Carry\r
+ INC w [BP].TB_Image ; Start @ Next Byte\r
+\r
+ SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+ JMP @TB_COPY_PLANE ; Go Copy the next Plane\r
+\r
+@TB_Exit:\r
+ ADD SP, 10 ; Deallocate workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 12 ; Exit and Clean up Stack\r
+\r
+TDRAW_BITMAP ENDP\r
+\r
+\r
+ ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+\r
+;==================================\r
+;COPY_PAGE (SourcePage%, DestPage%)\r
+;==================================\r
+;\r
+; Duplicate on display page onto another\r
+;\r
+; ENTRY: SourcePage = Display Page # to Duplicate\r
+; DestPage = Display Page # to hold copy\r
+;\r
+; EXIT: No meaningful values returned\r
+;\r
+\r
+CP_STACK STRUC\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ CP_DestP DW ? ; Page to hold copied image\r
+ CP_SourceP DW ? ; Page to Make copy from\r
+CP_STACK ENDS\r
+\r
+ PUBLIC COPY_PAGE\r
+\r
+COPY_PAGE PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ MOV BP, SP ; Set up Stack Frame\r
+ CLD ; Block Xfer Forwards\r
+\r
+ ; Make sure Page #'s are valid\r
+\r
+ MOV AX, [BP].CP_SourceP ; Get Source Page #\r
+ CMP AX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CP_Exit ; if so, abort\r
+\r
+ MOV BX, [BP].CP_DestP ; Get Destination Page #\r
+ CMP BX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CP_Exit ; if so, abort\r
+\r
+ CMP AX, BX ; Pages #'s the same?\r
+ JE @CP_Exit ; if so, abort\r
+\r
+ ; Setup DS:SI and ES:DI to Video Pages\r
+\r
+ SHL BX, 1 ; Scale index to Word\r
+ MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page\r
+\r
+ MOV BX, AX ; Index to Source page\r
+ SHL BX, 1 ; Scale index to Word\r
+ MOV SI, PAGE_ADDR[BX] ; Offset to Source Page\r
+\r
+ MOV CX, PAGE_SIZE ; Get size of Page\r
+ MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
+ MOV ES, AX ; ES:DI -> Dest Page\r
+ MOV DS, AX ; DS:SI -> Source Page\r
+\r
+ ; Setup VGA registers for Mem to Mem copy\r
+\r
+ OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
+ OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes\r
+\r
+ ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
+ ; Screw with the latches which are 8 bits x 4\r
+\r
+ REP MOVSB ; Copy entire Page!\r
+\r
+ ; Reset VGA for normal memory access\r
+\r
+ OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off\r
+\r
+@CP_Exit:\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 4 ; Exit and Clean up Stack\r
+\r
+COPY_PAGE ENDP\r
+\r
+\r
+;==========================================================================\r
+;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
+;==========================================================================\r
+;\r
+; Copies a Bitmap Image from one Display Page to Another\r
+; This Routine is Limited to copying Images with the same\r
+; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
+; Copying an Image to the Same Page is supported, but results\r
+; may be defined when the when the rectangular areas\r
+; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
+; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
+; No Paramter checking to done to insure that\r
+; X2 >= X1 and Y2 >= Y1. Be Careful...\r
+;\r
+; ENTRY: SourcePage = Display Page # with Source Image\r
+; X1 = Upper Left Xpos of Source Image\r
+; Y1 = Upper Left Ypos of Source Image\r
+; X2 = Lower Right Xpos of Source Image\r
+; Y2 = Lower Right Ypos of Source Image\r
+; DestPage = Display Page # to copy Image to\r
+; DestX1 = Xpos to Copy UL Corner of Image to\r
+; DestY1 = Ypos to Copy UL Corner of Image to\r
+;\r
+; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+;\r
+\r
+CB_STACK STRUC\r
+ CB_Height DW ? ; Height of Image in Lines\r
+ CB_Width DW ? ; Width of Image in "bands"\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DI, SI, DS, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DW ?x1 ; DS, DI, SI, BP\r
+ DD ? ; Caller\r
+ CB_DestY1 DW ? ; Destination Ypos\r
+ CB_DestX1 DW ? ; Destination Xpos\r
+ CB_DestP DW ? ; Page to Copy Bitmap To\r
+ CB_Y2 DW ? ; LR Ypos of Image\r
+ CB_X2 DW ? ; LR Xpos of Image\r
+ CB_Y1 DW ? ; UL Ypos of Image\r
+ CB_X1 DW ? ; UL Xpos of Image\r
+ CB_SourceP DW ? ; Page containing Source Bitmap\r
+CB_STACK ENDS\r
+\r
+ PUBLIC COPY_BITMAP\r
+\r
+COPY_BITMAP PROC FAR\r
+\r
+ ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ push bp\r
+ push ds\r
+ push si\r
+ push di\r
+ SUB SP, 4 ; Allocate WorkSpace on Stack\r
+ MOV BP, SP ; Set up Stack Frame\r
+\r
+ ; Prep Registers (and keep jumps short!)\r
+\r
+ MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
+ CLD ; Block Xfer Forwards\r
+\r
+ ; Make sure Parameters are valid\r
+\r
+ MOV BX, [BP].CB_SourceP ; Get Source Page #\r
+ CMP BX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CB_Abort ; if so, abort\r
+\r
+ MOV CX, [BP].CB_DestP ; Get Destination Page #\r
+ CMP CX, LAST_PAGE ; is it > Max Page #?\r
+ JAE @CB_Abort ; if so, abort\r
+\r
+ MOV AX, [BP].CB_X1 ; Get Source X1\r
+ XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1\r
+ AND AX, PLANE_BITS ; Check Plane Bits\r
+ JNZ @CB_Abort ; They should cancel out\r
+\r
+ ; Setup for Copy processing\r
+\r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
+\r
+ ; Compute Info About Images, Setup ES:SI & ES:DI\r
+\r
+ MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines\r
+ SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1\r
+ INC AX ; (add 1 since were not 0 based)\r
+ MOV [BP].CB_Height, AX ; Save on Stack for later use\r
+\r
+ MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels\r
+ MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1\r
+ SHR AX, 1 ; Get X2 Band (X2 / 4)\r
+ SHR DX, 1 ; Get X1 Band (X1 / 4)\r
+ SHR AX, 1 ; Get X2 Band (X2 / 4)\r
+ SHR DX, 1 ; Get X1 Band (X1 / 4)\r
+ SUB AX, DX ; AX = # of Bands - 1\r
+ INC AX ; AX = # of Bands\r
+ MOV [BP].CB_Width, AX ; Save on Stack for later use\r
+\r
+ SHL BX, 1 ; Scale Source Page to Word\r
+ MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page\r
+ MOV AX, [BP].CB_Y1 ; Get Source Y1 Line\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
+ ADD SI, AX ; SI = Offset to Line Y1\r
+ MOV AX, [BP].CB_X1 ; Get Source X1\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ ADD SI, AX ; SI = Byte Offset to (X1,Y1)\r
+\r
+ MOV BX, CX ; Dest Page Index to BX\r
+ SHL BX, 1 ; Scale Source Page to Word\r
+ MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page\r
+ MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line\r
+ MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
+ ADD DI, AX ; DI = Offset to Line Y1\r
+ MOV AX, [BP].CB_DestX1 ; Get Dest X1\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ SHR AX, 1 ; X1 / 4 = Byte offset\r
+ ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1)\r
+\r
+ MOV CX, [BP].CB_Width ; CX = Width of Image (Bands)\r
+ DEC CX ; CX = 1?\r
+ JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band\r
+\r
+ MOV BX, [BP].CB_X1 ; Get Source X1\r
+ AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?)\r
+ JZ @CB_Check_Right ; if so, check right alignment\r
+ JNZ @CB_Left_Band ; not aligned? well..\r
+\r
+@CB_Abort:\r
+ mov ax,0 ; Return False (Failure)\r
+ JMP @CB_Exit ; and Finish Up\r
+\r
+ ; Copy when Left & Right Clip Masks overlap...\r
+\r
+@CB_Only_One_Band:\r
+ MOV BX, [BP].CB_X1 ; Get Left Clip Mask\r
+ AND BX, PLANE_BITS ; Mask out Row #\r
+ MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask\r
+ MOV BX, [BP].CB_X2 ; Get Right Clip Mask\r
+ AND BX, PLANE_BITS ; Mask out Row #\r
+ AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
+\r
+ OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
+\r
+ MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ mov bx,0 ; BX = Offset into Image\r
+\r
+@CB_One_Loop:\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_One_Done ; Exit Loop if Finished\r
+\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_One_Loop ; Loop until Finished\r
+\r
+@CB_One_Done:\r
+ JMP @CB_Finish ; Outa Here!\r
+\r
+ ; Copy Left Edge of Bitmap\r
+\r
+@CB_Left_Band:\r
+\r
+ OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
+\r
+ MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ mov bx,0 ; BX = Offset into Image\r
+\r
+@CB_Left_Loop:\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished\r
+\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_Left_Loop ; Loop until Finished\r
+\r
+@CB_Left_Done:\r
+ INC DI ; Move Dest Over 1 band\r
+ INC SI ; Move Source Over 1 band\r
+ DEC [BP].CB_Width ; Band Width--\r
+\r
+ ; Determine if Right Edge of Bitmap needs special copy\r
+\r
+@CB_Check_Right:\r
+ MOV BX, [BP].CB_X2 ; Get Source X2\r
+ AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?)\r
+ CMP BL, 03h ; Plane = 3?\r
+ JE @CB_Copy_Middle ; Copy the Middle then!\r
+\r
+ ; Copy Right Edge of Bitmap\r
+\r
+@CB_Right_Band:\r
+\r
+ OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask\r
+\r
+ DEC [BP].CB_Width ; Band Width--\r
+ MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ MOV BX, [BP].CB_Width ; BX = Offset to Right Edge\r
+\r
+@CB_Right_Loop:\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished\r
+\r
+ MOV AL, ES:[SI+BX] ; Load Latches\r
+ MOV ES:[DI+BX], AL ; Unload Latches\r
+ ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_Right_Loop ; Loop until Finished\r
+\r
+@CB_Right_Done:\r
+\r
+ ; Copy the Main Block of the Bitmap\r
+\r
+@CB_Copy_Middle:\r
+\r
+ MOV CX, [BP].CB_Width ; Get Width Remaining\r
+ JCXZ @CB_Finish ; Exit if Done\r
+\r
+ OUT_8 SC_Data, ALL_PLANES ; Copy all Planes\r
+\r
+ MOV DX, SCREEN_WIDTH ; Get Width of Screen minus\r
+ SUB DX, CX ; Image width (for Adjustment)\r
+ MOV AX, [BP].CB_Height ; AX = # of Lines to Copy\r
+ MOV BX, CX ; BX = Quick REP reload count\r
+ MOV CX, ES ; Move VGA Segment\r
+ MOV DS, CX ; Into DS\r
+\r
+ ; Actual Copy Loop. REP MOVSB does the work\r
+\r
+@CB_Middle_Copy:\r
+ MOV CX, BX ; Recharge Rep Count\r
+ REP MOVSB ; Move Bands\r
+ LOOPjz AX, @CB_Finish ; Exit Loop if Finished\r
+\r
+ ADD SI, DX ; Adjust DS:SI to Next Line\r
+ ADD DI, DX ; Adjust ES:DI to Next Line\r
+\r
+ MOV CX, BX ; Recharge Rep Count\r
+ REP MOVSB ; Move Bands\r
+\r
+ ADD SI, DX ; Adjust DS:SI to Next Line\r
+ ADD DI, DX ; Adjust ES:DI to Next Line\r
+ LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done\r
+\r
+@CB_Finish:\r
+ OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on\r
+\r
+@CB_Exit:\r
+ ADD SP, 04 ; Deallocate stack workspace\r
+ ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ RET 16 ; Exit and Clean up Stack\r
+\r
+COPY_BITMAP ENDP\r
+\r
+ END ; End of Code Segment\r
--- /dev/null
+ \r
+ ' ===== SCREEN RESOLUTIONS =====\r
+ \r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
+ \r
+ ' ===== MODE X SETUP ROUTINES =====\r
+ \r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
+ \r
+ ' ===== BASIC GRAPHICS PRIMITIVES =====\r
+ \r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+ \r
+ ' ===== DAC COLOR REGISTER ROUTINES =====\r
+ \r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
+ \r
+ \r
+ ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+ \r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
+ \r
+ ' ===== TEXT DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
+ \r
+ ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+ \r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+ \r
+ ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+ \r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
--- /dev/null
+\r
+#ifndef __MODEX_H\r
+#define __MODEX_H\r
+\r
+ /* ===== SCREEN RESOLUTIONS ===== */\r
+\r
+#define Mode_320x200 0\r
+#define Mode_320x400 1\r
+#define Mode_360x200 2\r
+#define Mode_360x400 3\r
+#define Mode_320x240 4\r
+#define Mode_320x480 5\r
+#define Mode_360x240 6\r
+#define Mode_360x480 7\r
+\r
+ /* ===== MODE X SETUP ROUTINES ===== */\r
+\r
+int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages);\r
+int far pascal set_modex (int Mode);\r
+\r
+ /* ===== BASIC GRAPHICS PRIMITIVES ===== */\r
+\r
+void far pascal clear_vga_screen (int Color);\r
+void far pascal set_point (int Xpos, int Ypos, int Color);\r
+int far pascal read_point (int Xpos, int Ypos);\r
+void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+ int Color);\r
+void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+ int Color);\r
+\r
+ /* ===== DAC COLOR REGISTER ROUTINES ===== */\r
+\r
+void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue);\r
+void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue);\r
+void far pascal load_dac_registers (char far *PalData, int StartReg,\r
+ int EndReg, int VSync);\r
+void far pascal readd_dac_registers (char far *PalData, int StartReg,\r
+ int EndReg);\r
+\r
+ /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */\r
+\r
+void far pascal set_active_page (int PageNo);\r
+int far pascal get_active_page (void);\r
+void far pascal set_display_page (int PageNo);\r
+int far pascal get_display_page (void);\r
+void far pascal set_window (int DisplayPage, int XOffset, int YOffset);\r
+int far pascal get_x_offset (void);\r
+int far pascal get_y_offset (void);\r
+void far pascal sync_display (void);\r
+\r
+ /* ===== TEXT DISPLAY ROUTINES ===== */\r
+\r
+void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF,\r
+ int ColorB);\r
+void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF);\r
+void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+ int ColorF, int ColorB);\r
+void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+ int ColorF);\r
+void far pascal set_display_font (char far *FontData, int FontNumber);\r
+\r
+ /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */\r
+\r
+void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos,\r
+ int Width, int Height);\r
+void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos,\r
+ int Width, int Height);\r
+\r
+ /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */\r
+\r
+void far pascal copy_page (int SourcePage, int DestPage);\r
+void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2,\r
+ int DestPage, int DestX1, int DestY1);\r
+\r
+\r
+#endif\r
--- /dev/null
+Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 1 - 1\r
+\r
+\r
+ ;========================================================\r
+ ; MODEX.ASM - A Complete Mode X Library\r
+ ;\r
+ ; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
+ ; With considerable input from Michael Abrash\r
+ ;\r
+ ; The following information is donated to the public domain in\r
+ ; the hopes that save other programmers much frustration.\r
+ ;\r
+ ; If you do use this code in a product, it would be nice if\r
+ ; you include a line like "Mode X routines by Matt Pritchard"\r
+ ; in the credits.\r
+ ;\r
+ ; =========================================================\r
+ ;\r
+ ; All of this code is designed to be assembled with MASM 5.10a\r
+ ; but TASM 3.0 could be used as well.\r
+ ;\r
+ ; The routines contained are designed for use in a MEDIUM model\r
+ ; program. All Routines are FAR, and is assumed that a DGROUP\r
+ ; data segment exists and that DS will point to it on entry.\r
+ ;\r
+ ; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
+ ; will not be preserved, while the DS, BP, SI and DI registers\r
+ ; will be preserved.\r
+ ;\r
+ ; Unless specifically noted, All Parameters are assumed to be\r
+ ; "PASSED BY VALUE". That is, the actual value is placed on\r
+ ; the stack. When a reference is passed it is assumed to be\r
+ ; a near pointer to a variable in the DGROUP segment.\r
+ ;\r
+ ; Routines that return a single 16-Bit integer value will\r
+ ; return that value in the AX register.\r
+ ;\r
+ ; This code will *NOT* run on an 8086/8088 because 80286+\r
+ ; specific instructions are used. If you have an 8088/86\r
+ ; and VGA, you can buy an 80386-40 motherboard for about\r
+ ; $160 and move into the 90's.\r
+ ;\r
+ ; This code is reasonably optimized: Most drawing loops have\r
+ ; been unrolled once and memory references are minimized by\r
+ ; keeping stuff in registers when possible.\r
+ ;\r
+ ; Error Trapping varies by Routine. No Clipping is performed\r
+ ; so the caller should verify that all coordinates are valid.\r
+ ;\r
+ ; Several Macros are used to simplify common 2 or 3 instruction\r
+ ; sequences. Several Single letter Text Constants also\r
+ ; simplify common assembler expressions like "WORD PTR".\r
+ ;\r
+ ; ------------------ Mode X Variations ------------------\r
+ ;\r
+ ; Mode # Screen Size Max Pages Aspect Ratio (X:Y)\r
+ ;\r
+ ; 0 320 x 200 4 Pages 1.2:1\r
+ ; 1 320 x 400 2 Pages 2.4:1\r
+ ; 2 360 x 200 3 Pages 1.35:1\r
+ ; 3 360 x 400 1 Page 2.7:1\r
+ ; 4 320 x 240 3 Pages 1:1\r
+ ; 5 320 x 480 1 Page 2:1\r
+ ; 6 360 x 240 3 Pages 1.125:1\r
+ ; 7 360 x 480 1 Page 2.25:1\r
+ ;\r
+ ; -------------------- The Legal Stuff ------------------\r
+ ;\r
+ ; No warranty, either written or implied, is made as to\r
+ ; the accuracy and usability of this code product. Use\r
+ ; at your own risk. Batteries not included. Pepperoni\r
+ ; and extra cheese available for an additional charge.\r
+ ;\r
+ ; ----------------------- The Author --------------------\r
+ ;\r
+ ; Matt Pritchard is a paid programmer who'd rather be\r
+ ; writing games. He can be reached at: P.O. Box 140264,\r
+ ; Irving, TX 75014 USA. Michael Abrash is a living\r
+ ; god, who now works for Bill Gates (Microsoft).\r
+ ;\r
+ ; -------------------- Revision History -----------------\r
+ ; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
+ ; SET_MODEX now saves SI\r
+ ; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and\r
+ ; READ_DAC_REGISTERS. Expanded CLR Macro\r
+ ; to handle multiple registers\r
+ ;\r
+ \r
+ PAGE 255, 132\r
+ \r
+ .MODEL Medium\r
+ .286\r
+ \r
+ ; ===== MACROS =====\r
+ \r
+ ; Macro to OUT a 16 bit value to an I/O port\r
+ \r
+ OUT_16 MACRO Register, Value\r
+ IFDIFI <Register>, <DX> ; If DX not setup\r
+ MOV DX, Register ; then Select Register\r
+ ENDIF\r
+ IFDIFI <Value>, <AX> ; If AX not setup\r
+ MOV AX, Value ; then Get Data Value\r
+ ENDIF\r
+ OUT DX, AX ; Set I/O Register(s)\r
+ ENDM\r
+ \r
+ ; Macro to OUT a 8 bit value to an I/O Port\r
+ \r
+ OUT_8 MACRO Register, Value\r
+ IFDIFI <Register>, <DX> ; If DX not setup\r
+ MOV DX, Register ; then Select Register\r
+ ENDIF\r
+ IFDIFI <Value>, <AL> ; If AL not Setup\r
+ MOV AL, Value ; then Get Data Value\r
+ ENDIF\r
+ OUT DX, AL ; Set I/O Register\r
+ ENDM\r
+ \r
+ ; macros to PUSH and POP multiple registers\r
+ \r
+ PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ PUSH R1 ; Save R1\r
+ PUSHx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ ENDM\r
+ \r
+ POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+ IFNB <R1>\r
+ POP R1 ; Restore R1\r
+ POPx R2, R3, R4, R5, R6, R7, R8\r
+ ENDIF\r
+ ENDM\r
+ \r
+ ; Macro to Clear Registers to 0\r
+ \r
+ CLR MACRO Register, R2, R3, R4, R5, R6\r
+ IFNB <Register>\r
+ XOR Register, Register ; Set Register = 0\r
+ CLR R2, R3, R4, R5, R6\r
+ ENDIF\r
+ ENDM\r
+ \r
+ ; Macros to Decrement Counter & Jump on Condition\r
+ \r
+ LOOPx MACRO Register, Destination\r
+ DEC Register ; Counter--\r
+ JNZ Destination ; Jump if not 0\r
+ ENDM\r
+ \r
+ LOOPjz MACRO Register, Destination\r
+ DEC Register ; Counter--\r
+ JZ Destination ; Jump if 0\r
+ ENDM\r
+ \r
+ \r
+ ; ===== General Constants =====\r
+ \r
+ = 0000 False EQU 0\r
+ =-0001 True EQU -1\r
+ = 0000 nil EQU 0\r
+ \r
+ = BYTE PTR b EQU BYTE PTR\r
+ = WORD PTR w EQU WORD PTR\r
+ = DWORD PTR d EQU DWORD PTR\r
+ = OFFSET o EQU OFFSET\r
+ = FAR PTR f EQU FAR PTR\r
+ = SHORT s EQU SHORT\r
+ = ?,?,?,? ?x4 EQU <?,?,?,?>\r
+ = ?,?,? ?x3 EQU <?,?,?>\r
+ \r
+ ; ===== VGA Register Values =====\r
+ \r
+ = A000 VGA_Segment EQU 0A000h ; Vga Memory Segment\r
+ \r
+ = 03C0 ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller\r
+ = 03CE GC_Index EQU 03CEh ; VGA Graphics Controller\r
+ = 03C4 SC_Index EQU 03C4h ; VGA Sequencer Controller\r
+ = 03C5 SC_Data EQU 03C5h ; VGA Sequencer Data Port\r
+ = 03D4 CRTC_Index EQU 03D4h ; VGA CRT Controller\r
+ = 03D5 CRTC_Data EQU 03D5h ; VGA CRT Controller Data\r
+ = 03C2 MISC_OUTPUT EQU 03C2h ; VGA Misc Register\r
+ = 03DA INPUT_1 EQU 03DAh ; Input Status #1 Register\r
+ \r
+ = 03C8 DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register\r
+ = 03C7 DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register\r
+ = 03C9 PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W\r
+ \r
+ = 0033 PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg\r
+ = 0002 MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg\r
+ = 0004 READ_MAP EQU 004h ; GC Index: Read Map Register\r
+ = 000C START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi\r
+ = 000D START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo\r
+ \r
+ = 0102 MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1\r
+ = 1102 MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1\r
+ = 0F02 ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes\r
+ \r
+ = 0604 CHAIN4_OFF EQU 00604h ; Chain 4 mode Off\r
+ = 0100 ASYNC_RESET EQU 00100h ; (A)synchronous Reset\r
+ = 0300 SEQU_RESTART EQU 00300h ; Sequencer Restart\r
+ \r
+ = 0008 LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches\r
+ = FF08 LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU\r
+ \r
+ = 0008 VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit\r
+ = 0003 PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane #\r
+ = 000F ALL_PLANES EQU 0Fh ; All Bit Planes Selected\r
+ = 000F CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data\r
+ \r
+ = 1130 GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set\r
+ = 0003 ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer\r
+ = 0004 ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer\r
+ \r
+ ; Constants Specific for these routines\r
+ \r
+ = 0008 NUM_MODES EQU 8 ; # of Mode X Variations\r
+ \r
+ ; Specific Mode Data Table format...\r
+ \r
+ 000C Mode_Data_Table STRUC\r
+ 0000 00 M_MiscR DB ? ; Value of MISC_OUTPUT register\r
+ 0001 00 M_Pages DB ? ; Maximum Possible # of pages\r
+ 0002 0000 M_XSize DW ? ; X Size Displayed on screen\r
+ 0004 0000 M_YSize DW ? ; Y Size Displayed on screen\r
+ 0006 0000 M_XMax DW ? ; Maximum Possible X Size\r
+ 0008 0000 M_YMax DW ? ; Maximum Possible Y Size\r
+ 000A 0000 M_CRTC DW ? ; Table of CRTC register values\r
+ Mode_Data_Table ENDS\r
+ \r
+ ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
+ \r
+ 0000 .DATA?\r
+ \r
+ 0000 0000 SCREEN_WIDTH DW 0 ; Width of a line in Bytes\r
+ 0002 0000 SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels\r
+ \r
+ 0004 0000 LAST_PAGE DW 0 ; # of Display Pages\r
+ 0006 0004 [ PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page\r
+ 0000\r
+ ]\r
+ \r
+ 000E 0000 PAGE_SIZE DW 0 ; Size of Page in Addr Bytes\r
+ \r
+ 0010 0000 DISPLAY_PAGE DW 0 ; Page # currently displayed\r
+ 0012 0000 ACTIVE_PAGE DW 0 ; Page # currently active\r
+ \r
+ 0014 0000 CURRENT_PAGE DW 0 ; Offset of current Page\r
+ 0016 0000 CURRENT_SEGMENT DW 0 ; Segment of VGA memory\r
+ \r
+ 0018 0000 CURRENT_XOFFSET DW 0 ; Current Display X Offset\r
+ 001A 0000 CURRENT_YOFFSET DW 0 ; Current Display Y Offset\r
+ \r
+ 001C 0000 CURRENT_MOFFSET DW 0 ; Current Start Offset\r
+ \r
+ 001E 0000 MAX_XOFFSET DW 0 ; Current Display X Offset\r
+ 0020 0000 MAX_YOFFSET DW 0 ; Current Display Y Offset\r
+ \r
+ 0022 0000 0000 CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127\r
+ 0026 0000 0000 CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255\r
+ \r
+ 0000 .CODE\r
+ \r
+ ; ===== DATA TABLES =====\r
+ \r
+ ; Data Tables, Put in Code Segment for Easy Access\r
+ ; (Like when all the other Segment Registers are in\r
+ ; use!!) and reduced DGROUP requirements...\r
+ \r
+ ; Bit Mask Tables for Left/Right/Character Masks\r
+ \r
+ 0000 0F 0E 0C 08 Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H\r
+ \r
+ 0004 01 03 07 0F Right_Clip_Mask DB 01H, 03H, 07H, 0FH\r
+ \r
+ ; Bit Patterns for converting character fonts\r
+ \r
+ 0008 00 08 04 0C 02 0A Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH\r
+ 06 0E\r
+ 0010 01 09 05 0D 03 0B DB 01H,09H,05H,0DH,03H,0BH,07H,0FH\r
+ 07 0F\r
+ \r
+ ; CRTC Register Values for Various Configurations\r
+ \r
+ 0018 MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes\r
+ 0018 4009 DW 04009H ; Cell Height (1 Scan Line)\r
+ 001A 0014 DW 00014H ; Dword Mode off\r
+ 001C E317 DW 0E317H ; turn on Byte Mode\r
+ 001E 0000 DW nil ; End of CRTC Data for 400/480 Line Mode\r
+ \r
+ 0020 MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes\r
+ 0020 4109 DW 04109H ; Cell Height (2 Scan Lines)\r
+ 0022 0014 DW 00014H ; Dword Mode off\r
+ 0024 E317 DW 0E317H ; turn on Byte Mode\r
+ 0026 0000 DW nil ; End of CRTC Data for 200/240 Line Mode\r
+ \r
+ 0028 MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels\r
+ 0028 5F00 DW 05F00H ; Horz total\r
+ 002A 4F01 DW 04F01H ; Horz Displayed\r
+ 002C 5002 DW 05002H ; Start Horz Blanking\r
+ 002E 8203 DW 08203H ; End Horz Blanking\r
+ 0030 5404 DW 05404H ; Start H Sync\r
+ 0032 8005 DW 08005H ; End H Sync\r
+ 0034 0000 DW nil ; End of CRTC Data for 320 Horz pixels\r
+ \r
+ 0036 MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels\r
+ 0036 6B00 DW 06B00H ; Horz total\r
+ 0038 5901 DW 05901H ; Horz Displayed\r
+ 003A 5A02 DW 05A02H ; Start Horz Blanking\r
+ 003C 8E03 DW 08E03H ; End Horz Blanking\r
+ 003E 5E04 DW 05E04H ; Start H Sync\r
+ 0040 8A05 DW 08A05H ; End H Sync\r
+ 0042 0000 DW nil ; End of CRTC Data for 360 Horz pixels\r
+ \r
+ 0044 MODE_200_Tall:\r
+ 0044 MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes\r
+ 0044 BF06 DW 0BF06H ; Vertical Total\r
+ 0046 1F07 DW 01F07H ; Overflow\r
+ 0048 9C10 DW 09C10H ; V Sync Start\r
+ 004A 8E11 DW 08E11H ; V Sync End/Prot Cr0 Cr7\r
+ 004C 8F12 DW 08F12H ; Vertical Displayed\r
+ 004E 9615 DW 09615H ; V Blank Start\r
+ 0050 B916 DW 0B916H ; V Blank End\r
+ 0052 0000 DW nil ; End of CRTC Data for 200/400 Lines\r
+ \r
+ 0054 MODE_240_Tall:\r
+ 0054 MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes\r
+ 0054 0D06 DW 00D06H ; Vertical Total\r
+ 0056 3E07 DW 03E07H ; Overflow\r
+ 0058 EA10 DW 0EA10H ; V Sync Start\r
+ 005A 8C11 DW 08C11H ; V Sync End/Prot Cr0 Cr7\r
+ 005C DF12 DW 0DF12H ; Vertical Displayed\r
+ 005E E715 DW 0E715H ; V Blank Start\r
+ 0060 0616 DW 00616H ; V Blank End\r
+ 0062 0000 DW nil ; End of CRTC Data for 240/480 Lines\r
+ \r
+ ; Table of Display Mode Tables\r
+ \r
+ 0064 MODE_TABLE:\r
+ 0064 0074 R 0086 R DW o MODE_320x200, o MODE_320x400\r
+ 0068 00E0 R 00F2 R DW o MODE_360x200, o MODE_360x400\r
+ 006C 00BC R 00CE R DW o MODE_320x240, o MODE_320x480\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 2 - 1\r
+\r
+\r
+ 0070 0098 R 00AA R DW o MODE_360x240, o MODE_360x480\r
+ \r
+ ; Table of Display Mode Components\r
+ \r
+ 0074 MODE_320x200: ; Data for 320 by 200 Pixels\r
+ \r
+ 0074 63 DB 063h ; 400 scan Lines & 25 Mhz Clock\r
+ 0075 04 DB 4 ; Maximum of 4 Pages\r
+ 0076 0140 00C8 DW 320, 200 ; Displayed Pixels (X,Y)\r
+ 007A 0516 0330 DW 1302, 816 ; Max Possible X and Y Sizes\r
+ \r
+ 007E 0028 R 0044 R DW o MODE_320_Wide, o MODE_200_Tall\r
+ 0082 0020 R 0000 DW o MODE_Double_Line, nil\r
+ \r
+ 0086 MODE_320x400: ; Data for 320 by 400 Pixels\r
+ \r
+ 0086 63 DB 063h ; 400 scan Lines & 25 Mhz Clock\r
+ 0087 02 DB 2 ; Maximum of 2 Pages\r
+ 0088 0140 0190 DW 320, 400 ; Displayed Pixels X,Y\r
+ 008C 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes\r
+ \r
+ 0090 0028 R 0044 R DW o MODE_320_Wide, o MODE_400_Tall\r
+ 0094 0018 R 0000 DW o MODE_Single_Line, nil\r
+ \r
+ 0098 MODE_360x240: ; Data for 360 by 240 Pixels\r
+ \r
+ 0098 E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
+ 0099 03 DB 3 ; Maximum of 3 Pages\r
+ 009A 0168 00F0 DW 360, 240 ; Displayed Pixels X,Y\r
+ 009E 0444 02D8 DW 1092, 728 ; Max Possible X and Y Sizes\r
+ \r
+ 00A2 0036 R 0054 R DW o MODE_360_Wide, o MODE_240_Tall\r
+ 00A6 0020 R 0000 DW o MODE_Double_Line , nil\r
+ \r
+ 00AA MODE_360x480: ; Data for 360 by 480 Pixels\r
+ \r
+ 00AA E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
+ 00AB 01 DB 1 ; Only 1 Page Possible\r
+ 00AC 0168 01E0 DW 360, 480 ; Displayed Pixels X,Y\r
+ 00B0 0220 02D8 DW 544, 728 ; Max Possible X and Y Sizes\r
+ \r
+ 00B4 0036 R 0054 R DW o MODE_360_Wide, o MODE_480_Tall\r
+ 00B8 0018 R 0000 DW o MODE_Single_Line , nil\r
+ \r
+ 00BC MODE_320x240: ; Data for 320 by 240 Pixels\r
+ \r
+ 00BC E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
+ 00BD 03 DB 3 ; Maximum of 3 Pages\r
+ 00BE 0140 00F0 DW 320, 240 ; Displayed Pixels X,Y\r
+ 00C2 0440 0332 DW 1088, 818 ; Max Possible X and Y Sizes\r
+ \r
+ 00C6 0028 R 0054 R DW o MODE_320_Wide, o MODE_240_Tall\r
+ 00CA 0020 R 0000 DW o MODE_Double_Line, nil\r
+ \r
+ 00CE MODE_320x480: ; Data for 320 by 480 Pixels\r
+ \r
+ 00CE E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
+ 00CF 01 DB 1 ; Only 1 Page Possible\r
+ 00D0 0140 01E0 DW 320, 480 ; Displayed Pixels X,Y\r
+ 00D4 021C 0332 DW 540, 818 ; Max Possible X and Y Sizes\r
+ \r
+ 00D8 0028 R 0054 R DW o MODE_320_WIDE, o MODE_480_Tall\r
+ 00DC 0018 R 0000 DW o MODE_Single_Line, nil\r
+ \r
+ 00E0 MODE_360x200: ; Data for 360 by 200 Pixels\r
+ \r
+ 00E0 67 DB 067h ; 400 scan Lines & 28 Mhz Clock\r
+ 00E1 03 DB 3 ; Maximum of 3 Pages\r
+ 00E2 0168 00C8 DW 360, 200 ; Displayed Pixels (X,Y)\r
+ 00E6 0516 02D8 DW 1302, 728 ; Max Possible X and Y Sizes\r
+ \r
+ 00EA 0036 R 0044 R DW o MODE_360_Wide, MODE_200_Tall\r
+ 00EE 0020 R 0000 DW o MODE_Double_Line, nil\r
+ \r
+ 00F2 MODE_360x400: ; Data for 360 by 400 Pixels\r
+ \r
+ 00F2 67 DB 067h ; 400 scan Lines & 28 Mhz Clock\r
+ 00F3 01 DB 1 ; Maximum of 1 Pages\r
+ 00F4 0168 0190 DW 360, 400 ; Displayed Pixels X,Y\r
+ 00F8 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes\r
+ \r
+ 00FC 0036 R 0044 R DW o MODE_360_Wide, MODE_400_Tall\r
+ 0100 0018 R 0000 DW o MODE_Single_Line, nil\r
+ \r
+ \r
+ ; ===== MODE X SETUP ROUTINES =====\r
+ \r
+ ;======================================================\r
+ ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
+ ;======================================================\r
+ ;\r
+ ; Sets Up the specified version of Mode X. Allows for\r
+ ; the setup of multiple video pages, and a virtual\r
+ ; screen which can be larger than the displayed screen\r
+ ; (which can then be scrolled a pixel at a time)\r
+ ;\r
+ ; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+ ;\r
+ ; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio\r
+ ; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio\r
+ ; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio\r
+ ; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio\r
+ ; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio\r
+ ; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio\r
+ ; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
+ ; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio\r
+ ;\r
+ ; MaxXpos = The Desired Virtual Screen Width\r
+ ; MaxYpos = The Desired Virtual Screen Height\r
+ ; Pages = The Desired # of Video Pages\r
+ ;\r
+ ; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+ ;\r
+ \r
+ 0016 SVM_STACK STRUC\r
+ 0000 0000 SVM_Table DW ? ; Offset of Mode Info Table\r
+ 0002 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 000A 00000000 DD ? ; Caller\r
+ 000E 0000 SVM_Pages DW ? ; # of Screen Pages desired\r
+ 0010 0000 SVM_Ysize DW ? ; Vertical Screen Size Desired\r
+ 0012 0000 SVM_Xsize DW ? ; Horizontal Screen Size Desired\r
+ 0014 0000 SVM_Mode DW ? ; Display Resolution Desired\r
+ SVM_STACK ENDS\r
+ \r
+ PUBLIC SET_VGA_MODEX\r
+ \r
+ 0104 SET_VGA_MODEX PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0104 55 1 PUSH BP ; Save R1\r
+ 0105 1E 2 PUSH DS ; Save R1\r
+ 0106 56 3 PUSH SI ; Save R1\r
+ 0107 57 4 PUSH DI ; Save R1\r
+ 0108 83 EC 02 SUB SP, 2 ; Allocate workspace\r
+ 010B 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ ; Check Legality of Mode Request....\r
+ \r
+ 010D 8B 5E 14 MOV BX, [BP].SVM_Mode ; Get Requested Mode #\r
+ 0110 83 FB 08 CMP BX, NUM_MODES ; Is it 0..7?\r
+ 0113 73 47 JAE @SVM_BadModeSetup ; If Not, Error out\r
+ \r
+ 0115 D1 E3 SHL BX, 1 ; Scale BX\r
+ 0117 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
+ 011C 89 76 00 MOV [BP].SVM_Table, SI ; Save ptr for later use\r
+ \r
+ ; Check # of Requested Display Pages\r
+ \r
+ 011F 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Requested Pages\r
+ CLR CH ; Set Hi Word = 0!\r
+ 0122 32 ED 1 XOR CH, CH ; Set Register = 0\r
+ 0124 2E: 3A 4C 01 CMP CL, CS:[SI].M_Pages ; Check # Pages for mode\r
+ 0128 77 32 JA @SVM_BadModeSetup ; Report Error if too Many Pages\r
+ 012A E3 30 JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages\r
+ \r
+ ; Check Validity of X Size\r
+ \r
+ 012C 83 66 12 F8 AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0\r
+ \r
+ 0130 8B 46 12 MOV AX, [BP].SVM_XSize ; Get Logical Screen Width\r
+ 0133 2E: 3B 44 02 CMP AX, CS:[SI].M_XSize ; Check against Displayed X\r
+ 0137 72 23 JB @SVM_BadModeSetup ; Report Error if too small\r
+ 0139 2E: 3B 44 06 CMP AX, CS:[SI].M_XMax ; Check against Max X\r
+ 013D 77 1D JA @SVM_BadModeSetup ; Report Error if too big\r
+ \r
+ ; Check Validity of Y Size\r
+ \r
+ 013F 8B 5E 10 MOV BX, [BP].SVM_YSize ; Get Logical Screen Height\r
+ 0142 2E: 3B 5C 04 CMP BX, CS:[SI].M_YSize ; Check against Displayed Y\r
+ 0146 72 14 JB @SVM_BadModeSetup ; Report Error if too small\r
+ 0148 2E: 3B 5C 08 CMP BX, CS:[SI].M_YMax ; Check against Max Y\r
+ 014C 77 0E JA @SVM_BadModeSetup ; Report Error if too big\r
+ \r
+ ; Enough memory to Fit it all?\r
+ \r
+ 014E C1 E8 02 SHR AX, 2 ; # of Bytes:Line = XSize/4\r
+ 0151 F7 E1 MUL CX ; AX = Bytes/Line * Pages\r
+ 0153 F7 E3 MUL BX ; DX:AX = Total VGA mem needed\r
+ 0155 71 0A JNO @SVM_Continue ; Exit if Total Size > 256K\r
+ \r
+ 0157 4A DEC DX ; Was it Exactly 256K???\r
+ 0158 0B D0 OR DX, AX ; (DX = 1, AX = 0000)\r
+ 015A 74 05 JZ @SVM_Continue ; if so, it's valid...\r
+ \r
+ 015C @SVM_BadModeSetup:\r
+ \r
+ CLR AX ; Return Value = False\r
+ 015C 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 015E E9 00E6 JMP @SVM_Exit ; Normal Exit\r
+ \r
+ 0161 @SVM_Continue:\r
+ \r
+ 0161 B8 0013 MOV AX, 13H ; Start with Mode 13H\r
+ 0164 CD 10 INT 10H ; Let BIOS Set Mode\r
+ \r
+ OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode\r
+ 0166 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 0169 B8 0604 1 MOV AX, CHAIN4_OFF ; then Get Data Value\r
+ 016C EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset\r
+ 016D BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 0170 B8 0100 1 MOV AX, ASYNC_RESET ; then Get Data Value\r
+ 0173 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size\r
+ 0174 BA 03C2 1 MOV DX, MISC_OUTPUT ; then Select Register\r
+ 0177 2E: 8A 04 1 MOV AL, CS:[SI].M_MiscR ; then Get Data Value\r
+ 017A EE 1 OUT DX, AL ; Set I/O Register\r
+ OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ...\r
+ 017B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 017E B8 0300 1 MOV AX, SEQU_RESTART ; then Get Data Value\r
+ 0181 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register\r
+ 0182 BA 03D4 1 MOV DX, CRTC_INDEX ; then Select Register\r
+ 0185 B0 11 1 MOV AL, 11H ; then Get Data Value\r
+ 0187 EE 1 OUT DX, AL ; Set I/O Register\r
+ 0188 42 INC DX ; Point to Data\r
+ 0189 EC IN AL, DX ; Get Value, Bit 7 = Protect\r
+ 018A 24 7F AND AL, 7FH ; Mask out Write Protect\r
+ 018C EE OUT DX, AL ; And send it back\r
+ \r
+ 018D BA 03D4 MOV DX, CRTC_INDEX ; Vga Crtc Registers\r
+ 0190 83 C6 0A ADD SI, M_CRTC ; SI -> CRTC Parameter Data\r
+ \r
+ ; Load Tables of CRTC Parameters from List of Tables\r
+ \r
+ 0193 @SVM_Setup_Table:\r
+ \r
+ 0193 2E: 8B 3C MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl\r
+ 0196 83 C6 02 ADD SI, 2 ; Point to next Ptr Entry\r
+ 0199 0B FF OR DI, DI ; A nil Ptr means that we have\r
+ 019B 74 0D JZ @SVM_Set_Data ; finished CRTC programming\r
+ \r
+ 019D @SVM_Setup_CRTC:\r
+ 019D 2E: 8B 05 MOV AX, CS:[DI] ; Get CRTC Data from Table\r
+ 01A0 83 C7 02 ADD DI, 2 ; Advance Pointer\r
+ 01A3 0B C0 OR AX, AX ; At End of Data Table?\r
+ 01A5 74 EC JZ @SVM_Setup_Table ; If so, Exit & get next Table\r
+ \r
+ 01A7 EF OUT DX, AX ; Reprogram VGA CRTC reg\r
+ 01A8 EB F3 JMP s @SVM_Setup_CRTC ; Process Next Table Entry\r
+ \r
+ ; Initialize Page & Scroll info, DI = 0\r
+ \r
+ 01AA @SVM_Set_Data:\r
+ 01AA 89 3E 0010 R MOV DISPLAY_PAGE, DI ; Display Page = 0\r
+ 01AE 89 3E 0012 R MOV ACTIVE_PAGE, DI ; Active Page = 0\r
+ 01B2 89 3E 0014 R MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0\r
+ 01B6 89 3E 0018 R MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
+ 01BA 89 3E 001A R MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 3 - 1\r
+\r
+\r
+ 01BE 89 3E 001C R MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
+ \r
+ 01C2 B8 A000 MOV AX, VGA_SEGMENT ; Segment for VGA memory\r
+ 01C5 A3 0016 R MOV CURRENT_SEGMENT, AX ; Save for Future LES's\r
+ \r
+ ; Set Logical Screen Width, X Scroll and Our Data\r
+ \r
+ 01C8 8B 76 00 MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info\r
+ 01CB 8B 46 12 MOV AX, [BP].SVM_Xsize ; Get Display Width\r
+ \r
+ 01CE 8B C8 MOV CX, AX ; CX = Logical Width\r
+ 01D0 2E: 2B 4C 02 SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
+ 01D4 89 0E 001E R MOV MAX_XOFFSET, CX ; Set Maximum X Scroll\r
+ \r
+ 01D8 C1 E8 02 SHR AX, 2 ; Bytes = Pixels / 4\r
+ 01DB A3 0000 R MOV SCREEN_WIDTH, AX ; Save Width in Pixels\r
+ \r
+ 01DE D1 E8 SHR AX, 1 ; Offset Value = Bytes / 2\r
+ 01E0 B4 13 MOV AH, 13h ; CRTC Offset Register Index\r
+ 01E2 86 C4 XCHG AL, AH ; Switch format for OUT\r
+ 01E4 EF OUT DX, AX ; Set VGA CRTC Offset Reg\r
+ \r
+ ; Setup Data table, Y Scroll, Misc for Other Routines\r
+ \r
+ 01E5 8B 46 10 MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height\r
+ \r
+ 01E8 8B C8 MOV CX, AX ; CX = Logical Height\r
+ 01EA 2E: 2B 5C 04 SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
+ 01EE 89 0E 0020 R MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll\r
+ \r
+ 01F2 A3 0002 R MOV SCREEN_HEIGHT, AX ; Save Height in Pixels\r
+ 01F5 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Page Size in Bytes,\r
+ 01F9 A3 000E R MOV PAGE_SIZE, AX ; Save Page Size\r
+ \r
+ 01FC 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Pages\r
+ 01FF 89 0E 0004 R MOV LAST_PAGE, CX ; Save # of Pages\r
+ \r
+ CLR BX ; Page # = 0\r
+ 0203 33 DB 1 XOR BX, BX ; Set Register = 0\r
+ 0205 8B D3 MOV DX, BX ; Page 0 Offset = 0\r
+ \r
+ 0207 @SVM_Set_Pages:\r
+ \r
+ 0207 89 97 0006 R MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset\r
+ 020B 83 C3 02 ADD BX, 2 ; Page#++\r
+ 020E 03 D0 ADD DX, AX ; Compute Addr of Next Page\r
+ LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set\r
+ 0210 49 1 DEC CX ; Counter--\r
+ 0211 75 F4 1 JNZ @SVM_Set_Pages ; Jump if not 0\r
+ \r
+ ; Clear VGA Memory\r
+ \r
+ OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ 0213 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 0216 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value\r
+ 0219 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ 021A C4 3E 0014 R LES DI, d CURRENT_PAGE ; -> Start of VGA memory\r
+ \r
+ CLR AX ; AX = 0\r
+ 021E 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 0220 FC CLD ; Block Xfer Forwards\r
+ 0221 B9 8000 MOV CX, 8000H ; 32K * 4 * 2 = 256K\r
+ 0224 F3/ AB REP STOSW ; Clear dat memory!\r
+ \r
+ ; Setup Font Pointers\r
+ \r
+ 0226 B7 03 MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127\r
+ 0228 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
+ 022B CD 10 INT 10h ; Call VGA BIOS\r
+ \r
+ 022D 89 2E 0022 R MOV CHARSET_LOW, BP ; Save Char Set Offset\r
+ 0231 8C 06 0024 R MOV CHARSET_LOW+2, ES ; Save Char Set Segment\r
+ \r
+ 0235 B7 04 MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255\r
+ 0237 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
+ 023A CD 10 INT 10h ; Call VGA BIOS\r
+ \r
+ 023C 89 2E 0026 R MOV CHARSET_HI, BP ; Save Char Set Offset\r
+ 0240 8C 06 0028 R MOV CHARSET_HI+2, ES ; Save Char Set Segment\r
+ \r
+ 0244 B8 FFFF MOV AX, True ; Return Success Code\r
+ \r
+ 0247 @SVM_EXIT:\r
+ 0247 83 C4 02 ADD SP, 2 ; Deallocate workspace\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 024A 5F 1 POP DI ; Restore R1\r
+ 024B 5E 2 POP SI ; Restore R1\r
+ 024C 1F 3 POP DS ; Restore R1\r
+ 024D 5D 4 POP BP ; Restore R1\r
+ 024E CA 0008 RET 8 ; Exit & Clean Up Stack\r
+ \r
+ 0251 SET_VGA_MODEX ENDP\r
+ \r
+ \r
+ ;==================\r
+ ;SET_MODEX% (Mode%)\r
+ ;==================\r
+ ;\r
+ ; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
+ ;\r
+ ; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+ ; (See SET_VGA_MODEX for list)\r
+ ;\r
+ ; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+ ;\r
+ \r
+ 000A SM_STACK STRUC\r
+ 0000 0000 0000 DW ?,? ; BP, SI\r
+ 0004 00000000 DD ? ; Caller\r
+ 0008 0000 SM_Mode DW ? ; Desired Screen Resolution\r
+ SM_STACK ENDS\r
+ \r
+ PUBLIC SET_MODEX\r
+ \r
+ 0251 SET_MODEX PROC FAR\r
+ \r
+ PUSHx BP, SI ; Preserve Important registers\r
+ 0251 55 1 PUSH BP ; Save R1\r
+ 0252 56 2 PUSH SI ; Save R1\r
+ 0253 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ CLR AX ; Assume Failure\r
+ 0255 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 0257 8B 5E 08 MOV BX, [BP].SM_Mode ; Get Desired Mode #\r
+ 025A 83 FB 08 CMP BX, NUM_MODES ; Is it a Valid Mode #?\r
+ 025D 73 1C JAE @SMX_Exit ; If Not, don't Bother\r
+ \r
+ 025F 53 PUSH BX ; Push Mode Parameter\r
+ \r
+ 0260 D1 E3 SHL BX, 1 ; Scale BX to word Index\r
+ 0262 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
+ \r
+ 0267 2E: FF 74 02 PUSH CS:[SI].M_XSize ; Push Default X Size\r
+ 026B 2E: FF 74 04 PUSH CS:[SI].M_Ysize ; Push Default Y size\r
+ 026F 2E: 8A 44 01 MOV AL, CS:[SI].M_Pages ; Get Default # of Pages\r
+ CLR AH ; Hi Byte = 0\r
+ 0273 32 E4 1 XOR AH, AH ; Set Register = 0\r
+ 0275 50 PUSH AX ; Push # Pages\r
+ \r
+ 0276 9A ---- 0104 R CALL f SET_VGA_MODEX ; Set up Mode X!\r
+ \r
+ 027B @SMX_Exit:\r
+ POPx SI, BP ; Restore Registers\r
+ 027B 5E 1 POP SI ; Restore R1\r
+ 027C 5D 2 POP BP ; Restore R1\r
+ 027D CA 0002 RET 2 ; Exit & Clean Up Stack\r
+ \r
+ 0280 SET_MODEX ENDP\r
+ \r
+ \r
+ ; ===== BASIC GRAPHICS PRIMITIVES =====\r
+ \r
+ ;============================\r
+ ;CLEAR_VGA_SCREEN (ColorNum%)\r
+ ;============================\r
+ ;\r
+ ; Clears the active display page\r
+ ;\r
+ ; ENTRY: ColorNum = Color Value to fill the page with\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 000A CVS_STACK STRUC\r
+ 0000 0000 0000 DW ?,? ; DI, BP\r
+ 0004 00000000 DD ? ; Caller\r
+ 0008 00 00 CVS_COLOR DB ?,? ; Color to Set Screen to\r
+ CVS_STACK ENDS\r
+ \r
+ PUBLIC CLEAR_VGA_SCREEN\r
+ \r
+ 0280 CLEAR_VGA_SCREEN PROC FAR\r
+ \r
+ PUSHx BP, DI ; Preserve Important Registers\r
+ 0280 55 1 PUSH BP ; Save R1\r
+ 0281 57 2 PUSH DI ; Save R1\r
+ 0282 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ 0284 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 0287 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value\r
+ 028A EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ 028B C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ \r
+ 028F 8A 46 08 MOV AL, [BP].CVS_COLOR ; Get Color\r
+ 0292 8A E0 MOV AH, AL ; Copy for Word Write\r
+ 0294 FC CLD ; Block fill Forwards\r
+ \r
+ 0295 8B 0E 000E R MOV CX, PAGE_SIZE ; Get Size of Page\r
+ 0299 D1 E9 SHR CX, 1 ; Divide by 2 for Words\r
+ 029B F3/ AB REP STOSW ; Block Fill VGA memory\r
+ \r
+ POPx DI, BP ; Restore Saved Registers\r
+ 029D 5F 1 POP DI ; Restore R1\r
+ 029E 5D 2 POP BP ; Restore R1\r
+ 029F CA 0002 RET 2 ; Exit & Clean Up Stack\r
+ \r
+ 02A2 CLEAR_VGA_SCREEN ENDP\r
+ \r
+ \r
+ ;===================================\r
+ ;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
+ ;===================================\r
+ ;\r
+ ; Plots a single Pixel on the active display page\r
+ ;\r
+ ; ENTRY: Xpos = X position to plot pixel at\r
+ ; Ypos = Y position to plot pixel at\r
+ ; ColorNum = Color to plot pixel with\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 000E SP_STACK STRUC\r
+ 0000 0000 0000 DW ?,? ; BP, DI\r
+ 0004 00000000 DD ? ; Caller\r
+ 0008 00 00 SETP_Color DB ?,? ; Color of Point to Plot\r
+ 000A 0000 SETP_Ypos DW ? ; Y pos of Point to Plot\r
+ 000C 0000 SETP_Xpos DW ? ; X pos of Point to Plot\r
+ SP_STACK ENDS\r
+ \r
+ PUBLIC SET_POINT\r
+ \r
+ 02A2 SET_POINT PROC FAR\r
+ \r
+ PUSHx BP, DI ; Preserve Registers\r
+ 02A2 55 1 PUSH BP ; Save R1\r
+ 02A3 57 2 PUSH DI ; Save R1\r
+ 02A4 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 02A6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ \r
+ 02AA 8B 46 0A MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel\r
+ 02AD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
+ \r
+ 02B1 8B 5E 0C MOV BX, [BP].SETP_Xpos ; Get Xpos\r
+ 02B4 8B CB MOV CX, BX ; Copy to extract Plane # from\r
+ 02B6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4\r
+ 02B9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
+ \r
+ 02BB B8 0102 MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
+ 02BE 80 E1 03 AND CL, PLANE_BITS ; Get Plane Bits\r
+ 02C1 D2 E4 SHL AH, CL ; Get Plane Select Value\r
+ OUT_16 SC_Index, AX ; Select Plane\r
+ 02C3 BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 02C6 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ 02C7 8A 46 08 MOV AL,[BP].SETP_Color ; Get Pixel Color\r
+ 02CA 26: 88 01 MOV ES:[DI+BX], AL ; Draw Pixel\r
+ \r
+ POPx DI, BP ; Restore Saved Registers\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 4 - 1\r
+\r
+\r
+ 02CD 5F 1 POP DI ; Restore R1\r
+ 02CE 5D 2 POP BP ; Restore R1\r
+ 02CF CA 0006 RET 6 ; Exit and Clean up Stack\r
+ \r
+ 02D2 SET_POINT ENDP\r
+ \r
+ \r
+ ;==========================\r
+ ;READ_POINT% (Xpos%, Ypos%)\r
+ ;==========================\r
+ ;\r
+ ; Read the color of a pixel from the Active Display Page\r
+ ;\r
+ ; ENTRY: Xpos = X position of pixel to read\r
+ ; Ypos = Y position of pixel to read\r
+ ;\r
+ ; EXIT: AX = Color of Pixel at (Xpos, Ypos)\r
+ ;\r
+ \r
+ 000C RP_STACK STRUC\r
+ 0000 0000 0000 DW ?,? ; BP, DI\r
+ 0004 00000000 DD ? ; Caller\r
+ 0008 0000 RP_Ypos DW ? ; Y pos of Point to Read\r
+ 000A 0000 RP_Xpos DW ? ; X pos of Point to Read\r
+ RP_STACK ENDS\r
+ \r
+ PUBLIC READ_POINT\r
+ \r
+ 02D2 READ_POINT PROC FAR\r
+ \r
+ PUSHx BP, DI ; Preserve Registers\r
+ 02D2 55 1 PUSH BP ; Save R1\r
+ 02D3 57 2 PUSH DI ; Save R1\r
+ 02D4 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 02D6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ \r
+ 02DA 8B 46 08 MOV AX, [BP].RP_Ypos ; Get Line # of Pixel\r
+ 02DD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
+ \r
+ 02E1 8B 5E 0A MOV BX, [BP].RP_Xpos ; Get Xpos\r
+ 02E4 8B CB MOV CX, BX\r
+ 02E6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4\r
+ 02E9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
+ \r
+ 02EB B0 04 MOV AL, READ_MAP ; GC Read Mask Register\r
+ 02ED 8A E1 MOV AH, CL ; Get Xpos\r
+ 02EF 80 E4 03 AND AH, PLANE_BITS ; & mask out Plane #\r
+ OUT_16 GC_INDEX, AX ; Select Plane to read in\r
+ 02F2 BA 03CE 1 MOV DX, GC_INDEX ; then Select Register\r
+ 02F5 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ CLR AH ; Clear Return Value Hi byte\r
+ 02F6 32 E4 1 XOR AH, AH ; Set Register = 0\r
+ 02F8 26: 8A 01 MOV AL, ES:[DI+BX] ; Get Color of Pixel\r
+ \r
+ POPx DI, BP ; Restore Saved Registers\r
+ 02FB 5F 1 POP DI ; Restore R1\r
+ 02FC 5D 2 POP BP ; Restore R1\r
+ 02FD CA 0004 RET 4 ; Exit and Clean up Stack\r
+ \r
+ 0300 READ_POINT ENDP\r
+ \r
+ \r
+ ;======================================================\r
+ ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+ ;======================================================\r
+ ;\r
+ ; Fills a rectangular block on the active display Page\r
+ ;\r
+ ; ENTRY: Xpos1 = Left X position of area to fill\r
+ ; Ypos1 = Top Y position of area to fill\r
+ ; Xpos2 = Right X position of area to fill\r
+ ; Ypos2 = Bottom Y position of area to fill\r
+ ; ColorNum = Color to fill area with\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0016 FB_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DS, DI, SI, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 00 00 FB_Color DB ?,? ; Fill Color\r
+ 000E 0000 FB_Ypos2 DW ? ; Y pos of Lower Right Pixel\r
+ 0010 0000 FB_Xpos2 DW ? ; X pos of Lower Right Pixel\r
+ 0012 0000 FB_Ypos1 DW ? ; Y pos of Upper Left Pixel\r
+ 0014 0000 FB_Xpos1 DW ? ; X pos of Upper Left Pixel\r
+ FB_STACK ENDS\r
+ \r
+ PUBLIC FILL_BLOCK\r
+ \r
+ 0300 FILL_BLOCK PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0300 55 1 PUSH BP ; Save R1\r
+ 0301 1E 2 PUSH DS ; Save R1\r
+ 0302 56 3 PUSH SI ; Save R1\r
+ 0303 57 4 PUSH DI ; Save R1\r
+ 0304 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 0306 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ 030A FC CLD ; Direction Flag = Forward\r
+ \r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ 030B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 030E B0 02 1 MOV AL, MAP_MASK ; then Get Data Value\r
+ 0310 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ ; Validate Pixel Coordinates\r
+ ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
+ \r
+ 0311 8B 46 12 MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2?\r
+ 0314 8B 5E 0E MOV BX, [BP].FB_Ypos2 ; BX = Y2\r
+ 0317 3B C3 CMP AX, BX\r
+ 0319 7E 04 JLE @FB_NOSWAP1\r
+ \r
+ 031B 89 5E 12 MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1\r
+ 031E 93 XCHG AX, BX ; on stack for future use\r
+ \r
+ 031F @FB_NOSWAP1:\r
+ 031F 2B D8 SUB BX, AX ; Get Y width\r
+ 0321 43 INC BX ; Add 1 to avoid 0 value\r
+ 0322 89 5E 0E MOV [BP].FB_Ypos2, BX ; Save in Ypos2\r
+ \r
+ 0325 F7 26 0000 R MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line\r
+ 0329 03 F8 ADD DI, AX ; DI = Start of Line Y1\r
+ \r
+ 032B 8B 46 14 MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2\r
+ 032E 8B 5E 10 MOV BX, [BP].FB_Xpos2 ;\r
+ 0331 3B C3 CMP AX, BX\r
+ 0333 7E 04 JLE @FB_NOSWAP2 ; Skip Ahead if Ok\r
+ \r
+ 0335 89 46 10 MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2\r
+ 0338 93 XCHG AX, BX ; on stack for future use\r
+ \r
+ ; All our Input Values are in order, Now determine\r
+ ; How many full "bands" 4 pixels wide (aligned) there\r
+ ; are, and if there are partial bands (<4 pixels) on\r
+ ; the left and right edges.\r
+ \r
+ 0339 @FB_NOSWAP2:\r
+ 0339 8B D0 MOV DX, AX ; DX = X1 (Pixel Position)\r
+ 033B C1 EA 02 SHR DX, 2 ; DX/4 = Bytes into Line\r
+ 033E 03 FA ADD DI, DX ; DI = Addr of Upper-Left Corner\r
+ \r
+ 0340 8B CB MOV CX, BX ; CX = X2 (Pixel Position)\r
+ 0342 C1 E9 02 SHR CX, 2 ; CX/4 = Bytes into Line\r
+ \r
+ 0345 3B D1 CMP DX, CX ; Start and end in same band?\r
+ 0347 75 03 JNE @FB_NORMAL ; if not, check for l & r edges\r
+ 0349 E9 0086 JMP @FB_ONE_BAND_ONLY ; if so, then special processing\r
+ \r
+ 034C @FB_NORMAL:\r
+ 034C 2B CA SUB CX, DX ; CX = # bands -1\r
+ 034E 8B F0 MOV SI, AX ; SI = PLANE#(X1)\r
+ 0350 83 E6 03 AND SI, PLANE_BITS ; if Left edge is aligned then\r
+ 0353 74 27 JZ @FB_L_PLANE_FLUSH ; no special processing..\r
+ \r
+ ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
+ \r
+ OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
+ 0355 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0358 2E: 8A 84 0000 R 1 MOV AL, Left_Clip_Mask[SI] ; then Get Data Value\r
+ 035D EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 035E 8B F7 MOV SI, DI ; SI = Copy of Start Addr (UL)\r
+ \r
+ 0360 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ 0363 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color\r
+ 0366 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+ \r
+ 036A @FB_LEFT_LOOP:\r
+ 036A 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
+ 036D 03 F3 ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn\r
+ 036F 4A 1 DEC DX ; Counter--\r
+ 0370 74 08 1 JZ @FB_LEFT_CONT ; Jump if 0\r
+ \r
+ 0372 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
+ 0375 03 F3 ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn\r
+ 0377 4A 1 DEC DX ; Counter--\r
+ 0378 75 F0 1 JNZ @FB_LEFT_LOOP ; Jump if not 0\r
+ \r
+ 037A @FB_LEFT_CONT:\r
+ \r
+ 037A 47 INC DI ; Point to Middle (or Right) Block\r
+ 037B 49 DEC CX ; Reset CX instead of JMP @FB_RIGHT\r
+ \r
+ 037C @FB_L_PLANE_FLUSH:\r
+ 037C 41 INC CX ; Add in Left band to middle block\r
+ \r
+ ; DI = Addr of 1st middle Pixel (band) to fill\r
+ ; CX = # of Bands to fill -1\r
+ \r
+ 037D @FB_RIGHT:\r
+ 037D 8B 76 10 MOV SI, [BP].FB_Xpos2 ; Get Xpos2\r
+ 0380 83 E6 03 AND SI, PLANE_BITS ; Get Plane values\r
+ 0383 83 FE 03 CMP SI, 0003 ; Plane = 3?\r
+ 0386 74 2B JE @FB_R_EDGE_FLUSH ; Hey, add to middle\r
+ \r
+ ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
+ \r
+ OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask\r
+ 0388 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 038B 2E: 8A 84 0004 R 1 MOV AL, Right_Clip_Mask[SI] ; then Get Data Value\r
+ 0390 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0391 8B F7 MOV SI, DI ; Get Addr of Left Edge\r
+ 0393 03 F1 ADD SI, CX ; Add Width-1 (Bands)\r
+ 0395 4E DEC SI ; To point to top of Right Edge\r
+ \r
+ 0396 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ 0399 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color\r
+ 039C 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+ \r
+ 03A0 @FB_RIGHT_LOOP:\r
+ 03A0 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
+ 03A3 03 F3 ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn\r
+ 03A5 4A 1 DEC DX ; Counter--\r
+ 03A6 74 08 1 JZ @FB_RIGHT_CONT ; Jump if 0\r
+ \r
+ 03A8 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
+ 03AB 03 F3 ADD SI, BX ; Point to Next Line (Below)\r
+ LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn\r
+ 03AD 4A 1 DEC DX ; Counter--\r
+ 03AE 75 F0 1 JNZ @FB_RIGHT_LOOP ; Jump if not 0\r
+ \r
+ 03B0 @FB_RIGHT_CONT:\r
+ \r
+ 03B0 49 DEC CX ; Minus 1 for Middle bands\r
+ 03B1 74 51 JZ @FB_EXIT ; Uh.. no Middle bands...\r
+ \r
+ 03B3 @FB_R_EDGE_FLUSH:\r
+ \r
+ ; DI = Addr of Upper Left block to fill\r
+ ; CX = # of Bands to fill in (width)\r
+ \r
+ OUT_8 SC_Data, ALL_PLANES ; Write to All Planes\r
+ 03B3 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 03B6 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value\r
+ 03B8 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 03B9 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = DI Increment\r
+ 03BD 2B D1 SUB DX, CX ; = Screen_Width-# Planes Filled\r
+ \r
+ 03BF 8B D9 MOV BX, CX ; BX = Quick Refill for CX\r
+ 03C1 8B 76 0E MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill\r
+ 03C4 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 5 - 1\r
+\r
+\r
+ \r
+ 03C7 @FB_MIDDLE_LOOP:\r
+ 03C7 F3/ AA REP STOSB ; Fill in entire line\r
+ \r
+ 03C9 8B CB MOV CX, BX ; Recharge CX (Line Width)\r
+ 03CB 03 FA ADD DI, DX ; Point to start of Next Line\r
+ LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
+ 03CD 4E 1 DEC SI ; Counter--\r
+ 03CE 75 F7 1 JNZ @FB_MIDDLE_LOOP ; Jump if not 0\r
+ \r
+ 03D0 EB 32 JMP s @FB_EXIT ; Outa here\r
+ \r
+ 03D2 @FB_ONE_BAND_ONLY:\r
+ 03D2 8B F0 MOV SI, AX ; Get Left Clip Mask, Save X1\r
+ 03D4 83 E6 03 AND SI, PLANE_BITS ; Mask out Row #\r
+ 03D7 2E: 8A 84 0000 R MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
+ 03DC 8B F3 MOV SI, BX ; Get Right Clip Mask, Save X2\r
+ 03DE 83 E6 03 AND SI, PLANE_BITS ; Mask out Row #\r
+ 03E1 2E: 22 84 0004 R AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
+ \r
+ OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
+ 03E6 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 03E9 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 03EA 8B 4E 0E MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
+ 03ED 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color\r
+ 03F0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
+ \r
+ 03F4 @FB_ONE_LOOP:\r
+ 03F4 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels\r
+ 03F7 03 FB ADD DI, BX ; Point to Next Line (Below)\r
+ LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn\r
+ 03F9 49 1 DEC CX ; Counter--\r
+ 03FA 74 08 1 JZ @FB_EXIT ; Jump if 0\r
+ \r
+ 03FC 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels\r
+ 03FF 03 FB ADD DI, BX ; Point to Next Line (Below)\r
+ LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn\r
+ 0401 49 1 DEC CX ; Counter--\r
+ 0402 75 F0 1 JNZ @FB_ONE_LOOP ; Jump if not 0\r
+ \r
+ 0404 @FB_EXIT:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0404 5F 1 POP DI ; Restore R1\r
+ 0405 5E 2 POP SI ; Restore R1\r
+ 0406 1F 3 POP DS ; Restore R1\r
+ 0407 5D 4 POP BP ; Restore R1\r
+ 0408 CA 000A RET 10 ; Exit and Clean up Stack\r
+ \r
+ 040B FILL_BLOCK ENDP\r
+ \r
+ \r
+ ;=====================================================\r
+ ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+ ;=====================================================\r
+ ;\r
+ ; Draws a Line on the active display page\r
+ ;\r
+ ; ENTRY: Xpos1 = X position of first point on line\r
+ ; Ypos1 = Y position of first point on line\r
+ ; Xpos2 = X position of last point on line\r
+ ; Ypos2 = Y position of last point on line\r
+ ; ColorNum = Color to draw line with\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0014 DL_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x3 ; DI, SI, BP\r
+ 0006 00000000 DD ? ; Caller\r
+ 000A 00 00 DL_ColorF DB ?,? ; Line Draw Color\r
+ 000C 0000 DL_Ypos2 DW ? ; Y pos of last point\r
+ 000E 0000 DL_Xpos2 DW ? ; X pos of last point\r
+ 0010 0000 DL_Ypos1 DW ? ; Y pos of first point\r
+ 0012 0000 DL_Xpos1 DW ? ; X pos of first point\r
+ DL_STACK ENDS\r
+ \r
+ PUBLIC DRAW_LINE\r
+ \r
+ 040B DRAW_LINE PROC FAR\r
+ \r
+ PUSHx BP, SI, DI ; Preserve Important Registers\r
+ 040B 55 1 PUSH BP ; Save R1\r
+ 040C 56 2 PUSH SI ; Save R1\r
+ 040D 57 3 PUSH DI ; Save R1\r
+ 040E 8B EC MOV BP, SP ; Set up Stack Frame\r
+ 0410 FC CLD ; Direction Flag = Forward\r
+ \r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ 0411 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 0414 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value\r
+ 0416 EE 1 OUT DX, AL ; Set I/O Register\r
+ 0417 8A 6E 0A MOV CH, [BP].DL_ColorF ; Save Line Color in CH\r
+ \r
+ ; Check Line Type\r
+ \r
+ 041A 8B 76 12 MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2?\r
+ 041D 8B 7E 0E MOV DI, [BP].DL_Xpos2 ; DX = X2\r
+ 0420 3B F7 CMP SI, DI ; Is X1 < X2\r
+ 0422 74 5D JE @DL_VLINE ; If X1=X2, Draw Vertical Line\r
+ 0424 7C 02 JL @DL_NOSWAP1 ; If X1 < X2, don't swap\r
+ \r
+ 0426 87 F7 XCHG SI, DI ; X2 IS > X1, SO SWAP THEM\r
+ \r
+ 0428 @DL_NOSWAP1:\r
+ \r
+ ; SI = X1, DI = X2\r
+ \r
+ 0428 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2?\r
+ 042B 3B 46 0C CMP AX, [BP].DL_Ypos2 ; Y1 = Y2?\r
+ 042E 74 03 JE @DL_HORZ ; If so, Draw a Horizontal Line\r
+ \r
+ 0430 E9 0094 JMP @DL_BREZHAM ; Diagonal line... go do it...\r
+ \r
+ ; This Code draws a Horizontal Line in Mode X where:\r
+ ; SI = X1, DI = X2, and AX = Y1/Y2\r
+ \r
+ 0433 @DL_HORZ:\r
+ \r
+ 0433 F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width\r
+ 0437 8B D0 MOV DX, AX ; CX = Line offset into Page\r
+ \r
+ 0439 8B C6 MOV AX, SI ; Get Left edge, Save X1\r
+ 043B 83 E6 03 AND SI, PLANE_BITS ; Mask out Row #\r
+ 043E 2E: 8A 9C 0000 R MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
+ 0443 8B CF MOV CX, DI ; Get Right edge, Save X2\r
+ 0445 83 E7 03 AND DI, PLANE_BITS ; Mask out Row #\r
+ 0448 2E: 8A BD 0004 R MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
+ \r
+ 044D C1 E8 02 SHR AX, 2 ; Get X1 Byte # (=X1/4)\r
+ 0450 C1 E9 02 SHR CX, 2 ; Get X2 Byte # (=X2/4)\r
+ \r
+ 0453 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ 0457 03 FA ADD DI, DX ; Point to Start of Line\r
+ 0459 03 F8 ADD DI, AX ; Point to Pixel X1\r
+ \r
+ 045B 2B C8 SUB CX, AX ; CX = # Of Bands (-1) to set\r
+ 045D 75 02 JNZ @DL_LONGLN ; jump if longer than one segment\r
+ \r
+ 045F 22 DF AND BL, BH ; otherwise, merge clip masks\r
+ \r
+ 0461 @DL_LONGLN:\r
+ \r
+ OUT_8 SC_Data, BL ; Set the Left Clip Mask\r
+ 0461 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0464 8A C3 1 MOV AL, BL ; then Get Data Value\r
+ 0466 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0467 8A 46 0A MOV AL, [BP].DL_ColorF ; Get Line Color\r
+ 046A 8A D8 MOV BL, AL ; BL = Copy of Line Color\r
+ 046C AA STOSB ; Set Left (1-4) Pixels\r
+ \r
+ 046D E3 55 JCXZ @DL_EXIT ; Done if only one Line Segment\r
+ \r
+ 046F 49 DEC CX ; CX = # of Middle Segments\r
+ 0470 74 07 JZ @DL_XRSEG ; If no middle segments....\r
+ \r
+ ; Draw Middle Segments\r
+ \r
+ OUT_8 DX, ALL_PLANES ; Write to ALL Planes\r
+ 0472 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value\r
+ 0474 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0475 8A C3 MOV AL, BL ; Get Color from BL\r
+ 0477 F3/ AA REP STOSB ; Draw Middle (4 Pixel) Segments\r
+ \r
+ 0479 @DL_XRSEG:\r
+ OUT_8 DX, BH ; Select Planes for Right Clip Mask\r
+ 0479 8A C7 1 MOV AL, BH ; then Get Data Value\r
+ 047B EE 1 OUT DX, AL ; Set I/O Register\r
+ 047C 8A C3 MOV AL, BL ; Get Color Value\r
+ 047E AA STOSB ; Draw Right (1-4) Pixels\r
+ \r
+ 047F EB 43 JMP s @DL_EXIT ; We Are Done...\r
+ \r
+ \r
+ ; This Code Draws A Vertical Line. On entry:\r
+ ; CH = Line Color, SI & DI = X1\r
+ \r
+ 0481 @DL_VLINE:\r
+ \r
+ 0481 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1\r
+ 0484 8B 76 0C MOV SI, [BP].DL_Ypos2 ; SI = Y2\r
+ 0487 3B C6 CMP AX, SI ; Is Y1 < Y2?\r
+ 0489 7E 01 JLE @DL_NOSWAP2 ; if so, Don't Swap them\r
+ \r
+ 048B 96 XCHG AX, SI ; Ok, NOW Y1 < Y2\r
+ \r
+ 048C @DL_NOSWAP2:\r
+ \r
+ 048C 2B F0 SUB SI, AX ; SI = Line Height (Y2-Y1+1)\r
+ 048E 46 INC SI\r
+ \r
+ ; AX = Y1, DI = X1, Get offset into Page into AX\r
+ \r
+ 048F F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width\r
+ 0493 8B D7 MOV DX, DI ; Copy Xpos into DX\r
+ 0495 C1 EF 02 SHR DI, 2 ; DI = Xpos/4\r
+ 0498 03 C7 ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1\r
+ \r
+ 049A C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ 049E 03 F8 ADD DI, AX ; Point to Pixel X1, Y1\r
+ \r
+ ;Select Plane\r
+ \r
+ 04A0 8A CA MOV CL, DL ; CL = Save X1\r
+ 04A2 80 E1 03 AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #)\r
+ 04A5 B8 0102 MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
+ 04A8 D2 E4 SHL AH, CL ; Change to Correct Plane #\r
+ OUT_16 SC_Index, AX ; Select Plane\r
+ 04AA BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 04AD EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ 04AE 8A C5 MOV AL, CH ; Get Saved Color\r
+ 04B0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By\r
+ \r
+ 04B4 @DL_VLoop:\r
+ 04B4 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel\r
+ 04B7 03 FB ADD DI, BX ; Point to Next Line\r
+ LOOPjz SI, @DL_EXIT ; Lines--, Exit if done\r
+ 04B9 4E 1 DEC SI ; Counter--\r
+ 04BA 74 08 1 JZ @DL_EXIT ; Jump if 0\r
+ \r
+ 04BC 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel\r
+ 04BF 03 FB ADD DI, BX ; Point to Next Line\r
+ LOOPx SI, @DL_VLoop ; Lines--, Loop until Done\r
+ 04C1 4E 1 DEC SI ; Counter--\r
+ 04C2 75 F0 1 JNZ @DL_VLoop ; Jump if not 0\r
+ \r
+ 04C4 @DL_EXIT:\r
+ \r
+ 04C4 E9 0157 JMP @DL_EXIT2 ; Done!\r
+ \r
+ ; This code Draws a diagonal line in Mode X\r
+ \r
+ 04C7 @DL_BREZHAM:\r
+ 04C7 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ \r
+ 04CB 8B 46 10 MOV AX, [BP].DL_Ypos1 ; get Y1 value\r
+ 04CE 8B 5E 0C MOV BX, [BP].DL_Ypos2 ; get Y2 value\r
+ 04D1 8B 4E 12 MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos\r
+ \r
+ 04D4 3B D8 CMP BX, AX ; Y2-Y1 is?\r
+ 04D6 73 04 JNC @DL_DeltaYOK ; if Y2>=Y1 then goto...\r
+ \r
+ 04D8 93 XCHG BX, AX ; Swap em...\r
+ 04D9 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos\r
+ \r
+ 04DC @DL_DeltaYOK:\r
+ 04DC F7 26 0000 R MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1\r
+ \r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 6 - 1\r
+\r
+\r
+ 04E0 03 F8 ADD DI, AX ; DI -> Start of Line Y1 on Page\r
+ 04E2 8B C1 MOV AX, CX ; AX = Xpos (X1)\r
+ 04E4 C1 E8 02 SHR AX, 2 ; /4 = Byte Offset into Line\r
+ 04E7 03 F8 ADD DI, AX ; DI = Starting pos (X1,Y1)\r
+ \r
+ 04E9 B0 11 MOV AL, 11h ; Staring Mask\r
+ 04EB 80 E1 03 AND CL, PLANE_BITS ; Get Plane #\r
+ 04EE D2 E0 SHL AL, CL ; and shift into place\r
+ 04F0 8A 66 0A MOV AH, [BP].DL_ColorF ; Color in Hi Bytes\r
+ \r
+ 04F3 50 PUSH AX ; Save Mask,Color...\r
+ \r
+ 04F4 8A E0 MOV AH, AL ; Plane # in AH\r
+ 04F6 B0 02 MOV AL, MAP_MASK ; Select Plane Register\r
+ OUT_16 SC_Index, AX ; Select initial plane\r
+ 04F8 BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 04FB EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ 04FC 8B 46 12 MOV AX, [BP].DL_Xpos1 ; get X1 value\r
+ 04FF 8B 5E 10 MOV BX, [BP].DL_Ypos1 ; get Y1 value\r
+ 0502 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; get X2 value\r
+ 0505 8B 56 0C MOV DX, [BP].DL_Ypos2 ; get Y2 value\r
+ \r
+ 0508 8B 2E 0000 R MOV BP, SCREEN_WIDTH ; Use BP for Line width to\r
+ ; to avoid extra memory access\r
+ \r
+ 050C 2B D3 SUB DX, BX ; figure Delta_Y\r
+ 050E 73 05 JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1\r
+ \r
+ 0510 03 DA ADD BX, DX ; put Y2 into Y1\r
+ 0512 F7 DA NEG DX ; abs(Delta_Y)\r
+ 0514 91 XCHG AX, CX ; and exchange X1 and X2\r
+ \r
+ 0515 @DL_DeltaYOK2:\r
+ 0515 BB 8000 MOV BX, 08000H ; seed for fraction accumulator\r
+ \r
+ 0518 2B C8 SUB CX, AX ; figure Delta_X\r
+ 051A 72 03 JC @DL_DrawLeft ; if negative, go left\r
+ \r
+ 051C E9 0084 JMP @DL_DrawRight ; Draw Line that slopes right\r
+ \r
+ 051F @DL_DrawLeft:\r
+ \r
+ 051F F7 D9 NEG CX ; abs(Delta_X)\r
+ \r
+ 0521 3B CA CMP CX, DX ; is Delta_X < Delta_Y?\r
+ 0523 72 41 JB @DL_SteepLeft ; yes, so go do steep line\r
+ ; (Delta_Y iterations)\r
+ \r
+ ; Draw a Shallow line to the left in Mode X\r
+ \r
+ 0525 @DL_ShallowLeft:\r
+ CLR AX ; zero low word of Delta_Y * 10000h\r
+ 0525 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 0527 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
+ 0529 83 DA 00 SBB DX, 0 ; include carry\r
+ 052C F7 F1 DIV CX ; divide by Delta_X\r
+ \r
+ 052E 8B F3 MOV SI, BX ; SI = Accumulator\r
+ 0530 8B D8 MOV BX, AX ; BX = Add fraction\r
+ 0532 58 POP AX ; Get Color, Bit mask\r
+ 0533 BA 03C5 MOV DX, SC_Data ; Sequence controller data register\r
+ 0536 41 INC CX ; Inc Delta_X so we can unroll loop\r
+ \r
+ ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
+ \r
+ 0537 @DL_SLLLoop:\r
+ 0537 26: 88 25 MOV ES:[DI], AH ; set first pixel, plane data set up\r
+ LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
+ 053A 49 1 DEC CX ; Counter--\r
+ 053B 74 26 1 JZ @DL_SLLExit ; Jump if 0\r
+ \r
+ 053D 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 053F 73 02 JNC @DL_SLLL2nc ; move down on carry\r
+ \r
+ 0541 03 FD ADD DI, BP ; Move Down one line...\r
+ \r
+ 0543 @DL_SLLL2nc:\r
+ 0543 4F DEC DI ; Left one addr\r
+ 0544 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ 0546 3C 87 CMP AL, 87h ; wrap?, if AL <88 then Carry set\r
+ 0548 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 054B EE OUT DX, AL ; Set up New Bit Plane mask\r
+ \r
+ 054C 26: 88 25 MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
+ 054F 49 1 DEC CX ; Counter--\r
+ 0550 74 11 1 JZ @DL_SLLExit ; Jump if 0\r
+ \r
+ 0552 03 F3 ADD SI, BX ; add numerator to accumulator,\r
+ 0554 73 02 JNC @DL_SLLL3nc ; move down on carry\r
+ \r
+ 0556 03 FD ADD DI, BP ; Move Down one line...\r
+ \r
+ 0558 @DL_SLLL3nc: ; Now move left a pixel...\r
+ 0558 4F DEC DI ; Left one addr\r
+ 0559 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ 055B 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ 055D 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 0560 EE OUT DX, AL ; Set up New Bit Plane mask\r
+ 0561 EB D4 JMP s @DL_SLLLoop ; loop until done\r
+ \r
+ 0563 @DL_SLLExit:\r
+ 0563 E9 00B8 JMP @DL_EXIT2 ; and exit\r
+ \r
+ ; Draw a steep line to the left in Mode X\r
+ \r
+ 0566 @DL_SteepLeft:\r
+ CLR AX ; zero low word of Delta_Y * 10000h\r
+ 0566 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 0568 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X\r
+ 056A F7 F1 DIV CX ; divide by Delta_Y\r
+ \r
+ 056C 8B F3 MOV SI, BX ; SI = Accumulator\r
+ 056E 8B D8 MOV BX, AX ; BX = Add Fraction\r
+ 0570 58 POP AX ; Get Color, Bit mask\r
+ 0571 BA 03C5 MOV DX, SC_Data ; Sequence controller data register\r
+ 0574 41 INC CX ; Inc Delta_Y so we can unroll loop\r
+ \r
+ ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
+ \r
+ 0575 @DL_STLLoop:\r
+ \r
+ 0575 26: 88 25 MOV ES:[DI], AH ; set first pixel\r
+ LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
+ 0578 49 1 DEC CX ; Counter--\r
+ 0579 74 26 1 JZ @DL_STLExit ; Jump if 0\r
+ \r
+ 057B 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 057D 73 09 JNC @DL_STLnc2 ; No carry, just move down!\r
+ \r
+ 057F 4F DEC DI ; Move Left one addr\r
+ 0580 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ 0582 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ 0584 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 0587 EE OUT DX, AL ; Set up New Bit Plane mask\r
+ \r
+ 0588 @DL_STLnc2:\r
+ 0588 03 FD ADD DI, BP ; advance to next line.\r
+ \r
+ 058A 26: 88 25 MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
+ 058D 49 1 DEC CX ; Counter--\r
+ 058E 74 11 1 JZ @DL_STLExit ; Jump if 0\r
+ \r
+ 0590 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 0592 73 09 JNC @DL_STLnc3 ; No carry, just move down!\r
+ \r
+ 0594 4F DEC DI ; Move Left one addr\r
+ 0595 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
+ 0597 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
+ 0599 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 059C EE OUT DX, AL ; Set up New Bit Plane mask\r
+ \r
+ 059D @DL_STLnc3:\r
+ 059D 03 FD ADD DI, BP ; advance to next line.\r
+ 059F EB D4 JMP s @DL_STLLoop ; Loop until done\r
+ \r
+ 05A1 @DL_STLExit:\r
+ 05A1 EB 7B JMP @DL_EXIT2 ; and exit\r
+ \r
+ ; Draw a line that goes to the Right...\r
+ \r
+ 05A3 @DL_DrawRight:\r
+ 05A3 3B CA CMP CX, DX ; is Delta_X < Delta_Y?\r
+ 05A5 72 3E JB @DL_SteepRight ; yes, so go do steep line\r
+ ; (Delta_Y iterations)\r
+ \r
+ ; Draw a Shallow line to the Right in Mode X\r
+ \r
+ 05A7 @DL_ShallowRight:\r
+ CLR AX ; zero low word of Delta_Y * 10000h\r
+ 05A7 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 05A9 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
+ 05AB 83 DA 00 SBB DX, 0 ; include carry\r
+ 05AE F7 F1 DIV CX ; divide by Delta_X\r
+ \r
+ 05B0 8B F3 MOV SI, BX ; SI = Accumulator\r
+ 05B2 8B D8 MOV BX, AX ; BX = Add Fraction\r
+ 05B4 58 POP AX ; Get Color, Bit mask\r
+ 05B5 BA 03C5 MOV DX, SC_Data ; Sequence controller data register\r
+ 05B8 41 INC CX ; Inc Delta_X so we can unroll loop\r
+ \r
+ ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
+ \r
+ 05B9 @DL_SLRLoop:\r
+ 05B9 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up\r
+ LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
+ 05BC 49 1 DEC CX ; Counter--\r
+ 05BD 74 24 1 JZ @DL_SLRExit ; Jump if 0\r
+ \r
+ 05BF 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 05C1 73 02 JNC @DL_SLR2nc ; don't move down if carry not set\r
+ \r
+ 05C3 03 FD ADD DI, BP ; Move Down one line...\r
+ \r
+ 05C5 @DL_SLR2nc: ; Now move right a pixel...\r
+ 05C5 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ 05C7 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ 05C9 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 05CC EE OUT DX, AL ; Set up New Bit Plane mask\r
+ \r
+ 05CD 26: 88 25 MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
+ 05D0 49 1 DEC CX ; Counter--\r
+ 05D1 74 10 1 JZ @DL_SLRExit ; Jump if 0\r
+ \r
+ 05D3 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 05D5 73 02 JNC @DL_SLR3nc ; don't move down if carry not set\r
+ \r
+ 05D7 03 FD ADD DI, BP ; Move Down one line...\r
+ \r
+ 05D9 @DL_SLR3nc:\r
+ 05D9 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ 05DB 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ 05DD 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 05E0 EE OUT DX, AL ; Set up New Bit Plane mask\r
+ 05E1 EB D6 JMP s @DL_SLRLoop ; loop till done\r
+ \r
+ 05E3 @DL_SLRExit:\r
+ 05E3 EB 39 JMP @DL_EXIT2 ; and exit\r
+ \r
+ ; Draw a Steep line to the Right in Mode X\r
+ \r
+ 05E5 @DL_SteepRight:\r
+ CLR AX ; zero low word of Delta_Y * 10000h\r
+ 05E5 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 05E7 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X\r
+ 05E9 F7 F1 DIV CX ; divide by Delta_Y\r
+ \r
+ 05EB 8B F3 MOV SI, BX ; SI = Accumulator\r
+ 05ED 8B D8 MOV BX, AX ; BX = Add Fraction\r
+ 05EF 58 POP AX ; Get Color, Bit mask\r
+ 05F0 BA 03C5 MOV DX, SC_Data ; Sequence controller data register\r
+ 05F3 41 INC CX ; Inc Delta_Y so we can unroll loop\r
+ \r
+ ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
+ \r
+ 05F4 @STRLoop:\r
+ 05F4 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up\r
+ LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
+ 05F7 49 1 DEC CX ; Counter--\r
+ 05F8 74 24 1 JZ @DL_EXIT2 ; Jump if 0\r
+ \r
+ 05FA 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 05FC 73 08 JNC @STRnc2 ; if no carry then just go down...\r
+ \r
+ 05FE D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ 0600 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ 0602 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 0605 EE OUT DX, AL ; Set up New Bit Plane mask\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 7 - 1\r
+\r
+\r
+ \r
+ 0606 @STRnc2:\r
+ 0606 03 FD ADD DI, BP ; advance to next line.\r
+ \r
+ 0608 26: 88 25 MOV ES:[DI], AH ; set pixel\r
+ LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
+ 060B 49 1 DEC CX ; Counter--\r
+ 060C 74 10 1 JZ @DL_EXIT2 ; Jump if 0\r
+ \r
+ 060E 03 F3 ADD SI, BX ; add numerator to accumulator\r
+ 0610 73 08 JNC @STRnc3 ; if no carry then just go down...\r
+ \r
+ 0612 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0\r
+ 0614 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
+ 0616 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
+ 0619 EE OUT DX, AL ; Set up New Bit Plane mask\r
+ \r
+ 061A @STRnc3:\r
+ 061A 03 FD ADD DI, BP ; advance to next line.\r
+ 061C EB D6 JMP s @STRLoop ; loop till done\r
+ \r
+ 061E @DL_EXIT2:\r
+ POPx DI, SI, BP ; Restore Saved Registers\r
+ 061E 5F 1 POP DI ; Restore R1\r
+ 061F 5E 2 POP SI ; Restore R1\r
+ 0620 5D 3 POP BP ; Restore R1\r
+ 0621 CA 000A RET 10 ; Exit and Clean up Stack\r
+ \r
+ 0624 DRAW_LINE ENDP\r
+ \r
+ \r
+ ; ===== DAC COLOR REGISTER ROUTINES =====\r
+ \r
+ ;=================================================\r
+ ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
+ ;=================================================\r
+ ;\r
+ ; Sets a single (RGB) Vga Palette Register\r
+ ;\r
+ ; ENTRY: Register = The DAC # to modify (0-255)\r
+ ; Red = The new Red Intensity (0-63)\r
+ ; Green = The new Green Intensity (0-63)\r
+ ; Blue = The new Blue Intensity (0-63)\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 000E SDR_STACK STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 00 00 SDR_Blue DB ?,? ; Blue Data Value\r
+ 0008 00 00 SDR_Green DB ?,? ; Green Data Value\r
+ 000A 00 00 SDR_Red DB ?,? ; Red Data Value\r
+ 000C 00 00 SDR_Register DB ?,? ; Palette Register #\r
+ SDR_STACK ENDS\r
+ \r
+ PUBLIC SET_DAC_REGISTER\r
+ \r
+ 0624 SET_DAC_REGISTER PROC FAR\r
+ \r
+ 0624 55 PUSH BP ; Save BP\r
+ 0625 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ ; Select which DAC Register to modify\r
+ \r
+ OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register\r
+ 0627 BA 03C8 1 MOV DX, DAC_WRITE_ADDR ; then Select Register\r
+ 062A 8A 46 0C 1 MOV AL, [BP].SDR_Register ; then Get Data Value\r
+ 062D EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 062E BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register\r
+ OUT_8 DX, [BP].SDR_Red ; Set Red Intensity\r
+ 0631 8A 46 0A 1 MOV AL, [BP].SDR_Red ; then Get Data Value\r
+ 0634 EE 1 OUT DX, AL ; Set I/O Register\r
+ OUT_8 DX, [BP].SDR_Green ; Set Green Intensity\r
+ 0635 8A 46 08 1 MOV AL, [BP].SDR_Green ; then Get Data Value\r
+ 0638 EE 1 OUT DX, AL ; Set I/O Register\r
+ OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity\r
+ 0639 8A 46 06 1 MOV AL, [BP].SDR_Blue ; then Get Data Value\r
+ 063C EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 063D 5D POP BP ; Restore Registers\r
+ 063E CA 0008 RET 8 ; Exit & Clean Up Stack\r
+ \r
+ 0641 SET_DAC_REGISTER ENDP\r
+ \r
+ ;====================================================\r
+ ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
+ ;====================================================\r
+ ;\r
+ ; Reads the RGB Values of a single Vga Palette Register\r
+ ;\r
+ ; ENTRY: Register = The DAC # to read (0-255)\r
+ ; Red = Offset to Red Variable in DS\r
+ ; Green = Offset to Green Variable in DS\r
+ ; Blue = Offset to Blue Variable in DS\r
+ ;\r
+ ; EXIT: The values of the integer variables Red,\r
+ ; Green, and Blue are set to the values\r
+ ; taken from the specified DAC register.\r
+ ;\r
+ \r
+ 000E GDR_STACK STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 GDR_Blue DW ? ; Addr of Blue Data Value in DS\r
+ 0008 0000 GDR_Green DW ? ; Addr of Green Data Value in DS\r
+ 000A 0000 GDR_Red DW ? ; Addr of Red Data Value in DS\r
+ 000C 00 00 GDR_Register DB ?,? ; Palette Register #\r
+ GDR_STACK ENDS\r
+ \r
+ PUBLIC GET_DAC_REGISTER\r
+ \r
+ 0641 GET_DAC_REGISTER PROC FAR\r
+ \r
+ 0641 55 PUSH BP ; Save BP\r
+ 0642 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ ; Select which DAC Register to read in\r
+ \r
+ OUT_8 DAC_READ_ADDR, [BP].GDR_Register\r
+ 0644 BA 03C7 1 MOV DX, DAC_READ_ADDR ; then Select Register\r
+ 0647 8A 46 0C 1 MOV AL, [BP].GDR_Register ; then Get Data Value\r
+ 064A EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 064B BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register\r
+ CLR AX ; Clear AX\r
+ 064E 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ \r
+ 0650 EC IN AL, DX ; Read Red Value\r
+ 0651 8B 5E 0A MOV BX, [BP].GDR_Red ; Get Address of Red%\r
+ 0654 89 07 MOV [BX], AX ; *Red% = AX\r
+ \r
+ 0656 EC IN AL, DX ; Read Green Value\r
+ 0657 8B 5E 08 MOV BX, [BP].GDR_Green ; Get Address of Green%\r
+ 065A 89 07 MOV [BX], AX ; *Green% = AX\r
+ \r
+ 065C EC IN AL, DX ; Read Blue Value\r
+ 065D 8B 5E 06 MOV BX, [BP].GDR_Blue ; Get Address of Blue%\r
+ 0660 89 07 MOV [BX], AX ; *Blue% = AX\r
+ \r
+ 0662 5D POP BP ; Restore Registers\r
+ 0663 CA 0008 RET 8 ; Exit & Clean Up Stack\r
+ \r
+ 0666 GET_DAC_REGISTER ENDP\r
+ \r
+ \r
+ ;===========================================================\r
+ ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
+ ;===========================================================\r
+ ;\r
+ ; Sets a Block of Vga Palette Registers\r
+ ;\r
+ ; ENTRY: PalData = Far Pointer to Block of palette data\r
+ ; StartReg = First Register # in range to set (0-255)\r
+ ; EndReg = Last Register # in Range to set (0-255)\r
+ ; Sync = Wait for Vertical Retrace Flag (Boolean)\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ ; NOTES: PalData is a linear array of 3 byte Palette values\r
+ ; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
+ ;\r
+ \r
+ 0014 LDR_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x3 ; BP, DS, SI\r
+ 0006 00000000 DD ? ; Caller\r
+ 000A 0000 LDR_Sync DW ? ; Vertical Sync Flag\r
+ 000C 00 00 LDR_EndReg DB ?,? ; Last Register #\r
+ 000E 00 00 LDR_StartReg DB ?,? ; First Register #\r
+ 0010 00000000 LDR_PalData DD ? ; Far Ptr to Palette Data\r
+ LDR_STACK ENDS\r
+ \r
+ PUBLIC LOAD_DAC_REGISTERS\r
+ \r
+ 0666 LOAD_DAC_REGISTERS PROC FAR\r
+ \r
+ PUSHx BP, DS, SI ; Save Registers\r
+ 0666 55 1 PUSH BP ; Save R1\r
+ 0667 1E 2 PUSH DS ; Save R1\r
+ 0668 56 3 PUSH SI ; Save R1\r
+ 0669 8B EC mov BP, SP ; Set up Stack Frame\r
+ \r
+ 066B 8B 46 0A mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag\r
+ 066E 0B C0 or AX, AX ; is Sync Flag = 0?\r
+ 0670 74 05 jz @LDR_Load ; if so, skip call\r
+ \r
+ 0672 9A ---- 0795 R call f SYNC_DISPLAY ; wait for vsync\r
+ \r
+ ; Determine register #'s, size to copy, etc\r
+ \r
+ 0677 @LDR_Load:\r
+ \r
+ 0677 C5 76 10 lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data\r
+ 067A BA 03C8 mov DX, DAC_WRITE_ADDR ; DAC register # selector\r
+ \r
+ CLR AX, BX ; Clear for byte loads\r
+ 067D 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 067F 33 DB 2 XOR BX, BX ; Set Register = 0\r
+ 0681 8A 46 0E mov AL, [BP].LDR_StartReg ; Get Start Register\r
+ 0684 8A 5E 0C mov BL, [BP].LDR_EndReg ; Get End Register\r
+ \r
+ 0687 2B D8 sub BX, AX ; BX = # of DAC registers -1\r
+ 0689 43 inc BX ; BX = # of DAC registers\r
+ 068A 8B CB mov CX, BX ; CX = # of DAC registers\r
+ 068C 03 CB add CX, BX ; CX = " " * 2\r
+ 068E 03 CB add CX, BX ; CX = " " * 3\r
+ 0690 FC cld ; Block OUTs forward\r
+ 0691 EE out DX, AL ; set up correct register #\r
+ \r
+ ; Load a block of DAC Registers\r
+ \r
+ 0692 BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register\r
+ \r
+ 0695 F3/ 6E rep outsb ; block set DAC registers\r
+ \r
+ POPx SI, DS, BP ; Restore Registers\r
+ 0697 5E 1 POP SI ; Restore R1\r
+ 0698 1F 2 POP DS ; Restore R1\r
+ 0699 5D 3 POP BP ; Restore R1\r
+ 069A CA 000A ret 10 ; Exit & Clean Up Stack\r
+ \r
+ 069D LOAD_DAC_REGISTERS ENDP\r
+ \r
+ \r
+ ;====================================================\r
+ ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
+ ;====================================================\r
+ ;\r
+ ; Reads a Block of Vga Palette Registers\r
+ ;\r
+ ; ENTRY: PalData = Far Pointer to block to store palette data\r
+ ; StartReg = First Register # in range to read (0-255)\r
+ ; EndReg = Last Register # in Range to read (0-255)\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ ; NOTES: PalData is a linear array of 3 byte Palette values\r
+ ; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
+ ;\r
+ \r
+ 0012 RDR_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x3 ; BP, ES, DI\r
+ 0006 00000000 DD ? ; Caller\r
+ 000A 00 00 RDR_EndReg DB ?,? ; Last Register #\r
+ 000C 00 00 RDR_StartReg DB ?,? ; First Register #\r
+ 000E 00000000 RDR_PalData DD ? ; Far Ptr to Palette Data\r
+ RDR_STACK ENDS\r
+ \r
+ PUBLIC READ_DAC_REGISTERS\r
+ \r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 8 - 1\r
+\r
+\r
+ 069D READ_DAC_REGISTERS PROC FAR\r
+ \r
+ PUSHx BP, ES, DI ; Save Registers\r
+ 069D 55 1 PUSH BP ; Save R1\r
+ 069E 06 2 PUSH ES ; Save R1\r
+ 069F 57 3 PUSH DI ; Save R1\r
+ 06A0 8B EC mov BP, SP ; Set up Stack Frame\r
+ \r
+ ; Determine register #'s, size to copy, etc\r
+ \r
+ 06A2 C4 7E 0E les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer\r
+ 06A5 BA 03C7 mov DX, DAC_READ_ADDR ; DAC register # selector\r
+ \r
+ CLR AX, BX ; Clear for byte loads\r
+ 06A8 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 06AA 33 DB 2 XOR BX, BX ; Set Register = 0\r
+ 06AC 8A 46 0C mov AL, [BP].RDR_StartReg ; Get Start Register\r
+ 06AF 8A 5E 0A mov BL, [BP].RDR_EndReg ; Get End Register\r
+ \r
+ 06B2 2B D8 sub BX, AX ; BX = # of DAC registers -1\r
+ 06B4 43 inc BX ; BX = # of DAC registers\r
+ 06B5 8B CB mov CX, BX ; CX = # of DAC registers\r
+ 06B7 03 CB add CX, BX ; CX = " " * 2\r
+ 06B9 03 CB add CX, BX ; CX = " " * 3\r
+ 06BB FC cld ; Block INs forward\r
+ \r
+ ; Read a block of DAC Registers\r
+ \r
+ 06BC EE out DX, AL ; set up correct register #\r
+ 06BD BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register\r
+ \r
+ 06C0 F3/ 6C rep insb ; block read DAC registers\r
+ \r
+ POPx DI, ES, BP ; Restore Registers\r
+\r
+ 06C2 5F 1 POP DI ; Restore R1\r
+ 06C3 07 2 POP ES ; Restore R1\r
+ 06C4 5D 3 POP BP ; Restore R1\r
+ 06C5 CA 0008 ret 8 ; Exit & Clean Up Stack\r
+ \r
+ 06C8 READ_DAC_REGISTERS ENDP\r
+ \r
+ \r
+ ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+ \r
+ ;=========================\r
+ ;SET_ACTIVE_PAGE (PageNo%)\r
+ ;=========================\r
+ ;\r
+ ; Sets the active display Page to be used for future drawing\r
+ ;\r
+ ; ENTRY: PageNo = Display Page to make active\r
+ ; (values: 0 to Number of Pages - 1)\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0008 SAP_STACK STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 SAP_Page DW ? ; Page # for Drawing\r
+ SAP_STACK ENDS\r
+ \r
+ PUBLIC SET_ACTIVE_PAGE\r
+ \r
+ 06C8 SET_ACTIVE_PAGE PROC FAR\r
+ \r
+ 06C8 55 PUSH BP ; Preserve Registers\r
+ 06C9 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 06CB 8B 5E 06 MOV BX, [BP].SAP_Page ; Get Desired Page #\r
+ 06CE 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ 06D2 73 0D JAE @SAP_Exit ; IF Not, Do Nothing\r
+ \r
+ 06D4 89 1E 0012 R MOV ACTIVE_PAGE, BX ; Set Active Page #\r
+ \r
+ 06D8 D1 E3 SHL BX, 1 ; Scale Page # to Word\r
+ 06DA 8B 87 0006 R MOV AX, PAGE_ADDR[BX] ; Get offset to Page\r
+ \r
+ 06DE A3 0014 R MOV CURRENT_PAGE, AX ; And set for future LES's\r
+ \r
+ 06E1 @SAP_Exit:\r
+ 06E1 5D POP BP ; Restore Registers\r
+ 06E2 CA 0002 RET 2 ; Exit and Clean up Stack\r
+ \r
+ 06E5 SET_ACTIVE_PAGE ENDP\r
+ \r
+ \r
+ ;================\r
+ ;GET_ACTIVE_PAGE%\r
+ ;================\r
+ ;\r
+ ; Returns the Video Page # currently used for Drawing\r
+ ;\r
+ ; ENTRY: No Parameters are passed\r
+ ;\r
+ ; EXIT: AX = Current Video Page used for Drawing\r
+ ;\r
+ \r
+ PUBLIC GET_ACTIVE_PAGE\r
+ \r
+ 06E5 GET_ACTIVE_PAGE PROC FAR\r
+ \r
+ 06E5 A1 0012 R MOV AX, ACTIVE_PAGE ; Get Active Page #\r
+ 06E8 CB RET ; Exit and Clean up Stack\r
+ \r
+ 06E9 GET_ACTIVE_PAGE ENDP\r
+ \r
+ \r
+ ;===============================\r
+ ;SET_DISPLAY_PAGE (DisplayPage%)\r
+ ;===============================\r
+ ;\r
+ ; Sets the currently visible display page.\r
+ ; When called this routine syncronizes the display\r
+ ; to the vertical blank.\r
+ ;\r
+ ; ENTRY: PageNo = Display Page to show on the screen\r
+ ; (values: 0 to Number of Pages - 1)\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0008 SDP_STACK STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 SDP_Page DW ? ; Page # to Display...\r
+ SDP_STACK ENDS\r
+ \r
+ PUBLIC SET_DISPLAY_PAGE\r
+ \r
+ 06E9 SET_DISPLAY_PAGE PROC FAR\r
+ \r
+ 06E9 55 PUSH BP ; Preserve Registers\r
+ 06EA 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 06EC 8B 5E 06 MOV BX, [BP].SDP_Page ; Get Desired Page #\r
+ 06EF 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ 06F3 73 2B JAE @SDP_Exit ; IF Not, Do Nothing\r
+ \r
+ 06F5 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Display Page #\r
+ \r
+ 06F9 D1 E3 SHL BX, 1 ; Scale Page # to Word\r
+ 06FB 8B 8F 0006 R MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page\r
+ 06FF 03 0E 001C R ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
+ \r
+ ; Wait if we are currently in a Vertical Retrace\r
+ \r
+ 0703 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register\r
+ \r
+ 0706 @DP_WAIT0:\r
+ 0706 EC IN AL, DX ; Get VGA status\r
+ 0707 24 08 AND AL, VERT_RETRACE ; In Display mode yet?\r
+ 0709 75 FB JNZ @DP_WAIT0 ; If Not, wait for it\r
+ \r
+ ; Set the Start Display Address to the new page\r
+ \r
+ 070B BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
+ \r
+ 070E B0 0D MOV AL, START_DISP_LO ; Display Start Low Register\r
+ 0710 8A E1 MOV AH, CL ; Low 8 Bits of Start Addr\r
+ 0712 EF OUT DX, AX ; Set Display Addr Low\r
+ \r
+ 0713 B0 0C MOV AL, START_DISP_HI ; Display Start High Register\r
+ 0715 8A E5 MOV AH, CH ; High 8 Bits of Start Addr\r
+ 0717 EF OUT DX, AX ; Set Display Addr High\r
+ \r
+ ; Wait for a Vertical Retrace to smooth out things\r
+ \r
+ 0718 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register\r
+ \r
+ 071B @DP_WAIT1:\r
+ 071B EC IN AL, DX ; Get VGA status\r
+ 071C 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ 071E 74 FB JZ @DP_WAIT1 ; If Not, wait for it\r
+ \r
+ ; Now Set Display Starting Address\r
+ \r
+ \r
+ 0720 @SDP_Exit:\r
+ 0720 5D POP BP ; Restore Registers\r
+ 0721 CA 0002 RET 2 ; Exit and Clean up Stack\r
+ \r
+ 0724 SET_DISPLAY_PAGE ENDP\r
+ \r
+ \r
+ ;=================\r
+ ;GET_DISPLAY_PAGE%\r
+ ;=================\r
+ ;\r
+ ; Returns the Video Page # currently displayed\r
+ ;\r
+ ; ENTRY: No Parameters are passed\r
+ ;\r
+ ; EXIT: AX = Current Video Page being displayed\r
+ ;\r
+ \r
+ PUBLIC GET_DISPLAY_PAGE\r
+ \r
+ 0724 GET_DISPLAY_PAGE PROC FAR\r
+ \r
+ 0724 A1 0010 R MOV AX, DISPLAY_PAGE ; Get Display Page #\r
+ 0727 CB RET ; Exit & Clean Up Stack\r
+ \r
+ 0728 GET_DISPLAY_PAGE ENDP\r
+ \r
+ \r
+ ;=======================================\r
+ ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
+ ;=======================================\r
+ ;\r
+ ; Since a Logical Screen can be larger than the Physical\r
+ ; Screen, Scrolling is possible. This routine sets the\r
+ ; Upper Left Corner of the Screen to the specified Pixel.\r
+ ; Also Sets the Display page to simplify combined page\r
+ ; flipping and scrolling. When called this routine\r
+ ; syncronizes the display to the vertical blank.\r
+ ;\r
+ ; ENTRY: DisplayPage = Display Page to show on the screen\r
+ ; Xpos = # of pixels to shift screen right\r
+ ; Ypos = # of lines to shift screen down\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 000C SW_STACK STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 SW_Ypos DW ? ; Y pos of UL Screen Corner\r
+ 0008 0000 SW_Xpos DW ? ; X pos of UL Screen Corner\r
+ 000A 0000 SW_Page DW ? ; (new) Display Page\r
+ SW_STACK ENDS\r
+ \r
+ PUBLIC SET_WINDOW\r
+ \r
+ 0728 SET_WINDOW PROC FAR\r
+ \r
+ 0728 55 PUSH BP ; Preserve Registers\r
+ 0729 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ ; Check if our Scroll Offsets are Valid\r
+ \r
+ 072B 8B 5E 0A MOV BX, [BP].SW_Page ; Get Desired Page #\r
+ 072E 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid?\r
+ 0732 73 55 JAE @SW_Exit ; IF Not, Do Nothing\r
+ \r
+ 0734 8B 46 06 MOV AX, [BP].SW_Ypos ; Get Desired Y Offset\r
+ 0737 3B 06 0020 R CMP AX, MAX_YOFFSET ; Is it Within Limits?\r
+ 073B 77 4C JA @SW_Exit ; if not, exit\r
+ \r
+ 073D 8B 4E 08 MOV CX, [BP].SW_Xpos ; Get Desired X Offset\r
+ 0740 3B 0E 001E R CMP CX, MAX_XOFFSET ; Is it Within Limits?\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 9 - 1\r
+\r
+\r
+ 0744 77 43 JA @SW_Exit ; if not, exit\r
+ \r
+ ; Compute proper Display start address to use\r
+ \r
+ 0746 F7 26 0000 R MUL SCREEN_WIDTH ; AX = YOffset * Line Width\r
+ 074A C1 E9 02 SHR CX, 2 ; CX / 4 = Bytes into Line\r
+ 074D 03 C1 ADD AX, CX ; AX = Offset of Upper Left Pixel\r
+ \r
+ 074F A3 001C R MOV CURRENT_MOFFSET, AX ; Save Offset Info\r
+ \r
+ 0752 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Current Page #\r
+ 0756 D1 E3 SHL BX, 1 ; Scale Page # to Word\r
+ 0758 03 87 0006 R ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page\r
+ 075C 8B D8 MOV BX, AX ; BX = Desired Display Start\r
+ \r
+ 075E BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register\r
+ \r
+ ; Wait if we are currently in a Vertical Retrace\r
+ \r
+ 0761 @SW_WAIT0:\r
+ 0761 EC IN AL, DX ; Get VGA status\r
+ 0762 24 08 AND AL, VERT_RETRACE ; In Display mode yet?\r
+ 0764 75 FB JNZ @SW_WAIT0 ; If Not, wait for it\r
+ \r
+ ; Set the Start Display Address to the new window\r
+ \r
+ 0766 BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
+ 0769 B0 0D MOV AL, START_DISP_LO ; Display Start Low Register\r
+ 076B 8A E3 MOV AH, BL ; Low 8 Bits of Start Addr\r
+ 076D EF OUT DX, AX ; Set Display Addr Low\r
+ \r
+ 076E B0 0C MOV AL, START_DISP_HI ; Display Start High Register\r
+ 0770 8A E7 MOV AH, BH ; High 8 Bits of Start Addr\r
+ 0772 EF OUT DX, AX ; Set Display Addr High\r
+ \r
+ ; Wait for a Vertical Retrace to smooth out things\r
+ \r
+ 0773 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register\r
+ \r
+ 0776 @SW_WAIT1:\r
+ 0776 EC IN AL, DX ; Get VGA status\r
+ 0777 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ 0779 74 FB JZ @SW_WAIT1 ; If Not, wait for it\r
+ \r
+ ; Now Set the Horizontal Pixel Pan values\r
+ \r
+ OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register\r
+ 077B BA 03C0 1 MOV DX, ATTRIB_Ctrl ; then Select Register\r
+ 077E B0 33 1 MOV AL, PIXEL_PAN_REG ; then Get Data Value\r
+ 0780 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0781 8B 46 08 MOV AX, [BP].SW_Xpos ; Get Desired X Offset\r
+ 0784 24 03 AND AL, 03 ; Get # of Pixels to Pan (0-3)\r
+ 0786 D0 E0 SHL AL, 1 ; Shift for 256 Color Mode\r
+ 0788 EE OUT DX, AL ; Fine tune the display!\r
+ \r
+ 0789 @SW_Exit:\r
+ 0789 5D POP BP ; Restore Saved Registers\r
+ 078A CA 0006 RET 6 ; Exit and Clean up Stack\r
+ \r
+ 078D SET_WINDOW ENDP\r
+ \r
+ \r
+ ;=============\r
+ ;GET_X_OFFSET%\r
+ ;=============\r
+ ;\r
+ ; Returns the X coordinate of the Pixel currently display\r
+ ; in the upper left corner of the display\r
+ ;\r
+ ; ENTRY: No Parameters are passed\r
+ ;\r
+ ; EXIT: AX = Current Horizontal Scroll Offset\r
+ ;\r
+ \r
+ PUBLIC GET_X_OFFSET\r
+ \r
+ 078D GET_X_OFFSET PROC FAR\r
+ \r
+ 078D A1 0018 R MOV AX, CURRENT_XOFFSET ; Get current horz offset\r
+ 0790 CB RET ; Exit & Clean Up Stack\r
+ \r
+ 0791 GET_X_OFFSET ENDP\r
+ \r
+ \r
+ ;=============\r
+ ;GET_Y_OFFSET%\r
+ ;=============\r
+ ;\r
+ ; Returns the Y coordinate of the Pixel currently display\r
+ ; in the upper left corner of the display\r
+ ;\r
+ ; ENTRY: No Parameters are passed\r
+ ;\r
+ ; EXIT: AX = Current Vertical Scroll Offset\r
+ ;\r
+ \r
+ PUBLIC GET_Y_OFFSET\r
+ \r
+ 0791 GET_Y_OFFSET PROC FAR\r
+ \r
+ 0791 A1 001A R MOV AX, CURRENT_YOFFSET ; Get current vertical offset\r
+ 0794 CB RET ; Exit & Clean Up Stack\r
+ \r
+ 0795 GET_Y_OFFSET ENDP\r
+ \r
+ \r
+ ;============\r
+ ;SYNC_DISPLAY\r
+ ;============\r
+ ;\r
+ ; Pauses the computer until the next Vertical Retrace starts\r
+ ;\r
+ ; ENTRY: No Parameters are passed\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ PUBLIC SYNC_DISPLAY\r
+ \r
+ 0795 SYNC_DISPLAY PROC FAR\r
+ \r
+ 0795 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register\r
+ \r
+ ; Wait for any current retrace to end\r
+ \r
+ 0798 @SD_WAIT0:\r
+ 0798 EC IN AL, DX ; Get VGA status\r
+ 0799 24 08 AND AL, VERT_RETRACE ; In Display mode yet?\r
+ 079B 75 FB JNZ @SD_WAIT0 ; If Not, wait for it\r
+ \r
+ ; Wait for the start of the next vertical retrace\r
+ \r
+ 079D @SD_WAIT1:\r
+ 079D EC IN AL, DX ; Get VGA status\r
+ 079E 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
+ 07A0 74 FB JZ @SD_WAIT1 ; If Not, wait for it\r
+ \r
+ 07A2 CB RET ; Exit & Clean Up Stack\r
+ \r
+ 07A3 SYNC_DISPLAY ENDP\r
+ \r
+ \r
+ ; ===== TEXT DISPLAY ROUTINES =====\r
+ \r
+ ;==================================================\r
+ ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+ ;==================================================\r
+ ;\r
+ ; Draws an ASCII Text Character using the currently selected\r
+ ; 8x8 font on the active display page. It would be a simple\r
+ ; exercise to make this routine process variable height fonts.\r
+ ;\r
+ ; ENTRY: CharNum = ASCII character # to draw\r
+ ; Xpos = X position to draw Character at\r
+ ; Ypos = Y position of to draw Character at\r
+ ; ColorF = Color to draw text character in\r
+ ; ColorB = Color to set background to\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 001E GPC_STACK STRUC\r
+ 0000 0000 GPC_Width DW ? ; Screen Width-1\r
+ 0002 00 00 GPC_Lines DB ?,? ; Scan lines to Decode\r
+ 0004 0000 GPC_T_SETS DW ? ; Saved Charset Segment\r
+ 0006 0000 GPC_T_SETO DW ? ; Saved Charset Offset\r
+ 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0010 00000000 DD ? ; Caller\r
+ 0014 00 00 GPC_ColorB DB ?,? ; Background Color\r
+ 0016 00 00 GPC_ColorF DB ?,? ; Text Color\r
+ 0018 0000 GPC_Ypos DW ? ; Y Position to Print at\r
+ 001A 0000 GPC_Xpos DW ? ; X position to Print at\r
+ 001C 00 00 GPC_Char DB ?,? ; Character to Print\r
+ GPC_STACK ENDS\r
+ \r
+ PUBLIC GPRINTC\r
+ \r
+ 07A3 GPRINTC PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 07A3 55 1 PUSH BP ; Save R1\r
+ 07A4 1E 2 PUSH DS ; Save R1\r
+ 07A5 56 3 PUSH SI ; Save R1\r
+ 07A6 57 4 PUSH DI ; Save R1\r
+ 07A7 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack\r
+ 07AA 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 07AC C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ \r
+ 07B0 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
+ 07B3 8B D8 MOV BX, AX ; BX = Screen Width\r
+ 07B5 4B DEC BX ; = Screen Width-1\r
+ 07B6 89 5E 00 MOV [BP].GPC_Width, BX ; Save for later use\r
+ \r
+ 07B9 F7 66 18 MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width\r
+ 07BC 03 F8 ADD DI, AX ; DI -> Start of Line Ypos\r
+ \r
+ 07BE 8B 46 1A MOV AX, [BP].GPC_Xpos ; Get Xpos of Character\r
+ 07C1 8B C8 MOV CX, AX ; Save Copy of Xpos\r
+ 07C3 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4\r
+ 07C6 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos)\r
+ \r
+ ;Get Source ADDR of Character Bit Map & Save\r
+ \r
+ 07C8 8A 46 1C MOV AL, [BP].GPC_Char ; Get Character #\r
+ 07CB A8 80 TEST AL, 080h ; Is Hi Bit Set?\r
+ 07CD 74 0C JZ @GPC_LowChar ; Nope, use low char set ptr\r
+ \r
+ 07CF 24 7F AND AL, 07Fh ; Mask Out Hi Bit\r
+ 07D1 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
+ 07D5 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
+ 07D9 EB 08 JMP s @GPC_Set_Char ; Go Setup Character Ptr\r
+ \r
+ 07DB @GPC_LowChar:\r
+ \r
+ 07DB 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
+ 07DF 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
+ \r
+ 07E3 @GPC_Set_Char:\r
+ 07E3 89 56 04 MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
+ \r
+ 07E6 B4 00 MOV AH, 0 ; Valid #'s are 0..127\r
+ 07E8 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap\r
+ 07EB 03 D8 ADD BX, AX ; BX = Offset of Selected char\r
+ 07ED 89 5E 06 MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
+ \r
+ 07F0 83 E1 03 AND CX, PLANE_BITS ; Get Plane #\r
+ 07F3 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask\r
+ 07F5 D2 E5 SHL CH, CL ; And shift into position\r
+ 07F7 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble\r
+ \r
+ 07FA B0 04 MOV AL, 04 ; 4-Plane # = # of initial\r
+ 07FC 2A C1 SUB AL, CL ; shifts to align bit mask\r
+ 07FE 8A C8 MOV CL, AL ; Shift Count for SHL\r
+ \r
+ ;Get segment of character map\r
+ \r
+ OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
+ 0800 BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 0803 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value\r
+ 0805 EE 1 OUT DX, AL ; Set I/O Register\r
+ 0806 42 INC DX ; DX -> SC_Data\r
+ \r
+ 0807 B0 08 MOV AL, 08 ; 8 Lines to Process\r
+ 0809 88 46 02 MOV [BP].GPC_Lines, AL ; Save on Stack\r
+ \r
+ 080C 8E 5E 04 MOV DS, [BP].GPC_T_SETS ; Point to character set\r
+ \r
+ 080F @GPC_DECODE_CHAR_BYTE:\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 10 - 1\r
+\r
+\r
+ \r
+ 080F 8B 76 06 MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
+ \r
+ 0812 8A 3C MOV BH, [SI] ; Get Bit Map\r
+ 0814 46 INC SI ; Point to Next Line\r
+ 0815 89 76 06 MOV [BP].GPC_T_SETO, SI ; And save new Pointer...\r
+ \r
+ CLR AX ; Clear AX\r
+ 0818 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ \r
+ CLR BL ; Clear BL\r
+ 081A 32 DB 1 XOR BL, BL ; Set Register = 0\r
+ 081C D3 C3 ROL BX, CL ; BL holds left edge bits\r
+ 081E 8B F3 MOV SI, BX ; Use as Table Index\r
+ 0820 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits\r
+ 0823 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0828 74 07 JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set\r
+ \r
+ 082A 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ 082D EE OUT DX, AL ; Set up Screen Mask\r
+ 082E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 0831 @GPC_NO_LEFT1BITS:\r
+ 0831 32 C5 XOR AL, CH ; Invert mask for Background\r
+ 0833 74 07 JZ @GPC_NO_LEFT0BITS ; Hey, no need for this\r
+ \r
+ 0835 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ 0838 EE OUT DX, AL ; Set up Screen Mask\r
+ 0839 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ ;Now Do Middle/Last Band\r
+ \r
+ 083C @GPC_NO_LEFT0BITS:\r
+ 083C 47 INC DI ; Point to next Byte\r
+ 083D C1 C3 04 ROL BX, 4 ; Shift 4 bits\r
+ \r
+ 0840 8B F3 MOV SI, BX ; Make Lookup Pointer\r
+ 0842 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits\r
+ 0845 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 084A 74 07 JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set\r
+ \r
+ 084C 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ 084F EE OUT DX, AL ; Set up Screen Mask\r
+ 0850 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 0853 @GPC_NO_MIDDLE1BITS:\r
+ 0853 34 0F XOR AL, ALL_PLANES ; Invert mask for Background\r
+ 0855 74 07 JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
+ \r
+ 0857 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ 085A EE OUT DX, AL ; Set up Screen Mask\r
+ 085B 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 085E @GPC_NO_MIDDLE0BITS:\r
+ 085E 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask\r
+ 0861 80 F9 04 CMP CL, 4 ; Aligned by 4?\r
+ 0864 74 23 JZ @GPC_NEXT_LINE ; If so, Exit now..\r
+ \r
+ 0866 47 INC DI ; Point to next Byte\r
+ 0867 C1 C3 04 ROL BX, 4 ; Shift 4 bits\r
+ \r
+ 086A 8B F3 MOV SI, BX ; Make Lookup Pointer\r
+ 086C 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits\r
+ 086F 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0874 74 07 JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set\r
+ \r
+ 0876 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ 0879 EE OUT DX, AL ; Set up Screen Mask\r
+ 087A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 087D @GPC_NO_RIGHT1BITS:\r
+ \r
+ 087D 32 C5 XOR AL, CH ; Invert mask for Background\r
+ 087F 74 07 JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this\r
+ \r
+ 0881 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color\r
+ 0884 EE OUT DX, AL ; Set up Screen Mask\r
+ 0885 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 0888 @GPC_NO_RIGHT0BITS:\r
+ 0888 4F DEC DI ; Adjust for Next Line Advance\r
+ \r
+ 0889 @GPC_NEXT_LINE:\r
+ 0889 03 7E 00 ADD DI, [BP].GPC_Width ; Point to Next Line\r
+ 088C 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back\r
+ \r
+ 088F FE 4E 02 DEC [BP].GPC_Lines ; Count Down Lines\r
+ 0892 74 03 JZ @GPC_EXIT ; Ok... Done!\r
+ \r
+ 0894 E9 FF78 JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey!\r
+ \r
+ 0897 @GPC_EXIT:\r
+ 0897 83 C4 08 ADD SP, 08 ; Deallocate stack workspace\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 089A 5F 1 POP DI ; Restore R1\r
+ 089B 5E 2 POP SI ; Restore R1\r
+ 089C 1F 3 POP DS ; Restore R1\r
+ 089D 5D 4 POP BP ; Restore R1\r
+ 089E CA 000A RET 10 ; Exit and Clean up Stack\r
+ \r
+ 08A1 GPRINTC ENDP\r
+ \r
+ \r
+ ;==========================================\r
+ ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
+ ;==========================================\r
+ ;\r
+ ; Transparently draws an ASCII Text Character using the\r
+ ; currently selected 8x8 font on the active display page.\r
+ ;\r
+ ; ENTRY: CharNum = ASCII character # to draw\r
+ ; Xpos = X position to draw Character at\r
+ ; Ypos = Y position of to draw Character at\r
+ ; ColorF = Color to draw text character in\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 001C TGP_STACK STRUC\r
+ 0000 0000 TGP_Width DW ? ; Screen Width-1\r
+ 0002 00 00 TGP_Lines DB ?,? ; Scan lines to Decode\r
+ 0004 0000 TGP_T_SETS DW ? ; Saved Charset Segment\r
+ 0006 0000 TGP_T_SETO DW ? ; Saved Charset Offset\r
+ 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0010 00000000 DD ? ; Caller\r
+ 0014 00 00 TGP_ColorF DB ?,? ; Text Color\r
+ 0016 0000 TGP_Ypos DW ? ; Y Position to Print at\r
+ 0018 0000 TGP_Xpos DW ? ; X position to Print at\r
+ 001A 00 00 TGP_Char DB ?,? ; Character to Print\r
+ TGP_STACK ENDS\r
+ \r
+ PUBLIC TGPRINTC\r
+ \r
+ 08A1 TGPRINTC PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 08A1 55 1 PUSH BP ; Save R1\r
+ 08A2 1E 2 PUSH DS ; Save R1\r
+ 08A3 56 3 PUSH SI ; Save R1\r
+ 08A4 57 4 PUSH DI ; Save R1\r
+ 08A5 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack\r
+ 08A8 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 08AA C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ \r
+ 08AE A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
+ 08B1 8B D8 MOV BX, AX ; BX = Screen Width\r
+ 08B3 4B DEC BX ; = Screen Width-1\r
+ 08B4 89 5E 00 MOV [BP].TGP_Width, BX ; Save for later use\r
+ \r
+ 08B7 F7 66 16 MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width\r
+ 08BA 03 F8 ADD DI, AX ; DI -> Start of Line Ypos\r
+ \r
+ 08BC 8B 46 18 MOV AX, [BP].TGP_Xpos ; Get Xpos of Character\r
+ 08BF 8B C8 MOV CX, AX ; Save Copy of Xpos\r
+ 08C1 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4\r
+ 08C4 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos)\r
+ \r
+ ;Get Source ADDR of Character Bit Map & Save\r
+ \r
+ 08C6 8A 46 1A MOV AL, [BP].TGP_Char ; Get Character #\r
+ 08C9 A8 80 TEST AL, 080h ; Is Hi Bit Set?\r
+ 08CB 74 0C JZ @TGP_LowChar ; Nope, use low char set ptr\r
+ \r
+ 08CD 24 7F AND AL, 07Fh ; Mask Out Hi Bit\r
+ 08CF 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
+ 08D3 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
+ 08D7 EB 08 JMP s @TGP_Set_Char ; Go Setup Character Ptr\r
+ \r
+ 08D9 @TGP_LowChar:\r
+ \r
+ 08D9 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
+ 08DD 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
+ \r
+ 08E1 @TGP_Set_Char:\r
+ 08E1 89 56 04 MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
+ \r
+ 08E4 B4 00 MOV AH, 0 ; Valid #'s are 0..127\r
+ 08E6 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap\r
+ 08E9 03 D8 ADD BX, AX ; BX = Offset of Selected char\r
+ 08EB 89 5E 06 MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
+ \r
+ 08EE 83 E1 03 AND CX, PLANE_BITS ; Get Plane #\r
+ 08F1 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask\r
+ 08F3 D2 E5 SHL CH, CL ; And shift into position\r
+ 08F5 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble\r
+ \r
+ 08F8 B0 04 MOV AL, 04 ; 4-Plane # = # of initial\r
+ 08FA 2A C1 SUB AL, CL ; shifts to align bit mask\r
+ 08FC 8A C8 MOV CL, AL ; Shift Count for SHL\r
+ \r
+ ;Get segment of character map\r
+ \r
+ OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
+ 08FE BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 0901 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value\r
+ 0903 EE 1 OUT DX, AL ; Set I/O Register\r
+ 0904 42 INC DX ; DX -> SC_Data\r
+ \r
+ 0905 B0 08 MOV AL, 08 ; 8 Lines to Process\r
+ 0907 88 46 02 MOV [BP].TGP_Lines, AL ; Save on Stack\r
+ \r
+ 090A 8E 5E 04 MOV DS, [BP].TGP_T_SETS ; Point to character set\r
+ \r
+ 090D @TGP_DECODE_CHAR_BYTE:\r
+ \r
+ 090D 8B 76 06 MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
+ \r
+ 0910 8A 3C MOV BH, [SI] ; Get Bit Map\r
+ 0912 46 INC SI ; Point to Next Line\r
+ 0913 89 76 06 MOV [BP].TGP_T_SETO, SI ; And save new Pointer...\r
+ \r
+ 0916 8A 66 14 MOV AH, [BP].TGP_ColorF ; Get Foreground Color\r
+ \r
+ CLR BL ; Clear BL\r
+ 0919 32 DB 1 XOR BL, BL ; Set Register = 0\r
+ 091B D3 C3 ROL BX, CL ; BL holds left edge bits\r
+ 091D 8B F3 MOV SI, BX ; Use as Table Index\r
+ 091F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits\r
+ 0922 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0927 74 04 JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set\r
+ \r
+ 0929 EE OUT DX, AL ; Set up Screen Mask\r
+ 092A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ ;Now Do Middle/Last Band\r
+ \r
+ 092D @TGP_NO_LEFT1BITS:\r
+ \r
+ 092D 47 INC DI ; Point to next Byte\r
+ 092E C1 C3 04 ROL BX, 4 ; Shift 4 bits\r
+ \r
+ 0931 8B F3 MOV SI, BX ; Make Lookup Pointer\r
+ 0933 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits\r
+ 0936 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 093B 74 04 JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set\r
+ \r
+ 093D EE OUT DX, AL ; Set up Screen Mask\r
+ 093E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 0941 @TGP_NO_MIDDLE1BITS:\r
+ 0941 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask\r
+ 0944 80 F9 04 CMP CL, 4 ; Aligned by 4?\r
+ 0947 74 15 JZ @TGP_NEXT_LINE ; If so, Exit now..\r
+ \r
+ 0949 47 INC DI ; Point to next Byte\r
+ 094A C1 C3 04 ROL BX, 4 ; Shift 4 bits\r
+ \r
+ 094D 8B F3 MOV SI, BX ; Make Lookup Pointer\r
+ 094F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 11 - 1\r
+\r
+\r
+ 0952 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0957 74 04 JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set\r
+ \r
+ 0959 EE OUT DX, AL ; Set up Screen Mask\r
+ 095A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color\r
+ \r
+ 095D @TGP_NO_RIGHT1BITS:\r
+ \r
+ 095D 4F DEC DI ; Adjust for Next Line Advance\r
+ \r
+ 095E @TGP_NEXT_LINE:\r
+ 095E 03 7E 00 ADD DI, [BP].TGP_Width ; Point to Next Line\r
+ 0961 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back\r
+ \r
+ 0964 FE 4E 02 DEC [BP].TGP_Lines ; Count Down Lines\r
+ 0967 74 02 JZ @TGP_EXIT ; Ok... Done!\r
+ \r
+ 0969 EB A2 JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey!\r
+ \r
+ 096B @TGP_EXIT:\r
+ 096B 83 C4 08 ADD SP, 08 ; Deallocate stack workspace\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 096E 5F 1 POP DI ; Restore R1\r
+ 096F 5E 2 POP SI ; Restore R1\r
+ 0970 1F 3 POP DS ; Restore R1\r
+ 0971 5D 4 POP BP ; Restore R1\r
+ 0972 CA 0008 RET 8 ; Exit and Clean up Stack\r
+ \r
+ 0975 TGPRINTC ENDP\r
+ \r
+ \r
+ ;===============================================================\r
+ ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+ ;===============================================================\r
+ ;\r
+ ; Routine to quickly Print a null terminated ASCII string on the\r
+ ; active display page up to a maximum length.\r
+ ;\r
+ ; ENTRY: String = Far Pointer to ASCII string to print\r
+ ; MaxLen = # of characters to print if no null found\r
+ ; Xpos = X position to draw Text at\r
+ ; Ypos = Y position of to draw Text at\r
+ ; ColorF = Color to draw text in\r
+ ; ColorB = Color to set background to\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 001A PS_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 0000 PS_ColorB DW ? ; Background Color\r
+ 000E 0000 PS_ColorF DW ? ; Text Color\r
+ 0010 0000 PS_Ypos DW ? ; Y Position to Print at\r
+ 0012 0000 PS_Xpos DW ? ; X position to Print at\r
+ 0014 0000 PS_Len DW ? ; Maximum Length of string to print\r
+ 0016 0000 0000 PS_Text DW ?,? ; Far Ptr to Text String\r
+ PS_STACK ENDS\r
+ \r
+ PUBLIC PRINT_STR\r
+ \r
+ 0975 PRINT_STR PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0975 55 1 PUSH BP ; Save R1\r
+ 0976 1E 2 PUSH DS ; Save R1\r
+ 0977 56 3 PUSH SI ; Save R1\r
+ 0978 57 4 PUSH DI ; Save R1\r
+ 0979 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 097B @PS_Print_It:\r
+ \r
+ 097B 8B 4E 14 MOV CX, [BP].PS_Len ; Get Remaining text Length\r
+ 097E E3 2F JCXZ @PS_Exit ; Exit when out of text\r
+ \r
+ 0980 C4 7E 16 LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text\r
+ 0983 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character\r
+ 0986 25 00FF AND AX, 00FFh ; Clear High Word\r
+ 0989 74 24 JZ @PS_Exit ; Exit if null character\r
+ \r
+ 098B FF 4E 14 DEC [BP].PS_Len ; Remaining Text length--\r
+ 098E FF 46 16 INC [BP].PS_Text ; Point to Next text char\r
+ \r
+ ; Set up Call to GPRINTC\r
+ \r
+ 0991 50 PUSH AX ; Set Character Parameter\r
+ 0992 8B 5E 12 MOV BX, [BP].PS_Xpos ; Get Xpos\r
+ 0995 53 PUSH BX ; Set Xpos Parameter\r
+ 0996 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right\r
+ 0999 89 5E 12 MOV [BP].PS_Xpos, BX ; Save for next time through\r
+ \r
+ 099C 8B 5E 10 MOV BX, [BP].PS_Ypos ; Get Ypos\r
+ 099F 53 PUSH BX ; Set Ypos Parameter\r
+ \r
+ 09A0 8B 5E 0E MOV BX, [BP].PS_ColorF ; Get Text Color\r
+ 09A3 53 PUSH BX ; Set ColorF Parameter\r
+ \r
+ 09A4 8B 5E 0C MOV BX, [BP].PS_ColorB ; Get Background Color\r
+ 09A7 53 PUSH BX ; Set ColorB Parameter\r
+ \r
+ 09A8 9A ---- 07A3 R CALL f GPRINTC ; Print Character!\r
+ 09AD EB CC JMP s @PS_Print_It ; Process next character\r
+ \r
+ 09AF @PS_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 09AF 5F 1 POP DI ; Restore R1\r
+ 09B0 5E 2 POP SI ; Restore R1\r
+ 09B1 1F 3 POP DS ; Restore R1\r
+ 09B2 5D 4 POP BP ; Restore R1\r
+ 09B3 CA 000E RET 14 ; Exit and Clean up Stack\r
+ \r
+ 09B6 PRINT_STR ENDP\r
+ \r
+ \r
+ ;================================================================\r
+ ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+ ;================================================================\r
+ ;\r
+ ; Routine to quickly transparently Print a null terminated ASCII\r
+ ; string on the active display page up to a maximum length.\r
+ ;\r
+ ; ENTRY: String = Far Pointer to ASCII string to print\r
+ ; MaxLen = # of characters to print if no null found\r
+ ; Xpos = X position to draw Text at\r
+ ; Ypos = Y position of to draw Text at\r
+ ; ColorF = Color to draw text in\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0018 TPS_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 0000 TPS_ColorF DW ? ; Text Color\r
+ 000E 0000 TPS_Ypos DW ? ; Y Position to Print at\r
+ 0010 0000 TPS_Xpos DW ? ; X position to Print at\r
+ 0012 0000 TPS_Len DW ? ; Maximum Length of string to print\r
+ 0014 0000 0000 TPS_Text DW ?,? ; Far Ptr to Text String\r
+ TPS_STACK ENDS\r
+ \r
+ PUBLIC TPRINT_STR\r
+ \r
+ 09B6 TPRINT_STR PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 09B6 55 1 PUSH BP ; Save R1\r
+ 09B7 1E 2 PUSH DS ; Save R1\r
+ 09B8 56 3 PUSH SI ; Save R1\r
+ 09B9 57 4 PUSH DI ; Save R1\r
+ 09BA 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 09BC @TPS_Print_It:\r
+ \r
+ 09BC 8B 4E 12 MOV CX, [BP].TPS_Len ; Get Remaining text Length\r
+ 09BF E3 2B JCXZ @TPS_Exit ; Exit when out of text\r
+ \r
+ 09C1 C4 7E 14 LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
+ 09C4 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character\r
+ 09C7 25 00FF AND AX, 00FFh ; Clear High Word\r
+ 09CA 74 20 JZ @TPS_Exit ; Exit if null character\r
+ \r
+ 09CC FF 4E 12 DEC [BP].TPS_Len ; Remaining Text length--\r
+ 09CF FF 46 14 INC [BP].TPS_Text ; Point to Next text char\r
+ \r
+ ; Set up Call to TGPRINTC\r
+ \r
+ 09D2 50 PUSH AX ; Set Character Parameter\r
+ 09D3 8B 5E 10 MOV BX, [BP].TPS_Xpos ; Get Xpos\r
+ 09D6 53 PUSH BX ; Set Xpos Parameter\r
+ 09D7 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right\r
+ 09DA 89 5E 10 MOV [BP].TPS_Xpos, BX ; Save for next time through\r
+ \r
+ 09DD 8B 5E 0E MOV BX, [BP].TPS_Ypos ; Get Ypos\r
+ 09E0 53 PUSH BX ; Set Ypos Parameter\r
+ \r
+ 09E1 8B 5E 0C MOV BX, [BP].TPS_ColorF ; Get Text Color\r
+ 09E4 53 PUSH BX ; Set ColorF Parameter\r
+ \r
+ 09E5 9A ---- 08A1 R CALL f TGPRINTC ; Print Character!\r
+ 09EA EB D0 JMP s @TPS_Print_It ; Process next character\r
+ \r
+ 09EC @TPS_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 09EC 5F 1 POP DI ; Restore R1\r
+ 09ED 5E 2 POP SI ; Restore R1\r
+ 09EE 1F 3 POP DS ; Restore R1\r
+ 09EF 5D 4 POP BP ; Restore R1\r
+ 09F0 CA 000C RET 12 ; Exit and Clean up Stack\r
+ \r
+ 09F3 TPRINT_STR ENDP\r
+ \r
+ \r
+ ;===========================================\r
+ ;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
+ ;===========================================\r
+ ;\r
+ ; Allows the user to specify their own font data for\r
+ ; wither the lower or upper 128 characters.\r
+ ;\r
+ ; ENTRY: FontData = Far Pointer to Font Bitmaps\r
+ ; FontNumber = Which half of set this is\r
+ ; = 0, Lower 128 characters\r
+ ; = 1, Upper 128 characters\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 000C SDF_STACK STRUC\r
+ 0000 0000 DW ? ; BP\r
+ 0002 00000000 DD ? ; Caller\r
+ 0006 0000 SDF_Which DW ? ; Hi Table/Low Table Flag\r
+ 0008 00000000 SDF_Font DD ? ; Far Ptr to Font Table\r
+ SDF_STACK ENDS\r
+ \r
+ PUBLIC SET_DISPLAY_FONT\r
+ \r
+ 09F3 SET_DISPLAY_FONT PROC FAR\r
+ \r
+ 09F3 55 PUSH BP ; Preserve Registers\r
+ 09F4 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 09F6 C4 7E 08 LES DI, [BP].SDF_Font ; Get Far Ptr to Font\r
+ \r
+ 09F9 BE 0022 R MOV SI, o CHARSET_LOW ; Assume Lower 128 chars\r
+ 09FC F7 46 06 0001 TEST [BP].SDF_Which, 1 ; Font #1 selected?\r
+ 0A01 74 03 JZ @SDF_Set_Font ; If not, skip ahead\r
+ \r
+ 0A03 BE 0026 R MOV SI, o CHARSET_HI ; Ah, really it's 128-255\r
+ \r
+ 0A06 @SDF_Set_Font:\r
+ 0A06 89 3C MOV [SI], DI ; Set Font Pointer Offset\r
+ 0A08 8C 44 02 MOV [SI+2], ES ; Set Font Pointer Segment\r
+ \r
+ 0A0B 5D POP BP ; Restore Registers\r
+ 0A0C CA 0006 RET 6 ; We are Done.. Outa here\r
+ \r
+ 0A0F SET_DISPLAY_FONT ENDP\r
+ \r
+ \r
+ ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+ \r
+ ;======================================================\r
+ ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+ ;======================================================\r
+ ;\r
+ ; Draws a variable sized Graphics Bitmap such as a\r
+ ; picture or an Icon on the current Display Page in\r
+ ; Mode X. The Bitmap is stored in a linear byte array\r
+ ; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 12 - 1\r
+\r
+\r
+ ; This is the same linear manner as mode 13h graphics.\r
+ ;\r
+ ; ENTRY: Image = Far Pointer to Bitmap Data\r
+ ; Xpos = X position to Place Upper Left pixel at\r
+ ; Ypos = Y position to Place Upper Left pixel at\r
+ ; Width = Width of the Bitmap in Pixels\r
+ ; Height = Height of the Bitmap in Pixels\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0022 DB_STACK STRUC\r
+ 0000 0000 DB_LineO DW ? ; Offset to Next Line\r
+ 0002 0000 DB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
+ 0004 0000 DB_Start DW ? ; Addr of Upper Left Pixel\r
+ 0006 0000 DB_PixSkew DW ? ; # of bytes to Adjust EOL\r
+ 0008 0000 DB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
+ 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0012 00000000 DD ? ; Caller\r
+ 0016 0000 DB_Height DW ? ; Height of Bitmap in Pixels\r
+ 0018 0000 DB_Width DW ? ; Width of Bitmap in Pixels\r
+ 001A 0000 DB_Ypos DW ? ; Y position to Draw Bitmap at\r
+ 001C 0000 DB_Xpos DW ? ; X position to Draw Bitmap at\r
+ 001E 00000000 DB_Image DD ? ; Far Pointer to Graphics Bitmap\r
+ DB_STACK ENDS\r
+ \r
+ PUBLIC DRAW_BITMAP\r
+ \r
+ 0A0F DRAW_BITMAP PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0A0F 55 1 PUSH BP ; Save R1\r
+ 0A10 1E 2 PUSH DS ; Save R1\r
+ 0A11 56 3 PUSH SI ; Save R1\r
+ 0A12 57 4 PUSH DI ; Save R1\r
+ 0A13 83 EC 0A SUB SP, 10 ; Allocate workspace\r
+ 0A16 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 0A18 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ 0A1C FC CLD ; Direction Flag = Forward\r
+ \r
+ 0A1D 8B 46 1A MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos\r
+ 0A20 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
+ \r
+ 0A24 8B 5E 1C MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos\r
+ 0A27 8A CB MOV CL, BL ; Save Plane # in CL\r
+ 0A29 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line\r
+ \r
+ 0A2C 03 F8 ADD DI, AX ; ES:DI -> Start of Line\r
+ 0A2E 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel\r
+ 0A30 89 7E 04 MOV [BP].DB_Start, DI ; Save Starting Addr\r
+ \r
+ ; Compute line to line offset\r
+ \r
+ 0A33 8B 5E 18 MOV BX, [BP].DB_Width ; Get Width of Image\r
+ 0A36 8B D3 MOV DX, BX ; Save Copy in DX\r
+ 0A38 C1 EB 02 SHR BX, 2 ; /4 = width in bands\r
+ 0A3B A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width\r
+ 0A3E 2B C3 SUB AX, BX ; - (Bitmap Width/4)\r
+ \r
+ 0A40 89 46 00 MOV [BP].DB_LineO, AX ; Save Line Width offset\r
+ 0A43 89 5E 02 MOV [BP].DB_PixCount, BX ; Minimum # pix to copy\r
+ \r
+ 0A46 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
+ 0A49 89 56 06 MOV [BP].DB_PixSkew, DX ; Also End of Line Skew\r
+ 0A4C 89 56 08 MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count\r
+ \r
+ 0A4F 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane #\r
+ 0A52 B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ 0A55 D2 E4 SHL AH, CL ; Select correct Plane\r
+ OUT_16 SC_Index, AX ; Select Plane...\r
+ 0A57 BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 0A5A EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ 0A5B 8A FC MOV BH, AH ; BH = Saved Plane Mask\r
+ 0A5D B3 04 MOV BL, 4 ; BL = Planes to Copy\r
+ \r
+ 0A5F @DB_COPY_PLANE:\r
+ \r
+ 0A5F C5 76 1E LDS SI, [BP].DB_Image ; DS:SI-> Source Image\r
+ 0A62 8B 56 16 MOV DX, [BP].DB_Height ; # of Lines to Copy\r
+ 0A65 8B 7E 04 MOV DI, [BP].DB_Start ; ES:DI-> Dest pos\r
+ \r
+ 0A68 @DB_COPY_LINE:\r
+ 0A68 8B 4E 02 MOV CX, [BP].DB_PixCount ; Min # to copy\r
+ \r
+ 0A6B F6 C1 FC TEST CL, 0FCh ; 16+PixWide?\r
+ 0A6E 74 18 JZ @DB_COPY_REMAINDER ; Nope...\r
+ \r
+ ; Pixel Copy loop has been unrolled to x4\r
+ \r
+ 0A70 @DB_COPY_LOOP:\r
+ 0A70 A4 MOVSB ; Copy Bitmap Pixel\r
+ 0A71 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0A74 A4 MOVSB ; Copy Bitmap Pixel\r
+ 0A75 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0A78 A4 MOVSB ; Copy Bitmap Pixel\r
+ 0A79 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0A7C A4 MOVSB ; Copy Bitmap Pixel\r
+ 0A7D 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ \r
+ 0A80 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4\r
+ 0A83 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left?\r
+ 0A86 75 E8 JNZ @DB_COPY_LOOP ; if so, do another block\r
+ \r
+ 0A88 @DB_COPY_REMAINDER:\r
+ 0A88 E3 07 JCXZ @DB_NEXT_LINE ; Any Pixels left on line\r
+ \r
+ 0A8A @DB_COPY2:\r
+ 0A8A A4 MOVSB ; Copy Bitmap Pixel\r
+ 0A8B 83 C6 03 ADD SI,3 ; Skip to Next Byte in same plane\r
+ LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done\r
+ 0A8E 49 1 DEC CX ; Counter--\r
+ 0A8F 75 F9 1 JNZ @DB_COPY2 ; Jump if not 0\r
+ \r
+ 0A91 @DB_NEXT_LINE:\r
+ \r
+ ; any Partial Pixels? (some planes only)\r
+ \r
+ 0A91 0B 4E 08 OR CX, [BP].DB_SkewFlag ; Get Skew Count\r
+ 0A94 74 03 JZ @DB_NEXT2 ; if no partial pixels\r
+ \r
+ 0A96 A4 MOVSB ; Copy Bitmap Pixel\r
+ 0A97 4F DEC DI ; Back up to align\r
+ 0A98 4E DEC SI ; Back up to align\r
+ \r
+ 0A99 @DB_NEXT2:\r
+ 0A99 03 76 06 ADD SI, [BP].DB_PixSkew ; Adjust Skew\r
+ 0A9C 03 7E 00 ADD DI, [BP].DB_LineO ; Set to Next Display Line\r
+ LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more\r
+ 0A9F 4A 1 DEC DX ; Counter--\r
+ 0AA0 75 C6 1 JNZ @DB_COPY_LINE ; Jump if not 0\r
+ \r
+ ; Copy Next Plane....\r
+ \r
+ 0AA2 FE CB DEC BL ; Planes to Go--\r
+ 0AA4 74 1B JZ @DB_Exit ; Hey! We are done\r
+ \r
+ 0AA6 D0 C7 ROL BH, 1 ; Next Plane in line...\r
+ OUT_8 SC_Data, BH ; Select Plane\r
+ 0AA8 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0AAB 8A C7 1 MOV AL, BH ; then Get Data Value\r
+ 0AAD EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0AAE 3C 12 CMP AL, 12h ; Carry Set if AL=11h\r
+ 0AB0 83 56 04 00 ADC [BP].DB_Start, 0 ; Screen Addr =+Carry\r
+ 0AB4 FF 46 1E INC w [BP].DB_Image ; Start @ Next Byte\r
+ \r
+ 0AB7 83 6E 08 01 SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ 0ABB 83 56 08 00 ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
+ \r
+ 0ABF EB 9E JMP s @DB_COPY_PLANE ; Go Copy the Next Plane\r
+ \r
+ 0AC1 @DB_Exit:\r
+ 0AC1 83 C4 0A ADD SP, 10 ; Deallocate workspace\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0AC4 5F 1 POP DI ; Restore R1\r
+ 0AC5 5E 2 POP SI ; Restore R1\r
+ 0AC6 1F 3 POP DS ; Restore R1\r
+ 0AC7 5D 4 POP BP ; Restore R1\r
+ 0AC8 CA 000C RET 12 ; Exit and Clean up Stack\r
+ \r
+ 0ACB DRAW_BITMAP ENDP\r
+ \r
+ \r
+ ;=======================================================\r
+ ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+ ;=======================================================\r
+ ;\r
+ ; Transparently Draws a variable sized Graphics Bitmap\r
+ ; such as a picture or an Icon on the current Display Page\r
+ ; in Mode X. Pixels with a value of 0 are not drawn,\r
+ ; leaving the previous "background" contents intact.\r
+ ;\r
+ ; The Bitmap format is the same as for the DRAW_BITMAP function.\r
+ ;\r
+ ; ENTRY: Image = Far Pointer to Bitmap Data\r
+ ; Xpos = X position to Place Upper Left pixel at\r
+ ; Ypos = Y position to Place Upper Left pixel at\r
+ ; Width = Width of the Bitmap in Pixels\r
+ ; Height = Height of the Bitmap in Pixels\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0022 TB_STACK STRUC\r
+ 0000 0000 TB_LineO DW ? ; Offset to Next Line\r
+ 0002 0000 TB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
+ 0004 0000 TB_Start DW ? ; Addr of Upper Left Pixel\r
+ 0006 0000 TB_PixSkew DW ? ; # of bytes to Adjust EOL\r
+ 0008 0000 TB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
+ 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0012 00000000 DD ? ; Caller\r
+ 0016 0000 TB_Height DW ? ; Height of Bitmap in Pixels\r
+ 0018 0000 TB_Width DW ? ; Width of Bitmap in Pixels\r
+ 001A 0000 TB_Ypos DW ? ; Y position to Draw Bitmap at\r
+ 001C 0000 TB_Xpos DW ? ; X position to Draw Bitmap at\r
+ 001E 00000000 TB_Image DD ? ; Far Pointer to Graphics Bitmap\r
+ TB_STACK ENDS\r
+ \r
+ PUBLIC TDRAW_BITMAP\r
+ \r
+ 0ACB TDRAW_BITMAP PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0ACB 55 1 PUSH BP ; Save R1\r
+ 0ACC 1E 2 PUSH DS ; Save R1\r
+ 0ACD 56 3 PUSH SI ; Save R1\r
+ 0ACE 57 4 PUSH DI ; Save R1\r
+ 0ACF 83 EC 0A SUB SP, 10 ; Allocate workspace\r
+ 0AD2 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ 0AD4 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
+ 0AD8 FC CLD ; Direction Flag = Forward\r
+ \r
+ 0AD9 8B 46 1A MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos\r
+ 0ADC F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
+ \r
+ 0AE0 8B 5E 1C MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos\r
+ 0AE3 8A CB MOV CL, BL ; Save Plane # in CL\r
+ 0AE5 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line\r
+ \r
+ 0AE8 03 F8 ADD DI, AX ; ES:DI -> Start of Line\r
+ 0AEA 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel\r
+ 0AEC 89 7E 04 MOV [BP].TB_Start, DI ; Save Starting Addr\r
+ \r
+ ; Compute line to line offset\r
+ \r
+ 0AEF 8B 5E 18 MOV BX, [BP].TB_Width ; Get Width of Image\r
+ 0AF2 8B D3 MOV DX, BX ; Save Copy in DX\r
+ 0AF4 C1 EB 02 SHR BX, 2 ; /4 = width in bands\r
+ 0AF7 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width\r
+ 0AFA 2B C3 SUB AX, BX ; - (Bitmap Width/4)\r
+ \r
+ 0AFC 89 46 00 MOV [BP].TB_LineO, AX ; Save Line Width offset\r
+ 0AFF 89 5E 02 MOV [BP].TB_PixCount, BX ; Minimum # pix to copy\r
+ \r
+ 0B02 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
+ 0B05 89 56 06 MOV [BP].TB_PixSkew, DX ; Also End of Line Skew\r
+ 0B08 89 56 08 MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count\r
+ \r
+ 0B0B 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane #\r
+ 0B0E B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ 0B11 D2 E4 SHL AH, CL ; Select correct Plane\r
+ OUT_16 SC_Index, AX ; Select Plane...\r
+ 0B13 BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 0B16 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ 0B17 8A FC MOV BH, AH ; BH = Saved Plane Mask\r
+ 0B19 B3 04 MOV BL, 4 ; BL = Planes to Copy\r
+ \r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 13 - 1\r
+\r
+\r
+ 0B1B @TB_COPY_PLANE:\r
+ \r
+ 0B1B C5 76 1E LDS SI, [BP].TB_Image ; DS:SI-> Source Image\r
+ 0B1E 8B 56 16 MOV DX, [BP].TB_Height ; # of Lines to Copy\r
+ 0B21 8B 7E 04 MOV DI, [BP].TB_Start ; ES:DI-> Dest pos\r
+ \r
+ ; Here AH is set with the value to be considered\r
+ ; "Transparent". It can be changed!\r
+ \r
+ 0B24 B4 00 MOV AH, 0 ; Value to Detect 0\r
+ \r
+ 0B26 @TB_COPY_LINE:\r
+ 0B26 8B 4E 02 MOV CX, [BP].TB_PixCount ; Min # to copy\r
+ \r
+ 0B29 F6 C1 FC TEST CL, 0FCh ; 16+PixWide?\r
+ 0B2C 74 3A JZ @TB_COPY_REMAINDER ; Nope...\r
+ \r
+ ; Pixel Copy loop has been unrolled to x4\r
+ \r
+ 0B2E @TB_COPY_LOOP:\r
+ 0B2E AC LODSB ; Get Pixel Value in AL\r
+ 0B2F 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0B32 38 E0 CMP AL, AH ; It is "Transparent"?\r
+ 0B34 74 03 JE @TB_SKIP_01 ; Skip ahead if so\r
+ 0B36 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+ \r
+ 0B39 @TB_SKIP_01:\r
+ 0B39 AC LODSB ; Get Pixel Value in AL\r
+ 0B3A 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0B3D 38 E0 CMP AL, AH ; It is "Transparent"?\r
+ 0B3F 74 04 JE @TB_SKIP_02 ; Skip ahead if so\r
+ 0B41 26: 88 45 01 MOV ES:[DI+1], AL ; Copy Pixel to VGA screen\r
+ \r
+ 0B45 @TB_SKIP_02:\r
+ 0B45 AC LODSB ; Get Pixel Value in AL\r
+ 0B46 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0B49 38 E0 CMP AL, AH ; It is "Transparent"?\r
+ 0B4B 74 04 JE @TB_SKIP_03 ; Skip ahead if so\r
+ 0B4D 26: 88 45 02 MOV ES:[DI+2], AL ; Copy Pixel to VGA screen\r
+ \r
+ 0B51 @TB_SKIP_03:\r
+ 0B51 AC LODSB ; Get Pixel Value in AL\r
+ 0B52 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0B55 38 E0 CMP AL, AH ; It is "Transparent"?\r
+ 0B57 74 04 JE @TB_SKIP_04 ; Skip ahead if so\r
+ 0B59 26: 88 45 03 MOV ES:[DI+3], AL ; Copy Pixel to VGA screen\r
+ \r
+ 0B5D @TB_SKIP_04:\r
+ 0B5D 83 C7 04 ADD DI, 4 ; Adjust Pixel Write Location\r
+ 0B60 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4\r
+ 0B63 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left?\r
+ 0B66 75 C6 JNZ @TB_COPY_LOOP ; if so, do another block\r
+ \r
+ 0B68 @TB_COPY_REMAINDER:\r
+ 0B68 E3 0F JCXZ @TB_NEXT_LINE ; Any Pixels left on line\r
+ \r
+ 0B6A @TB_COPY2:\r
+ 0B6A AC LODSB ; Get Pixel Value in AL\r
+ 0B6B 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane\r
+ 0B6E 38 E0 CMP AL, AH ; It is "Transparent"?\r
+ 0B70 74 03 JE @TB_SKIP_05 ; Skip ahead if so\r
+ 0B72 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+ \r
+ 0B75 @TB_SKIP_05:\r
+ 0B75 47 INC DI ; Advance Dest Addr\r
+ LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done\r
+ 0B76 49 1 DEC CX ; Counter--\r
+ 0B77 75 F1 1 JNZ @TB_COPY2 ; Jump if not 0\r
+ \r
+ 0B79 @TB_NEXT_LINE:\r
+ \r
+ ; any Partial Pixels? (some planes only)\r
+ \r
+ 0B79 0B 4E 08 OR CX, [BP].TB_SkewFlag ; Get Skew Count\r
+ 0B7C 74 09 JZ @TB_NEXT2 ; if no partial pixels\r
+ \r
+ 0B7E AC LODSB ; Get Pixel Value in AL\r
+ 0B7F 4E DEC SI ; Backup to Align\r
+ 0B80 38 E0 CMP AL, AH ; It is "Transparent"?\r
+ 0B82 74 03 JE @TB_NEXT2 ; Skip ahead if so\r
+ 0B84 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
+ \r
+ 0B87 @TB_NEXT2:\r
+ 0B87 03 76 06 ADD SI, [BP].TB_PixSkew ; Adjust Skew\r
+ 0B8A 03 7E 00 ADD DI, [BP].TB_LineO ; Set to Next Display Line\r
+ LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More\r
+ 0B8D 4A 1 DEC DX ; Counter--\r
+ 0B8E 75 96 1 JNZ @TB_COPY_LINE ; Jump if not 0\r
+ \r
+ ;Copy Next Plane....\r
+ \r
+ 0B90 FE CB DEC BL ; Planes to Go--\r
+ 0B92 74 1C JZ @TB_Exit ; Hey! We are done\r
+ \r
+ 0B94 D0 C7 ROL BH, 1 ; Next Plane in line...\r
+ OUT_8 SC_Data, BH ; Select Plane\r
+ 0B96 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0B99 8A C7 1 MOV AL, BH ; then Get Data Value\r
+ 0B9B EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0B9C 3C 12 CMP AL, 12h ; Carry Set if AL=11h\r
+ 0B9E 83 56 04 00 ADC [BP].TB_Start, 0 ; Screen Addr =+Carry\r
+ 0BA2 FF 46 1E INC w [BP].TB_Image ; Start @ Next Byte\r
+ \r
+ 0BA5 83 6E 08 01 SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ 0BA9 83 56 08 00 ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
+ \r
+ 0BAD E9 FF6B JMP @TB_COPY_PLANE ; Go Copy the next Plane\r
+ \r
+ 0BB0 @TB_Exit:\r
+ 0BB0 83 C4 0A ADD SP, 10 ; Deallocate workspace\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0BB3 5F 1 POP DI ; Restore R1\r
+ 0BB4 5E 2 POP SI ; Restore R1\r
+ 0BB5 1F 3 POP DS ; Restore R1\r
+ 0BB6 5D 4 POP BP ; Restore R1\r
+ 0BB7 CA 000C RET 12 ; Exit and Clean up Stack\r
+ \r
+ 0BBA TDRAW_BITMAP ENDP\r
+ \r
+ \r
+ ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+ \r
+ ;==================================\r
+ ;COPY_PAGE (SourcePage%, DestPage%)\r
+ ;==================================\r
+ ;\r
+ ; Duplicate on display page onto another\r
+ ;\r
+ ; ENTRY: SourcePage = Display Page # to Duplicate\r
+ ; DestPage = Display Page # to hold copy\r
+ ;\r
+ ; EXIT: No meaningful values returned\r
+ ;\r
+ \r
+ 0010 CP_STACK STRUC\r
+ 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 0008 00000000 DD ? ; Caller\r
+ 000C 0000 CP_DestP DW ? ; Page to hold copied image\r
+ 000E 0000 CP_SourceP DW ? ; Page to Make copy from\r
+ CP_STACK ENDS\r
+ \r
+ PUBLIC COPY_PAGE\r
+ \r
+ 0BBA COPY_PAGE PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0BBA 55 1 PUSH BP ; Save R1\r
+ 0BBB 1E 2 PUSH DS ; Save R1\r
+ 0BBC 56 3 PUSH SI ; Save R1\r
+ 0BBD 57 4 PUSH DI ; Save R1\r
+ 0BBE 8B EC MOV BP, SP ; Set up Stack Frame\r
+ 0BC0 FC CLD ; Block Xfer Forwards\r
+ \r
+ ; Make sure Page #'s are valid\r
+ \r
+ 0BC1 8B 46 0E MOV AX, [BP].CP_SourceP ; Get Source Page #\r
+ 0BC4 3B 06 0004 R CMP AX, LAST_PAGE ; is it > Max Page #?\r
+ 0BC8 73 3D JAE @CP_Exit ; if so, abort\r
+ \r
+ 0BCA 8B 5E 0C MOV BX, [BP].CP_DestP ; Get Destination Page #\r
+ 0BCD 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #?\r
+ 0BD1 73 34 JAE @CP_Exit ; if so, abort\r
+ \r
+ 0BD3 3B C3 CMP AX, BX ; Pages #'s the same?\r
+ 0BD5 74 30 JE @CP_Exit ; if so, abort\r
+ \r
+ ; Setup DS:SI and ES:DI to Video Pages\r
+ \r
+ 0BD7 D1 E3 SHL BX, 1 ; Scale index to Word\r
+ 0BD9 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page\r
+ \r
+ 0BDD 8B D8 MOV BX, AX ; Index to Source page\r
+ 0BDF D1 E3 SHL BX, 1 ; Scale index to Word\r
+ 0BE1 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; Offset to Source Page\r
+ \r
+ 0BE5 8B 0E 000E R MOV CX, PAGE_SIZE ; Get size of Page\r
+ 0BE9 A1 0016 R MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
+ 0BEC 8E C0 MOV ES, AX ; ES:DI -> Dest Page\r
+ 0BEE 8E D8 MOV DS, AX ; DS:SI -> Source Page\r
+ \r
+ ; Setup VGA registers for Mem to Mem copy\r
+ \r
+ OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
+ 0BF0 BA 03CE 1 MOV DX, GC_Index ; then Select Register\r
+ 0BF3 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value\r
+ 0BF6 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes\r
+ 0BF7 BA 03C4 1 MOV DX, SC_Index ; then Select Register\r
+ 0BFA B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value\r
+ 0BFD EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
+ ; Screw with the latches which are 8 bits x 4\r
+ \r
+ 0BFE F3/ A4 REP MOVSB ; Copy entire Page!\r
+ \r
+ ; Reset VGA for normal memory access\r
+ \r
+ OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off\r
+ 0C00 BA 03CE 1 MOV DX, GC_Index ; then Select Register\r
+ 0C03 B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value\r
+ 0C06 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ 0C07 @CP_Exit:\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0C07 5F 1 POP DI ; Restore R1\r
+ 0C08 5E 2 POP SI ; Restore R1\r
+ 0C09 1F 3 POP DS ; Restore R1\r
+ 0C0A 5D 4 POP BP ; Restore R1\r
+ 0C0B CA 0004 RET 4 ; Exit and Clean up Stack\r
+ \r
+ 0C0E COPY_PAGE ENDP\r
+ \r
+ \r
+ ;==========================================================================\r
+ ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
+ ;==========================================================================\r
+ ;\r
+ ; Copies a Bitmap Image from one Display Page to Another\r
+ ; This Routine is Limited to copying Images with the same\r
+ ; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
+ ; Copying an Image to the Same Page is supported, but results\r
+ ; may be defined when the when the rectangular areas\r
+ ; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
+ ; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
+ ; No Paramter checking to done to insure that\r
+ ; X2 >= X1 and Y2 >= Y1. Be Careful...\r
+ ;\r
+ ; ENTRY: SourcePage = Display Page # with Source Image\r
+ ; X1 = Upper Left Xpos of Source Image\r
+ ; Y1 = Upper Left Ypos of Source Image\r
+ ; X2 = Lower Right Xpos of Source Image\r
+ ; Y2 = Lower Right Ypos of Source Image\r
+ ; DestPage = Display Page # to copy Image to\r
+ ; DestX1 = Xpos to Copy UL Corner of Image to\r
+ ; DestY1 = Ypos to Copy UL Corner of Image to\r
+ ;\r
+ ; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
+ ;\r
+ \r
+ 0020 CB_STACK STRUC\r
+ 0000 0000 CB_Height DW ? ; Height of Image in Lines\r
+ 0002 0000 CB_Width DW ? ; Width of Image in "bands"\r
+ 0004 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP\r
+ 0000\r
+ 000C 00000000 DD ? ; Caller\r
+ 0010 0000 CB_DestY1 DW ? ; Destination Ypos\r
+ 0012 0000 CB_DestX1 DW ? ; Destination Xpos\r
+ 0014 0000 CB_DestP DW ? ; Page to Copy Bitmap To\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 14 - 1\r
+\r
+\r
+ 0016 0000 CB_Y2 DW ? ; LR Ypos of Image\r
+ 0018 0000 CB_X2 DW ? ; LR Xpos of Image\r
+ 001A 0000 CB_Y1 DW ? ; UL Ypos of Image\r
+ 001C 0000 CB_X1 DW ? ; UL Xpos of Image\r
+ 001E 0000 CB_SourceP DW ? ; Page containing Source Bitmap\r
+ CB_STACK ENDS\r
+ \r
+ PUBLIC COPY_BITMAP\r
+ \r
+ 0C0E COPY_BITMAP PROC FAR\r
+ \r
+ PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
+ 0C0E 55 1 PUSH BP ; Save R1\r
+ 0C0F 1E 2 PUSH DS ; Save R1\r
+ 0C10 56 3 PUSH SI ; Save R1\r
+ 0C11 57 4 PUSH DI ; Save R1\r
+ 0C12 83 EC 04 SUB SP, 4 ; Allocate WorkSpace on Stack\r
+ 0C15 8B EC MOV BP, SP ; Set up Stack Frame\r
+ \r
+ ; Prep Registers (and keep jumps short!)\r
+ \r
+ 0C17 8E 06 0016 R MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
+ 0C1B FC CLD ; Block Xfer Forwards\r
+ \r
+ ; Make sure Parameters are valid\r
+ \r
+ 0C1C 8B 5E 1E MOV BX, [BP].CB_SourceP ; Get Source Page #\r
+ 0C1F 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #?\r
+ 0C23 73 7D JAE @CB_Abort ; if so, abort\r
+ \r
+ 0C25 8B 4E 14 MOV CX, [BP].CB_DestP ; Get Destination Page #\r
+ 0C28 3B 0E 0004 R CMP CX, LAST_PAGE ; is it > Max Page #?\r
+ 0C2C 73 74 JAE @CB_Abort ; if so, abort\r
+ \r
+ 0C2E 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1\r
+ 0C31 33 46 12 XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1\r
+ 0C34 83 E0 03 AND AX, PLANE_BITS ; Check Plane Bits\r
+ 0C37 75 69 JNZ @CB_Abort ; They should cancel out\r
+ \r
+ ; Setup for Copy processing\r
+ \r
+ OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
+ 0C39 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register\r
+ 0C3C B0 02 1 MOV AL, MAP_MASK ; then Get Data Value\r
+ 0C3E EE 1 OUT DX, AL ; Set I/O Register\r
+ OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
+ 0C3F BA 03CE 1 MOV DX, GC_Index ; then Select Register\r
+ 0C42 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value\r
+ 0C45 EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ ; Compute Info About Images, Setup ES:SI & ES:DI\r
+ \r
+ 0C46 8B 46 16 MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines\r
+ 0C49 2B 46 1A SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1\r
+ 0C4C 40 INC AX ; (add 1 since were not 0 based)\r
+ 0C4D 89 46 00 MOV [BP].CB_Height, AX ; Save on Stack for later use\r
+ \r
+ 0C50 8B 46 18 MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels\r
+ 0C53 8B 56 1C MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1\r
+ 0C56 C1 E8 02 SHR AX, 2 ; Get X2 Band (X2 / 4)\r
+ 0C59 C1 EA 02 SHR DX, 2 ; Get X1 Band (X1 / 4)\r
+ 0C5C 2B C2 SUB AX, DX ; AX = # of Bands - 1\r
+ 0C5E 40 INC AX ; AX = # of Bands\r
+ 0C5F 89 46 02 MOV [BP].CB_Width, AX ; Save on Stack for later use\r
+ \r
+ 0C62 D1 E3 SHL BX, 1 ; Scale Source Page to Word\r
+ 0C64 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page\r
+ 0C68 8B 46 1A MOV AX, [BP].CB_Y1 ; Get Source Y1 Line\r
+ 0C6B F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
+ 0C6F 03 F0 ADD SI, AX ; SI = Offset to Line Y1\r
+ 0C71 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1\r
+ 0C74 C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset\r
+ 0C77 03 F0 ADD SI, AX ; SI = Byte Offset to (X1,Y1)\r
+ \r
+ 0C79 8B D9 MOV BX, CX ; Dest Page Index to BX\r
+ 0C7B D1 E3 SHL BX, 1 ; Scale Source Page to Word\r
+ 0C7D 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page\r
+ 0C81 8B 46 10 MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line\r
+ 0C84 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
+ 0C88 03 F8 ADD DI, AX ; DI = Offset to Line Y1\r
+ 0C8A 8B 46 12 MOV AX, [BP].CB_DestX1 ; Get Dest X1\r
+ 0C8D C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset\r
+ 0C90 03 F8 ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1)\r
+ \r
+ 0C92 8B 4E 02 MOV CX, [BP].CB_Width ; CX = Width of Image (Bands)\r
+ 0C95 49 DEC CX ; CX = 1?\r
+ 0C96 74 0F JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band\r
+ \r
+ 0C98 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Source X1\r
+ 0C9B 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?)\r
+ 0C9E 74 70 JZ @CB_Check_Right ; if so, check right alignment\r
+ 0CA0 75 41 JNZ @CB_Left_Band ; not aligned? well..\r
+ \r
+ 0CA2 @CB_Abort:\r
+ CLR AX ; Return False (Failure)\r
+ 0CA2 33 C0 1 XOR AX, AX ; Set Register = 0\r
+ 0CA4 E9 00D7 JMP @CB_Exit ; and Finish Up\r
+ \r
+ ; Copy when Left & Right Clip Masks overlap...\r
+ \r
+ 0CA7 @CB_Only_One_Band:\r
+ 0CA7 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Left Clip Mask\r
+ 0CAA 83 E3 03 AND BX, PLANE_BITS ; Mask out Row #\r
+ 0CAD 2E: 8A 87 0000 R MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask\r
+ 0CB2 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Right Clip Mask\r
+ 0CB5 83 E3 03 AND BX, PLANE_BITS ; Mask out Row #\r
+ 0CB8 2E: 22 87 0004 R AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
+ \r
+ OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
+ 0CBD BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0CC0 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0CC1 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ 0CC4 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ CLR BX ; BX = Offset into Image\r
+ 0CC8 33 DB 1 XOR BX, BX ; Set Register = 0\r
+ \r
+ 0CCA @CB_One_Loop:\r
+ 0CCA 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches\r
+ 0CCD 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches\r
+ 0CD0 03 DA ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_One_Done ; Exit Loop if Finished\r
+ 0CD2 49 1 DEC CX ; Counter--\r
+ 0CD3 74 0B 1 JZ @CB_One_Done ; Jump if 0\r
+ \r
+ 0CD5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches\r
+ 0CD8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches\r
+ 0CDB 03 DA ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_One_Loop ; Loop until Finished\r
+ 0CDD 49 1 DEC CX ; Counter--\r
+ 0CDE 75 EA 1 JNZ @CB_One_Loop ; Jump if not 0\r
+ \r
+ 0CE0 @CB_One_Done:\r
+ 0CE0 E9 0094 JMP @CB_Finish ; Outa Here!\r
+ \r
+ ; Copy Left Edge of Bitmap\r
+ \r
+ 0CE3 @CB_Left_Band:\r
+ \r
+ OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
+ 0CE3 BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0CE6 2E: 8A 87 0000 R 1 MOV AL, Left_Clip_Mask[BX] ; then Get Data Value\r
+ 0CEB EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0CEC 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ 0CEF 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ CLR BX ; BX = Offset into Image\r
+ 0CF3 33 DB 1 XOR BX, BX ; Set Register = 0\r
+ \r
+ 0CF5 @CB_Left_Loop:\r
+ 0CF5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches\r
+ 0CF8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches\r
+ 0CFB 03 DA ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished\r
+ 0CFD 49 1 DEC CX ; Counter--\r
+ 0CFE 74 0B 1 JZ @CB_Left_Done ; Jump if 0\r
+ \r
+ 0D00 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches\r
+ 0D03 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches\r
+ 0D06 03 DA ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_Left_Loop ; Loop until Finished\r
+ 0D08 49 1 DEC CX ; Counter--\r
+ 0D09 75 EA 1 JNZ @CB_Left_Loop ; Jump if not 0\r
+ \r
+ 0D0B @CB_Left_Done:\r
+ 0D0B 47 INC DI ; Move Dest Over 1 band\r
+ 0D0C 46 INC SI ; Move Source Over 1 band\r
+ 0D0D FF 4E 02 DEC [BP].CB_Width ; Band Width--\r
+ \r
+ ; Determine if Right Edge of Bitmap needs special copy\r
+ \r
+ 0D10 @CB_Check_Right:\r
+ 0D10 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Source X2\r
+ 0D13 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?)\r
+ 0D16 80 FB 03 CMP BL, 03h ; Plane = 3?\r
+ 0D19 74 2C JE @CB_Copy_Middle ; Copy the Middle then!\r
+ \r
+ ; Copy Right Edge of Bitmap\r
+ \r
+ 0D1B @CB_Right_Band:\r
+ \r
+ OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask\r
+ 0D1B BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0D1E 2E: 8A 87 0004 R 1 MOV AL, Right_Clip_Mask[BX] ; then Get Data Value\r
+ 0D23 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0D24 FF 4E 02 DEC [BP].CB_Width ; Band Width--\r
+ 0D27 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
+ 0D2A 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
+ 0D2E 8B 5E 02 MOV BX, [BP].CB_Width ; BX = Offset to Right Edge\r
+ \r
+ 0D31 @CB_Right_Loop:\r
+ 0D31 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches\r
+ 0D34 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches\r
+ 0D37 03 DA ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished\r
+ 0D39 49 1 DEC CX ; Counter--\r
+ 0D3A 74 0B 1 JZ @CB_Right_Done ; Jump if 0\r
+ \r
+ 0D3C 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches\r
+ 0D3F 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches\r
+ 0D42 03 DA ADD BX, DX ; Advance Offset to Next Line\r
+ LOOPx CX, @CB_Right_Loop ; Loop until Finished\r
+ 0D44 49 1 DEC CX ; Counter--\r
+ 0D45 75 EA 1 JNZ @CB_Right_Loop ; Jump if not 0\r
+ \r
+ 0D47 @CB_Right_Done:\r
+ \r
+ ; Copy the Main Block of the Bitmap\r
+ \r
+ 0D47 @CB_Copy_Middle:\r
+ \r
+ 0D47 8B 4E 02 MOV CX, [BP].CB_Width ; Get Width Remaining\r
+ 0D4A E3 2B JCXZ @CB_Finish ; Exit if Done\r
+ \r
+ OUT_8 SC_Data, ALL_PLANES ; Copy all Planes\r
+ 0D4C BA 03C5 1 MOV DX, SC_Data ; then Select Register\r
+ 0D4F B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value\r
+ 0D51 EE 1 OUT DX, AL ; Set I/O Register\r
+ \r
+ 0D52 8B 16 0000 R MOV DX, SCREEN_WIDTH ; Get Width of Screen minus\r
+ 0D56 2B D1 SUB DX, CX ; Image width (for Adjustment)\r
+ 0D58 8B 46 00 MOV AX, [BP].CB_Height ; AX = # of Lines to Copy\r
+ 0D5B 8B D9 MOV BX, CX ; BX = Quick REP reload count\r
+ 0D5D 8C C1 MOV CX, ES ; Move VGA Segment\r
+ 0D5F 8E D9 MOV DS, CX ; Into DS\r
+ \r
+ ; Actual Copy Loop. REP MOVSB does the work\r
+ \r
+ 0D61 @CB_Middle_Copy:\r
+ 0D61 8B CB MOV CX, BX ; Recharge Rep Count\r
+ 0D63 F3/ A4 REP MOVSB ; Move Bands\r
+ LOOPjz AX, @CB_Finish ; Exit Loop if Finished\r
+ 0D65 48 1 DEC AX ; Counter--\r
+ 0D66 74 0F 1 JZ @CB_Finish ; Jump if 0\r
+ \r
+ 0D68 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line\r
+ 0D6A 03 FA ADD DI, DX ; Adjust ES:DI to Next Line\r
+ \r
+ 0D6C 8B CB MOV CX, BX ; Recharge Rep Count\r
+ 0D6E F3/ A4 REP MOVSB ; Move Bands\r
+ \r
+ 0D70 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line\r
+ 0D72 03 FA ADD DI, DX ; Adjust ES:DI to Next Line\r
+ LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done\r
+ 0D74 48 1 DEC AX ; Counter--\r
+ 0D75 75 EA 1 JNZ @CB_Middle_Copy ; Jump if not 0\r
+ \r
+ 0D77 @CB_Finish:\r
+ OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on\r
+ 0D77 BA 03CE 1 MOV DX, GC_Index ; then Select Register\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Page 15 - 1\r
+\r
+\r
+ 0D7A B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value\r
+ 0D7D EF 1 OUT DX, AX ; Set I/O Register(s)\r
+ \r
+ 0D7E @CB_Exit:\r
+ 0D7E 83 C4 04 ADD SP, 04 ; Deallocate stack workspace\r
+ POPx DI, SI, DS, BP ; Restore Saved Registers\r
+ 0D81 5F 1 POP DI ; Restore R1\r
+ 0D82 5E 2 POP SI ; Restore R1\r
+ 0D83 1F 3 POP DS ; Restore R1\r
+ 0D84 5D 4 POP BP ; Restore R1\r
+ 0D85 CA 0010 RET 16 ; Exit and Clean up Stack\r
+ \r
+ 0D88 COPY_BITMAP ENDP\r
+ \r
+ END ; End of Code Segment\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Symbols 16 - 1\r
+\r
+\r
+\r
+\r
+Macros:\r
+\r
+ N a m e Type\r
+\r
+CLR . . . . . . . . . . . . . . Proc\r
+LOOPjz . . . . . . . . . . . . . Proc\r
+LOOPx . . . . . . . . . . . . . Proc\r
+OUT_16 . . . . . . . . . . . . . Proc\r
+OUT_8 . . . . . . . . . . . . . Proc\r
+POPx . . . . . . . . . . . . . . Proc\r
+PUSHx . . . . . . . . . . . . . Proc\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Symbols 17 - 1\r
+\r
+\r
+\r
+\r
+Structures and Unions:\r
+\r
+ N a m e Size\r
+ Offset Type\r
+\r
+CB_STACK . . . . . . . . . . . . 0020\r
+ CB_Height . . . . . . . . . . 0000 Word\r
+ CB_Width . . . . . . . . . . . 0002 Word\r
+ CB_DestY1 . . . . . . . . . . 0010 Word\r
+ CB_DestX1 . . . . . . . . . . 0012 Word\r
+ CB_DestP . . . . . . . . . . . 0014 Word\r
+ CB_Y2 . . . . . . . . . . . . 0016 Word\r
+ CB_X2 . . . . . . . . . . . . 0018 Word\r
+ CB_Y1 . . . . . . . . . . . . 001A Word\r
+ CB_X1 . . . . . . . . . . . . 001C Word\r
+ CB_SourceP . . . . . . . . . . 001E Word\r
+CP_STACK . . . . . . . . . . . . 0010\r
+ CP_DestP . . . . . . . . . . . 000C Word\r
+ CP_SourceP . . . . . . . . . . 000E Word\r
+CVS_STACK . . . . . . . . . . . 000A\r
+ CVS_COLOR . . . . . . . . . . 0008 Byte\r
+DB_STACK . . . . . . . . . . . . 0022\r
+ DB_LineO . . . . . . . . . . . 0000 Word\r
+ DB_PixCount . . . . . . . . . 0002 Word\r
+ DB_Start . . . . . . . . . . . 0004 Word\r
+ DB_PixSkew . . . . . . . . . . 0006 Word\r
+ DB_SkewFlag . . . . . . . . . 0008 Word\r
+ DB_Height . . . . . . . . . . 0016 Word\r
+ DB_Width . . . . . . . . . . . 0018 Word\r
+ DB_Ypos . . . . . . . . . . . 001A Word\r
+ DB_Xpos . . . . . . . . . . . 001C Word\r
+ DB_Image . . . . . . . . . . . 001E DWord\r
+DL_STACK . . . . . . . . . . . . 0014\r
+ DL_ColorF . . . . . . . . . . 000A Byte\r
+ DL_Ypos2 . . . . . . . . . . . 000C Word\r
+ DL_Xpos2 . . . . . . . . . . . 000E Word\r
+ DL_Ypos1 . . . . . . . . . . . 0010 Word\r
+ DL_Xpos1 . . . . . . . . . . . 0012 Word\r
+FB_STACK . . . . . . . . . . . . 0016\r
+ FB_Color . . . . . . . . . . . 000C Byte\r
+ FB_Ypos2 . . . . . . . . . . . 000E Word\r
+ FB_Xpos2 . . . . . . . . . . . 0010 Word\r
+ FB_Ypos1 . . . . . . . . . . . 0012 Word\r
+ FB_Xpos1 . . . . . . . . . . . 0014 Word\r
+GDR_STACK . . . . . . . . . . . 000E\r
+ GDR_Blue . . . . . . . . . . . 0006 Word\r
+ GDR_Green . . . . . . . . . . 0008 Word\r
+ GDR_Red . . . . . . . . . . . 000A Word\r
+ GDR_Register . . . . . . . . . 000C Byte\r
+GPC_STACK . . . . . . . . . . . 001E\r
+ GPC_Width . . . . . . . . . . 0000 Word\r
+ GPC_Lines . . . . . . . . . . 0002 Byte\r
+ GPC_T_SETS . . . . . . . . . . 0004 Word\r
+ GPC_T_SETO . . . . . . . . . . 0006 Word\r
+ GPC_ColorB . . . . . . . . . . 0014 Byte\r
+ GPC_ColorF . . . . . . . . . . 0016 Byte\r
+ GPC_Ypos . . . . . . . . . . . 0018 Word\r
+ GPC_Xpos . . . . . . . . . . . 001A Word\r
+ GPC_Char . . . . . . . . . . . 001C Byte\r
+LDR_STACK . . . . . . . . . . . 0014\r
+ LDR_Sync . . . . . . . . . . . 000A Word\r
+ LDR_EndReg . . . . . . . . . . 000C Byte\r
+ LDR_StartReg . . . . . . . . . 000E Byte\r
+ LDR_PalData . . . . . . . . . 0010 DWord\r
+Mode_Data_Table . . . . . . . . 000C\r
+ M_MiscR . . . . . . . . . . . 0000 Byte\r
+ M_Pages . . . . . . . . . . . 0001 Byte\r
+ M_XSize . . . . . . . . . . . 0002 Word\r
+ M_YSize . . . . . . . . . . . 0004 Word\r
+ M_XMax . . . . . . . . . . . . 0006 Word\r
+ M_YMax . . . . . . . . . . . . 0008 Word\r
+ M_CRTC . . . . . . . . . . . . 000A Word\r
+PS_STACK . . . . . . . . . . . . 001A\r
+ PS_ColorB . . . . . . . . . . 000C Word\r
+ PS_ColorF . . . . . . . . . . 000E Word\r
+ PS_Ypos . . . . . . . . . . . 0010 Word\r
+ PS_Xpos . . . . . . . . . . . 0012 Word\r
+ PS_Len . . . . . . . . . . . . 0014 Word\r
+ PS_Text . . . . . . . . . . . 0016 Word\r
+RDR_STACK . . . . . . . . . . . 0012\r
+ RDR_EndReg . . . . . . . . . . 000A Byte\r
+ RDR_StartReg . . . . . . . . . 000C Byte\r
+ RDR_PalData . . . . . . . . . 000E DWord\r
+RP_STACK . . . . . . . . . . . . 000C\r
+ RP_Ypos . . . . . . . . . . . 0008 Word\r
+ RP_Xpos . . . . . . . . . . . 000A Word\r
+SAP_STACK . . . . . . . . . . . 0008\r
+ SAP_Page . . . . . . . . . . . 0006 Word\r
+SDF_STACK . . . . . . . . . . . 000C\r
+ SDF_Which . . . . . . . . . . 0006 Word\r
+ SDF_Font . . . . . . . . . . . 0008 DWord\r
+SDP_STACK . . . . . . . . . . . 0008\r
+ SDP_Page . . . . . . . . . . . 0006 Word\r
+SDR_STACK . . . . . . . . . . . 000E\r
+ SDR_Blue . . . . . . . . . . . 0006 Byte\r
+ SDR_Green . . . . . . . . . . 0008 Byte\r
+ SDR_Red . . . . . . . . . . . 000A Byte\r
+ SDR_Register . . . . . . . . . 000C Byte\r
+SM_STACK . . . . . . . . . . . . 000A\r
+ SM_Mode . . . . . . . . . . . 0008 Word\r
+SP_STACK . . . . . . . . . . . . 000E\r
+ SETP_Color . . . . . . . . . . 0008 Byte\r
+ SETP_Ypos . . . . . . . . . . 000A Word\r
+ SETP_Xpos . . . . . . . . . . 000C Word\r
+SVM_STACK . . . . . . . . . . . 0016\r
+ SVM_Table . . . . . . . . . . 0000 Word\r
+ SVM_Pages . . . . . . . . . . 000E Word\r
+ SVM_Ysize . . . . . . . . . . 0010 Word\r
+ SVM_Xsize . . . . . . . . . . 0012 Word\r
+ SVM_Mode . . . . . . . . . . . 0014 Word\r
+SW_STACK . . . . . . . . . . . . 000C\r
+ SW_Ypos . . . . . . . . . . . 0006 Word\r
+ SW_Xpos . . . . . . . . . . . 0008 Word\r
+ SW_Page . . . . . . . . . . . 000A Word\r
+TB_STACK . . . . . . . . . . . . 0022\r
+ TB_LineO . . . . . . . . . . . 0000 Word\r
+ TB_PixCount . . . . . . . . . 0002 Word\r
+ TB_Start . . . . . . . . . . . 0004 Word\r
+ TB_PixSkew . . . . . . . . . . 0006 Word\r
+ TB_SkewFlag . . . . . . . . . 0008 Word\r
+ TB_Height . . . . . . . . . . 0016 Word\r
+ TB_Width . . . . . . . . . . . 0018 Word\r
+ TB_Ypos . . . . . . . . . . . 001A Word\r
+ TB_Xpos . . . . . . . . . . . 001C Word\r
+ TB_Image . . . . . . . . . . . 001E DWord\r
+TGP_STACK . . . . . . . . . . . 001C\r
+ TGP_Width . . . . . . . . . . 0000 Word\r
+ TGP_Lines . . . . . . . . . . 0002 Byte\r
+ TGP_T_SETS . . . . . . . . . . 0004 Word\r
+ TGP_T_SETO . . . . . . . . . . 0006 Word\r
+ TGP_ColorF . . . . . . . . . . 0014 Byte\r
+ TGP_Ypos . . . . . . . . . . . 0016 Word\r
+ TGP_Xpos . . . . . . . . . . . 0018 Word\r
+ TGP_Char . . . . . . . . . . . 001A Byte\r
+TPS_STACK . . . . . . . . . . . 0018\r
+ TPS_ColorF . . . . . . . . . . 000C Word\r
+ TPS_Ypos . . . . . . . . . . . 000E Word\r
+ TPS_Xpos . . . . . . . . . . . 0010 Word\r
+ TPS_Len . . . . . . . . . . . 0012 Word\r
+ TPS_Text . . . . . . . . . . . 0014 Word\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Symbols 18 - 1\r
+\r
+\r
+\r
+\r
+Segments and Groups:\r
+\r
+ N a m e Size Length Align Combine Class\r
+\r
+DGROUP . . . . . . . . . . . . . GROUP\r
+_DATA . . . . . . . . . . . . . 16 Bit 0000 Word Public 'DATA' \r
+_BSS . . . . . . . . . . . . . . 16 Bit 002A Word Public 'BSS' \r
+MODEX_TEXT . . . . . . . . . . . 16 Bit 0D88 Word Public 'CODE' \r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Symbols 19 - 1\r
+\r
+\r
+\r
+\r
+Procedures, parameters and locals:\r
+\r
+ N a m e Type Value Attr\r
+\r
+CLEAR_VGA_SCREEN . . . . . . . . P Far 0280 MODEX_TEXT Length= 0022 Public\r
+COPY_BITMAP . . . . . . . . . . P Far 0C0E MODEX_TEXT Length= 017E Public\r
+COPY_PAGE . . . . . . . . . . . P Far 0BBA MODEX_TEXT Length= 0054 Public\r
+DRAW_BITMAP . . . . . . . . . . P Far 0A0F MODEX_TEXT Length= 00BC Public\r
+DRAW_LINE . . . . . . . . . . . P Far 040B MODEX_TEXT Length= 02A7 Public\r
+FILL_BLOCK . . . . . . . . . . . P Far 0300 MODEX_TEXT Length= 010B Public\r
+GET_ACTIVE_PAGE . . . . . . . . P Far 06E5 MODEX_TEXT Length= 0004 Public\r
+GET_DAC_REGISTER . . . . . . . . P Far 0641 MODEX_TEXT Length= 0025 Public\r
+GET_DISPLAY_PAGE . . . . . . . . P Far 0724 MODEX_TEXT Length= 0004 Public\r
+GET_X_OFFSET . . . . . . . . . . P Far 078D MODEX_TEXT Length= 0004 Public\r
+GET_Y_OFFSET . . . . . . . . . . P Far 0791 MODEX_TEXT Length= 0004 Public\r
+GPRINTC . . . . . . . . . . . . P Far 07A3 MODEX_TEXT Length= 00FE Public\r
+LOAD_DAC_REGISTERS . . . . . . . P Far 0666 MODEX_TEXT Length= 0037 Public\r
+PRINT_STR . . . . . . . . . . . P Far 0975 MODEX_TEXT Length= 0041 Public\r
+READ_DAC_REGISTERS . . . . . . . P Far 069D MODEX_TEXT Length= 002B Public\r
+READ_POINT . . . . . . . . . . . P Far 02D2 MODEX_TEXT Length= 002E Public\r
+SET_ACTIVE_PAGE . . . . . . . . P Far 06C8 MODEX_TEXT Length= 001D Public\r
+SET_DAC_REGISTER . . . . . . . . P Far 0624 MODEX_TEXT Length= 001D Public\r
+SET_DISPLAY_FONT . . . . . . . . P Far 09F3 MODEX_TEXT Length= 001C Public\r
+SET_DISPLAY_PAGE . . . . . . . . P Far 06E9 MODEX_TEXT Length= 003B Public\r
+SET_MODEX . . . . . . . . . . . P Far 0251 MODEX_TEXT Length= 002F Public\r
+SET_POINT . . . . . . . . . . . P Far 02A2 MODEX_TEXT Length= 0030 Public\r
+SET_VGA_MODEX . . . . . . . . . P Far 0104 MODEX_TEXT Length= 014D Public\r
+SET_WINDOW . . . . . . . . . . . P Far 0728 MODEX_TEXT Length= 0065 Public\r
+SYNC_DISPLAY . . . . . . . . . . P Far 0795 MODEX_TEXT Length= 000E Public\r
+TDRAW_BITMAP . . . . . . . . . . P Far 0ACB MODEX_TEXT Length= 00EF Public\r
+TGPRINTC . . . . . . . . . . . . P Far 08A1 MODEX_TEXT Length= 00D4 Public\r
+TPRINT_STR . . . . . . . . . . . P Far 09B6 MODEX_TEXT Length= 003D Public\r
+\fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33\r
+modex.asm Symbols 20 - 1\r
+\r
+\r
+\r
+\r
+Symbols:\r
+\r
+ N a m e Type Value Attr\r
+\r
+?x3 . . . . . . . . . . . . . . Text ?,?,?\r
+?x4 . . . . . . . . . . . . . . Text ?,?,?,?\r
+@CB_Abort . . . . . . . . . . . L Near 0CA2 MODEX_TEXT \r
+@CB_Check_Right . . . . . . . . L Near 0D10 MODEX_TEXT \r
+@CB_Copy_Middle . . . . . . . . L Near 0D47 MODEX_TEXT \r
+@CB_Exit . . . . . . . . . . . . L Near 0D7E MODEX_TEXT \r
+@CB_Finish . . . . . . . . . . . L Near 0D77 MODEX_TEXT \r
+@CB_Left_Band . . . . . . . . . L Near 0CE3 MODEX_TEXT \r
+@CB_Left_Done . . . . . . . . . L Near 0D0B MODEX_TEXT \r
+@CB_Left_Loop . . . . . . . . . L Near 0CF5 MODEX_TEXT \r
+@CB_Middle_Copy . . . . . . . . L Near 0D61 MODEX_TEXT \r
+@CB_One_Done . . . . . . . . . . L Near 0CE0 MODEX_TEXT \r
+@CB_One_Loop . . . . . . . . . . L Near 0CCA MODEX_TEXT \r
+@CB_Only_One_Band . . . . . . . L Near 0CA7 MODEX_TEXT \r
+@CB_Right_Band . . . . . . . . . L Near 0D1B MODEX_TEXT \r
+@CB_Right_Done . . . . . . . . . L Near 0D47 MODEX_TEXT \r
+@CB_Right_Loop . . . . . . . . . L Near 0D31 MODEX_TEXT \r
+@CP_Exit . . . . . . . . . . . . L Near 0C07 MODEX_TEXT \r
+@CodeSize . . . . . . . . . . . Number 0001h \r
+@DB_COPY2 . . . . . . . . . . . L Near 0A8A MODEX_TEXT \r
+@DB_COPY_LINE . . . . . . . . . L Near 0A68 MODEX_TEXT \r
+@DB_COPY_LOOP . . . . . . . . . L Near 0A70 MODEX_TEXT \r
+@DB_COPY_PLANE . . . . . . . . . L Near 0A5F MODEX_TEXT \r
+@DB_COPY_REMAINDER . . . . . . . L Near 0A88 MODEX_TEXT \r
+@DB_Exit . . . . . . . . . . . . L Near 0AC1 MODEX_TEXT \r
+@DB_NEXT2 . . . . . . . . . . . L Near 0A99 MODEX_TEXT \r
+@DB_NEXT_LINE . . . . . . . . . L Near 0A91 MODEX_TEXT \r
+@DL_BREZHAM . . . . . . . . . . L Near 04C7 MODEX_TEXT \r
+@DL_DeltaYOK2 . . . . . . . . . L Near 0515 MODEX_TEXT \r
+@DL_DeltaYOK . . . . . . . . . . L Near 04DC MODEX_TEXT \r
+@DL_DrawLeft . . . . . . . . . . L Near 051F MODEX_TEXT \r
+@DL_DrawRight . . . . . . . . . L Near 05A3 MODEX_TEXT \r
+@DL_EXIT2 . . . . . . . . . . . L Near 061E MODEX_TEXT \r
+@DL_EXIT . . . . . . . . . . . . L Near 04C4 MODEX_TEXT \r
+@DL_HORZ . . . . . . . . . . . . L Near 0433 MODEX_TEXT \r
+@DL_LONGLN . . . . . . . . . . . L Near 0461 MODEX_TEXT \r
+@DL_NOSWAP1 . . . . . . . . . . L Near 0428 MODEX_TEXT \r
+@DL_NOSWAP2 . . . . . . . . . . L Near 048C MODEX_TEXT \r
+@DL_SLLExit . . . . . . . . . . L Near 0563 MODEX_TEXT \r
+@DL_SLLL2nc . . . . . . . . . . L Near 0543 MODEX_TEXT \r
+@DL_SLLL3nc . . . . . . . . . . L Near 0558 MODEX_TEXT \r
+@DL_SLLLoop . . . . . . . . . . L Near 0537 MODEX_TEXT \r
+@DL_SLR2nc . . . . . . . . . . . L Near 05C5 MODEX_TEXT \r
+@DL_SLR3nc . . . . . . . . . . . L Near 05D9 MODEX_TEXT \r
+@DL_SLRExit . . . . . . . . . . L Near 05E3 MODEX_TEXT \r
+@DL_SLRLoop . . . . . . . . . . L Near 05B9 MODEX_TEXT \r
+@DL_STLExit . . . . . . . . . . L Near 05A1 MODEX_TEXT \r
+@DL_STLLoop . . . . . . . . . . L Near 0575 MODEX_TEXT \r
+@DL_STLnc2 . . . . . . . . . . . L Near 0588 MODEX_TEXT \r
+@DL_STLnc3 . . . . . . . . . . . L Near 059D MODEX_TEXT \r
+@DL_ShallowLeft . . . . . . . . L Near 0525 MODEX_TEXT \r
+@DL_ShallowRight . . . . . . . . L Near 05A7 MODEX_TEXT \r
+@DL_SteepLeft . . . . . . . . . L Near 0566 MODEX_TEXT \r
+@DL_SteepRight . . . . . . . . . L Near 05E5 MODEX_TEXT \r
+@DL_VLINE . . . . . . . . . . . L Near 0481 MODEX_TEXT \r
+@DL_VLoop . . . . . . . . . . . L Near 04B4 MODEX_TEXT \r
+@DL_XRSEG . . . . . . . . . . . L Near 0479 MODEX_TEXT \r
+@DP_WAIT0 . . . . . . . . . . . L Near 0706 MODEX_TEXT \r
+@DP_WAIT1 . . . . . . . . . . . L Near 071B MODEX_TEXT \r
+@DataSize . . . . . . . . . . . Number 0000h \r
+@FB_EXIT . . . . . . . . . . . . L Near 0404 MODEX_TEXT \r
+@FB_LEFT_CONT . . . . . . . . . L Near 037A MODEX_TEXT \r
+@FB_LEFT_LOOP . . . . . . . . . L Near 036A MODEX_TEXT \r
+@FB_L_PLANE_FLUSH . . . . . . . L Near 037C MODEX_TEXT \r
+@FB_MIDDLE_LOOP . . . . . . . . L Near 03C7 MODEX_TEXT \r
+@FB_NORMAL . . . . . . . . . . . L Near 034C MODEX_TEXT \r
+@FB_NOSWAP1 . . . . . . . . . . L Near 031F MODEX_TEXT \r
+@FB_NOSWAP2 . . . . . . . . . . L Near 0339 MODEX_TEXT \r
+@FB_ONE_BAND_ONLY . . . . . . . L Near 03D2 MODEX_TEXT \r
+@FB_ONE_LOOP . . . . . . . . . . L Near 03F4 MODEX_TEXT \r
+@FB_RIGHT_CONT . . . . . . . . . L Near 03B0 MODEX_TEXT \r
+@FB_RIGHT_LOOP . . . . . . . . . L Near 03A0 MODEX_TEXT \r
+@FB_RIGHT . . . . . . . . . . . L Near 037D MODEX_TEXT \r
+@FB_R_EDGE_FLUSH . . . . . . . . L Near 03B3 MODEX_TEXT \r
+@GPC_DECODE_CHAR_BYTE . . . . . L Near 080F MODEX_TEXT \r
+@GPC_EXIT . . . . . . . . . . . L Near 0897 MODEX_TEXT \r
+@GPC_LowChar . . . . . . . . . . L Near 07DB MODEX_TEXT \r
+@GPC_NEXT_LINE . . . . . . . . . L Near 0889 MODEX_TEXT \r
+@GPC_NO_LEFT0BITS . . . . . . . L Near 083C MODEX_TEXT \r
+@GPC_NO_LEFT1BITS . . . . . . . L Near 0831 MODEX_TEXT \r
+@GPC_NO_MIDDLE0BITS . . . . . . L Near 085E MODEX_TEXT \r
+@GPC_NO_MIDDLE1BITS . . . . . . L Near 0853 MODEX_TEXT \r
+@GPC_NO_RIGHT0BITS . . . . . . . L Near 0888 MODEX_TEXT \r
+@GPC_NO_RIGHT1BITS . . . . . . . L Near 087D MODEX_TEXT \r
+@GPC_Set_Char . . . . . . . . . L Near 07E3 MODEX_TEXT \r
+@Interface . . . . . . . . . . . Number 0000h \r
+@LDR_Load . . . . . . . . . . . L Near 0677 MODEX_TEXT \r
+@Model . . . . . . . . . . . . . Number 0004h \r
+@PS_Exit . . . . . . . . . . . . L Near 09AF MODEX_TEXT \r
+@PS_Print_It . . . . . . . . . . L Near 097B MODEX_TEXT \r
+@SAP_Exit . . . . . . . . . . . L Near 06E1 MODEX_TEXT \r
+@SDF_Set_Font . . . . . . . . . L Near 0A06 MODEX_TEXT \r
+@SDP_Exit . . . . . . . . . . . L Near 0720 MODEX_TEXT \r
+@SD_WAIT0 . . . . . . . . . . . L Near 0798 MODEX_TEXT \r
+@SD_WAIT1 . . . . . . . . . . . L Near 079D MODEX_TEXT \r
+@SMX_Exit . . . . . . . . . . . L Near 027B MODEX_TEXT \r
+@STRLoop . . . . . . . . . . . . L Near 05F4 MODEX_TEXT \r
+@STRnc2 . . . . . . . . . . . . L Near 0606 MODEX_TEXT \r
+@STRnc3 . . . . . . . . . . . . L Near 061A MODEX_TEXT \r
+@SVM_BadModeSetup . . . . . . . L Near 015C MODEX_TEXT \r
+@SVM_Continue . . . . . . . . . L Near 0161 MODEX_TEXT \r
+@SVM_EXIT . . . . . . . . . . . L Near 0247 MODEX_TEXT \r
+@SVM_Set_Data . . . . . . . . . L Near 01AA MODEX_TEXT \r
+@SVM_Set_Pages . . . . . . . . . L Near 0207 MODEX_TEXT \r
+@SVM_Setup_CRTC . . . . . . . . L Near 019D MODEX_TEXT \r
+@SVM_Setup_Table . . . . . . . . L Near 0193 MODEX_TEXT \r
+@SW_Exit . . . . . . . . . . . . L Near 0789 MODEX_TEXT \r
+@SW_WAIT0 . . . . . . . . . . . L Near 0761 MODEX_TEXT \r
+@SW_WAIT1 . . . . . . . . . . . L Near 0776 MODEX_TEXT \r
+@TB_COPY2 . . . . . . . . . . . L Near 0B6A MODEX_TEXT \r
+@TB_COPY_LINE . . . . . . . . . L Near 0B26 MODEX_TEXT \r
+@TB_COPY_LOOP . . . . . . . . . L Near 0B2E MODEX_TEXT \r
+@TB_COPY_PLANE . . . . . . . . . L Near 0B1B MODEX_TEXT \r
+@TB_COPY_REMAINDER . . . . . . . L Near 0B68 MODEX_TEXT \r
+@TB_Exit . . . . . . . . . . . . L Near 0BB0 MODEX_TEXT \r
+@TB_NEXT2 . . . . . . . . . . . L Near 0B87 MODEX_TEXT \r
+@TB_NEXT_LINE . . . . . . . . . L Near 0B79 MODEX_TEXT \r
+@TB_SKIP_01 . . . . . . . . . . L Near 0B39 MODEX_TEXT \r
+@TB_SKIP_02 . . . . . . . . . . L Near 0B45 MODEX_TEXT \r
+@TB_SKIP_03 . . . . . . . . . . L Near 0B51 MODEX_TEXT \r
+@TB_SKIP_04 . . . . . . . . . . L Near 0B5D MODEX_TEXT \r
+@TB_SKIP_05 . . . . . . . . . . L Near 0B75 MODEX_TEXT \r
+@TGP_DECODE_CHAR_BYTE . . . . . L Near 090D MODEX_TEXT \r
+@TGP_EXIT . . . . . . . . . . . L Near 096B MODEX_TEXT \r
+@TGP_LowChar . . . . . . . . . . L Near 08D9 MODEX_TEXT \r
+@TGP_NEXT_LINE . . . . . . . . . L Near 095E MODEX_TEXT \r
+@TGP_NO_LEFT1BITS . . . . . . . L Near 092D MODEX_TEXT \r
+@TGP_NO_MIDDLE1BITS . . . . . . L Near 0941 MODEX_TEXT \r
+@TGP_NO_RIGHT1BITS . . . . . . . L Near 095D MODEX_TEXT \r
+@TGP_Set_Char . . . . . . . . . L Near 08E1 MODEX_TEXT \r
+@TPS_Exit . . . . . . . . . . . L Near 09EC MODEX_TEXT \r
+@TPS_Print_It . . . . . . . . . L Near 09BC MODEX_TEXT \r
+@code . . . . . . . . . . . . . Text MODEX_TEXT\r
+@data . . . . . . . . . . . . . Text DGROUP\r
+@fardata? . . . . . . . . . . . Text FAR_BSS\r
+@fardata . . . . . . . . . . . . Text FAR_DATA\r
+@stack . . . . . . . . . . . . . Text DGROUP\r
+ACTIVE_PAGE . . . . . . . . . . Word 0012 _BSS \r
+ALL_PLANES_ON . . . . . . . . . Number 0F02h \r
+ALL_PLANES . . . . . . . . . . . Number 000Fh \r
+ASYNC_RESET . . . . . . . . . . Number 0100h \r
+ATTRIB_Ctrl . . . . . . . . . . Number 03C0h \r
+CHAIN4_OFF . . . . . . . . . . . Number 0604h \r
+CHARSET_HI . . . . . . . . . . . Word 0026 _BSS \r
+CHARSET_LOW . . . . . . . . . . Word 0022 _BSS \r
+CHAR_BITS . . . . . . . . . . . Number 000Fh \r
+CRTC_Data . . . . . . . . . . . Number 03D5h \r
+CRTC_Index . . . . . . . . . . . Number 03D4h \r
+CURRENT_MOFFSET . . . . . . . . Word 001C _BSS \r
+CURRENT_PAGE . . . . . . . . . . Word 0014 _BSS \r
+CURRENT_SEGMENT . . . . . . . . Word 0016 _BSS \r
+CURRENT_XOFFSET . . . . . . . . Word 0018 _BSS \r
+CURRENT_YOFFSET . . . . . . . . Word 001A _BSS \r
+Char_Plane_Data . . . . . . . . Byte 0008 MODEX_TEXT \r
+DAC_READ_ADDR . . . . . . . . . Number 03C7h \r
+DAC_WRITE_ADDR . . . . . . . . . Number 03C8h \r
+DISPLAY_PAGE . . . . . . . . . . Word 0010 _BSS \r
+False . . . . . . . . . . . . . Number 0000h \r
+GC_Index . . . . . . . . . . . . Number 03CEh \r
+GET_CHAR_PTR . . . . . . . . . . Number 1130h \r
+INPUT_1 . . . . . . . . . . . . Number 03DAh \r
+LAST_PAGE . . . . . . . . . . . Word 0004 _BSS \r
+LATCHES_OFF . . . . . . . . . . Number FF08h \r
+LATCHES_ON . . . . . . . . . . . Number 0008h \r
+Left_Clip_Mask . . . . . . . . . Byte 0000 MODEX_TEXT \r
+MAP_MASK_PLANE1 . . . . . . . . Number 0102h \r
+MAP_MASK_PLANE2 . . . . . . . . Number 1102h \r
+MAP_MASK . . . . . . . . . . . . Number 0002h \r
+MAX_XOFFSET . . . . . . . . . . Word 001E _BSS \r
+MAX_YOFFSET . . . . . . . . . . Word 0020 _BSS \r
+MISC_OUTPUT . . . . . . . . . . Number 03C2h \r
+MODE_200_Tall . . . . . . . . . L Near 0044 MODEX_TEXT \r
+MODE_240_Tall . . . . . . . . . L Near 0054 MODEX_TEXT \r
+MODE_320_Wide . . . . . . . . . L Near 0028 MODEX_TEXT \r
+MODE_320x200 . . . . . . . . . . L Near 0074 MODEX_TEXT \r
+MODE_320x240 . . . . . . . . . . L Near 00BC MODEX_TEXT \r
+MODE_320x400 . . . . . . . . . . L Near 0086 MODEX_TEXT \r
+MODE_320x480 . . . . . . . . . . L Near 00CE MODEX_TEXT \r
+MODE_360_Wide . . . . . . . . . L Near 0036 MODEX_TEXT \r
+MODE_360x200 . . . . . . . . . . L Near 00E0 MODEX_TEXT \r
+MODE_360x240 . . . . . . . . . . L Near 0098 MODEX_TEXT \r
+MODE_360x400 . . . . . . . . . . L Near 00F2 MODEX_TEXT \r
+MODE_360x480 . . . . . . . . . . L Near 00AA MODEX_TEXT \r
+MODE_400_Tall . . . . . . . . . L Near 0044 MODEX_TEXT \r
+MODE_480_Tall . . . . . . . . . L Near 0054 MODEX_TEXT \r
+MODE_Double_Line . . . . . . . . L Near 0020 MODEX_TEXT \r
+MODE_Single_Line . . . . . . . . L Near 0018 MODEX_TEXT \r
+MODE_TABLE . . . . . . . . . . . L Near 0064 MODEX_TEXT \r
+NUM_MODES . . . . . . . . . . . Number 0008h \r
+PAGE_ADDR . . . . . . . . . . . Word 0006 _BSS \r
+PAGE_SIZE . . . . . . . . . . . Word 000E _BSS \r
+PEL_DATA_REG . . . . . . . . . . Number 03C9h \r
+PIXEL_PAN_REG . . . . . . . . . Number 0033h \r
+PLANE_BITS . . . . . . . . . . . Number 0003h \r
+READ_MAP . . . . . . . . . . . . Number 0004h \r
+ROM_8x8_Hi . . . . . . . . . . . Number 0004h \r
+ROM_8x8_Lo . . . . . . . . . . . Number 0003h \r
+Right_Clip_Mask . . . . . . . . Byte 0004 MODEX_TEXT \r
+SCREEN_HEIGHT . . . . . . . . . Word 0002 _BSS \r
+SCREEN_WIDTH . . . . . . . . . . Word 0000 _BSS \r
+SC_Data . . . . . . . . . . . . Number 03C5h \r
+SC_Index . . . . . . . . . . . . Number 03C4h \r
+SEQU_RESTART . . . . . . . . . . Number 0300h \r
+START_DISP_HI . . . . . . . . . Number 000Ch \r
+START_DISP_LO . . . . . . . . . Number 000Dh \r
+True . . . . . . . . . . . . . . Number -0001h \r
+VERT_RETRACE . . . . . . . . . . Number 0008h \r
+VGA_Segment . . . . . . . . . . Number A000h \r
+b . . . . . . . . . . . . . . . Text BYTE PTR\r
+d . . . . . . . . . . . . . . . Text DWORD PTR\r
+f . . . . . . . . . . . . . . . Text FAR PTR\r
+nil . . . . . . . . . . . . . . Number 0000h \r
+o . . . . . . . . . . . . . . . Text OFFSET\r
+s . . . . . . . . . . . . . . . Text SHORT\r
+w . . . . . . . . . . . . . . . Text WORD PTR\r
+\r
+ 0 Warnings\r
+ 0 Errors\r
--- /dev/null
+\r
+PACKING LIST FOR MODEX104\r
+\r
+DIRECTORY: \ - The Mode X Library versoon 1.04 \r
+\r
+ASM BAT 26 05-14-93 6:00p - Batch File to Assemble MODEX.ASM\r
+MODE-X TXT 2135 05-14-93 6:00p - File Describing MODE X Routines\r
+MODEX ASM 117039 05-14-93 6:00p - Assembly source to Mode X Library\r
+MODEX BI 3238 05-14-93 6:00p - Include File for BASIC/PDS\r
+MODEX H 2943 05-14-93 6:00p - Include File for C/C++\r
+MODEX OBJ 5208 05-14-93 6:00p - The Mode X Library\r
+README DOC 3259 05-14-93 6:00p - Information on this Product\r
+PACKING LST 4767 05-14-93 6:00p - This File\r
+\r
+DIRECTORY: \DEMOS - Mode X Demos\r
+\r
+CHARDEMO EXE 13066 05-14-93 6:00p - Demo of Multiple Fonts & Color Cycling\r
+TEST6 EXE 19990 05-14-93 6:00p - Main Mode X Demo\r
+ROM_8X8 FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE\r
+SPACEAGE FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE\r
+SYSTEM FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE\r
+\r
+DIRECTORY: \DEMOS\BASIC7 - Demo Sources for Microsoft BASIC 7.1 (PDS)\r
+\r
+MAKE-LIB BAT 166 05-14-93 6:00p - Batch File to make MODEX.LIB/.QLB\r
+MODEX BI 3238 05-14-93 6:00p - Include File for MODE X Library\r
+MODEX LIB 7189 05-14-93 6:00p - Mode X & Utility Libraries for QBX\r
+MODEX OBJ 5208 05-14-93 6:00p - Mode X Library - Object File\r
+MODEX QLB 11141 05-14-93 6:00p - Mode X & Utility Quick Library\r
+TEST6 BAS 12733 05-14-93 6:00p - Main Demo Source Code (TEST6.EXE)\r
+UASM-BC7 BAT 43 05-14-93 6:00p - Batch file to Make UTILS.OBJ for QBX\r
+UTILS ASM 8506 05-14-93 6:00p - Basic Utilities - Assembler source\r
+UTILS BI 2028 05-14-93 6:00p - Basic Utilities - Basic Includes\r
+UTILS OBJ 681 05-14-93 6:00p - Basic Utilities - Object File\r
+CHARDEMO BAS 3431 05-14-93 6:00p - Source to CHARDEMO.EXE\r
+\r
+DIRECTORY: \DEMOS\C - Demo Sources for Borland C/C++\r
+\r
+C_UTILS ASM 8782 05-14-93 6:00p - C Utilities - Assembler source\r
+C_UTILS H 2623 05-14-93 6:00p - C Utilities - C Includes\r
+C_UTILS OBJ 648 05-14-93 6:00p - C Utilities - Object File\r
+MODEX H 2943 05-14-93 6:00p - Mode X Library C Incldues\r
+MODEX OBJ 5208 05-14-93 6:00p - Mode X Library\r
+UTLS-ASM BAT 36 05-14-93 6:00p - Batch File to Make C_UTILS.OBJ\r
+X-DEMO C 15085 05-14-93 6:00p - Source to Main Demo (TEST6) in C\r
+X-DEMO EXE 41090 05-14-93 6:00p - C Version of Main Demo\r
+X-DEMO PRJ 5188 05-14-93 6:00p - Borland C Project file\r
+\r
+DIRECTORY: \DEMOS\PASCAL - Demo Sources for Turbo Pascal\r
+\r
+TEST5 PAS 15873 05-14-93 6:00p - Source for a TP Version of TEST6.EXE\r
+\r
+DIRECTORY: \DEMOS\QB45 - Demo Sources for Microsoft QuickBASIC 4.5\r
+\r
+MAKE-LIB BAT 164 05-14-93 6:00p - Batch File to make MODEX.LIB/.QLB\r
+MODEX BI 3238 05-14-93 6:00p - Include File for MODE X Library\r
+MODEX LIB 7189 05-14-93 6:00p - Mode X & Utility Libraries for QB45\r
+MODEX OBJ 5208 05-14-93 6:00p - Mode X Library - Object File\r
+MODEX QLB 9739 05-14-93 6:00p - Mode X & Utility Quick Library/QB45\r
+TEST6A BAS 12743 05-14-93 6:00p - Main Demo Source Code (TEST6.EXE)\r
+TEST6A EXE 40544 05-14-93 6:00p - QB45 Version of Main Demo\r
+UASM-QB4 BAT 30 05-14-93 6:00p - Batch file to Make UTILS.OBJ for QB45\r
+UTILS ASM 8506 05-14-93 6:00p - Basic Utilities - Assembler source\r
+UTILS BI 2028 05-14-93 6:00p - Basic Utilities - Basic Includes\r
+UTILS OBJ 628 05-14-93 6:00p - Basic Utilities - Object File\r
+\r
+DIRECTORY: \FONTEDIT - Font Editor\r
+\r
+CSEDIT EXE 39242 05-14-93 6:00p - Font Editor Program\r
+CSEDIT DOC 8629 05-14-93 6:00p - Font Editor Documentation\r
+CHARSETS CS 2144 05-14-93 6:00p - Internal Fonts for Editor\r
+MOUSEIMG CS 128 05-14-93 6:00p - Mouse Pointers for Editor\r
+PALETTE CS 768 05-14-93 6:00p - Palette for Editor\r
+INVERSE FNT 1024 05-14-93 6:00p - Sample Font\r
+ROM_8X8 FNT 1024 05-14-93 6:00p - Sample Font\r
+SPACEAGE FNT 1024 05-14-93 6:00p - Sample Font\r
+SYSTEM FNT 1024 05-14-93 6:00p - Sample Font\r
+\r
+DIRECTORY: \PALEDIT - Palette Editor\r
+\r
+PALEDIT EXE 31954 05-14-93 6:00p - Palette Editor Program\r
+PALEDIT DOC 6688 05-14-93 6:00p - Palette Editor Documentation\r
+CHARSETS CS 2144 05-14-93 6:00p - Internal Fonts for Editor\r
+MOUSEIMG CS 128 05-14-93 6:00p - Mouse Pointers for Editor\r
+GAMECOLR PAL 768 05-14-93 6:00p - Sample Palette\r
+PRIME PAL 768 05-14-93 6:00p - Sample Palette\r
+RGB PAL 768 05-14-93 6:00p - Sample Palette\r
--- /dev/null
+ \r
+PALEDIT - A Simple VGA 256 Color Palette Editor\r
+ \r
+ \r
+PALEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X\r
+Library for VGA Graphics.\r
+ \r
+WHAT YOU NEED TO RUN PALEDIT:\r
+ \r
+ * A Vga Monitor\r
+ * A Microsoft Compatible Mouse\r
+ \r
+ A Mouse is most definitely required, as the keyboard is used for\r
+ nothing except entering file names.\r
+ \r
+FILES NEEDED IN THE CURRENT DIRECTORY:\r
+ \r
+ PALEDIT.EXE - The Palette Editor Program\r
+ CHARSETS.CS - The Palette Editor's Internal Fonts\r
+ MOUSEIMG.CS - The Palette Editor's Mouse Pointer\r
+ \r
+SAMPLE PALETTE FILE THAT SHOULD BE INCLUDED:\r
+ \r
+ RGB.PAL - A Simple Palette with Reds, Greens, and Blues\r
+ PRIME.PAL - A Simple Palette\r
+ GAMECOLR.PAL - A Bright Palette from a Game of mine.\r
+ \r
+WHAT IT EDITS:\r
+ \r
+ The VGA DAC Registers, all 256 of them.\r
+ \r
+HOW IT WORKS/FEATURES:\r
+ \r
+ PALEDIT allows the user to see the entire VGA Palette of 256 colors\r
+ and select and modify the RED, GREEN, and BLUE values of any individual\r
+ color (DAC) register. The entire group of 256 colors can be saved to\r
+ a disk file for later retrieval.\r
+ \r
+ Individual "SLIDERS" show the current RED, GREEN, and BLUE color\r
+ components of the current color and allow them to be changed.\r
+ \r
+ The Following operations can be performed.\r
+ \r
+ * Raise, Lower, and set the RED, GREEN, or BLUE components.\r
+ * Copy the current RGB values to another Color (DAC) Register\r
+ * Brighten the selected color\r
+ * Darken and selected color\r
+ * Reset the selected color to its original state\r
+ * Blend an entire range of colors, creating a smooth\r
+ Transition from one color to another\r
+ * Optionally Lock out the first 16 colors to prevent\r
+ Accidental Modification\r
+ \r
+DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN:\r
+ \r
+ COLOR SLIDERS: In the upper left of the screen there are\r
+ Three Rectangular Boxes: One for each primary color:\r
+ RED, GREEN, and BLUE. Each Box has an arrow at each\r
+ end, and a scale bar in the middle, connecting the two\r
+ arrows. The scale bar is much like a thermometer,\r
+ indicating how much of that color is in the selected\r
+ color. To the right of each Box, the name of the color\r
+ is indicated, along with the content color in the form\r
+ of a number from 0 to 63; where 0 means none of that\r
+ color goes into making the selected color, and 63 means\r
+ that the selected color is saturated with that color.\r
+ \r
+ Clicking the mouse on the slider's left arrow box will\r
+ decrease the amount of that primary color in the selected\r
+ color. Holding the mouse button down will reduce the\r
+ color value all the way to 0.\r
+ \r
+ Clicking the mouse on the slider's right arrow box will\r
+ increase the amount of that primary color in the selected\r
+ color. Holding the mouse button down will increase the\r
+ color value all the way to 63.\r
+ \r
+ Clicking the mouse on the scale bar will set the amount\r
+ of that primary color to the value the represents that\r
+ position on the slider.\r
+ \r
+ LOCK Button: Clicking the button toggles the lockout of the\r
+ first 16 colors. When they are locked out, they can not\r
+ be modified, and when selected the word "LOCKED" will\r
+ appear below the color # on the Color Information Display.\r
+ \r
+ LOAD Button: Clicking this button will load the Palette file\r
+ that is named in the Palette File name box. If no name is\r
+ given or no such file exists, then nothing will be loaded.\r
+ \r
+ SAVE Button: Clicking this button will save the current Palette\r
+ in a file using the name given in the Palette File Name Box.\r
+ If a Valid name is not provided, nothing will be saved.\r
+ \r
+ QUIT Button: Clicking this button will return you to DOS.\r
+ Nothing is saved, and no confirmation is given.\r
+ \r
+ \r
+ Color Information Display: This Box is on the left side of the\r
+ Screen, below the Color Sliders. It shows the number of the\r
+ currently selected color (from 0 to 255) and indicates if\r
+ that color is locked. To the right of this box is a big\r
+ square showing the current color.\r
+ \r
+ LIGHTER Button: Clicking this button will make the selected\r
+ color brighter.\r
+ \r
+ DARKER Button: Clicking this button will make the selected\r
+ color darker.\r
+ \r
+ RESET Button: Clicking this button will restore the selected\r
+ color to the value it had when it was first selected.\r
+ \r
+ BLEND Button: Clicking this button will let you Blend a range\r
+ of colors together. One end of the range of colors is the\r
+ currently selected color. After Clicking the BLEND button.\r
+ You must click on the color at the other end of the range\r
+ in the Palette Display Box. All of the colors in between\r
+ those two colors will be changed to represent a gradual\r
+ transition from the color at one end to the color at the\r
+ other end.\r
+ \r
+ PALETTE FILE NAME BOX: This Text Box is used to enter the name\r
+ of a Palette file to load or the name to save the current\r
+ Palette as. Just click on the Box, and it will change color\r
+ and a flashing cursor will appear. Now you type in a filename\r
+ or edit the existing filename. Press <RETURN> or click\r
+ outside the text box to end editing.\r
+ \r
+ PALETTE DISPLAY BOX: This Box shows all 256 colors in an array\r
+ of 32 by 8 color blocks. The Currently Selected Color will\r
+ have a Box around it. Clicking on a color with the Left\r
+ Mouse button will make that color the new currently selected\r
+ color. Clicking on a color with the Right Mouse Button will\r
+ copy the color value from the old selected color to it, before\r
+ it is made the new selected color.\r
+ \r
+ Message Bar: At the very bottom of the screen, this Bar will display\r
+ information and messages for various functions.\r
+ \r
+PALETTE FILE FORMAT:\r
+ \r
+ BINARY image, in order of VGA DAC (Color) Number. 3 Bytes Per\r
+ Color, 256 Colors. 768 Bytes total. The Files will be exactly\r
+ 768 bytes in size.\r
+ \r
+ COLOR:\r
+ RED: 1 BYTE\r
+ GREEN: 1 BYTE\r
+ BLUE: 1 BYTE\r
+ \r
+ PALETTE: Array (0 to 255) of COLOR\r
+ \r
+COMMENTS, QUESTIONS, BUG REPORTS, etc:\r
+ \r
+ Send the to the Author: Matt Pritchard\r
+ \r
+ Through the 80xxx Fidonet Echo or\r
+ \r
+ Matt Pritchard\r
+ P.O. Box 140264\r
+ Irving, TX 75014\r
+ \r
+CREDITS:\r
+ \r
+ This Palette Editor was written in QuickBASIC 4.5\r
--- /dev/null
+\r
+=========================================================================\r
+ þ þ þþþþþ þþþþ þþþþþ þ þ þ þþþþþ þ þ \r
+ þþ þþ þ þ þ þ þ þ þ þþ þ þ þ þ\r
+ þ þ þ þ þ þ þ þþþþ þ þ þ þ þ þþþþþ\r
+ þ þ þ þ þ þ þ þ þ þ þ þ þ\r
+ þ þ þþþþþ þþþþ þþþþþ þ þ þþþþþ þþ þþþþþ þ\r
+=========================================================================\r
+ MODE X 1.04\r
+=========================================================================\r
+ Library & Editors by Matt Pritchard: Release 1.04 on 14 Mar 93\r
+=========================================================================\r
+\r
+MODEX104 is a library of high performance assembler routines for setting,\r
+accessing, and manipulating the Undocumented 256 Color Modes available in\r
+all VGA adaptors.\r
+\r
+MODEX104 includes the following elements:\r
+\r
+ MODE X Library - A library of MODE X routines written in assembly.\r
+\r
+ FONT EDITOR - An editor for creating and modifying fonts for use by\r
+ The MODE X Library.\r
+\r
+ PALETTE EDITOR - An editor for creating and modifying palettes for\r
+ use in VGA 256 Color modes.\r
+\r
+ MODE X Demos - Programs that show off the various features of the\r
+ MODE X Library\r
+\r
+ MODE X Demo Source - The Full source code for the MODE X Demos for \r
+ the following Languages: Microsoft QuickBASIC 4.5,\r
+ Microsoft BASIC 7.1 PDS, Borland C/C++ 3.1,\r
+ and Borland Turbo Pascal.\r
+\r
+THE LEGAL STUFF:\r
+\r
+ The Mode X Library has been placed into the Public Domain by the\r
+ Author (Matt Pritchard). The Font Editor and Palette Editor are also\r
+ placed into the Public Domain by the Author (Matt Pritchard). The\r
+ Source Code to the above editors is not in the Public Domain.\r
+\r
+ The Mode X Demos and the Mode X Demo Sources have been placed into the\r
+ Public domain by the Author (Matt Pritchard).\r
+\r
+ The Mode X Library may be used freely in any non commerical product.\r
+ It would be nice if the author was credited for the contribution, \r
+ but it is not necessary. No $$$ involved.\r
+ \r
+ The Mode X Library may be used freely in a commercial product, *IF*\r
+ the author (Matt Pritchard) is credited for the contribution. That's\r
+ it. No $$$ involved.\r
+\r
+ The Mode X Library should not be re-sold or modified and re-sold.\r
+ No fee in excess of $5 should be charged for duplication of this\r
+ Library.\r
+\r
+CONTRIBUTORS: The following people have contributed to this effort.\r
+\r
+ Michael Abrash - He told us all how to do it in the first place.\r
+ Scott Wyatt - He ported the Main Demo code to Turbo Pascal.\r
+\r
+THE AUTHOR:\r
+\r
+ The author of MODEX104 is Matt Pritchard.\r
+ All Questions and correspondance can be directed to:\r
+\r
+ "Matt Pritchard" on Fido Net ECHO Conference: 80xxx\r
+\r
+ or mailed to: Matt Pritchard\r
+ P.O. Box 140264\r
+ Irving, TX 75014-0264\r
+\r
+ Questions, Inquiries, Comments, Donations, etc are quite welcome.\r
+\r
+\r
--- /dev/null
+MASM c_utils, c_utils, c_utils, nul;
\ No newline at end of file
--- /dev/null
+#! /bin/bash
+wmake clean;wmake
+cp x_demo.exe ../../../
--- /dev/null
+/* X-DEMO.C - a Mode "X" Demo */\r
+/* By Matt Pritchard, 14 Apr, 1993 */\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+\r
+#include "modex.h"\r
+#include "c_utils.h"\r
+\r
+#define MAX_SHAPES 32\r
+#define MAX_SPRITES 64\r
+\r
+ /* routines in this file */\r
+\r
+void demo_res (int, int, int);\r
+int get_key (void);\r
+void error_out (char*);\r
+void load_shapes (void);\r
+int int_sqrt (int, int);\r
+void page_demo (void);\r
+\r
+ /* Structures for Sprites */\r
+\r
+struct Shape\r
+{\r
+ unsigned char Image[512];\r
+ int X_Width;\r
+ int Y_Width;\r
+} Img [MAX_SHAPES];\r
+\r
+struct Sprite\r
+{\r
+ int X_pos;\r
+ int Y_pos;\r
+ int X_Dir;\r
+ int Y_Dir;\r
+ int Shape;\r
+ int Last_X [2];\r
+ int Last_Y [2];\r
+} Obj [MAX_SPRITES];\r
+\r
+\r
+ /* MAIN */\r
+\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+\r
+ /* if (argc > 0)\r
+ {\r
+ while (argc > 0)\r
+ {\r
+ dos_print ("Unknown Argument: ");\r
+ dos_print (makefp argv[argc]);\r
+ argc--;\r
+ }\r
+ return (0);\r
+\r
+ }\r
+ */\r
+\r
+ init_random ();\r
+\r
+ load_shapes ();\r
+\r
+ demo_res ( Mode_320x200, 320, 200 );\r
+ demo_res ( Mode_320x400, 320, 400 );\r
+\r
+ demo_res ( Mode_360x200, 360, 200 );\r
+ demo_res ( Mode_360x400, 360, 400 );\r
+\r
+ demo_res ( Mode_320x240, 320, 240 );\r
+ demo_res ( Mode_320x480, 320, 480 );\r
+\r
+ demo_res ( Mode_360x240, 360, 240 );\r
+ demo_res ( Mode_360x480, 360, 480 );\r
+\r
+ page_demo ();\r
+\r
+ set_video_mode (3);\r
+ dos_print ("This Mode X Demo is Finished");\r
+ return (0);\r
+\r
+}\r
+\r
+\r
+ /* Demonstrate a given resolution */\r
+\r
+\r
+void demo_res (int Screen_Mode, int X_max, int Y_max)\r
+{\r
+\r
+char *Error1 = "Failure while calling SET_MODEX";\r
+char *Error2 = "Failure during READ_PIXEL test";\r
+\r
+char *Abort_Msg = "Demo aborted by User";\r
+\r
+char *Demo_Msg = " This is a MODE X demo ";\r
+char *Scrn_Msg = "Screen Resolution is by ";\r
+char *Cont_Msg = "Press <ANY KEY> to Continue";\r
+\r
+char *Line_Msg = "LINE TEST";\r
+char *Fill_Msg = "FILL TEST";\r
+char *Pixel_Msg = "PIXEL TEST";\r
+\r
+char Text[10];\r
+\r
+int x1, y1, x2, y2 = 0;\r
+int x, y, z = 0;\r
+int X_Center, gap = 0;\r
+\r
+\r
+ if (set_modex (Screen_Mode) == 0)\r
+ {\r
+ error_out (Error1);\r
+ }\r
+\r
+ X_Center = X_max / 2;\r
+\r
+ x1 = 10;\r
+ y1 = 10;\r
+ x2 = X_max - 1;\r
+ y2 = Y_max - 1;\r
+\r
+ for (z = 0; z <= 3; z++)\r
+ {\r
+ y = 31 - z -z;\r
+ draw_line (x1+z, y1+z, x2-z, y1+z, y);\r
+ draw_line (x1+z, y1+z, x1+z, y2-z, y);\r
+ draw_line (x1+z, y2-z, x2-z, y2-z, y);\r
+ draw_line (x2-z, y1+z, x2-z, y2-z, y);\r
+ }\r
+\r
+ for (x = 0; x < (X_max / 10); x++)\r
+ {\r
+ tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) );\r
+ draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE);\r
+ }\r
+\r
+ for (y = 0; y < (Y_max / 10); y++)\r
+ {\r
+ tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) );\r
+ draw_line (0, y*10+9, 3, y*10+9, c_bWHITE);\r
+ }\r
+\r
+ for (x = 0; x <= 63; x++)\r
+ {\r
+ z = 15 + (x * 3 / 4);\r
+ set_dac_register (64+x, z, z, z);\r
+ set_dac_register (128+x, 0, z, z);\r
+\r
+ draw_line (103-x, 60, 40+x, 123, 64+x);\r
+ draw_line (40, 60+x, 103, 123-x, 128+x);\r
+\r
+ }\r
+\r
+ tprint_str (Line_Msg, 9, 37, 130, c_BLUE);\r
+\r
+ y = 60;\r
+ gap = 0;\r
+ for (x = 0; x <= 9; x++)\r
+ {\r
+ fill_block (120, y, 120+x, y+gap, 64+x);\r
+ fill_block (140 - (15-x), y, 150+x, y+gap, 230+x);\r
+ fill_block (170 - (15-x), y, 170, y+gap, 128+x);\r
+ y = y + gap + 2;\r
+ gap++;\r
+ }\r
+\r
+ tprint_str (Fill_Msg, 9, 110, 46, c_GREEN);\r
+\r
+ for (x = 190; x <= 250; x+=2)\r
+ {\r
+ for (y = 60; y <= 122; y+=2)\r
+ {\r
+ z = (x+x+y+y) & 0xff;\r
+ set_point (x, y, z);\r
+ }\r
+ }\r
+\r
+ tprint_str (Pixel_Msg, 10, 182, 130, c_RED);\r
+\r
+ for (x = 190; x <= 250; x+=2)\r
+ {\r
+ for (y = 60; y <= 122; y+=2)\r
+ {\r
+ z = (x+x+y+y) & 0xff;\r
+ if (read_point(x, y) != z)\r
+ {\r
+ error_out (Error2);\r
+ }\r
+ }\r
+ }\r
+\r
+ print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE);\r
+\r
+ x = X_Center - 124;\r
+ print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK);\r
+\r
+ sprintf (Text, "%3d", X_max);\r
+ print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK);\r
+\r
+ sprintf (Text, "%3d", Y_max);\r
+ print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK);\r
+\r
+ for (x = 0; x <= 15; x++)\r
+ {\r
+ set_dac_register (230+x, 63-x*4, 0, 15+x*3);\r
+ draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x);\r
+ }\r
+\r
+ tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW);\r
+\r
+ if (get_key () == Ky_ESC)\r
+ {\r
+ error_out (Abort_Msg);\r
+ }\r
+\r
+ return ;\r
+\r
+}\r
+\r
+\r
+ /* Wait for a Keystroke */\r
+\r
+\r
+int get_key(void)\r
+{\r
+\r
+int c = 0;\r
+\r
+ while (c == 0)\r
+ {\r
+ c = scan_keyboard ();\r
+ }\r
+\r
+ return (c);\r
+\r
+}\r
+\r
+\r
+ /* Error Handling Routine */\r
+\r
+\r
+void error_out (char * text)\r
+{\r
+\r
+ set_video_mode (3);\r
+ dos_print (text);\r
+ exit (EXIT_SUCCESS);\r
+\r
+}\r
+\r
+\r
+ /* Routine to generate random sprites */\r
+\r
+\r
+void load_shapes ()\r
+{\r
+\r
+unsigned char Grid[33][33];\r
+\r
+char *Error1 = "Bad Shape Selected Error";\r
+\r
+int Shape;\r
+int x, y, z;\r
+int Style, Color;\r
+int X_Width, Y_Width, Center, S_Width;\r
+int Hollow_X, Hollow_Y;\r
+\r
+ for (Shape = 0; Shape < MAX_SHAPES; Shape++)\r
+ {\r
+ for (y = 0; y <= 32; y++)\r
+ {\r
+ for (x = 0; x <= 32; x++)\r
+ {\r
+ Grid[x][y] = c_BLACK;\r
+ }\r
+ }\r
+\r
+ Style = random_int (6);\r
+ Color = 1 + random_int (15);\r
+\r
+ switch (Style)\r
+\r
+ {\r
+ /* SOLID BOXES */\r
+\r
+ case 0:\r
+\r
+ {\r
+ do\r
+ {\r
+ X_Width = 3 + random_int(30);\r
+ Y_Width = 3 + random_int(30);\r
+\r
+ } while ( (X_Width * Y_Width) >= 512);\r
+\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ Grid[x][y] = Color;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+ /* HOLLOW BOXES */\r
+\r
+ case 1:\r
+\r
+ {\r
+ do {\r
+ X_Width = 6 + random_int(27);\r
+ Y_Width = 6 + random_int(27);\r
+ } while ( (X_Width * Y_Width) >= 512);\r
+\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ Grid[x][y] = Color;\r
+ }\r
+ }\r
+\r
+ Hollow_X = 1 + random_int ((X_Width / 2) -1);\r
+ Hollow_Y = 1 + random_int ((Y_Width / 2) -1);\r
+\r
+ for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++)\r
+ {\r
+ for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++)\r
+ {\r
+ Grid[x][y] = c_BLACK;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ /* SOLID DIAMOND */\r
+\r
+ case 2:\r
+\r
+ {\r
+\r
+ X_Width = 3 + 2 * random_int(10);\r
+ Y_Width = X_Width;\r
+ Center = X_Width / 2;\r
+\r
+ for (y = 0; y <= Center; y++)\r
+ {\r
+ for (x = 0; x <= y; x++)\r
+ {\r
+ Grid [Center-x+1][y+1] = Color;\r
+ Grid [Center+x+1][y+1] = Color;\r
+ Grid [Center-x+1][Y_Width-y] = Color;\r
+ Grid [Center+x+1][Y_Width-y] = Color;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ /* HOLLOW DIAMOND */\r
+\r
+ case 3:\r
+\r
+ {\r
+\r
+ X_Width = 3 + 2 * random_int(10);\r
+ Y_Width = X_Width;\r
+ Center = X_Width / 2;\r
+ S_Width = random_int (Center);\r
+\r
+ for (y = 0; y <= Center; y++)\r
+ {\r
+ for (x = 0; x <= y; x++)\r
+ {\r
+ if ( x+(Center-y) >= S_Width )\r
+ {\r
+ Grid [Center-x+1][y+1] = Color;\r
+ Grid [Center+x+1][y+1] = Color;\r
+ Grid [Center-x+1][Y_Width-y] = Color;\r
+ Grid [Center+x+1][Y_Width-y] = Color;\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ /* BALL */\r
+\r
+ case 4:\r
+\r
+ {\r
+\r
+ X_Width = 7 + 2 * random_int (8);\r
+ Y_Width = X_Width;\r
+ Center = 1 + X_Width / 2;\r
+\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ z = int_sqrt(Center-x, Center-y);\r
+ if (z < Center)\r
+ {\r
+ Grid[x][y] = 150 + Color * 2 + z * 3;\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ /* HOLLOW BALLS */\r
+\r
+ case 5:\r
+\r
+ {\r
+ X_Width = 7 + 2 * random_int (8);\r
+ Y_Width = X_Width;\r
+ Center = 1 + X_Width / 2;\r
+ S_Width = random_int (X_Width);\r
+\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ z = int_sqrt(Center-x, Center-y);\r
+ if ( (z < Center) && (z >= S_Width) )\r
+ {\r
+ Grid[x][y] = 150 + Color * 2 + z * 3;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ break;\r
+ }\r
+\r
+ default:\r
+\r
+ {\r
+ error_out (Error1);\r
+ break;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ z = 0;\r
+ for (y = 1; y <= Y_Width; y++)\r
+ {\r
+ for (x = 1; x <= X_Width; x++)\r
+ {\r
+ Img[Shape].Image[z] = Grid[x][y];\r
+ z++;\r
+ }\r
+ }\r
+\r
+ Img[Shape].X_Width = X_Width;\r
+ Img[Shape].Y_Width = Y_Width;\r
+\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+ /* Quickie Psuedo Integer Square Root Routine */\r
+\r
+\r
+int int_sqrt ( int x, int y )\r
+{\r
+\r
+int Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144};\r
+\r
+int r, d;\r
+\r
+ d = (x * x) + (y * y);\r
+ r = 0;\r
+\r
+ while ( d >= Sqr_Table[r] )\r
+ {\r
+ r++;\r
+ }\r
+\r
+ return (r);\r
+\r
+}\r
+\r
+\r
+ /* The Bit Sprite Demo */\r
+\r
+\r
+void page_demo ()\r
+{\r
+\r
+char *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call";\r
+\r
+int Last_Objects[2], Visible_Objects;\r
+\r
+int Screen_X = 384;\r
+int Screen_Y = 224;\r
+\r
+int x, y, z;\r
+int c, dc;\r
+int x1, y1, x2, y2;\r
+\r
+int Sprite_X, Sprite_Y;\r
+int Current_Page;\r
+int New_X, New_Y;\r
+\r
+int View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD;\r
+int Set_Color, Prev_Color, S_Dir, P_Dir;\r
+\r
+int Demo_Running = True;\r
+int redo, code;\r
+\r
+int pee;\r
+pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3);\r
+ if ( pee > 0)\r
+ {\r
+ set_video_mode (3);\r
+ dos_print (Error1);\r
+ fprintf(stdout, "return value is %d\n", pee);\r
+ //error_out (Error1);\r
+ exit (EXIT_SUCCESS);\r
+ }\r
+\r
+ set_active_page (0);\r
+ clear_vga_screen (c_BLACK);\r
+\r
+ print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK);\r
+\r
+ draw_line (10, 18, 350, 18, c_YELLOW);\r
+ print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK);\r
+ print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK);\r
+ print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK);\r
+ print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK);\r
+\r
+ print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK);\r
+ print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK);\r
+ print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK);\r
+\r
+ print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK);\r
+ print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK);\r
+ print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK);\r
+\r
+ print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK);\r
+ print_str (" SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK);\r
+ print_str (" SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK);\r
+ print_str (" PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK);\r
+ print_str (" COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK);\r
+\r
+ for (x = 0; x <=60; x++)\r
+ {\r
+ set_dac_register (50 + x, 3 + x, 0, 60 - x);\r
+ set_dac_register (150 + x, 3 + x, 0, 60 - x);\r
+ }\r
+\r
+ c = 0;\r
+ dc = 1;\r
+ for (x = 0; x <= (Screen_X / 2); x++)\r
+ {\r
+ draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50);\r
+ draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50);\r
+ c+= dc;\r
+ if ((c == 0) || (c == 60) ) { dc = -dc;}\r
+ }\r
+\r
+ tprint_str ("Press <ANY KEY> to Continue", 99, 72, 190, c_bWHITE);\r
+ tprint_str ("< > = Faster < > = Slower", 99, 72, 204, c_bGREEN);\r
+ tprint_str ("< > = Fewer Shapes < > = More Shapes", 99, 32, 218, c_bCYAN);\r
+\r
+ tgprintc (43, 80, 204, c_YELLOW);\r
+ tgprintc (45, 200, 204, c_YELLOW);\r
+\r
+ tgprintc (25, 40, 218, c_YELLOW);\r
+ tgprintc (24, 200, 218, c_YELLOW);\r
+\r
+ copy_page (0, 1);\r
+ copy_page (0, 2);\r
+\r
+ for (x = 0; x < MAX_SPRITES; x++)\r
+ {\r
+ do {\r
+ Obj[x].X_Dir = random_int(7) - 3;\r
+ Obj[x].Y_Dir = random_int(7) - 3;\r
+ } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+\r
+ Obj[x].Shape = x % MAX_SHAPES;\r
+\r
+ Sprite_X = Img[Obj[x].Shape].X_Width;\r
+ Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+ Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2);\r
+ Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2);\r
+\r
+ Obj[x].Last_X[0] = Obj[x].X_pos;\r
+ Obj[x].Last_X[1] = Obj[x].X_pos;\r
+ Obj[x].Last_Y[0] = Obj[x].Y_pos;\r
+ Obj[x].Last_Y[1] = Obj[x].Y_pos;\r
+\r
+ }\r
+\r
+ Current_Page = 0;\r
+\r
+ View_X = 0;\r
+ View_Y = 0;\r
+ View_Max = 3;\r
+ View_Cnt = 0;\r
+ View_XD = 1;\r
+ View_YD = 1;\r
+\r
+ Set_Color = 3;\r
+ S_Dir = 1;\r
+ Prev_Color = 0;\r
+ P_Dir = 1;\r
+\r
+ Visible_Objects = MAX_SPRITES / 2;\r
+ Last_Objects[0] = 0;\r
+ Last_Objects[1] = 0;\r
+\r
+ while (Demo_Running)\r
+ {\r
+\r
+ set_active_page (Current_Page);\r
+\r
+ /* Erase Old Images */\r
+\r
+ for (x = 0; x <= Last_Objects[Current_Page]; x++)\r
+ {\r
+ z = 2;\r
+ y = Obj[x].Shape;\r
+ x1 = Obj[x].Last_X[Current_Page];\r
+ y1 = Obj[x].Last_Y[Current_Page];\r
+ x2 = x1 + Img[y].X_Width -1;\r
+ y2 = y1 + Img[y].Y_Width -1;\r
+\r
+ x1 = x1 & 0xfffc;\r
+ x2 = x2 | 0x0003;\r
+\r
+ copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1);\r
+ }\r
+\r
+ /* Draw new images */\r
+\r
+ for (x = 0; x <= Visible_Objects; x++)\r
+ {\r
+ Sprite_X = Img[Obj[x].Shape].X_Width;\r
+ Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+ /* Move Sprite */\r
+\r
+ do\r
+ {\r
+ redo = False;\r
+ New_X = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+ if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) )\r
+ {\r
+ Obj[x].X_Dir = -Obj[x].X_Dir;\r
+ if (random_int(20) == 1)\r
+ {\r
+ do\r
+ {\r
+ Obj[x].X_Dir = random_int(7) - 3;\r
+ Obj[x].Y_Dir = random_int(7) - 3;\r
+ } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+ redo = True;\r
+ }\r
+ }\r
+ } while (redo);\r
+ Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+\r
+ do\r
+ {\r
+ redo = False;\r
+ New_Y = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+ if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) )\r
+ {\r
+ Obj[x].Y_Dir = -Obj[x].Y_Dir;\r
+ if (random_int(20) == 1)\r
+ {\r
+ do\r
+ {\r
+ Obj[x].X_Dir = random_int(7) - 3;\r
+ Obj[x].Y_Dir = random_int(7) - 3;\r
+ } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+ redo = True;\r
+ }\r
+ }\r
+ } while (redo);\r
+\r
+ Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+ /* Draw Sprite */\r
+\r
+ tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y);\r
+\r
+ Obj[x].Last_X[Current_Page] = Obj[x].X_pos;\r
+ Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos;\r
+\r
+ }\r
+\r
+ Last_Objects[Current_Page] = Visible_Objects;\r
+\r
+\r
+ /* Pan Screen Back & Forth */\r
+\r
+ View_Cnt++;\r
+ if (View_Cnt >= View_Max)\r
+ {\r
+ View_X+= View_XD;\r
+ if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;}\r
+ if (View_XD < 0)\r
+ {\r
+ View_Y+= View_YD;\r
+ if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;}\r
+ }\r
+\r
+ set_window (Current_Page, View_X, View_Y);\r
+\r
+ View_Cnt = 0;\r
+ }\r
+ else\r
+ {\r
+ set_display_page (Current_Page);\r
+ }\r
+\r
+ /* Cycle Colors */\r
+\r
+ set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+ set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color);\r
+\r
+ set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+ set_dac_register (150 + Set_Color, 63, 63, Set_Color);\r
+\r
+ Set_Color+= S_Dir;\r
+ if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;}\r
+\r
+ Prev_Color+= P_Dir;\r
+ if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;}\r
+\r
+ /* Check for Keystroke */\r
+\r
+ Current_Page = Current_Page ^ 0x01;\r
+\r
+ code = scan_keyboard ();\r
+\r
+ if (code == Ky_ESC) {Demo_Running = False;}\r
+\r
+ if (code == Ky_Plus)\r
+ {\r
+ if (View_Max < 12) {View_Max++;}\r
+ }\r
+\r
+ if (code == Ky_Minus)\r
+ {\r
+ if (View_Max > 1) {View_Max--;}\r
+ if (View_Cnt >= View_Max) {View_Cnt = 0;}\r
+ }\r
+\r
+ if (code == Ky_Up)\r
+ {\r
+ if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;}\r
+ }\r
+\r
+ if (code == Ky_Down)\r
+ {\r
+ if (Visible_Objects > 0) {Visible_Objects--;}\r
+ }\r
+\r
+ }\r
+\r
+}\r