From 4423bda56aab2192f037bec035a3412153b2b3a7 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Thu, 22 Sep 2016 13:29:56 -0500 Subject: [PATCH] 16_pm worked on~ --- DEBUG.16W | 16 +- MMDUMP.16W | Bin 66 -> 22 bytes bcexmm.dsk | Bin 461 -> 762 bytes bcexmm.exe | Bin 66142 -> 0 bytes bcexmm.prj | Bin 7365 -> 6774 bytes src/0.c | 588 +++---- src/16.ses | 16 +- src/_scroll.c | 788 +++++----- src/bakapi.c | 628 ++++---- src/bakapi.h | 62 +- src/emmtest.c | 150 +- src/emsdump.c | 116 +- src/emstest.c | 10 +- src/exmmtest.c | 3 +- src/lib/16_dbg.c | 152 +- src/lib/16_dbg.h | 50 +- src/lib/16_hc.c | 1074 ++++++------- src/lib/16_hc.h | 108 +- src/lib/16_head.h | 2 + src/lib/16_map.c | 312 ++-- src/lib/16_mm.c | 3629 ++++++++++++++++++++++---------------------- src/lib/16_mm.h | 432 +++--- src/lib/16_pm.c | 87 +- src/lib/16_sprit.c | 236 +-- src/lib/16_sprit.h | 148 +- src/lib/16_vrs.c | 278 ++-- src/lib/16_vrs.h | 156 +- src/lib/_croll16.c | 1850 +++++++++++----------- src/lib/bakapee.c | 556 +++---- src/lib/ems.c | 10 +- src/lib/ems.h | 40 +- src/lib/mapread.c | 490 +++--- src/lib/midi.c | 1460 +++++++++--------- src/lib/midi.h | 164 +- src/lib/modex16.h | 384 ++--- src/lib/scroll16.c | 1832 +++++++++++----------- src/lib/scroll16.h | 190 +-- src/lib/xms.c | 374 ++--- src/lib/xms.h | 56 +- src/lib/zcroll16.c | 720 ++++----- src/lib/zcroll16.h | 232 +-- src/midi.c | 1740 ++++++++++----------- src/miditest.c | 224 +-- src/scroll.c | 736 ++++----- src/testemm.c | 550 +++---- src/testemm0.c | 552 +++---- src/testsnd.c | 900 +++++------ src/tesuto.c | 688 ++++----- src/tesuto.h | 40 +- src/tsthimem.c | 590 +++---- src/vrstest.c | 348 ++--- 51 files changed, 11873 insertions(+), 11894 deletions(-) delete mode 100755 bcexmm.exe diff --git a/DEBUG.16W b/DEBUG.16W index 5fb5e282..e42fdf08 100755 --- a/DEBUG.16W +++ b/DEBUG.16W @@ -1,12 +1,8 @@ -Seg:0 Size:8568 Owner:0xfe7e +Seg:0 Size:8601 Owner:0x0 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++0 -Seg:2178 Size:256 Owner:0x5434 +Seg:2199 Size:256 Owner:0x5424 ++++ -Seg:2278 Size:17 Owner:0x9480 -+ -Seg:27ec Size:44 Owner:0x0 -++0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Seg:b818 Size:10216 Owner:0x0 -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Seg:e000 Size:8191 Owner:0x0 -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \ No newline at end of file +Seg:280e Size:44 Owner:0x0 ++0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Seg:b83a Size:18373 Owner:0x0 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \ No newline at end of file diff --git a/MMDUMP.16W b/MMDUMP.16W index 4bf1c809f6d6b2988d2b2f86a1bfb477c54c02e3..86d239b00841ce04466efae3ed916a82d1f0cd6a 100755 GIT binary patch literal 22 dcmXr0FfcGmu`)F=GEvabWzbZxRWRV?0suDL1PTBE literal 66 zcmXr0FfcGmu`)F=Hc`;fWzbZxRWRV?GJuF$nphYBMFo*WO_HtBQq5C=q7_h40KNAO AMF0Q* diff --git a/bcexmm.dsk b/bcexmm.dsk index b1f56e47ef6d21ac09a1dde6261b3b34e374cad8..81894b494a595c5452c0980cd68b4b69c5f98441 100755 GIT binary patch delta 159 zcmX@h{EKyhf_w_YVg^m_)uP$5h#r$9N-HU zW&sILR$(-rs30d@#UR4K#K6M91r%dr(9&}b2mp}`Ul{jpbj)Jp4Pjs~0!jhFWVIKQ k`56^hfTnl=4QB_L@|DqK@;XN8$?F-#I5>d(|Nj{n0QD;)F8}}l delta 30 mcmeyxdX{;D!o=fp%wHHYH!)^0GJj>1ntYH+n&tn01_l7N5eoYN diff --git a/bcexmm.exe b/bcexmm.exe deleted file mode 100755 index a86e8183762894315e6a60343929f1191e77a859..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66142 zcmeFa3wTpi);GRSa&l=>($JPtZfOu3gj!Uppp;7mO?5^}1T7$1EKn{AEv88;3cXBJ zNKdJkaYkjFSMf5A*B8dB1>eC+YpXJhTxJx(Q3f1MN!3olwv>?b{nkDwmmSyb9P1SPPf~ zNCbS!I<&6=?gy*_xB!;|(g3G4Ht`tX&w%#M-6 zU=zOw1OT4`+5k;}mjF)z9s|???f~2fm;e|82s4}53HS`~Az&xqS->vn zvqdwYM>AXe67VLV4zL!m2;c-<4md3!9`F(1_khiSazGIv1)vA~mCY7^3Gf4!0d4|Z z3%C@J0Z0MV8)l1l18xIcte-84fLF!Y;&TbJ#RkB9z!ZQTpa*^fNg*W0E+=9 z)3SB<0Wts&4gp^P|CO4pTLS1Ck*zxf*ag@Q_!;1KfD>>rU?|}G;n}*QfIWaW0gnJS z0M-JQ0_Fqq0Xv3e>wXKk5|9Z<2lRoir6a*}z(l}Kd$w*kD>I}4k^!4FjI{##0qI)C zW&lQsj2Qvlz&`^#2G|U^2e2A&JKzG%1x6cSIN-33u~z`y0F$1vv4EEW2LPV|$_ywE z@C~3BFy6?R3s3~O3-A!&KL9TQ-T{0B2m;OktO<qqBL3_}jJ*Yz0QfDQ ze=`np2`C@W*c`wpz;l2-fNnr)7Go0uvjC-ldcX@8gWrHKU`#e+!vRH?qP$BWlYj(( z2)JtkV@nY?1K_y~eFwM-@C@Juz+Ql6BGLhF&SC5Zz{9}DUk-i)-p2Dy_}v2d5+Gf{ z*fPKjz)(OEVBIA28Q?X*S->H{M}X0jkp^%xpc?T1KL0mzVCMzK3I4SEG>w<;9W71J zFv)f?YdHMu23D`Xm-%g#%s=5l7MLY$tz-?&InB}`sc(l|9qNAV_^eruD|OzUn!Po> zpZYCcwnM`X9{06aeaE}}wsoxjK-P(OE-*H!7^ zuI=a)q%X9G{kDy$OJZB^Wm$(Bnj3#IfA8qU2fyxbI3Rs}rU`{K^K8E9joQ?T{F><- znAV+FX{ecA#cb}$O~Qh=HEi!__xQ#YlC4n-%-(q2+X4j*&3pDib{&em9uFo;i9s_O z6_*Q*Z0~S?S}pTie9YABNo>kP3*TPL9Bl?6=bH%)`ujAyF4etroi4DG$&<ITf;rw0K@#G(|#YKDeNS%#0)H%hyqjy-?&P!N_QLr_!EB21| z+ZKVhx3MOXKP<*WF>BKChoyKZVNH7eumTUOSQE>v|FGfk&LzU$(HSka2@SUUG$<(Z zy|hJWNQSLR1iDy3bwHOA+N1}zg0MYJOprd2KF|HaGt5ylL-tr4b#sJ?-{ihuE=uo8 z2YoI2;PKo~JR_vTh^Ds7dXK>&FV+}>tqyrUetzH5$kZZ+@*)x)SFRA;dPm&~K`G#G zKT<%uQb2P{V;=9ImK`>>a~k7q2%M0cw2aud3U-68`DUrpMm>GVH~kT2_v)Gi791(r z9%0)x2aiimqg1H(Z~P_mKlUh-^^dTe=8W6+Adjz8RI*L{a_?}aPZj)yA%8&_{h7r3 z)6u41%Y?@9dq>wyPZgLaq1GAN#(ah0bW|o4hFy{~WN>8ZYnfw2nvZ2jf8)g}W!f5N zO>BOzP!B%3O|3;Hhd(K&IVidUZ)lX-qsg`jNG27SD5a>Rd6?2D2{MS%LIsy9jOHHi z6~R%8Sj(12m?P3mHR!2FnSv23nD=Aw=+|duTe=3w*|Ye1=B%$u&%8rWkWsdc)W|lw zMy?PM<3GDFqv*EXdKP78PP5A;SLg%l<#>|8T^C{~Vkt!^v>`-|2+Wo<)IbWMw1FuI zT4=d3=YwDxes-XLEcB~kK|TFy+0BLXrB3Oz^$Umu?HOVpwg@%M8 zDurTU;6+(#i$*9C(8R8hiXiWgWY#c6UVNPw6wX&7^{rJVsmSO%b7AGJHD@&L`I1xV z;|<9*kVj9VqfM8ckM2B#?%Z7Q`El#RSqFMgKHPh9(xz1BaZ|919tk%$drxgH_`LU1 z?H@x0lj_8aP359EC8*Un#g~qKyN$hMAPI7sG8PwMKtfTD7iYP`2)Tv4H<_4g8~zu& z0yjg5s6X8FQ!%JVUWClWz)6%VOc-#d4Zc?6Tvy;W+14~ijD?@N7~yIo zZrg352KYKLanlTkoM=N%bIt+R+}0w|;hQ02zQZ`uVysbsU~otVS75p9FEsg`#0(?zeeMz zzX==)0o6COK$O%eV~36fuaQ2D^guhRf$I70&Q#WW0{Vt@sA0FGZR156Sq;-&sBsO9 zUf}R=oTRy0>A|ZkjoQj>3jXv(n#XC;xZ&(V2vMTi#SVu?KHJ1JF6Fsb@6a%fhp!!dj-)ZVq zSq|Fk-fd)&X7_9yDu|v03ewqGP$VQ?1Z|C1s|$|0jEEsb*R=&StZw(8tPdOo^1xB? zp|PoXV_%~BYCC_)A_KJD`7LAZ&Q2G;PQU>C$^0F%Jh8d^wch>LFK(H%NtYik==A2y zyK%05^8C&({cYw7T4YtFLDK3_pt2!2H9H$XMP zRzi=}RDGZ2(QYdIKG^769{wUIBF_GXF8CXYo!#pUYnXQ&!i;YS!ACmAX{9Q0lBDxF zMNQ3FO?k4pd7U296w32E``*xYl*%<{MeiqmXHWROj$(Q!|L_e_cJ_4KBtLTTrH><1 z<*+w28=ZaT=JoscAC>lDg*vL;Ejar+Ci1+$+UV@TsC*+nuBRhSMjh6U61lb@%mh&S zUB^QCEo0F1mI+{ey+d=j&G|jsRCp%mz^1}}h037yEmNDbUqGl5@I-#Tze0~jS(!&S zNg9I3Dsgkw+vu)j^8v5LSJlJ3iIduNSUiHMs8O8jN}FHT{cZ1>J#NA*mMvFBSD+ibR#ubj+JlxBN^^sLVTvQdeWR zbVCywQ4_k`qpJxm@D2w1^M3kMUum~y14S~XE$9XzkjKQJew#f|8Tx7Nr`0_O%3~h$ zwo3!cLv_wGf!jk;VK>MeoAqJVVMm=fHQQsHYWIj!v%Ch!D}k#+*Z*|mhsO;_KPhzV zG|=R%PaUsBMxQn?E_AHRe55Kt+Jib$kfdXN2t0%UMR?v9QhDCwV&k2iTIaV8zYdWQ zDnow0qg}^Xhdm@!bTvTRt_p3-4E*5?jdO2rO;x9BgEr81#^9?u0THBGO)ELSRhQ>P z_B+#)rmsyen1+}yFyC%oVP0+CXZnS?++1nC*ZjTt@x*HrOA09`P3KZs`0!(eB=V6q6@b3@L4|h*e%x*V4$Orxx)citszb zHmN{7ehU5%V?zH$biGWCNSE!zwMYy(&S)L zd%wVR1-UgcMf+<^e%%@{vbq+r3-!0ycry+yxY>5&4mcn_U04%>m0A-@@+{nI4c;|X zgDF7k9p-9c!}nUJ4#yGE1{wCz6Wu|y0Hym!TX_#-i z298<7gnHZ9l;D;1hbH9e5jkY5kxh7ZY>JJ{=4Z&?k(Cl0GeJVe3GGM#-*LNstnxFC zekj3QN?alOTE&)z!?p&!hP4CWF4m(kUgrb{ug>e(ip>DML%@DT{kz(Im>QLEgTrqz zvLM_P7BVIRH!?$gvqOty*1OgQKz0c z>VcqP<5C)qw18eBv}MB9aVZ!~qw5bo+262l5~ZJ1kF51+B5OGKYo3QPxA2Tq0>zS^ zS~wp;St*zW;SWecgT|(Kb%E_+(3vE21}w(J=;9bS;R^g-3s%5{@ucpwvaEeM%{3nv6h_XCtA*v z^Tue-D^a62eS%~eJ0Lq4O4;Yl?LCC8mz*Q0Z4~9Xg;%GY8Qe=HONYmS+1N}b4=O5! zfJlcqmybjU04H(|U>yi108^F(>3#EuDtA0Zx)kO+z}#2&?(UMkxn$BEJZ3t^MF)Jd z13?EI@FYuz8xCKE%F0JdX?m7>(AyPo$ia-j@5902feJY|1oQ;0m8Sw@!jjF%NkIdm ze4aN!nv|VVi0?~M3M~P*jJ80N)GTVrXxOc{&6CiE&`;hGnbZr#>*VvOa&mohUPE*J zp}dAeIWp9u4{J{|YlU_Pv+n;Z{X6+Qxj8DV_02kFrG)fzD0q<9X$hP;OY9;hPRPYz z@mwpN(e^d8OMlPma`>^^;2>`4T_lgN6%T6nN5mT5NI!%(sKbwuNhd9VZB&%>G4Bv1 zz4p*N8a-DEkvce=gL=+mawNcQp|Ti4k)1N(*-KL3lA1!S_smdvp2vAUCBk!*EMbQ( z_kFje(jXl~ZNbrjnR0Ms;N5U==v$po5ctJ53@U_!(A<;2lWwm6A!aJxGhT^fA(C)9yuASD2-P zc*w$o)Lp2gl2J6&iN7a6|A0y$d(BcC$_PAb(gmMTlEAmFZBaBSxWpap`puYJ;6{aK zh^th}q_0+*wvjou-p`~0qAsxYyGlnS0$I0ijznzw&OJ!+#RLY)d?qI2j(oE;LV><-D|bgCB82jYFTQoZs6>DYXp(*?8vXvlKDi<+SA+sCEF+#x z5)3eBA30PM>Q&D&>{qg?Lrhhkq%@^yr4^Ee3PisJCaRQ?p6Rw$>U~uqYlYEQ8nXI| z!myk|UB2aE89rxdPu$NO&zzd+i8|&2+ zodw#MuhkN9{rfsCkrvxF7j*jzLiL5=HfQ(EZO)T>F>`Nno@#e~f7_m^neHJ|9hHM& zzfXc!<3YW@ps(H8f7_n-K;PxENB>@hQ4*zFHPQ{Dbdz3MZ<0L541-)0dh*Fa8)B^w ziVt3c-^2&6F+O;W<-uzbeajLB|9X@ECcXa#(SNJPFJ^f3SPI#R1&Y-{OjG*P_Fkc> z@tQhVYUIVnj9sC(pZF{2 zQI@6t;5d{Km&wpgy{Dfa2>*R9YzQhCX2fpyFnsW$s3en+KuGJEWnc!sib440?+-Y63T%qDTMGusX#|K{0MI-1a;8 zY>f!#IzFc*G0N8}F>pwP)r8qbA!+MgF&8f8h{_6w6Icz-lQ;&hkYnZ#r8CB*JB4&h z6@kTEiwQ7zv#;tDyc=Lnh|I8lS0GOYp~k?=Covyjze?|rCi|Rv4Y`LrqmU%5rb~z8 zzwR@bV@RG5SbvfdLu*80lSXQvgPwg3J`>*P#V6zKU8Or|+jRmR5#3fK4*KN^0Y)2nT`*J_6%+5VsIWG5$>df5k z%F$O9ij^aCE5z!daC)Se<*FoePnFqMC9k_I4RzO0xJYgdP^2VRE9kgW z-Ic1F4yV9!3rxqlQd3<)VqJy4uFx3h?&8BR5sJx!`c&P6`ZPeg4u-=o?EXo^b^hri zb)g2FOW0MzCVuI7C9nRyjUWG9n&f3pC!|?97cjU%U&*BK_G)r`A9vUMy&5xswk0nU zYi}s4&wab}wLT-waO3qSpPShHQo~<1c5nPtYLWKM3XEcvX18EekU{&oF_n52`!e;VtGpEwl!JzY#G~X)jf+-2#!>m{FG7I_!B6( z4Nh#{x%mRGhmF#Hd;w<4!uiCK99b_>7KodMcf2hI0vr$PTC#u z8w9?RV>4|tX4N>aHw>6;GWZ5v{qybVhs;g!TX(OqeQupR-;6h7s$dx7lZQgy~ zwQwQD)KrUXJ&t1Ji+ndLQ-<4+!rSv)b?WN2K-DR_tizws}%069{1%uhHR~qp@}@khy`P=!&X3-XzRK59WN3a{#?~;apdf zW~TChH4&!4EeqXAO>8FOU|W%@P5Zp>9DO3D-bJ;Z9CbF5CN*lIQf+H#>LIHI*E zL}X~OqYW*SI`yUS!iD)hXDF5X61|^G?J*T4vexIwtwo8lGtp6(RQK*wx7WB+V7p+; zWz?Lm^y+qMv_WId>0+;WrzYW@8n%lp+MH%=bRZY9AY;wxEMh?-oQ7H6(KV+%@b#Tu z;vI@`uU<*zI~MYND85r8?9wtM@ak(nWO>0cl#I}t;1FfS+WNURlQo<7NxNTUH6E?+ zk9kUXyBKCMv#lmD7s05z!k$u7DLyL=WeadN`iT@P^4S zpP;*$opF2L2jRprQp!#FqN#a9DxqACxpe0oz*t*FVUhl?`2r)xlR!bWbI|*=kxLI; z6rwJ|s3VrNfAq;mW~@EPhk>VtTpL=rF!(g(RE9$#lvl3SD+dUoM}=a2O+C$rq78yV z{mZ8%Y(F$=chY7xHl}aM-RC|OO{eG7LmiG7aRV&Hz~k7lC*u?|s**BYF)$TQDryip zDjp9<#8H{Mn?_v%#aKDkK&sMar^OW*txiUuTb+-nuV}7GbVzeBw34ot{vJ%CK*{h# z&hD(;()%=vh{U)&=AFf3FeIh5B`cDTNLgaLqXC(17tpw4xIpK0~vevLkf6FD!VWGV7_DDoQgiFhhP~oYOR{5YBMD zqjrU6aaftw&Y3Y_c2KjU5;5s>NRY2z_L|@jfD){F72qJ``gO#u5VZ)X^oTU|{{?xK zZlDs3RD!nSx6!#y+fmPWV!p4$&mzz{2xjyw#Tg7$%Hj)rQ7Nz=YCIK4J_^t6=tZS# z<5N~sN=h?`DvkItE|;ABP^XnHP&gMD8-4=28-okOq#P4314F{#RA?9kD=J&+v=^CR zTC4Q5Tk6T&2KqCxQsWRNHugP3=#=Fbt}-o1mkpyoiP#n!5jqjefZ zcuqL#blB`XKIN$QZ_=lZnyaRH|6;>V*~#BzY~15LkT12@?~cuEsbmhtYv>k=;ZU|0xT5TPorszFL|md5kd->vJG(gRTymzI0n?gQ`5Fx{K-CS6E;p& zH4J{x<;lZP|KrZh!S9vzLDm7<06+vkJ4FLAVzGdfs>I$l*6g(mm~y+gV5p;Ge6O!n zkA6ow0W!!Pd2p|cnSN9&wZB*+cnxIK21Xx-%SiTKtQ6#%eoU+J3_>~?XS)L8;f_H< zZ+i{nn@V&-2n7bIYSA+TJGrjlXT5D*%wtp7NwW*gI~-HMUjG3$A7fP8yD&H;!t8LM zKg?sRpb%i#sg!Pq2SiWd>zAVh%Jt}X3m0N0dl40nsr@6fqrw``m`s@svcrvsWfzoF zy4Bx7=7T0gV@qj%U{@GB$~b44L2dR7 zF}csYZ?2M`981{25pKaE_C-Wh^FQ_`7#9=J=!vRr0?u{yzKcC}(>6`-yCU;ywlTO! z^xL~GC@`7cZJb695<55tuS2HXG>FwmMdAI&6)n_{;g2hSsgPTmy`hR}J8ltbrjOB?JSO@X1ZC`cK^b-6;jkXAWooe}Oq$%~LdV6}95zzk zhZwXc{1P*GeNd!=hY6#_Re&-HowbbSXj(c=q~7fLo|pCpC4$n{d&uGc@5y@`_SOLM zUSd)5?okTVcKnic6v-VAVe&Pef6g5dKj$iGNUy!(5M+dx?;T5dl@)Cy2@+-{ohv%q zzfR}x@aCa6Lx~%sgX$0~=TSAZgLoiio6tca3lCSO{SB@)GuC%}eNksf&coiUHN=YO$LUm%t zpU~O=8r9eR2-TnHB2?F~4(t@(O9gZBog2(2TsCa5LtvxBDAEr@`Bo- zIv36s-a*=qTf<8C{4SUg*T9G-@ilh%z%`7#%Q0_+m3c??T&ZiLVqwu__0#BFTBoH$ zAj%_c?(@kb@cLO;I9!t%9SNiJtKj0NaJA^M{wc9qgsOrWx85KN+61)})@P-O+q=Po z9lM$2Ow606VeS-|M3GsNYcn|g2=UvBAsKVMp{~9^qe++s&z~s|OFZVm)lxyY6&~TR z^mzzJ`G$Kgg&Rco(y^1ljAP&F=g~mh>^z%>36WI5=c&j=1{`8K`%>;1uO?U@yojgi z{d7dL>qaF}$)AuYj>g&tp>b&zWu19Uoy|KeGE}?h@>*q)Dy*bhDF(OK?2|Rs`r5Eu zUBOM)KJ2_Za2PA8wn~2`%*A%SLkC+c)i?b@gbqUJg&MEEU4J1$sTi8=(ui=yh(_no zFdP3pm*4Xl>NosVF|2(nG$$2%TzLlpmN5(YELV98v~^s12uv__1&9f>q?0 zNI`hh8#&}5)}v>mR>-gZJaDNyUqTpUfpRrnqzgk(SEWxTl1HigHT`CLr)1|Te*Ww9R1>Z5A@tiIm~Fu7oTnX|48S)(;Knv%DCbDl zKHm{$KC=EAcnA7xn0qRZsR-p9$m+uT7lmnDgIh~9z{B3=N#^zqSz9-v(kxVZE#<)e z7c@a%RX@X2c(**T5UI`FTybF`{Jn0RBu0})M~kzdIL~&Jq}`p>Mh6BHW2#%!wut8; zkb0Zd)LftMA+rH;>3q=b0ISMMElJFwVU!w)Y1P)3meE)SvL-gv4 zM?9YJ5()du<-$v<)G77A*Qty+QpO?QIE(?`6}N8G;b5^fO);o14kX%W`o}Qsacv3Z z;MGm?)8hfG|1}m&5fbBfcAK52Jjty^-7x;)o6F~~3E=e@wO9-dJb-Dnofd&cES2t? z4!^r+sI4iHxwZ_+rjkX-g4$<%{HO!C=~k9?y8AVc;T-`d2pXE_z%K3cWZIf+v7FJ7 zyN?cK;7o^Fj;(1d56RhymtUQ?_lThqnyDfmcth9P=)k**shC&azgWCAzk z{(u}BIaL@rr_9bC?+94H(Zttdg~Q;`?vD(vQy2}9?!&OFx^ZfFS2wNo61-Xk-TOOi z4TnxXpYp-U=Q5P`$QAu^MW3zdax8%lAZ1~QMar9b-ts5|Qf5aCrx(te;GY}i@pd6H;W>-&m zjAs#Xw+F>Uq-e@{x-I0d>X$w-@AG807WMPB%GsZX$(^`*nn=f?4fGrxJbj>t^Li+0 zX|NR45R7poy+VUPxV7%b$8u~E@@4>e*=)t!kSc>n&;7ZI#r{I@ot|lwC z-*HwLz2JgN0hUoBD58C9uO9QJCO9ohW^kgC3-5&DJU=9g4(8x(r*rdYgK!k9O@naP zIeV2wPj>c21-C(k zuh2{)rBShKNy0bc-FhxrRbvoOx}_20V~_`4SVBzLF>o3qz1T{DL_~Ziau*VnzZHk; za4Jz5a|$C`tMN9KQL4~GO^xbG^@lR>2oIe{H==ozjAK?F961hQQrF;wf|4CPHao-K zw^h|=aYXll1)(%X8K9QHy>!qoqCI(U<5PXv5I#KAP|UQW)ZzRvE(}0&s?0whreVGa z%{3uj!qhe(3h#9frFpY3^sLBFTL!U}5sK`5Z7E6RMJc+^mH`Em#%ml<@VOpPxO=Co z9a0n2?l0xDiwBBScuSOazK-nn9K!)FEGHf~7ipr7)C+QfQ8Jtq z!c84?cplCi-YL!=UsWGoP2#6D=Gj~k+JpI0Q4j3}qCil{NkT0>5tR&P73%6iofOs| zd`Q{rkn$Ir1f zowyc?&oXeLa`V;JGzO$83MkZykge&m=(8T>gwXh_qajL)xzXoHilxyIyig;vnkt!9 zOtLk3qrsw5KQBf32abV^k2A(NqHg`&B2XHc%m21JV~~u=2!{ALAIv$*rToK zkFf_{de|w0d<`zV2+^4wu%9=0%Qv_7wWZHTBtd(3j(*K_n7SQP8AV5TrHwfW>TP z{KM+_hnEFpd@35kEgoe!+zN5Gkt#B901ZdLfC2PkbO2EfWdOZ+&H&vcgybuRy({w~mu3y{f0Hl*WaS<{s68p`LLnYHFck z*8Y$RzLypw1Kw;DPIX5dFJVjIcmH~||5oF%+o?0m0U6MSExLC>iq(bn223Ge(3T5u zOPsG2G%93<5HpZX_v7_~f00dC+KEl^#sb$lU@PcI>*U&U?F=TklO2*Fn+dpQsG{@SX3nXP|4);;|2v{G}bRG3`5yHAUi1Z!SSGtQz4 zP$_mKvV%Af4qv9PR4?F?ugH_rMA7t=NO7h}92Q&>FHnwEQt^htKZYh~offP&zA7uL zzHU8+pQWojk1Y49z6NK1LlJWH)Lrb{F5I`*n}GM4_x;svDjzgSny=aS*K!??G4^;w z|H0trj!i@IuWI*x9K6L>Y7u-zR<>P;FX@&0-uL3o>!CrsMb5J)z2Xa7-G=&4uWtDC zvYzdNTF@aX$R|_G?wJj{FO#Xb^4)TQb=~jl_ca_+JptU#NR9N6g>+L(q^G+5g=|UfY1wLn&hR)A{54BaH7ns+J*#Ud97+!@R>`?t(nKCteLe^__$<{wmz>o`o>f2ryq)U1I`qNx|g?O)<_+T;jZtvIwE z5xt!-M&~MA_3b7pbIsjy8Qu$|duFswJzhg0sXV5I&y_U0Z=t&=8wbSpelEJ2IMKx( znX~T)p|oO1hFo~F(xieespwn9`pn($-Vd*Hi+c|gd~GHCdi}Z1WbaR4<4ewD@R$m+ z#1)TLBBn1sh6aTa-2a2%;Kk5y;jS3Pvkiz>hnf`^8DK2rI{PY)45SQtK?)}A+!i1v z9JW*WM68pFPEq#Y!9Z4F_lTA_hAEa}Y{*;5gGfVO&9BU3ar`yK_?xI?<|7))Ge$Jt zD29I<^g-Ssf^heB!xn>jE)^w96@60GsRn0HLs9>$R~_VD^}qY-$(L#LrTV+} z2b6#HhlSk@hikvWjVBm%0NK)1Vb;80YEk1T7prr$;t z1Ds+b&H9luA5M(k142bo3i+*p*(XKA4*hJ8e7Q#qQdw z@cZWV$0MSlGWLBl92i*n^zZ{2U0d$KU4l?Ose~Uip4U~1x{%t86R4ML`7dmy;b1e~ zMAN>Xa@b!K#tS(-Ft;#VZC#IZs-g0PEuW9TU6#$BuOc<`SI?*%)s^v|xT_I-SA;LN zO{2zM#ADUhfwn}`lG&>$D$wEwCOy}_&!Zur&`tgu>~)>%!r9ncf26*-;ZQ@%jd1Pc z;B5Mwg>Wmwt-i~|A|dpy<#V(x3?-eet$}u9+42+IA&G4*y3wMU7KtCahkm4No+Ii> zy54tMtQ<`BS*bqMkE^>*K1Tt`F#;%PAOY6@IRR95>cFzGx3()SQor^Gl_mdsl?@wM zS^R2iRr)6guQnf%aD(FX4?q4_hdX&5e=(7HzJ#fYOE7+gWs){c6#p7o@OUwXd**Nl z9k=?ou}w~S6Sm5i!|vy9)-a}6c!|5QLSlkH#pRH!esaOe(37O1Ze_Pgxd13}-j>p)VDpcYW`NPH!F^k;8LD@FHoY+!6aEX8#_~aG zc--9F=KKcE+DNAq9PVSlA^6_vkS;|;L%RDnE2l@LaHQg?f{NWvXSCfIeW4E*_ za;Of39NavL5k>CNEuUx!*95c3Ipx87HQZ+oRt#@?nl4Z{Uoi-c+0)Ud&Y`6;tcUBF+1wVEkj{DN8%1e zod0r<^|#=9Ga$CwV>s28-ejPM!Nz9KpvLLI$m+r}N>l!V4NL3$G2rS=Wdg==wI1x0Uli6EtpGeikej(ENV2`3vM-)oh2EH~%a( ze*tfP(Qu{tc(OJ9BEI=&BU^Ad!&}uSuHOPCJh9!f%4*rroURp@p}1)Ofq2b_Ze-RQUo-P5VtK=%_0-Os80rV#%8usFiE#So_Zn7e|-BMAbT+bcf+OjABJ!s~GY>TmhTIV)K4-rM3Wy?0 zBXQ?VW%MMcuhWXdGE@@1L?LawGS4ABHVH}$c`#vA(ZTp=C^WUaJcs|W>3P9XAP=Q0 z>69IpxU=*K!0XV+DHeF4MV)U7jX^oy^_hcrq826I9J#cugziD;*|mvoKk3-3-RuXrlhS`TazZL!(n-& zjTg+NgJNOI7M86kEgD3J=%WvC_MMU|y5YNu1|i-Rec+owWZUSy3o!6GA83nBJ*-4E zwk|gEv;7K_rxKH=L=VOXaaw_M6zz0mfvMP2BDUce^A1+c z*;YwxQ;MIG=P;ubFWe^~Rtxq9&l<34*{fI$yd%lU@iODz8 zR6zS`YU{APQgn=bNC}FRP~^a7@pK>?o#UWw7@A2nbZD#wC;6g&D|K9vgtk64DN2wc zfI+Oh^wJTsc*oE$UOpP3thA9mG_*3w2)&t)k2pe=0x;0b*a6&OYq}@aX|bUMUxP9L z_$y`tHCLo>3c02j-qgCP>%$hUdM}T!niodK~ ze*_(@40pZu5URL_^K~XE@K`Q3Mmi10XUGx?zzN6g4TKNbRO~N%Te2hmoLnx_#KE37yTa|V} za3c)Afo5D`zpp67YD@c>h7gD{1bDl+h2iEjZpWU|B{8}_1Y=*jk8ktP*yNL9-(1|X zf`gtovPF|3><2C+{-Imaum?Z``ah!mX5?YGX9l5-(NH~<03*D_{ax}M#yh$qJ8TNM zeDyjnxjvBlKcco(Ioungme_)$zFaMKXo05CdEtC`Fy>pq<>(;dY80-b#DysrbGN&q z__o@tI&IOn>L$;YrTD8JkY*Td3w%f$y%h{^xnlONZnFfgqF3W{l|f($cyXc;vlKBD z%aw93{JEH1aqmeyH>S*=obtK3V z81g-c!4)h@tLMjfgrkLE0g)PweTisS+yK7L;p&p8Tu}?Tg^MOC$^kllGGM$~F9 zal9}iPe{%a#9zF9;F*F$*q*f=FJq!1{-`+=)d8(SW_4LnW^2A7&6R^7Uah4Z1C)~U zED-0EOXos^(-lV>76vyd*#BHXv8u6tLxaH{ZbXCms^cQKny~^JvYcP#Is@{Q57;xKi1pUW)_d7m0UW^Be+7UbAsORtt-vGv*%0wc=a zxtuxAdP}NIuCoW;=MTfVg{SblI}D+K;Ao+<>^e&X`0$#y=clc3WGZL7vxYiG+NdR9^N0W%!!0a*ekXt2Sij~U5alb}K&q}UIODHbR|S=-^W7$`>r`c668XNpK8 z->s+f(7CyVdM{oEj>{cm*MF}BLpY*E=}?ph?hmetw5h-F$Nw_czH_ygA5|iW9Cex@ z=0}A9>(M|ZGBSm7*I`V{j}Ael-K5O%Q8s_J@@2bxgb9o@*xBccD^8k=`$x{I42 zNSQpJY+&9QC>xM2xH)jLH6lL>HT-R0n&M(lPF(UF-a zYJkM+^_W~fP;A@C0FMdb)^T8c7H9pq*tAgF+03_PB3i$+@pJ)JvEG7cf6!greX#1G zi*K>uPrhNk>9|c)olDnMy| z*Mp+2;|KD-L;vtIII5?-e&6OdT{4w|sHp!t>olFD{Bc(~`P6QXRhc%R0yF_?Jk*Sc zfBJu1N0grHahWwa>bPF_7S5Tp;1)!vksZf1sEr(Pa4THLeU03>=z7})wYT>qmb>6E zmG^hX=q1O!?8Gj+Yo`mln<__Wk8@G(;q@O?>#lNkSG>==0*)ASz6FQgUS|+W?6uQw zMnRwNT>(m9?ryAJTj(9qtCFAqJjB$h*2JpPDZTOCE_b9i5)i_xRV?}eTdeW)-Ww}K zrI!c-4UiAQvJ7e?F)GXVs5Rs6Z*{|jZ&;|I)v-{O9(mV&5qc;FVnQWKpW$*69Abny8f(`bIRAg@->+^7yTMxpynSsUIg* zPRX8mr1~hH9zFJET(pZw`A=T3Pbp-N(={YV#_vVqfC-I7Ir$n(Eu8Z6fSyp?bzNA7SsX>e16`3A>+F(=A1FreR1g>3Byw?PnCa zk##g`v+v{Y+GwE%y`cQnlUME8xabxep9X~eTnYQNJ^K+JmW;4!C9Kj;TkA7*(S;FP zVb5U_y=@PL&yIyB#fRS-3m+06epf6!H9q|QSonZ)9*u=x9G|{97Ct;a{BSIMKzhAC zO8Bs*_ctI?D0R2m2;TOf1BgMkU#fLY>!b!1=^6gkGJR?3_FhuFRAU=FdES$8( zXgOEK!iU9&&y9r-NWU@`eocJ(S7PCJ#fOhFM(MdMKD;0ner0_41F`TC@!?xz;d$}l ze~pC?=&wNu(Rydar+3A|2hjg$EPP6Q`aj0P2c%D?7sUC=m>rq%=_kj+2lQ7-EPR06 zu8W0V5ns-0vGB?9;eU&T4~-8G#li>3!w7SfPHQCnf7;q@U)XwWNf~1^W@Ie3&(A2! z*qHHD##XAHGpV$ZjKGU~fg23v-0vTcrSg{|7QcvR)62S>dyiodm?m})e~ z!CECpExn(pelnL$$Xv#j7JKZ)tKB8V%huV;)|Ql-*zz)O=`#DRCU(Qs1^KMthIy{5 zZ@P}%npuwj^fMv$!&YO>U0G7RcEV+omc$SWT~_QVzU0obRpl#JRZUpC^ll}x> z>N5IWT2|^QDfN`w%a+?cD@*K31*S!&%yQFhCbrgHQeJK^E?sB8vt*s!Q)Z|1t4h5k zqfN}Tu6P~&tSu|U&p%2z?VtRZSZPVI(mFd^u3`+$hzoYah5wVq;)V~GyX=mVr5^ib zlk6pH)^Pro++8xke$&cT<#znP!&{CHwo`?Mow}&pzOKXrGXDJ%xQsRIkMIxaIDWl2xTEC^Z;~0%jNgNOp=@aK4iNc?m1` z6uUjsGVe}cWviD>%k(BN9+FjFvSM{f>9ow%UK0b3K%PhqL#k+e0vJOrxw*V#-rC}& zB~$G4N>;4F;Ix;oEiNs$dn(K9OIDXHy|a9DLMDdpKTjK)K5I2b)=bJh#a>WmU+ZR_tC{<}O)XvfOjgxCDGS#TN|-&dQlME_<HvGD`r#{Wp9b8P~P#?d?na`Q_(E{}VPeU2Bhy4((NEOTSBSy<+^ zSC+U-?By$ItV{uo_9g2e+cY1$?O^VbRjXHd*3k$mFC(5|N?YqLTj4HVW3ODbdNnel zM3R%y_DXzsWlqQmuZ{D^URs7ZfM$0^Xdrbia0}gWZZr{!*c&)ge-Jrh(WPtHh((uQ zk(+Y`M=sCJxtt@H<>p+rhM7uAmra|7j^s4VTUk~)o40a`UHMhI#$M)LR^qlV^}5~O zwVo29>Dtm|W6SOHR^0=Vn5leeacTB+E^D#SEL5!2J~20E;u>}-M2m+&qNcC}o|h%e zsVpsVPr3ANM6Ox0%)3TepDL+Y*Wl?ItW8twv&y`ymqn+H*|V>?dA18v1n9W*?##9J zi!zsHE*)o|X3vCtM`P_v(E*@#!oMP=2??lpZVAnT|5COauAhyeOG_GN5qm}E-4inJ zwij0vuUbtKPT`(1Pw{G`SzElKqG4&(3UQjC{n ziY%z1<=&-Bu^un?u4b#SY`aTQE}sV3%3}Aj%3=(RHN~r!drOykuyU~_-tu+!2@^0F zJnnV&)#wm6@>LYCUbW1=vbc2F>JkPiFIm2-v}Bn*k_)Nt@?sf8(2{lb;7e&w{%oUBhJs_YQI?Sr2t7u{a zLolwfVxV8_lz$y6Uh@yq#Ol1K#Eof;XN*!DZQbg!6`*=GkGGe4*DS#hDk)uxK@A?1 zEQ_XFyK-ImKTJp!WJj71Wim#a2XhcL7CbMe1s;8}nkmiyL7TDmLk(EQew-_j6tV6o z_b!R_NL(isdpzz{OT4JuvuXWg(KcP)4h%`JP5g-WN2HCWi+>J$V846HkL@5}0DyUoy z)wpc=^70Z7CUwtB2+n{Gk5E;PDUzBHABj%jtyU?HB)!Z&dnQu}q}t=#ilMExw;aqu zpO<5PP)7kLHA0d~>G|799cGXAFDqYLvUJt*RcK%FYCe+Dr;syV5ypUFJ9F6V0qSiBmeI?_ArpRc_9oZ6#JAxgdIwMd8m^F=~qUPhA(m_SWk3Q;I6 zS$%FrF;1N~`8i}^l7jrNjC4;ax{4J?o)nvHCA4lNqo|9C_+?&Yj*IrGk_qEr4XwB& z!If@wO|hGse3#AUb9qcyu`rO41SM^0NmPd1?&5Vwr>@!z`nDS*2lJpZ#X-PIdFS&9 zJ#K_6(|J@0o>>NAhdj>8%Ccu;End6My=uiu*fCdKb(uX9c|AIH0=s5a#j0f`%6c%! zboG+bGB*~3sP+Syf_l$K?;t4P|L1;SN+_Sv^ocygeucb&A5HY5hNtq6c%F}vAf11V z=lM{){r`8)6=@lZ0AmSwODq0!A)ZYdAwGy*i7;?sK-dj9emTC?3XGB>Y`%cs|`q%ZaLa4$y`v9uDwR0B5#}Y2Er+APqGD3Bc(X5LMVV#bB z$>@*z=%}h|sbt)#!xj)iyjn;I-iBkZ5kkwt8Y;{TxQ`IZ`T!xs=}m-KSgJrThB6%A zW+_x5{`?7>LdamYOrZDC81erbLhyG>nVx7ttJw%b@Fq8#Ku8+9Rk)0hp#YAg1G$1i za4MT!NeJGNQxLpj%BE2WUZ!Drgy8N11+f9SmO?TB*AZfmAfthNMj;oVF532FV*nhv z5Xe~y$wU+#B4-W&N3fmCY!pI6Xfz=hEDACn$ZQJ1WqZs;$i)!^cQ)eBU*T&4pq7wJ zA_)1kenTO6ZI5*lf}6~g4#6FgY!vm(<$&K1as^;7Avlr3wA5F4WtXiWmF7Mxf*P zY!={Wgj@rlj@4a@-_*hQasp}y$)^zN;p+fb5^_C&{<1Fn34s2#F8e8f{%9?`ft3k# zZw;Hx?o^NhRw~fdVQdb&Ls&|FEP5h zhZO=|B4j?`RYDd3ju5gC@Hrv307jA!(a>2($gOOIK(Ai1+W;04t0KT_ge+!51bUa5 z-45s_q!{oklDH*+9fT|ej397;A=w4*$RQqV=xa} zF3>>)=4HbLdZ(IIuweqdPR%MI<87bx*3Yq0HzR93%HGtp8;eNd>>#G2|oU!wLq__vikv#6Y>BC zC|%*lHUjDh*~G>&xHxC|kuYTGraD#+_?(c<0Feeq1HeOr<3Uy|(77%4 z5TK2ahXEEEE{_1_5b|^O6{C0F*`s{$-J?za1zcf^7?59L5dT~QHmQq+fT?-ybpmqjb6Q617s`u zd5{*!GwAslggnb$!`x~U)1PBuWS=djKhMsxJVJiMLXb`%FR(N0Q$l{r`dJ~a#Y%sX zoo1gA@)GM~blFw<%k1w=s|E53>tgp3@+$j|Jud=zjrFpS4#D$@&jIR7j{~bHU=-#RH*V#Ah1R;&AlZ{9K@&-G}<`D8G>t=pJ-eRK#GYg36P0TLL zBV-555Z)zZC$kCkGD-T|Y?MGpZqxsZjTDR`kl(Y7f{tbD(s!{3ggJz~!|oSu7JxLf z`-J}>(@A@8wjAxQ+%#;Sxz^+4L$27#_IOMjoO z7wEpM^bgp*0^Q@2{vo?Zpxd?5_po(BPZE$nu)Bp9L;WxlrtFFd9GxHoT6MQK>7$t1rj1;h%l0MqfMGrE7?_=hY2=JARu*kgys=Icq>Lm3LJ$Hp8bC{_Z{F>72E#P z_TJ~D7eWeYB1rEbMHG^dKp;&zf*#WoLyAdgB7y}GP%MZFq9QiL22w>zC{jeOSP;Pm zHjsr5z^=mQh~Y(H1GdH7er~YbmZM^peq197To~o?3ezF?0=_L;P>@bzhWXPB_eYKJ^TtSj zu2KHPSNZAVGSX;&_A!3oYCmuR9_#M(%j(HTgN?7S*kN8{3&^KvhUVwbP^li%&-wNC zD1QM!bJUl-*5;ocypFxM44iNT4Wq3D;bwOWJZntr>@N4_Q*7XJev=Jc!Kc|kAAXw+ z^yRdG0(nz7EvW#ca$0r)NaM6v1JIAtvI{^uzug8hI4#zI>Cb722Veky&;~O3qc$** zKWqboc)bl|@p(3o&F{B?96rGYa?w-zGxPW)8~8swrgpzDrVpU0eJ$35FY`;>1%WUm z510>T)APmE)wDkGga-+;ZHK-MZY`|DPK6 z4L@Xe=Uenbcjr4`w0?G@z6a*q#?uh!35ZB%Qonvc8ZEFtLUOed{t18<*q;IDl79i9 zOa2vrrkI=EEzs@hS(OIZeLu!O^;i0-UFiv6j+5a320%{=Cjsb5;URzRzx!+d!(V&C zncAIl+>+-bO4IpI0J_V^_-8hT8s>EQGrRUvi28P?~dVCpzmcGvTO8BDn555nMNe2(Ft!1lP@=HlN!Jw`8|2 zw|3$&-PHd%fVfU`!Ud{0ONTE9t3e<3=C9ho<$S#jT){Wm02haCpby_-1AX~hHju*i z+CVDbV*_b?hYj@OZ`wdQ-(~|De76ns=dano0REm0WODj;K{E#OgElaTzib0p{9PN! z=I_`*4qs&hxqO!mGT(=W;>*qyv^@(kw*YAVaWNiYg0&IlMU-Z? z0Dl@cDiAEHr6~x2R@A`&w4mj4FL)E#LxjgJrzsEM4J1}B#!chqa?5c`4#fwGE+yX>n-A1GyH5jsUb2gySSgb6o@gy>f7Kx#h$nvF=x65zIfN_Cy2F+9n3yE;_rL zCR*V8ih9u)fG*I*xZIn|!|>tte`nld1$_vjJ%9ZQh(u2*%8J7Gp9UI<5F6;pn}RG= z7V9RO*+l3nF2*MvzVVCrB{s$0#7Jn>^bY`9G427N$KnkDdMtJW(A=^YfF6`fQJ`k6 z?tU6Jzt5JC15t0!bo zGi@&jtRAMzfYGDVTeRnzVwVHZ1-gmd>~4W>6>ee|^Vb$qIl8X*c`L42q6aX#E?Rx* z(fMoR|60yDRcPHp7_Cy`P>yDRD?~e+A^V_;FKKZ50ys)Q3eI?s5zv;mw}mrit7Ha0Tyc1ATZu8|cdi+dvAx(gsp_jt!*oOdIIO z^K2lUXV^dn&$5C3yuS?$;4N$*lXtR#fxN8^4C0sCKo<73b$hb;P#ehMJ#8SDx3qyg zaHdZ4zp(7Nz;;Be7;QJho%P&J40jW(yVF67&Z)=5WB0o!9}Ypo9G55N@Gt_roCjaQ zEo{Zw|FuWh$6I61jO%}g5T1*$M40}4g>ZM#2HVbD|1$&+o-Sf=;7X^j_)#f@yUTV^ z$Xx&P@a4;!WVX}pC;Y>bj+saK5BV)KmAI_9V`gXZ7BCNio=foE{48t6UcfQwa@L!z zW;tvPP7Bvzmwh)*UEajL`CjaKV{aaN@6TbkeJwWHcj5SLFE+tH!`}8$>{S1NEopQ`(%zLPnJVmYM z1JxQFEv@6z)T{h9wSmu28~JS2z~`vV{64jn&r{p@e6^h~R6F=0wTmxSuk)wX8+?h{ z!=G1g@)y-!{<3N)*LC; znWM!X^J;O-ED%4Mh2l3e0ZZ^UxMR?nU4-MkW;lcIgH!kZ;G$uyFAiriaAGx?a~Ui?Ouiaof2{8l!U-@vZo)7iDyODp7e;3)VmoJrk{ zW34$j^}3fW#D?6H*dKct8*1zMeD*$Hz&_>+*)eRMea#Wa5lz5R+N*~4NDdqTXzUJ~or8u2RI zAsW~|v6+1#wy^KTM)s%J#tiuy^T+@ZEQ3X386qy0jYMzRSoD!GVt|YlBV{U%HT$s` zoaM*h&^`td*cu1(y+NZ?NaEF?(FD+FDo)a8fIbUApCvfslAw~7FwA$AiV2TfkW&f^9?i|yvK*&%E-ehnI(1Z@JvT$U*AXKlqi)=NCV zhKmPTp?HW*6!Y0#VgXwq9%e6yg{%QI*#kNp1Raiu73??AB808L^^=tt`*j%M^%(Vy zxXiE#qk9M=`vp$$zr+#yQJjz+$GP*@>|q>uEyh{b6FBC28hYbd9Bw_2bFG)4KbGS( zYXwGrCC;!`T_g`7U7JGE?vSbo8a&%K zKcUA?^Z77Ly;O3sRtm9QD)Fu~#6f9_L(&poN{=`$!^95~Hl9@zAyvFERf6!UL=mKt zMX0(+gsY|^LbVo+R2$J)wG}a{ooJ%kiv-m{B&qJ=BGp4QS3N}wl_FZHRMAGIiMDEx zXs@zFN0lu)s~pi)4HuWH5u&HMO7v2rMQ?SrxIz_+zN%adP!(dJ8jBP7N|C3k#1K^@ zhO3EUgqkEqsT;&-HCbGvZpH1t*`i3@DN58`qD;*Z2Af8f(#B%j1eii65@tQg!-c?7%Vf7VG=>I9cRma5% z^^G{Cz7>JScOu64UNkX&5{bsoqK)y3xXd^q(u`ll2;-#4H+~mI#-F0XI0a+oOx|E{ zIl~b0enZL!4O7lHEcvwIk*kdWxzX^-w~ZkAp%E%SHp1jTjW5JEMx^}JNR)pV&85d| zAsd{Z%jFMdn*7P^Cx18l%VaB4 z_O=Gfa%&L&jgVE=M0uk%Nj`1eAfLA;%a^Si(*?!$GTJQweFJd zSaali)&uf@^`JaxJtRN0=F5+*1@aSXu{>-&AwRXAl%HEq$uF!I;6=JL_fngSA5bWUZ9HSgYg-YqdOSt&x9Nn#mluo@zO+60Tr<)Jm47R^#6qmZ3&s6?!!;FkZtNp{LQ9 z%VRNDHNnk{1k6`>i_Ds0HfV;cTrDwgwZ^rKcDVP`0hfR};eJ*Z+{o$%>U76Fte#jk zT!t$deQ^gW75A6=W92ZAJ%sCS3sL%`DDiQW^d#+h8u#T?58hSj|&=YwhJ{jxiDY!i{6)WwVG1J|SneI-05ucCUu1E3R z`~qe*tWNoQ%xs%64{pWmwjJ}}PRxV5G0W}2JoqMNy0`d1{th3+-{V902dM2ZX1Z_j zxy|vV-AIh)EyUIQa;&fWh--1lXfhurrtqu8R9+;e@d|MZuNTw#Byl^REM{PReg~f> zX7XFbEIwV#<}<{de5Sac&ldCe9L#@nG55_Ei}@1q1Yakf=6l4m{E%46e-Y2|6PW)_ zi&uG|T+hSgCLSvrc)Z-q6Xh13EVuHeayM@w-{4*49^PFZ#Py~_d;sRcL6{4(F&AEm zIdGUf%16j!{3`iRevLfNua)2M0{Ja3mf!PI`2#PPKVr@Q6R(zk@ar*G)?-ebfH`pv z=ETRPSFFI=Y@G}en`JcS&3N&)OcbBWWbuu>NPH)oiXUZj5rDZVRNW%tF+X)vv&10G zQ6tnHn4cD4&UqMf&O*#7kBVp2V`8;hBzCFC#R0Wg{D?V98c&L7<0;YFcv^Hfo)H6$ z=P*yaAPS5Z#W>?7@w~B2tTkR1>x`A+4P&)9WULWw%~!&4CH262bk zAm*6=5ciw!h(+dptjiCG-R41Y*!)m@Y3>uhnxBZ%<{=SeeJ8@LKShFdN?c+|+166B zmu1Lo%aS84ubg6q$az+%JYR)kcZNEzUXl8rqV%XXgTvWKUI9PDW+^F6KP zb)MGp22UG#r>Cu4rh)_u(9@RX=i+_QtM@W$B7ZRq1 zhkPSTLmH`>A+c(1NSt~(q>0)T60hC}Nl@>HB&m->lGTxr_Uh}9F6y_Ct|}<>Qk4+e zU3Cw=Oy!04R%1eYs>;wlYF229x-T?UJr3Eh3JpZV_Lp-Vw)CYQ)!SV8l1-+K6veam07( zx`=WClI_=um>JrO^v`4PXWMG?QNmm~gA8zWv~8!svWFoX^)xPR)XT_fbeU1wsJF48(G|w#MtzNKjWUh>jk1g{8x1oOqed84 zMvXE`qpmV0Mfr>eqKb^&QR9unQMVeuM%`w38&5ZyHNM>#(RhYY+4v4)X5*R0`o^=2 zw;Rtk4mZBjIMMhnqfPW2BPIH7qbT}*V|H{aV`22u#xv2+8LOh#80(`OjGfV2j1QuB z7(YhuG)_eCGH}<@2#9&pXcV*8NRD~iXdSc9=o7Qw$c#B)RK*-LZixBFm>%)inCRduBnhZ88n+!F#HW_Aij~{N1h%Ye5#21^T@nz!VL3R!c6nqgjuFYywkK2?=s^O?>3VX?=d?k-e-1C zoNEqDoM+}HK42CkK4g|A&NpvJeAt|txX`>W@lo@^#K+8~iI1BvB`!9%BtB{GNPNmX znD~tON#YXohs34kuZho@0ZA{Ip-C^AO_P?HEs~a-y^>a#eUet1gOgU9Ba+sb*CoAT zRwu19Z%JBj&Pdu|E=byBK9%#%sG&C^M5 zm=VeUFr$;-G+QUXWp+q@+e}S<*X*CX&%7#mzv)XpVAdvoVXjI(Vs1=6YVJ(-a7nwN z_#4dvaZ#8yC4;a=3Zpxn8ruVxCl&S%>DGKJ5srIV3UD+p#k#>xGZ#A*G002%#*Yj8 z2pS+RbJID9^S(uT7+r&;zkK-=yBO(dQ@T>l$F*jmAG+KqugABzU8bqhcpIb-Mw$rK z9beuYy9BtvsxD=%9r&2)jB9~*`zwuWu$!Z>a>O-UV=%kaDQCA)ja8A*4`2=$`K%{k z`s-zGW0xUs6yOYVEmll+y&+hsWuTmB;N!4^>Hm9+J;<_=o?bJ2gtg#6ltcF!k7G9~ z3wa4n#VyD@r<^kEFIz%JScPWlhA!}baAU4TEzE7<2w`XSi$IRbn);COur`3xfUoxq#O{`z zexs)?YX>+T_#K{$S$hY6%+m?Geq2A!`O(vob#(Aeyj@u*z?n$j%-e=_cJR60Uf6RN z`k~HfZ+jeP+vU&nc4n6Xrkk7hd0Vjp2Oo%?&_blo1wI=4dc_WY2)=?!@QCzE;C=XF zDi;PIhVPHXyb8xpbQSbXc0X3zHvbojui1EEVTTnDT*P5E#VIFGu4OlYRwIBPBk>jF z;5{mh-HN<)-?NeG4%hxO@J;my@S_n7#~Y`|ob~+*z4*c8la_m6bd>g8!i@hkn0{D3BAnkY3-)~M~ z@1x90;1`+KW4F?#TR3(uK1BLz;1jU3@tKo;ML;$C9PstPuMa4}uC2|7O#^q!uW*n@ zw>~=rZj?Ve<$N9D<-a1$IN*N^`IG(bwC9&lTr&iI0`Ma2IVPmt&KJVgWA|6#dls*N z!j>_wwCPYD{xA=KZk-JL`0zPA!ojP^wJH+$DZocYKC7BI`1R3s_$u;Z2bi&)(WSh( zgYOV~GrI(J-3)y1*m~B=!7qz_jI{>-R^T_p-pATG_}sW)(H`)0;77-C(Lvhu857?` zbpkvC_|o_=)y2WDN^Z=$0iFr`#^hkkGdG}Pr%aCbhjel!@Nx(5aAY*@<NV`qfUuI&HrL2iMs^&u!j zvd^K-6#fgxj;(=Q!^IUyYqI;r7`yRk8%7O;6>J)Q6`W`UDMB2u4gzx=0yNXv7#x}+ zJzV^q#y_u4Pcs|BKmbB|Ivl6)>C>3c5Y~@2btc?G(upy*=|WrT@^lWA8%arZxt3E& zpyNYd>wJxMc>+|Va^qNHFrCEf`3Uj$97WWn`H6fxonjYL!OHP(J1?waocLx=dVBt1 zF5U_I^Z9*$d2YJ%%Z+u)_51#EopeSFwG;h_b?Oap>&HBeg$Hp9#dl|kc*dHG(Sd(Y z5LO1rw=)pq0DloZ!vr3rjCRs{SW`VN=<~GGQ`=x9kS>|AzLXy05J2e>Zbv@CogKWQ zFskh8gfnPep!vbhmqGDAa=ibv+cl8FxPFm&PJLIRKH%@?;6vowi8pahIeMHBzVe*( zBklCfXibLnG4$9H`N1EBf}T)Lng z7~e(I9*pm^)b6v!cLL#CGVI9N`Oh8S?e6&ANclh)|M>2td(9@jBhs1O9RH z`;#2J-}mGHuJ14Rp>xZ3`RPnKc7K*ryD;9DQ9m)>{iy$EjrS^w$9QKu{W*8M^SNK1 z*E!?pAMZjc593`%<-zxl_jOLV;k@x~pn5RgHBLR-C=9w!>0Pf+|>gBaJ??vLJiZTXy8GvY!xRs_`kq^lj>mfYU-QX+8}E*%>5Q{8?k?WX z2WQ6nU-R4lZ@j=f``T za{T@G-_oI1TjKLY zXXw<)p=XrvBeNd{~g{DxwJMpUn=je^G zb~@;RYDxz^kVoY~55Q2V)&nIg@BB z<_2;mlXD|EQz+sla;Cy*Xo)It_>6xy(|*n^)QnrniQ%aXzc$d1H6&A#={$`!0F7Ux zpi*X#a|chy)(-EFU!UL^tO10?&reY6?5A#7Z?E-p)oJSGc00Cp{F>3uHYW?F> zJoae}So}3rRd65rg4b7+N>`5Hab-A*moLC#KccJZzZ`+RVAQx19}!RWyR_WR(_ z%K}D^B-mTzyv?s>*!;VOv3GesWBbT?kDUE*8Z!E#eRNaXruYGZ4wCZ$zm`}YNua%` zHneXSIUkbq5jh{jX@Ks+z7f4m_3uVsQ7r69Z)XPhv3lzfTMv zATgNaia{-j0a~zwoSo$C;tvsH!ueZbFrUO=0g1sQBnEKaBWFLH3yHx(5(6apTVn7s ziNUKR23trBR+AXKLt^kQjr4mY1|OX(1}jJmR-P*cYe)>>jODMKD+Va+hs4+(pg>#9%9lK?4zI2Z_NR5`(=Y25$jGeREM0x*n`sM63CLST(#{2SyWMYu%xTp5lHD(HJ+N5!4l~nFu zW1`J>Qp4{e=K@+KokOdn5=roGX&x?iL#yCT(}TF|{cqNo{rP{KTv6p>+@OP28N@HN z#zeXcXq8;v(2P3$mo+A`{U@z5g#Wj#F^6+#m1f*tV_rZ)!4b)LjCP)ca@@V#M)w?f zOGtDOPB(M#eql839bAuBLyzFD=5x3ac@(dNf^qktEpFcT<379v+KoH%AtFZjM2VOz zZW6P^ono$dT&x${#BTAKI3|7*m&iUcTMm()dBsERVP;=BgwNNcqOVo>Mr8=NK zQO8uU5oyF5&5brjccY(CX-qPv8S{;2jAh1ZW4*E6*lipzjv7H`xEWfLr;99&jDC70G+j$eejW6U+;s)n>{ysm(zve&kpSchokt{lh zuA;9PC9W5f#0>F-cuA}gJH$Tmr!b^P2Fu2>H>fp0j+BAeq{zit>I9tUS-3;m9rr)! z)m|OmFHFVF&qFBpG)fHwg+s6hdO7QhvyV}@Jy3?Th)Fn=ycunN0(W7b#f{pR@HS%w zZqKg9jakh7xM}ekdtLYDUEF{D0=HU!!5fZKxY3%-FGjywp=a&!&Y}}W`cf#B%OTsT zcvq1L(Yq42Obhrlyrfuz*Atj#_)*OT?a{LwF$BCYMcgJn7T<|eI6@7T$+DH~BGcty zStQHkSXm8=bCcyvc|x9)Oi7HkR|Tn16^>DFq#COj)kGzzBz2K$u3D&8s*P%^+N+ML zv+AlYRXtTN)mvSm`l>iC!4pM510>`3(dvmQu8PCcQeY0v68JWRyV7+Rc=*TH(IY- zd#t_IJJx&F0qdakq4lx#iFMfe)cV}|!a8CdvyNNeSl?McSU*|6SSPHL)*lw07Yd=d!8^r!n|G%7KJQv@Ah;z7=W17gW6~k# zL%`?j*=FpFS7TJih(b{f{;U^wiFsm^ct?C7e#JP(%I312>-o5M{Q~YU?QD3>j-l*8l*d6m3I zUMmYg#Zp-gtynFum-TXj+$^_48}65%%5R_zf0Vz<-{mP80QrblgTUES!KsVXvucD< zV5~FVF!mYyjYGz_#_z@)^L}%Yxz^lj?l!+Pe>G2=K~}hxU=6lLTGdvaHQt(HJ!!pU z&G63guJEq$uJi8n?)3%+#0R7Vqz4QL7#>g>a6`b00V@L52W$`cDS!t?1SSPG4eSs& zG|(5=KPWpWKd3CIBB&~;HfTc7jX_g`mIoaVY8~7sI4}5_;1j_z#1qmyq+>{rkl`Vv zA>%@(giH&W88SEIq zqdyv*ZWJ9A8)sXY`5afS5)xePVKB zhR2MIxjLparaY!9W_rv6F^|SP8M8EIRm`g~n_^y%*&Fk2%%3r4Y-nuj*bcG1V@Jo{ z6Z=T)(%5CO8)83Lw%N$HbS$ zkBzU7A0K~H{IvKx;%CL*7k_{JL-CKqFN$9h|6Kgq_)YO|#J>}NDE>(N>G`#Edc&&`+vUV+T>Nq8gL1o2-74-A!fc@qc ziUB)zU&vw&^W_)77z^vye{k-wyuOIc&d%+Zo&|h;@x*deS4cLxfG?`9^OY9YlQBB7 z`r=^F#4{K>gU|5_{l1OJ@n!YP9Nw2@IKCYMc9zfozxJDCF~H=B5uG zoI4m$zuX}XSY8JTO#&(_H>dy5+!R2=v^Tb{xR_{}Jt!w7I~@Ri2Okha;c3~rII^_I zFz}@|KrAq>rX0gmUp=-Omd2QGTowHcJ@O9E8=RRlG@Ys*o;Or`gHaaProN`I2G#q` zrva6gH*9DQ{FDKiIcZ2*sDJamgtEd$M>Py~04(fS2(vs@H0ZuFkgue?wvJG~u`skp zel6LTVLq~01vkIe24LF*oT3qa5PfiQF6=9))x4{{v#hx>;;zCnRFIum26vU3U3o?v{ zHBQjOU(9$Hs;jSs-5f;K*TQ;@_R&o$febhiK^)&7oam>FZ(@l<8z0$ELI;qz1Rerx zQ0CB~={X<@)V$wt*mOh0V2nWq_(sQQv>VET$y9$J3&q!$SHi?p zPBpAWQR*z;0GKvQ*M_U?a9TdBSrk^BLHPz}rH@FfuGH32bq$2DZC%+}hL8rz&ad&; z;~PSTC25e+HouWe9dL|tYS^{GsYBY>V|IRRg>IH@`!QwgSO+s9pCq&dT_gipGGwk{Tq2 zf~7}0y<^wWAIQ@4E@j39olSC~3-X&~)Iq;lL>)NWK%YivBYsqc4%wCrv6etFsnwMQ zxmD?8l@zRQOOX#!l@HToG!#`Z09=@l^+Q25ROz@H=#t_y;iB6731>o}2H7ISiUInm zwvJX4zJg-dO)1te)M?6)^!|FTtg7!g99D02rI>TNo*n3RcHmMskk%2R3039O0JI(e zXutAW7y$J70A*F7#ROo|v;ndv38H!aQrU z_t0{f>GJu=Ml#t91&HZt?0C}EgsZQnqU{w@p`JT!81n@1h1wP#+JyC!R+t)cbh?He zr3`gdoDW;FK3^4aKYWTPfyRXfgb-6ib^Wl){5qO3u>kY85uhHsq18i%Bc`st!q&DE z>I!SC^^8KMx6m613Fz$ve1#cf^NB`UDZ+OsOKVK@-z6#(&e*i^_3jW1fn}Vb)kRKt z$l$awS(&M0az>@(jIkAT`!q*W!(?w=9V`_3eV=XW5H@A&{UDU?*mA5RV4{`5gfr8& z&FZUl2jDSS7b|5|W9uj$45{f-UX`lNOf#5@90x0dL@SU2qox&x9-+G0LWX(0sJs-) z0R|?S)*MBs2~_r*AjEDA>ZhV%WUvgzSt(eL>WKG?*aT822$$4gt&5D{BZ{SEhQHUH zE`@eSf3?pvr`52!POPpYTCV31R+B~RBWYeS zfS^9yhLWjDprFW!;04vy^j*U0ipnRzge(S1dv&(w1d42&?UEf`W@9u$hf!2fc}WS% z)dYl(IghHbdAu+mBw;XVjRDs7M4hIgE7Th@g^Z;jk-N4Eh9ZlL7`2j-Aylk#^h6Do z^;MVn2w#UAtTixEiq_IvstDH5C$YK-3@f?%39P=1O(-vdTUJaa@X!#97|`S)0ldoc zB5)F964opy{sl8hV`|3cPb#iGFWGrWR0=bjMa2_zYcWoXE8B}Hh^6K z-uJ`k2Vk%Y!#{@_fS@+vQY1X6%sL&7B?eSC6e!mJC13$PcY!*2*?IX@<%QWqvb^k} zWwj6+7!735`NTqXWFeMJ&7KKlW3h84l$V_|u2S<>9r9<8AzRq*g~p_UiNL6;xYP#0 zu?+kR@pf!!Iz~T%tfLfQu0ojKVptmLAdQxdhrA6y&uc2j`i50GsVG2>67G)LWqcE~~>%cCAg^O)URCnAd7c{Ul`ibF&2H1?~;57+! zM#s{t?g1i68X0LaC!r>>Q#hz?7w0Ft8*&N%fNl&CTPFd(*Pv_!owfoR4w69@hGnPLF*tfA@hfZ8 zj0%h3QQ7e9@7~JFDhQ(85oq-S=GwrmbF7V16(A0c1$o4$*RS5`r<)zHU6VI3>1VT05A4`Cy6 z2lvxJ>L~1*5C)w>kC?5XSw?17I#ka1VpI!a)-f!^$}nND0(+HVFF|1VyoNzmF{@#6 zufRv{M4a;EPhZ&q7Bd?w)T4n0<(Dxm2@A@=@~jB|mz~|~>}|XrW_jE3wAF R98p(H${gPskOu0*e*q}zDKG#4 diff --git a/bcexmm.prj b/bcexmm.prj index e5ab4e6fe8291cf9cf99e35c77b293b2a4f426bd..a9e71b315010eccf1cc980a91a5b0164d944cf71 100755 GIT binary patch delta 940 zcmZ`&O=uHQ5dPk7YPL<vfo&_&@((5{Jl7*$ae%_(*eYsuw-iD3ff}*Q+zNSBwC597w9Q-rdGn~2p|6;>B^8@E=n5--?6IriovW`*!w;#fl<^|0M7e6P@b!Z(EP5w=v= zO+xnzyBU*{Rpxf&t~8keyzFT)t1#JHX9k5{E$mid>oCj0vO>5z5H=}Y`v;T*WV&K~ zN6faqJ^T98>E;+i3!)JRS-keBC7L~UiCIV>z*o7g;y5yE>w%(_=eO`a<#E~wQi*6> zFoduZ%Y#2x-c$u`HxTxG!G z&0A(0gLUNSf2PPPGMAM8-T`u&C?94US=LM^x;PvkX`5~y|nP54-}DYxfmptTy6ICAm>&tGP%^`f|HZadqgAmi~#vyc*uPg_n1*fKKXNMKZj&A zK{b<&n;qn^5lqLhA9qmC-lj!A*Kr#J7cq)!NTCZEWHEq24B<4+;4IGL0#c+QaO@Y= CQs5l` diff --git a/src/0.c b/src/0.c index ae51d058..09e8953d 100755 --- a/src/0.c +++ b/src/0.c @@ -1,294 +1,294 @@ -#include -#include -#include -#include - -#include "src/tesuto.h" - -#define FILENAME_1 "data/aconita.vrl" -#define FILENAME_2 "data/aconita.pal" - -static unsigned char palette[768]; -global_game_variables_t gvar; -player_t player[1]; - -int main(int argc,char **argv) { - struct vrl1_vgax_header *vrl_header; - vrl1_vgax_offset_t *vrl_lineoffs; - unsigned char *buffer; - unsigned int bufsz; - int fd; - char *bakapee1,*bakapee2; - - bakapee1=malloc(64); - bakapee2=malloc(1024); - - IN_Startup(); - IN_Default(0,&player,ctrl_Joystick); - IN_initplayer(&player, 0); - - if (argc < 3) { - fprintf(stderr,"drawvrl \n"); - bakapee1 = FILENAME_1;//"data/aconita.vrl"; - bakapee2 = FILENAME_2;//"data/aconita.pal"; - //return 1; - }else{ - if(argv[1]) bakapee1 = argv[1]; - if(argv[2]) bakapee2 = argv[2]; - } - - fd = open(bakapee1,O_RDONLY|O_BINARY); - if (fd < 0) { - fprintf(stderr,"Unable to open '%s'\n", bakapee1); - return 1; - } - { - unsigned long sz = lseek(fd,0,SEEK_END); - if (sz < sizeof(*vrl_header)) return 1; - if (sz >= 65535UL) return 1; - - bufsz = (unsigned int)sz; - buffer = malloc(bufsz); - if (buffer == NULL) return 1; - - lseek(fd,0,SEEK_SET); - if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1; - - vrl_header = (struct vrl1_vgax_header*)buffer; - if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1; - if (vrl_header->width == 0 || vrl_header->height == 0) return 1; - } - close(fd); - - probe_dos(); - if (!probe_vga()) { - printf("VGA probe failed\n"); - return 1; - } - VGAmodeX(1, 1, &gvar); - - /* load color palette */ - fd = open(bakapee2,O_RDONLY|O_BINARY); - if (fd >= 0) { - unsigned int i; - - read(fd,palette,768); - close(fd); - - vga_palette_lseek(0); - for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2); - } - - /* preprocess the sprite to generate line offsets */ - vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - if (vrl_lineoffs == NULL) return 1; - - /* setup camera and screen~ */ - modexHiganbanaPageSetup(&gvar.video); - gvar.video.page[1].dx=gvar.video.page[0].dx=16; - gvar.video.page[1].dy=gvar.video.page[0].dy=16; - modexShowPage(&(gvar.video.page[0])); - - #define VMEMHEIGHT gvar.video.page[0].height+gvar.video.page[1].height - - //4 this dose the screen - { - unsigned int i,j,o; - /* fill screen with a distinctive pattern */ - for (i=0;i < gvar.video.page[0].width;i++) { - o = i >> 2; - vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); - for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew) - vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! - } - } - - //while (getch() != 13); - - /* make distinctive pattern offscreen, render sprite, copy onscreen. - * this time, we render the distinctive pattern to another offscreen location and just copy. - * note this version is much faster too! */ - { - unsigned int i,j,o,o2; - int x,y,rx,ry,w,h; - unsigned int overdraw = 1; // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks. - // if the sprite's edge pixels are clear anyway, you can set this to 0. - VGA_RAM_PTR omemptr; - int xdir=1,ydir=1; - - //4 this dose the sprite? wwww - /* fill pattern offset with a distinctive pattern */ - for (i=0;i < gvar.video.page[0].width;i++) { - o = (i >> 2) + (0x10000UL - (uint16_t)gvar.video.page[1].data); - vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); - for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew) - vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! - } - - /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */ - x = 0; - y = 0; - - /* do it */ - omemptr = vga_state.vga_graphics_ram; // save original mem ptr - - while(!IN_KeyDown(sc_Escape)) - { - IN_ReadControl(0,&player); - if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0])); - if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1])); - if(IN_KeyDown(68)) //f10 - { - //gvar.kurokku.fpscap=!gvar.kurokku.fpscap; - IN_UserInput(1,1); - } - - /* render box bounds. y does not need modification, but x and width must be multiple of 4 */ - if (x >= overdraw) rx = (x - overdraw) & (~3); - else rx = -(gvar.video.page[0].dx); - if (y >= overdraw) ry = (y - overdraw); - else ry = -(gvar.video.page[0].dy); - h = vrl_header->height + overdraw + y - ry; - w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3); - if ((rx+w) > gvar.video.page[0].width) w = gvar.video.page[0].width-rx; - if ((ry+h) > gvar.video.page[0].height) h = (gvar.video.page[0].height)-ry; - - /* block copy pattern to where we will draw the sprite */ - vga_setup_wm1_block_copy(); - o2 = gvar.video.page[0].pagesize; - o = (0x10000UL - (uint16_t)gvar.video.page[1].data) + (ry * gvar.video.page[0].stridew) + (rx >> 2); // source offscreen - for (i=0;i < h;i++,o += gvar.video.page[0].stridew,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ - vga_restore_rm0wm0(); - - /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */ - vga_state.vga_draw_stride_limit = (gvar.video.page[0].width + 3/*round up*/ - x) >> 2; - vga_state.vga_draw_stride = w >> 2; - vga_state.vga_graphics_ram = omemptr + gvar.video.page[0].pagesize; - - /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ - draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - - /* restore ptr */ - vga_state.vga_graphics_ram = omemptr; - - /* block copy to visible RAM from offscreen */ - vga_setup_wm1_block_copy(); - o = gvar.video.page[0].pagesize; // source offscreen - o2 = (ry * gvar.video.page[0].stridew) + (rx >> 2); // dest visible (original stride) - for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += gvar.video.page[0].stridew) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ - vga_restore_rm0wm0(); - - /* restore stride */ - vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew; - - /* step */ - x += xdir; y += ydir; - if ((x + vrl_header->width) >= ((gvar.video.page[0].width + gvar.video.page[0].dx) - 1) || x == -(gvar.video.page[0].dx)) - xdir = -xdir; - if ((y + vrl_header->height) >= ((gvar.video.page[0].height + gvar.video.page[0].dy) - 1) || y == -(gvar.video.page[0].dy)) - ydir = -ydir; - //printf("[x%u y%u] [rx%u ry%u] [w%u h%u]\n", x, y, rx, ry, w, h); - } - } - - IN_UserInput(1,1); - - while(!IN_KeyDown(sc_Escape)) - { - if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0])); - if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1])); - } - - modexShowPage(&(gvar.video.page[0])); - /* another handy "demo" effect using VGA write mode 1. - * we can take what's on screen and vertically squash it like an old analog TV set turning off. */ - { - unsigned int blank_line_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height * 2); - unsigned int copy_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height); - unsigned int display_ofs = 0x0000; - unsigned int i,y,soh,doh,dstart; - unsigned int dh_blankfill = 8; - unsigned int dh_step = 8; - uint32_t sh,dh,yf,ystep; - - /* copy active display (0) to offscreen buffer (0x4000) */ - vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew; - vga_setup_wm1_block_copy(); - vga_wm1_mem_block_copy(copy_ofs,display_ofs,gvar.video.page[0].stridew * gvar.video.page[0].height); - vga_restore_rm0wm0(); - - /* need a blank line as well */ - for (i=0;i < gvar.video.page[0].stridew;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0; - - sh = dh = gvar.video.page[0].height; - while (dh >= dh_step) { - /* stop animating if the user hits ENTER */ - if (kbhit()) { - if (getch() == 13) break; - } - - /* wait for vsync end */ - vga_wait_for_vsync_end(); - - /* what scalefactor to use for stretching? */ - ystep = (0x10000UL * sh) / dh; - dstart = (gvar.video.page[0].height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen - doh = display_ofs; - soh = copy_ofs; - yf = 0; - y = 0; - - /* for performance, keep VGA in write mode 1 the entire render */ - vga_setup_wm1_block_copy(); - - /* blank lines */ - if (dstart >= dh_blankfill) y = dstart - dh_blankfill; - else y = 0; - doh = gvar.video.page[0].stridew * y; - - while (y < dstart) { - vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew); - doh += gvar.video.page[0].stridew; - y++; - } - - /* draw */ - while (y < (dh+dstart)) { - soh = copy_ofs + ((yf >> 16UL) * gvar.video.page[0].stridew); - vga_wm1_mem_block_copy(doh,soh,gvar.video.page[0].stridew); - doh += gvar.video.page[0].stridew; - yf += ystep; - y++; - } - - /* blank lines */ - while (y < gvar.video.page[0].height && y < (dh+dstart+dh_blankfill)) { - vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew); - doh += gvar.video.page[0].stridew; - y++; - } - - /* done */ - vga_restore_rm0wm0(); - - /* wait for vsync */ - vga_wait_for_vsync(); - - /* make it shrink */ - dh -= dh_step; - if (dh < 40) dh_step = 1; - } - } - - IN_Shutdown(); - VGAmodeX(0, 1, &gvar); - free(vrl_lineoffs); - buffer = NULL; - free(buffer); - bufsz = 0; - free(bakapee1); - free(bakapee2); - return 0; -} +#include +#include +#include +#include + +#include "src/tesuto.h" + +#define FILENAME_1 "data/aconita.vrl" +#define FILENAME_2 "data/aconita.pal" + +static unsigned char palette[768]; +global_game_variables_t gvar; +player_t player[1]; + +int main(int argc,char **argv) { + struct vrl1_vgax_header *vrl_header; + vrl1_vgax_offset_t *vrl_lineoffs; + unsigned char *buffer; + unsigned int bufsz; + int fd; + char *bakapee1,*bakapee2; + + bakapee1=malloc(64); + bakapee2=malloc(1024); + + IN_Startup(); + IN_Default(0,&player,ctrl_Joystick); + IN_initplayer(&player, 0); + + if (argc < 3) { + fprintf(stderr,"drawvrl \n"); + bakapee1 = FILENAME_1;//"data/aconita.vrl"; + bakapee2 = FILENAME_2;//"data/aconita.pal"; + //return 1; + }else{ + if(argv[1]) bakapee1 = argv[1]; + if(argv[2]) bakapee2 = argv[2]; + } + + fd = open(bakapee1,O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Unable to open '%s'\n", bakapee1); + return 1; + } + { + unsigned long sz = lseek(fd,0,SEEK_END); + if (sz < sizeof(*vrl_header)) return 1; + if (sz >= 65535UL) return 1; + + bufsz = (unsigned int)sz; + buffer = malloc(bufsz); + if (buffer == NULL) return 1; + + lseek(fd,0,SEEK_SET); + if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1; + + vrl_header = (struct vrl1_vgax_header*)buffer; + if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1; + if (vrl_header->width == 0 || vrl_header->height == 0) return 1; + } + close(fd); + + probe_dos(); + if (!probe_vga()) { + printf("VGA probe failed\n"); + return 1; + } + VGAmodeX(1, 1, &gvar); + + /* load color palette */ + fd = open(bakapee2,O_RDONLY|O_BINARY); + if (fd >= 0) { + unsigned int i; + + read(fd,palette,768); + close(fd); + + vga_palette_lseek(0); + for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2); + } + + /* preprocess the sprite to generate line offsets */ + vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + if (vrl_lineoffs == NULL) return 1; + + /* setup camera and screen~ */ + modexHiganbanaPageSetup(&gvar.video); + gvar.video.page[1].dx=gvar.video.page[0].dx=16; + gvar.video.page[1].dy=gvar.video.page[0].dy=16; + modexShowPage(&(gvar.video.page[0])); + + #define VMEMHEIGHT gvar.video.page[0].height+gvar.video.page[1].height + + //4 this dose the screen + { + unsigned int i,j,o; + /* fill screen with a distinctive pattern */ + for (i=0;i < gvar.video.page[0].width;i++) { + o = i >> 2; + vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); + for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew) + vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! + } + } + + //while (getch() != 13); + + /* make distinctive pattern offscreen, render sprite, copy onscreen. + * this time, we render the distinctive pattern to another offscreen location and just copy. + * note this version is much faster too! */ + { + unsigned int i,j,o,o2; + int x,y,rx,ry,w,h; + unsigned int overdraw = 1; // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks. + // if the sprite's edge pixels are clear anyway, you can set this to 0. + VGA_RAM_PTR omemptr; + int xdir=1,ydir=1; + + //4 this dose the sprite? wwww + /* fill pattern offset with a distinctive pattern */ + for (i=0;i < gvar.video.page[0].width;i++) { + o = (i >> 2) + (0x10000UL - (uint16_t)gvar.video.page[1].data); + vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); + for (j=0;j < VMEMHEIGHT;j++,o += gvar.video.page[0].stridew) + vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! + } + + /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */ + x = 0; + y = 0; + + /* do it */ + omemptr = vga_state.vga_graphics_ram; // save original mem ptr + + while(!IN_KeyDown(sc_Escape)) + { + IN_ReadControl(0,&player); + if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0])); + if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1])); + if(IN_KeyDown(68)) //f10 + { + //gvar.kurokku.fpscap=!gvar.kurokku.fpscap; + IN_UserInput(1,1); + } + + /* render box bounds. y does not need modification, but x and width must be multiple of 4 */ + if (x >= overdraw) rx = (x - overdraw) & (~3); + else rx = -(gvar.video.page[0].dx); + if (y >= overdraw) ry = (y - overdraw); + else ry = -(gvar.video.page[0].dy); + h = vrl_header->height + overdraw + y - ry; + w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3); + if ((rx+w) > gvar.video.page[0].width) w = gvar.video.page[0].width-rx; + if ((ry+h) > gvar.video.page[0].height) h = (gvar.video.page[0].height)-ry; + + /* block copy pattern to where we will draw the sprite */ + vga_setup_wm1_block_copy(); + o2 = gvar.video.page[0].pagesize; + o = (0x10000UL - (uint16_t)gvar.video.page[1].data) + (ry * gvar.video.page[0].stridew) + (rx >> 2); // source offscreen + for (i=0;i < h;i++,o += gvar.video.page[0].stridew,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ + vga_restore_rm0wm0(); + + /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */ + vga_state.vga_draw_stride_limit = (gvar.video.page[0].width + 3/*round up*/ - x) >> 2; + vga_state.vga_draw_stride = w >> 2; + vga_state.vga_graphics_ram = omemptr + gvar.video.page[0].pagesize; + + /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ + draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + + /* restore ptr */ + vga_state.vga_graphics_ram = omemptr; + + /* block copy to visible RAM from offscreen */ + vga_setup_wm1_block_copy(); + o = gvar.video.page[0].pagesize; // source offscreen + o2 = (ry * gvar.video.page[0].stridew) + (rx >> 2); // dest visible (original stride) + for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += gvar.video.page[0].stridew) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ + vga_restore_rm0wm0(); + + /* restore stride */ + vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew; + + /* step */ + x += xdir; y += ydir; + if ((x + vrl_header->width) >= ((gvar.video.page[0].width + gvar.video.page[0].dx) - 1) || x == -(gvar.video.page[0].dx)) + xdir = -xdir; + if ((y + vrl_header->height) >= ((gvar.video.page[0].height + gvar.video.page[0].dy) - 1) || y == -(gvar.video.page[0].dy)) + ydir = -ydir; + //printf("[x%u y%u] [rx%u ry%u] [w%u h%u]\n", x, y, rx, ry, w, h); + } + } + + IN_UserInput(1,1); + + while(!IN_KeyDown(sc_Escape)) + { + if(IN_KeyDown(2)) modexShowPage(&(gvar.video.page[0])); + if(IN_KeyDown(3)) modexShowPage(&(gvar.video.page[1])); + } + + modexShowPage(&(gvar.video.page[0])); + /* another handy "demo" effect using VGA write mode 1. + * we can take what's on screen and vertically squash it like an old analog TV set turning off. */ + { + unsigned int blank_line_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height * 2); + unsigned int copy_ofs = (gvar.video.page[0].stridew * gvar.video.page[0].height); + unsigned int display_ofs = 0x0000; + unsigned int i,y,soh,doh,dstart; + unsigned int dh_blankfill = 8; + unsigned int dh_step = 8; + uint32_t sh,dh,yf,ystep; + + /* copy active display (0) to offscreen buffer (0x4000) */ + vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = gvar.video.page[0].stridew; + vga_setup_wm1_block_copy(); + vga_wm1_mem_block_copy(copy_ofs,display_ofs,gvar.video.page[0].stridew * gvar.video.page[0].height); + vga_restore_rm0wm0(); + + /* need a blank line as well */ + for (i=0;i < gvar.video.page[0].stridew;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0; + + sh = dh = gvar.video.page[0].height; + while (dh >= dh_step) { + /* stop animating if the user hits ENTER */ + if (kbhit()) { + if (getch() == 13) break; + } + + /* wait for vsync end */ + vga_wait_for_vsync_end(); + + /* what scalefactor to use for stretching? */ + ystep = (0x10000UL * sh) / dh; + dstart = (gvar.video.page[0].height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen + doh = display_ofs; + soh = copy_ofs; + yf = 0; + y = 0; + + /* for performance, keep VGA in write mode 1 the entire render */ + vga_setup_wm1_block_copy(); + + /* blank lines */ + if (dstart >= dh_blankfill) y = dstart - dh_blankfill; + else y = 0; + doh = gvar.video.page[0].stridew * y; + + while (y < dstart) { + vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew); + doh += gvar.video.page[0].stridew; + y++; + } + + /* draw */ + while (y < (dh+dstart)) { + soh = copy_ofs + ((yf >> 16UL) * gvar.video.page[0].stridew); + vga_wm1_mem_block_copy(doh,soh,gvar.video.page[0].stridew); + doh += gvar.video.page[0].stridew; + yf += ystep; + y++; + } + + /* blank lines */ + while (y < gvar.video.page[0].height && y < (dh+dstart+dh_blankfill)) { + vga_wm1_mem_block_copy(doh,blank_line_ofs,gvar.video.page[0].stridew); + doh += gvar.video.page[0].stridew; + y++; + } + + /* done */ + vga_restore_rm0wm0(); + + /* wait for vsync */ + vga_wait_for_vsync(); + + /* make it shrink */ + dh -= dh_step; + if (dh < 40) dh_step = 1; + } + } + + IN_Shutdown(); + VGAmodeX(0, 1, &gvar); + free(vrl_lineoffs); + buffer = NULL; + free(buffer); + bufsz = 0; + free(bakapee1); + free(bakapee2); + return 0; +} diff --git a/src/16.ses b/src/16.ses index 60043f41..faba5120 100755 --- a/src/16.ses +++ b/src/16.ses @@ -1,8 +1,8 @@ -# SciTE session file - -buffer.1.path=/dos/z/16/src/16.c -buffer.1.position=1 - -buffer.2.path=/dos/z/16/src/16.h -buffer.2.position=1 -buffer.2.current=1 +# SciTE session file + +buffer.1.path=/dos/z/16/src/16.c +buffer.1.position=1 + +buffer.2.path=/dos/z/16/src/16.h +buffer.2.position=1 +buffer.2.current=1 diff --git a/src/_scroll.c b/src/_scroll.c index 5a16247d..0db48708 100755 --- a/src/_scroll.c +++ b/src/_scroll.c @@ -1,394 +1,394 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "src/lib/scroll16.h" -#include "src/lib/16_timer.h" -#include "src/lib/wcpu/wcpu.h" -#include "src/lib/16_sprite.h" -#include "src/lib/16_ca.h" -#include "src/lib/16_mm.h" -//#include "src/lib/16_head.h"//included already - -//#define FADE -#define MODEX //this is for mode x initiating - -//word far *clock= (word far*) 0x046C; /* 18.2hz clock */ -//bitmap_t *p; -global_game_variables_t gvar; -static map_t map; -player_t player[MaxPlayers]; -map_view_t mv[4]; -byte *ppal; -//word pn=0; //i forgot ww -float t; -sword bakapee; -pan_t pan; -//debugswitches -boolean panswitch=0; -//extern boolean pageflipflop=1; - unsigned int i; - const char *cpus; - //static int persist_aniframe = 0; /* gonna be increased to 1 before being used, so 0 is ok for default */ - - //map_view_db_t pgid[4]; - word pg; -//#ifdef FADE - static word paloffset=0; - byte *dpal; -//#endif - byte *gpal; - byte *ptr; - byte *mappalptr; - -void main(int argc, char *argv[]) -{ - struct sprite sp; - __segment sega; - void __based(sega)* bigbuffer; - - byte *mesg=malloc(sizeof(dword)); - int i; - - if(argv[1]) bakapee = atoi(argv[1]); - else bakapee = 1; - - gvar.mm.mmstarted=0; - gvar.bigbuffer=bigbuffer; - - MM_Startup(&gvar.mm, &gvar.mmi); - CA_Startup(&gvar); - // DOSLIB: check our environment - probe_dos(); - - // DOSLIB: what CPU are we using? - // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. - // So this code by itself shouldn't care too much what CPU it's running on. Except that other - // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for - // the CPU to carry out tasks. --J.C. - cpu_probe(); - - // DOSLIB: check for VGA - if (!probe_vga()) { - printf("VGA probe failed\n"); - return; - } - // hardware must be VGA or higher! - if (!(vga_state.vga_flags & VGA_IS_VGA)) { - printf("This program requires VGA or higher graphics hardware\n"); - return; - } - - if (_DEBUG_INIT() == 0) { -#ifdef DEBUGSERIAL - printf("WARNING: Failed to initialize DEBUG output\n"); -#endif - } - _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log - _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U); - - pan.pn=1; - - start_timer(&gvar); - - /* create the map */ - fprintf(stderr, "testing map load~ "); - loadmap("data/test.map", &map); - chkmap(&map, 0); - printf("chkmap ok "); - fprintf(stderr, "yay map loaded~~\n"); - - /* draw the tiles */ -#ifdef MODEX - ptr = map.data; - - /* data */ - i = read_vrs(&gvar, "data/spri/chikyuu.vrs", sp.spritesheet); - if (i) - { - puts("Error! Did not load sprite!"); - return; - } - puts("Sprite should be loaded now"); - putch('q'); - print_anim_ids(&sp); - putch('r'); - i = set_anim_by_id(&sp, 10); - if (i == -1) - { - printf("Anim id not found!"); - return; - } -/* player[0].spri = malloc(...) - * read_vrs(&gvar, "data/spri/chikyuu.vrs", player[0].spri->spritesheet); // load sprite - putch('s'); - print_anim_ids(player[0].spri); - putch('t'); - i = set_anim_by_id(player[0].spri, 10); - if (i == -1) - { - printf("Anim id not found!"); - return; - }*/ - player[0].spri = &sp; - -#endif - /* input! */ - IN_Startup(); - IN_Default(0,&player,ctrl_Joystick); - - /* save the palette */ -#ifdef MODEX -#ifdef FADE - dpal = modexNewPal(); - modexPalSave(dpal); - modexFadeOff(4, dpal); -#endif - - textInit(); - VGAmodeX(bakapee, 1, &gvar); -#ifdef FADE - modexPalBlack(); //reset the palette~ -#endif -#endif - modexLoadPalFile("data/spri/chikyuu.pal", &ppal); - modexPalUpdate1(ppal); -#ifdef MODEX -#ifdef FADE - gpal = modexNewPal(); - modexPalSave(gpal); - modexSavePalFile("data/g.pal", gpal); - modexPalBlack(); //so player will not see loadings~ -#endif -#endif - - /* setup camera and screen~ */ - modexHiganbanaPageSetup(&gvar.video); - for(i=0;idata, mv[0].page->data, mv[0].page->pagesize); - - //TODO: put player in starting position of spot - //default player position on the viewable map - player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx; - player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny; - IN_initplayer(&player, 0); - //IN_initplayer(&player, 1); - -#ifndef SPRITE - modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); - //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); -#else - //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA); - //PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32, player[0].data); - animate_spri(player[0].spri); -#endif - - if(!pageflipflop) modexShowPage(mv[1].page); - else modexShowPage(mv[0].page);//!(gvar.video.p) - shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible. - - /* buffer pages */ -// modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47); -// modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45); -// { -// unsigned int k,j,o; -// /* fill screen with a distinctive pattern */ -// for (k=0;k < vga_state.vga_width;k++) { -// o = k >> 2; -// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); -// for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) -// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! -// } -// } - modexClearRegion(mv[3].page, 0, 128, 24, 36, 15); - -#ifdef MODEX -#ifdef FADE - modexFadeOn(4, gpal); -#endif -#endif - while(!IN_KeyDown(sc_Escape) && player[0].hp>0) - { - shinku(&gvar); - //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square - //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction - //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map - - //player movement - IN_ReadControl(0,&player); - if(!panswitch){ - walk(mv, player, 0); - }else{ - panpagemanual(mv, player, 0); - //printf(" player[0].q: %d", player[0].q); printf(" player[0].d: %d\n", player[0].d); - } - - //the scripting stuff.... - //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) - if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) - { - short i; - for(i=800; i>=400; i--) - { - sound(i); - } - nosound(); - } - if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; } - //debugging binds! - if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; } - if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; } - if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; } - if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; } - if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page); - IN_UserInput(1,1); - } //p -#ifdef MODEX -#ifdef FADE - if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page); IN_UserInput(1,1); } - if(IN_KeyDown(22)){ -// paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0); -// printf("1paloffset = %d\n", paloffset/3); -// modexPalUpdate(map.tiles->data, &paloffset, 0, 0); -// printf("2paloffset = %d\n", paloffset/3); -// modexpdump(mv[0].page); modexpdump(mv[1].page); - IN_UserInput(1,1); - } -#endif -#endif - //pan switch - if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);} //f12 - if(IN_KeyDown(87)) //f11 - { - pageflipflop=!pageflipflop; - IN_UserInput(1,1); -// VGAmodeX(0, 0, &gvar); -// IN_Shutdown(); -// __asm -// { -// mov ah,31h -// int 21h -// } - } - if(IN_KeyDown(68)) //f10 - { - gvar.kurokku.fpscap=!gvar.kurokku.fpscap; - IN_UserInput(1,1); - } - if(IN_KeyDown(67)) //f9 - { - modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2); - modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3); - modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4); - modexClearRegion(mv[3].page, 0, 0, 20, 36, 15); - //IN_UserInput(1,1); - } - if(IN_KeyDown(66)) //f8 - { -// modexDrawSprite(mv[0].page, 16, 16, p); -// modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data)); - } - //TODO fmemtest into page - /*if(IN_KeyDown(4+1)) //4 - { - pg=1; - SELECT_ALL_PLANES(); - _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4); - }*/ - - //9 - if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); } - //if(IN_KeyDown(11)){ modexPalOverscan(15); } - if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break; //incase things go out of sync! - } - - /* fade back to text mode */ - /* but 1st lets save the game palette~ */ -#ifdef MODEX -#ifdef FADE - modexPalSave(gpal); - modexSavePalFile("data/g.pal", gpal); - modexFadeOff(4, gpal); -#endif - VGAmodeX(0, 1, &gvar); -#endif - IN_Shutdown(); - MM_FreePtr(&bigbuffer, &gvar.mm); - CA_Shutdown(&gvar); - MM_Shutdown(&gvar.mm); - printf("\nProject 16 scroll.exe. This is just a test file!\n"); - printf("version %s\n", VERSION); - printf("tx: %d ", mv[0].tx); - printf("ty: %d\n", mv[0].ty); - printf("\n"); - printf("player vars:\n"); - printf(" x: %d", player[0].x); printf(" y: %d\n", player[0].y); - //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8); - //else printf("\nplayer[0].y: %d\n", player[0].y); - printf(" tx: %d", player[0].tx); printf(" ty: %d\n", player[0].ty); - printf(" triggx: %d", player[0].triggerx); printf(" triggy: %d\n", player[0].triggery); - printf(" hp: %d", (player[0].hp)); printf(" q: %d", player[0].q); printf(" player.info.dir: %d", player[0].info.dir); printf(" player.d: %d ", player[0].d); - printf(" pdir=%d\n", player[0].pdir); - printf(" tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]); -// printf("palette offset: %d\n", paloffset/3); -//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize()); -//++++ printf("Total free: %zu\n", GetFreeSize()); -//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n"); -//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n"); - printf("Virtual Screen: %dx", gvar.video.page[0].width); printf("%d ", gvar.video.page[0].height); - printf("Screen: %dx", gvar.video.page[0].sw); printf("%d\n", gvar.video.page[0].sh); - printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw); printf("%d ", gvar.video.page[0].tilesh); - printf("tile resolution: %dx", gvar.video.page[0].tw); printf("%d\n", gvar.video.page[0].th); - printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx); printf("%d\n", gvar.video.page[0].tilemidposscreeny); - modexprintmeminfo(&gvar.video); - //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf(" mv[%u].ty: %d ", pan.pn, mv[pan.pn].ty); - printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r); - printf("pageflipflop=%u\n", pageflipflop); - //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk); - //0000printf("gvar.video.clk=%f", gvar.video.clk); - printf("\n"); - //printf("map.width=%d map.height=%d map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]); - - printf("\n"); - switch(detectcpu()) - { - case 0: cpus = "8086/8088 or 186/88"; break; - case 1: cpus = "286"; break; - case 2: cpus = "386 or newer"; break; - default: cpus = "internal error"; break; - } - printf("detected CPU type: %s\n", cpus); -#ifdef MODEX -#ifdef FADE - modexFadeOn(4, dpal); -#endif -#endif -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/lib/scroll16.h" +#include "src/lib/16_timer.h" +#include "src/lib/wcpu/wcpu.h" +#include "src/lib/16_sprite.h" +#include "src/lib/16_ca.h" +#include "src/lib/16_mm.h" +//#include "src/lib/16_head.h"//included already + +//#define FADE +#define MODEX //this is for mode x initiating + +//word far *clock= (word far*) 0x046C; /* 18.2hz clock */ +//bitmap_t *p; +global_game_variables_t gvar; +static map_t map; +player_t player[MaxPlayers]; +map_view_t mv[4]; +byte *ppal; +//word pn=0; //i forgot ww +float t; +sword bakapee; +pan_t pan; +//debugswitches +boolean panswitch=0; +//extern boolean pageflipflop=1; + unsigned int i; + const char *cpus; + //static int persist_aniframe = 0; /* gonna be increased to 1 before being used, so 0 is ok for default */ + + //map_view_db_t pgid[4]; + word pg; +//#ifdef FADE + static word paloffset=0; + byte *dpal; +//#endif + byte *gpal; + byte *ptr; + byte *mappalptr; + +void main(int argc, char *argv[]) +{ + struct sprite sp; + __segment sega; + void __based(sega)* bigbuffer; + + byte *mesg=malloc(sizeof(dword)); + int i; + + if(argv[1]) bakapee = atoi(argv[1]); + else bakapee = 1; + + gvar.mm.mmstarted=0; + gvar.bigbuffer=bigbuffer; + + MM_Startup(&gvar.mm, &gvar.mmi); + CA_Startup(&gvar); + // DOSLIB: check our environment + probe_dos(); + + // DOSLIB: what CPU are we using? + // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. + // So this code by itself shouldn't care too much what CPU it's running on. Except that other + // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for + // the CPU to carry out tasks. --J.C. + cpu_probe(); + + // DOSLIB: check for VGA + if (!probe_vga()) { + printf("VGA probe failed\n"); + return; + } + // hardware must be VGA or higher! + if (!(vga_state.vga_flags & VGA_IS_VGA)) { + printf("This program requires VGA or higher graphics hardware\n"); + return; + } + + if (_DEBUG_INIT() == 0) { +#ifdef DEBUGSERIAL + printf("WARNING: Failed to initialize DEBUG output\n"); +#endif + } + _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log + _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U); + + pan.pn=1; + + start_timer(&gvar); + + /* create the map */ + fprintf(stderr, "testing map load~ "); + loadmap("data/test.map", &map); + chkmap(&map, 0); + printf("chkmap ok "); + fprintf(stderr, "yay map loaded~~\n"); + + /* draw the tiles */ +#ifdef MODEX + ptr = map.data; + + /* data */ + i = read_vrs(&gvar, "data/spri/chikyuu.vrs", sp.spritesheet); + if (i) + { + puts("Error! Did not load sprite!"); + return; + } + puts("Sprite should be loaded now"); + putch('q'); + print_anim_ids(&sp); + putch('r'); + i = set_anim_by_id(&sp, 10); + if (i == -1) + { + printf("Anim id not found!"); + return; + } +/* player[0].spri = malloc(...) + * read_vrs(&gvar, "data/spri/chikyuu.vrs", player[0].spri->spritesheet); // load sprite + putch('s'); + print_anim_ids(player[0].spri); + putch('t'); + i = set_anim_by_id(player[0].spri, 10); + if (i == -1) + { + printf("Anim id not found!"); + return; + }*/ + player[0].spri = &sp; + +#endif + /* input! */ + IN_Startup(); + IN_Default(0,&player,ctrl_Joystick); + + /* save the palette */ +#ifdef MODEX +#ifdef FADE + dpal = modexNewPal(); + modexPalSave(dpal); + modexFadeOff(4, dpal); +#endif + + textInit(); + VGAmodeX(bakapee, 1, &gvar); +#ifdef FADE + modexPalBlack(); //reset the palette~ +#endif +#endif + modexLoadPalFile("data/spri/chikyuu.pal", &ppal); + modexPalUpdate1(ppal); +#ifdef MODEX +#ifdef FADE + gpal = modexNewPal(); + modexPalSave(gpal); + modexSavePalFile("data/g.pal", gpal); + modexPalBlack(); //so player will not see loadings~ +#endif +#endif + + /* setup camera and screen~ */ + modexHiganbanaPageSetup(&gvar.video); + for(i=0;idata, mv[0].page->data, mv[0].page->pagesize); + + //TODO: put player in starting position of spot + //default player position on the viewable map + player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx; + player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny; + IN_initplayer(&player, 0); + //IN_initplayer(&player, 1); + +#ifndef SPRITE + modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); + //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); +#else + //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA); + //PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32, player[0].data); + animate_spri(player[0].spri); +#endif + + if(!pageflipflop) modexShowPage(mv[1].page); + else modexShowPage(mv[0].page);//!(gvar.video.p) + shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible. + + /* buffer pages */ +// modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47); +// modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45); +// { +// unsigned int k,j,o; +// /* fill screen with a distinctive pattern */ +// for (k=0;k < vga_state.vga_width;k++) { +// o = k >> 2; +// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); +// for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) +// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! +// } +// } + modexClearRegion(mv[3].page, 0, 128, 24, 36, 15); + +#ifdef MODEX +#ifdef FADE + modexFadeOn(4, gpal); +#endif +#endif + while(!IN_KeyDown(sc_Escape) && player[0].hp>0) + { + shinku(&gvar); + //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square + //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction + //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map + + //player movement + IN_ReadControl(0,&player); + if(!panswitch){ + walk(mv, player, 0); + }else{ + panpagemanual(mv, player, 0); + //printf(" player[0].q: %d", player[0].q); printf(" player[0].d: %d\n", player[0].d); + } + + //the scripting stuff.... + //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) + if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) + { + short i; + for(i=800; i>=400; i--) + { + sound(i); + } + nosound(); + } + if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; } + //debugging binds! + if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; } + if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; } + if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; } + if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; } + if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page); + IN_UserInput(1,1); + } //p +#ifdef MODEX +#ifdef FADE + if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page); IN_UserInput(1,1); } + if(IN_KeyDown(22)){ +// paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0); +// printf("1paloffset = %d\n", paloffset/3); +// modexPalUpdate(map.tiles->data, &paloffset, 0, 0); +// printf("2paloffset = %d\n", paloffset/3); +// modexpdump(mv[0].page); modexpdump(mv[1].page); + IN_UserInput(1,1); + } +#endif +#endif + //pan switch + if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);} //f12 + if(IN_KeyDown(87)) //f11 + { + pageflipflop=!pageflipflop; + IN_UserInput(1,1); +// VGAmodeX(0, 0, &gvar); +// IN_Shutdown(); +// __asm +// { +// mov ah,31h +// int 21h +// } + } + if(IN_KeyDown(68)) //f10 + { + gvar.kurokku.fpscap=!gvar.kurokku.fpscap; + IN_UserInput(1,1); + } + if(IN_KeyDown(67)) //f9 + { + modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2); + modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3); + modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4); + modexClearRegion(mv[3].page, 0, 0, 20, 36, 15); + //IN_UserInput(1,1); + } + if(IN_KeyDown(66)) //f8 + { +// modexDrawSprite(mv[0].page, 16, 16, p); +// modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data)); + } + //TODO fmemtest into page + /*if(IN_KeyDown(4+1)) //4 + { + pg=1; + SELECT_ALL_PLANES(); + _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4); + }*/ + + //9 + if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); } + //if(IN_KeyDown(11)){ modexPalOverscan(15); } + if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break; //incase things go out of sync! + } + + /* fade back to text mode */ + /* but 1st lets save the game palette~ */ +#ifdef MODEX +#ifdef FADE + modexPalSave(gpal); + modexSavePalFile("data/g.pal", gpal); + modexFadeOff(4, gpal); +#endif + VGAmodeX(0, 1, &gvar); +#endif + IN_Shutdown(); + MM_FreePtr(&bigbuffer, &gvar.mm); + CA_Shutdown(&gvar); + MM_Shutdown(&gvar.mm); + printf("\nProject 16 scroll.exe. This is just a test file!\n"); + printf("version %s\n", VERSION); + printf("tx: %d ", mv[0].tx); + printf("ty: %d\n", mv[0].ty); + printf("\n"); + printf("player vars:\n"); + printf(" x: %d", player[0].x); printf(" y: %d\n", player[0].y); + //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8); + //else printf("\nplayer[0].y: %d\n", player[0].y); + printf(" tx: %d", player[0].tx); printf(" ty: %d\n", player[0].ty); + printf(" triggx: %d", player[0].triggerx); printf(" triggy: %d\n", player[0].triggery); + printf(" hp: %d", (player[0].hp)); printf(" q: %d", player[0].q); printf(" player.info.dir: %d", player[0].info.dir); printf(" player.d: %d ", player[0].d); + printf(" pdir=%d\n", player[0].pdir); + printf(" tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]); +// printf("palette offset: %d\n", paloffset/3); +//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize()); +//++++ printf("Total free: %zu\n", GetFreeSize()); +//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n"); +//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n"); + printf("Virtual Screen: %dx", gvar.video.page[0].width); printf("%d ", gvar.video.page[0].height); + printf("Screen: %dx", gvar.video.page[0].sw); printf("%d\n", gvar.video.page[0].sh); + printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw); printf("%d ", gvar.video.page[0].tilesh); + printf("tile resolution: %dx", gvar.video.page[0].tw); printf("%d\n", gvar.video.page[0].th); + printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx); printf("%d\n", gvar.video.page[0].tilemidposscreeny); + modexprintmeminfo(&gvar.video); + //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf(" mv[%u].ty: %d ", pan.pn, mv[pan.pn].ty); + printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r); + printf("pageflipflop=%u\n", pageflipflop); + //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk); + //0000printf("gvar.video.clk=%f", gvar.video.clk); + printf("\n"); + //printf("map.width=%d map.height=%d map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]); + + printf("\n"); + switch(detectcpu()) + { + case 0: cpus = "8086/8088 or 186/88"; break; + case 1: cpus = "286"; break; + case 2: cpus = "386 or newer"; break; + default: cpus = "internal error"; break; + } + printf("detected CPU type: %s\n", cpus); +#ifdef MODEX +#ifdef FADE + modexFadeOn(4, dpal); +#endif +#endif +} diff --git a/src/bakapi.c b/src/bakapi.c index a74e7711..a94cf391 100755 --- a/src/bakapi.c +++ b/src/bakapi.c @@ -1,314 +1,314 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You screen.heightould have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "src/bakapi.h" - -/* - * BAKAPEE! - */ -global_game_variables_t gvar; -static bakapee_t bakapee; -word key,d,xpos,ypos,xdir,ydir; -sword vgamodex_mode = 1; // 320x240 default -int ch=0x0; - -void -main(int argc, char *argvar[]) -{ - char *a; - int i; - word panq=1, pand=0; - boolean panswitch=0; - - // allow changing default mode from command line - for (i=1;i < argc;) { - a = argvar[i++]; - - if (*a == '-') { - do { a++; } while (*a == '-'); - - if (!strcmp(a,"mx")) { - // (based on src/lib/modex16.c) - // 1 = 320x240 - // 2 = 160x120 - // 3 = 320x200 - // 4 = 192x144 - // 5 = 256x192 - vgamodex_mode = (sword)strtoul(argvar[i++],NULL,0); - } - else { - fprintf(stderr,"Unknown switch %s\n",a); - return; - } - } - else { - fprintf(stderr,"Unknown command arg %s\n",a); - return; - } - } - - // DOSLIB: check our environment - probe_dos(); - - // DOSLIB: what CPU are we using? - // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. - // So this code by itself shouldn't care too much what CPU it's running on. Except that other - // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for - // the CPU to carry out tasks. --J.C. - cpu_probe(); - - // DOSLIB: check for VGA - if (!probe_vga()) { - printf("VGA probe failed\n"); - return; - } - // hardware must be VGA or higher! - if (!(vga_state.vga_flags & VGA_IS_VGA)) { - printf("This program requires VGA or higher graphics hardware\n"); - return; - } - - // main variables values - d=4; // switch variable - key=2; // default screensaver number - xpos=TILEWHD; - ypos=TILEWHD; - xdir=1; - ydir=1; - - VGAmodeX(vgamodex_mode, 1, &gvar); // TODO: Suggestion: Instead of magic numbers for the first param, might I suggest defining an enum or some #define constants that are easier to remember? --J.C. - // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in. - // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C. - - bakapee.xx = rand()&0%gvar.video.page[0].width; - bakapee.yy = rand()&0%gvar.video.page[0].height; - bakapee.gq = 0; - bakapee.sx=0; - bakapee.sy=0; - bakapee.bakax=0; - bakapee.bakay=0; - bakapee.coor=0; - bakapee.tile=0; - - /* setup camera and screen~ */ - gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]); - textInit(); - - //modexPalUpdate(bmp.palette); //____ - //modexDrawBmp(VGA, 0, 0, &bmp, 0); //____ - //getch(); //____ - - modexShowPage(&gvar.video.page[0]); - -// screen savers -#ifdef BOINK - while(d>0) // on! - { - int c; - /* run screensaver routine until keyboard input */ - while (key > 0) { - if (kbhit()) { - if(!panswitch) - { - getch(); // eat keyboard input - break; - }else c=getch(); - } - - if(!panswitch) ding(&gvar.video.page[0], &bakapee, key); - else ding(&gvar.video.page[0], &bakapee, 2); - if(panswitch!=0) - { - //right movement - if((c==0x4d && pand == 0) || pand == 2) - { - if(pand == 0){ pand = 2; } - if(panq<=(TILEWH/(4))) - { - gvar.video.page[0].dx++; - modexShowPage(&gvar.video.page[0]); - panq++; - } else { panq = 1; pand = 0; } - } - //left movement - if((c==0x4b && pand == 0) || pand == 4) - { - if(pand == 0){ pand = 4; } - if(panq<=(TILEWH/(4))) - { - gvar.video.page[0].dx--; - modexShowPage(&gvar.video.page[0]); - panq++; - } else { panq = 1; pand = 0; } - } - //down movement - if((c==0x50 && pand == 0) || pand == 3) - { - if(pand == 0){ pand = 3; } - if(panq<=(TILEWH/(4))) - { - gvar.video.page[0].dy++; - modexShowPage(&gvar.video.page[0]); - panq++; - } else { panq = 1; pand = 0; } - } - //up movement - if((c==0x48 && pand == 0) || pand == 1) - { - if(pand == 0){ pand = 1; } - if(panq<=(TILEWH/(4))) - { - gvar.video.page[0].dy--; - modexShowPage(&gvar.video.page[0]); - panq++; - } else { panq = 1; pand = 0; } - } - if(c==0x71 || c==0xb1 || c=='p') - { - //getch(); // eat keyboard input - panswitch=0; - break; // 'q' or 'ESC' or 'p' - } - } - } - - { - - // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in. - // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C. - VGAmodeX(0, 0, &gvar); - // user imput switch - //fprintf(stderr, "xx=%d yy=%d tile=%d\n", bakapee.xx, bakapee.yy, bakapee.tile); - //fprintf(stderr, "dx=%d dy=%d ", gvar.video.page[0].dx, gvar.video.page[0].dy); - printf("Tiled mode is "); - switch (bakapee.tile) - { - case 0: - printf("off. "); - break; - case 1: - printf("on. "); - break; - } - //printf("\n"); - printf("Pan mode is "); - switch (panswitch) - { - case 0: - printf("off.\n"); - break; - case 1: - printf("on.\n"); - break; - } - printf("Enter 1, 2, 3, 4, 5, 6, 8, or 9 to run a screensaver, or enter 0 to quit.\n"); -pee: - c = getch(); - switch (c) { - case 27: /* Escape key */ - case '0': - d=0; - break; - case 'p': // test pan - switch (panswitch) - { - case 0: - panswitch=1; - break; - case 1: - panswitch=0; - break; - } - goto pee; - break; - case 'b': // test tile change - switch (bakapee.tile) - { - case 0: - bakapee.tile=1; - break; - case 1: - bakapee.tile=0; - break; - } - key=0; - break; - case '8': - c+=8; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '9': - key = c - '0'; - VGAmodeX(vgamodex_mode, 0, &gvar); - gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]); - // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in. - // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C. - modexShowPage(&gvar.video.page[0]); - break; - default: - key=0; - break; - } - } - } -#else // !defined(BOINK) -// FIXME: Does not compile. Do you want to remove this? -// TODO: This is a testing sextion for textrendering and panning for project 16 --sparky4 - while(1) - { // conditions of screen saver -// while(!kbhit()) -// { -// ding(&gvar.video.page[0], &bakapee, key); -// } - //end of screen savers - //pdump(&gvar.video.page[0]); - -// mxOutText(xpos+1, ypos+gvar.video.page[0].height-48, "========================================"); -// mxOutText(xpos+1, ypos+gvar.video.page[0].height-40, "| |Chikyuu:$line1"); -// mxOutText(xpos+1, ypos+gvar.video.page[0].height-32, "| |$line2"); -// mxOutText(xpos+1, ypos+gvar.video.page[0].height-24, "| |$line3"); -// mxOutText(xpos+1, ypos+gvar.video.page[0].height-16, "| |$line4"); -// mxOutText(xpos+1, ypos+gvar.video.page[0].height-8, "========================================"); - - ding(&gvar.video.page[0], &bakapee, key); - modexPanPage(&gvar.video.page[0], xpos, ypos); - c = getch(); - -// xpos+=xdir; -// ypos+=ydir; -// if( (xpos>(gvar.video.page[0].sw-gvar.video.page[0].width-1)) || (xpos<1)){xdir=-xdir;} -// if( (ypos>(gvar.video.page[0].sh-gvar.video.page[0].height-1)) || (ypos<1)){ydir=-ydir;} -// ch=getch(); - if(ch==0x71)break; // 'q' - if(ch==0x1b)break; // 'ESC' - } - VGAmodeX(0, 1, &gvar); -#endif // defined(BOINK) -// printf("page.width=%u ", gvar.video.page[0].width); printf("page.height=%u\n", gvar.video.page[0].height); - printf("bakapi ver. 1.04.16.04\nis made by sparky4i†ƒÖ…j feel free to use it ^^\nLicence: GPL v3\n"); - printf("compiled on 2016/04/04\n"); -} -//pee! +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You screen.heightould have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/bakapi.h" + +/* + * BAKAPEE! + */ +global_game_variables_t gvar; +static bakapee_t bakapee; +word key,d,xpos,ypos,xdir,ydir; +sword vgamodex_mode = 1; // 320x240 default +int ch=0x0; + +void +main(int argc, char *argvar[]) +{ + char *a; + int i; + word panq=1, pand=0; + boolean panswitch=0; + + // allow changing default mode from command line + for (i=1;i < argc;) { + a = argvar[i++]; + + if (*a == '-') { + do { a++; } while (*a == '-'); + + if (!strcmp(a,"mx")) { + // (based on src/lib/modex16.c) + // 1 = 320x240 + // 2 = 160x120 + // 3 = 320x200 + // 4 = 192x144 + // 5 = 256x192 + vgamodex_mode = (sword)strtoul(argvar[i++],NULL,0); + } + else { + fprintf(stderr,"Unknown switch %s\n",a); + return; + } + } + else { + fprintf(stderr,"Unknown command arg %s\n",a); + return; + } + } + + // DOSLIB: check our environment + probe_dos(); + + // DOSLIB: what CPU are we using? + // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. + // So this code by itself shouldn't care too much what CPU it's running on. Except that other + // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for + // the CPU to carry out tasks. --J.C. + cpu_probe(); + + // DOSLIB: check for VGA + if (!probe_vga()) { + printf("VGA probe failed\n"); + return; + } + // hardware must be VGA or higher! + if (!(vga_state.vga_flags & VGA_IS_VGA)) { + printf("This program requires VGA or higher graphics hardware\n"); + return; + } + + // main variables values + d=4; // switch variable + key=2; // default screensaver number + xpos=TILEWHD; + ypos=TILEWHD; + xdir=1; + ydir=1; + + VGAmodeX(vgamodex_mode, 1, &gvar); // TODO: Suggestion: Instead of magic numbers for the first param, might I suggest defining an enum or some #define constants that are easier to remember? --J.C. + // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in. + // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C. + + bakapee.xx = rand()&0%gvar.video.page[0].width; + bakapee.yy = rand()&0%gvar.video.page[0].height; + bakapee.gq = 0; + bakapee.sx=0; + bakapee.sy=0; + bakapee.bakax=0; + bakapee.bakay=0; + bakapee.coor=0; + bakapee.tile=0; + + /* setup camera and screen~ */ + gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]); + textInit(); + + //modexPalUpdate(bmp.palette); //____ + //modexDrawBmp(VGA, 0, 0, &bmp, 0); //____ + //getch(); //____ + + modexShowPage(&gvar.video.page[0]); + +// screen savers +#ifdef BOINK + while(d>0) // on! + { + int c; + /* run screensaver routine until keyboard input */ + while (key > 0) { + if (kbhit()) { + if(!panswitch) + { + getch(); // eat keyboard input + break; + }else c=getch(); + } + + if(!panswitch) ding(&gvar.video.page[0], &bakapee, key); + else ding(&gvar.video.page[0], &bakapee, 2); + if(panswitch!=0) + { + //right movement + if((c==0x4d && pand == 0) || pand == 2) + { + if(pand == 0){ pand = 2; } + if(panq<=(TILEWH/(4))) + { + gvar.video.page[0].dx++; + modexShowPage(&gvar.video.page[0]); + panq++; + } else { panq = 1; pand = 0; } + } + //left movement + if((c==0x4b && pand == 0) || pand == 4) + { + if(pand == 0){ pand = 4; } + if(panq<=(TILEWH/(4))) + { + gvar.video.page[0].dx--; + modexShowPage(&gvar.video.page[0]); + panq++; + } else { panq = 1; pand = 0; } + } + //down movement + if((c==0x50 && pand == 0) || pand == 3) + { + if(pand == 0){ pand = 3; } + if(panq<=(TILEWH/(4))) + { + gvar.video.page[0].dy++; + modexShowPage(&gvar.video.page[0]); + panq++; + } else { panq = 1; pand = 0; } + } + //up movement + if((c==0x48 && pand == 0) || pand == 1) + { + if(pand == 0){ pand = 1; } + if(panq<=(TILEWH/(4))) + { + gvar.video.page[0].dy--; + modexShowPage(&gvar.video.page[0]); + panq++; + } else { panq = 1; pand = 0; } + } + if(c==0x71 || c==0xb1 || c=='p') + { + //getch(); // eat keyboard input + panswitch=0; + break; // 'q' or 'ESC' or 'p' + } + } + } + + { + + // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in. + // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C. + VGAmodeX(0, 0, &gvar); + // user imput switch + //fprintf(stderr, "xx=%d yy=%d tile=%d\n", bakapee.xx, bakapee.yy, bakapee.tile); + //fprintf(stderr, "dx=%d dy=%d ", gvar.video.page[0].dx, gvar.video.page[0].dy); + printf("Tiled mode is "); + switch (bakapee.tile) + { + case 0: + printf("off. "); + break; + case 1: + printf("on. "); + break; + } + //printf("\n"); + printf("Pan mode is "); + switch (panswitch) + { + case 0: + printf("off.\n"); + break; + case 1: + printf("on.\n"); + break; + } + printf("Enter 1, 2, 3, 4, 5, 6, 8, or 9 to run a screensaver, or enter 0 to quit.\n"); +pee: + c = getch(); + switch (c) { + case 27: /* Escape key */ + case '0': + d=0; + break; + case 'p': // test pan + switch (panswitch) + { + case 0: + panswitch=1; + break; + case 1: + panswitch=0; + break; + } + goto pee; + break; + case 'b': // test tile change + switch (bakapee.tile) + { + case 0: + bakapee.tile=1; + break; + case 1: + bakapee.tile=0; + break; + } + key=0; + break; + case '8': + c+=8; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '9': + key = c - '0'; + VGAmodeX(vgamodex_mode, 0, &gvar); + gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]); + // this code is written around modex16 which so far is a better fit than using DOSLIB vga directly, so leave MXLIB code in. + // we'll integrate DOSLIB vga into that part of the code instead for less disruption. -- J.C. + modexShowPage(&gvar.video.page[0]); + break; + default: + key=0; + break; + } + } + } +#else // !defined(BOINK) +// FIXME: Does not compile. Do you want to remove this? +// TODO: This is a testing sextion for textrendering and panning for project 16 --sparky4 + while(1) + { // conditions of screen saver +// while(!kbhit()) +// { +// ding(&gvar.video.page[0], &bakapee, key); +// } + //end of screen savers + //pdump(&gvar.video.page[0]); + +// mxOutText(xpos+1, ypos+gvar.video.page[0].height-48, "========================================"); +// mxOutText(xpos+1, ypos+gvar.video.page[0].height-40, "| |Chikyuu:$line1"); +// mxOutText(xpos+1, ypos+gvar.video.page[0].height-32, "| |$line2"); +// mxOutText(xpos+1, ypos+gvar.video.page[0].height-24, "| |$line3"); +// mxOutText(xpos+1, ypos+gvar.video.page[0].height-16, "| |$line4"); +// mxOutText(xpos+1, ypos+gvar.video.page[0].height-8, "========================================"); + + ding(&gvar.video.page[0], &bakapee, key); + modexPanPage(&gvar.video.page[0], xpos, ypos); + c = getch(); + +// xpos+=xdir; +// ypos+=ydir; +// if( (xpos>(gvar.video.page[0].sw-gvar.video.page[0].width-1)) || (xpos<1)){xdir=-xdir;} +// if( (ypos>(gvar.video.page[0].sh-gvar.video.page[0].height-1)) || (ypos<1)){ydir=-ydir;} +// ch=getch(); + if(ch==0x71)break; // 'q' + if(ch==0x1b)break; // 'ESC' + } + VGAmodeX(0, 1, &gvar); +#endif // defined(BOINK) +// printf("page.width=%u ", gvar.video.page[0].width); printf("page.height=%u\n", gvar.video.page[0].height); + printf("bakapi ver. 1.04.16.04\nis made by sparky4i†ƒÖ…j feel free to use it ^^\nLicence: GPL v3\n"); + printf("compiled on 2016/04/04\n"); +} +//pee! diff --git a/src/bakapi.h b/src/bakapi.h index 1270fab7..7c1fb1ab 100755 --- a/src/bakapi.h +++ b/src/bakapi.h @@ -1,31 +1,31 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __BAKAPI_H_ -#define __BAKAPI_H_ - -#include "src/lib/bakapee.h" - -//project 16 testing define switch for veiwing the contents of the video memory --sparky4 -#define BOINK // what does this mean? --J.C. - -#endif /*__BAKAPI_H_*/ +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __BAKAPI_H_ +#define __BAKAPI_H_ + +#include "src/lib/bakapee.h" + +//project 16 testing define switch for veiwing the contents of the video memory --sparky4 +#define BOINK // what does this mean? --J.C. + +#endif /*__BAKAPI_H_*/ diff --git a/src/emmtest.c b/src/emmtest.c index eefab9ea..e8bfe1f5 100755 --- a/src/emmtest.c +++ b/src/emmtest.c @@ -8,8 +8,8 @@ minor mods by Alex Russell to simplify - Must use memory model with FAR code - + Must use memory model with FAR code + Open Watcom patch by sparky4~ */ @@ -17,11 +17,11 @@ #include #include #include -#include +#include + +#include "src/lib/exmm/memory.h" +#include "src/lib/types.h" -#include "src/lib/exmm/memory.h" -#include "src/lib/types.h" - #define PEMMDATAPAGENUM 4 void TransformData(char *pEmmData, unsigned int len) @@ -37,30 +37,30 @@ void TransformData(char *pEmmData, unsigned int len) int main(int argc, char *argv[]) { - byte *pEmmData; - int hEData; - unsigned long advi; - unsigned long i=0; - char huge *p =(char huge *)(GetEMMSeg0()*0x10000); + byte *pEmmData; + int hEData; + unsigned long advi; + unsigned long i=0; + char huge *p =(char huge *)(GetEMMSeg0()*0x10000); if(OpenEMM() != SUCCESS) { // make sure we got EMM printf("EMM unavailable.\n"); exit(1); } - else + else { - printf("Emm %x available\n", EMVer()); - printf("EMS pages available are %lu\n", EMMCoreLeft()); - //printf("EMM Hardware Information %lu\n", EMInfo()); + printf("Emm %x available\n", EMVer()); + printf("EMS pages available are %lu\n", EMMCoreLeft()); + //printf("EMM Hardware Information %lu\n", EMInfo()); } - - printf("b4 EMS pEmmData=%p\n", pEmmData); - //printf("b4 EMS *pEmmData=%s\n", *pEmmData); - advi=EMMCoreLeft()*EMMPAGESIZE; - printf("advi=%lu\n", advi); - - pEmmData = (byte *)EMMalloc(&hEData, EMMCoreLeft()); // get 6 * 16K bytes - 96K + + printf("b4 EMS pEmmData=%p\n", pEmmData); + //printf("b4 EMS *pEmmData=%s\n", *pEmmData); + advi=EMMCoreLeft()*EMMPAGESIZE; + printf("advi=%lu\n", advi); + + pEmmData = (byte *)EMMalloc(&hEData, EMMCoreLeft()); // get 6 * 16K bytes - 96K if(pEmmData == NULL/* || pEmmData0 == NULL*/) { printf("Not enough EMM or out of handles.\n"); @@ -68,73 +68,73 @@ int main(int argc, char *argv[]) } else printf("EMM allocate OK\n"); - - printf("EMS pages available are %lu\n", EMMCoreLeft()); - - - + + printf("EMS pages available are %lu\n", EMMCoreLeft()); + + + printf("Map 1st 4 pages\n"); MapEMM(hEData, 0, PEMMDATAPAGENUM); // load 1st 4 pages into page frame: 0-3 - //memset(pEmmData, 0x0e, 64000u); -//0000 printf("(advi*EMMPAGESIZE)=%lu\n", advi); - memset(pEmmData, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE)); -//qqqq memset(pEmmData+0x10000, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE)); -//---- UnmapEMM(hEData, 0, 4); // not absolutely necessary - printf("%p= %c %c %c %c %c %c %c %c\n", pEmmData, -*pEmmData, *(pEmmData+1), *(pEmmData+2), *(pEmmData+3), *(pEmmData+4), *(pEmmData+5), *(pEmmData+6), *(pEmmData+7)); + //memset(pEmmData, 0x0e, 64000u); +//0000 printf("(advi*EMMPAGESIZE)=%lu\n", advi); + memset(pEmmData, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE)); +//qqqq memset(pEmmData+0x10000, atoi(argv[1]), 0xffff);//sizeof(atoi(argv[1])));//((EMMCoreLeft())*EMMPAGESIZE)); +//---- UnmapEMM(hEData, 0, 4); // not absolutely necessary + printf("%p= %c %c %c %c %c %c %c %c\n", pEmmData, +*pEmmData, *(pEmmData+1), *(pEmmData+2), *(pEmmData+3), *(pEmmData+4), *(pEmmData+5), *(pEmmData+6), *(pEmmData+7)); /*printf("Map next 2 pages\n"); MapEMM(hEData, 4, 2); // map last 2 pages: 4-5 - memset(pEmmData, 0x04, 32768u); -// memset(pEmmData, atoi(argv[0]), 32768u); - printf("*pEmmData=%c\n", *pEmmData); - printf(" pEmmData=%p\n", pEmmData);*/ + memset(pEmmData, 0x04, 32768u); +// memset(pEmmData, atoi(argv[0]), 32768u); + printf("*pEmmData=%c\n", *pEmmData); + printf(" pEmmData=%p\n", pEmmData);*/ /*MapEMM(hEData, 0, 4); // do some stuff with the first 64K of file data. printf("Transform data\n"); - TransformData(pEmmData, 64000UL); + TransformData(pEmmData, 64000UL); printf("*pEmmData=%lu\n", *pEmmData); MapEMM(hEData, 4, 2); // only unmaps 1st two pages of prior 64k mapping // do stuff with remaining 32K of data - TransformData(pEmmData, 32768UL); - printf("*pEmmData=%lu\n", *pEmmData);*/ - if(atoi(argv[2])) - { - while(p<(char huge *)((GetEMMSeg0()*0x10000)+0xffff) && !kbhit()) - { - if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p, -*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), -*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15)); - // (*p)++; - i++; - p++; - } - } - /*if(atoi(argv[3])) - p =(char huge *)(GetEMMSeg0()*0x20000); - while(p<(char huge *)((GetEMMSeg0()*0x20000)+0xffff) && !kbhit()) - { - if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p, -*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), -*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15)); - // (*p)++; - i++; - p++; - } - //free(p); - }*/ - if(!atoi(argv[3])) + TransformData(pEmmData, 32768UL); + printf("*pEmmData=%lu\n", *pEmmData);*/ + if(atoi(argv[2])) { - UnmapEMM(hEData, 0, PEMMDATAPAGENUM); // should unmap before freeing + while(p<(char huge *)((GetEMMSeg0()*0x10000)+0xffff) && !kbhit()) + { + if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p, +*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), +*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15)); + // (*p)++; + i++; + p++; + } + } + /*if(atoi(argv[3])) + p =(char huge *)(GetEMMSeg0()*0x20000); + while(p<(char huge *)((GetEMMSeg0()*0x20000)+0xffff) && !kbhit()) + { + if((i%16)==0) printf("%p= %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", p, +*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), +*(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15)); + // (*p)++; + i++; + p++; + } + //free(p); + }*/ + if(!atoi(argv[3])) + { + UnmapEMM(hEData, 0, PEMMDATAPAGENUM); // should unmap before freeing //printf("after EMS *pEmmData=%c\n", *pEmmData); printf("Close emm\n"); EMMFree(hEData); // finished with the file data - CloseEMM(); - } - printf("after EMS pEmmData=%p\n", pEmmData); - printf("EMS pages available are %lu\n", EMMCoreLeft()); - printf("GetEMMSeg0=%p\n", GetEMMSeg0()*0x10000); - //printf("EMMPAGESIZE=%d\n", EMMPAGESIZE); - return 0; + CloseEMM(); + } + printf("after EMS pEmmData=%p\n", pEmmData); + printf("EMS pages available are %lu\n", EMMCoreLeft()); + printf("GetEMMSeg0=%p\n", GetEMMSeg0()*0x10000); + //printf("EMMPAGESIZE=%d\n", EMMPAGESIZE); + return 0; } diff --git a/src/emsdump.c b/src/emsdump.c index b07f7c66..45069863 100755 --- a/src/emsdump.c +++ b/src/emsdump.c @@ -1,58 +1,58 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -//#include - -#include "src/lib/exmm/memory.h" - -int main(int argc, char *argv[]) -{ - unsigned long i=0; - char near w; - char huge *p =(char huge *)(GetEMMSeg0()*0x10000);//0xD0000000; - //char far *q =(char far *)0x53332225; - printf("1p=%p %ul\n", p, GetEMMSeg0()); - //while(!kbhit()){ printf("%p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff)); } - //while(!kbhit()){ printf("%p\n", ((GetEMMSeg0()*0x10000)+0xffff)); } - if(argv[1]) { printf("switch on!\n"); while(!kbhit()){} } - while(p<=(char huge *)((GetEMMSeg0()*0x10000)+0xffff)/*i<262144UL*/ && !kbhit()) - { - if(argv[1]!=NULL) (*p) = i; else - //else printf("%p= %x% %ul\n", p, *p, i); - if((i%8)==0) printf("%p= %c %c %c %c %c %c %c %c\n", p, -*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7)); -// (*p)++; -// printf(" %p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff)); - i++; - p++; - } - w=104; - //printf("*q=%d\n",*q); - //printf(" q=%p\n", q); - printf(" p=%p\n", p); - printf(" w=%d\n", w); - printf(" w=%p\n", w); - printf("GetEMMSeg0()=%p\n", GetEMMSeg0()*0x10000); - return 0; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +//#include + +#include "src/lib/exmm/memory.h" + +int main(int argc, char *argv[]) +{ + unsigned long i=0; + char near w; + char huge *p =(char huge *)(GetEMMSeg0()*0x10000);//0xD0000000; + //char far *q =(char far *)0x53332225; + printf("1p=%p %ul\n", p, GetEMMSeg0()); + //while(!kbhit()){ printf("%p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff)); } + //while(!kbhit()){ printf("%p\n", ((GetEMMSeg0()*0x10000)+0xffff)); } + if(argv[1]) { printf("switch on!\n"); while(!kbhit()){} } + while(p<=(char huge *)((GetEMMSeg0()*0x10000)+0xffff)/*i<262144UL*/ && !kbhit()) + { + if(argv[1]!=NULL) (*p) = i; else + //else printf("%p= %x% %ul\n", p, *p, i); + if((i%8)==0) printf("%p= %c %c %c %c %c %c %c %c\n", p, +*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7)); +// (*p)++; +// printf(" %p\n", ((GetEMMSeg0()*0x10000)+0x0fffffff)); + i++; + p++; + } + w=104; + //printf("*q=%d\n",*q); + //printf(" q=%p\n", q); + printf(" p=%p\n", p); + printf(" w=%d\n", w); + printf(" w=%p\n", w); + printf("GetEMMSeg0()=%p\n", GetEMMSeg0()*0x10000); + return 0; +} diff --git a/src/emstest.c b/src/emstest.c index f9c6500d..8c570b2e 100755 --- a/src/emstest.c +++ b/src/emstest.c @@ -1,7 +1,7 @@ -#include -#include -#include -#include "src\lib\ems.c" +#include +#include +#include +#include "src\lib\ems.c" /* Test function for the EMM routines */ @@ -55,4 +55,4 @@ } emmclose(emmhandle); - } + } diff --git a/src/exmmtest.c b/src/exmmtest.c index bddf4a09..aa21497e 100755 --- a/src/exmmtest.c +++ b/src/exmmtest.c @@ -98,7 +98,8 @@ main(int argc, char *argv[]) //printf("main()=%Fp start MM\n", *argv[0]); MM_Startup(&gvar); PM_Startup(&gvar); - //PM_UnlockMainMem(&gvar); + PM_CheckMainMem(&gvar); + PM_UnlockMainMem(&gvar); CA_Startup(&gvar); // printf(" done!\n"); PRINTBB; diff --git a/src/lib/16_dbg.c b/src/lib/16_dbg.c index 2215c420..7766a1d4 100755 --- a/src/lib/16_dbg.c +++ b/src/lib/16_dbg.c @@ -1,76 +1,76 @@ - -#include "src/16.h" - -// TODO: Could we also provide a build mode to emit debug to the "Bochs E9 hack?" -#ifdef DEBUGSERIAL -# include -# include -# include - -unsigned char _DEBUG_INITed = 0; -struct info_8250 *_DEBUG_uart = NULL; - -int _DEBUG_INIT() { - if (!_DEBUG_INITed) { - unsigned int i; - uint16_t port; - - if (!init_8250()) return 0; - - // what does the BIOS say the serial ports are? - probe_8250_bios_ports(); - for (i=0;i < bios_8250_ports;i++) { - port = get_8250_bios_port(i); - if (port == 0) continue; - probe_8250(port); - } - - // what about the standard serial ports? - for (i=0;i < (sizeof(standard_8250_ports)/sizeof(standard_8250_ports[0]));i++) { - port = standard_8250_ports[i]; - if (port == 0) continue; - probe_8250(port); - } - - // pick the first port, which is probably COM1 - if (base_8250_ports == 0) return 0; // FIXME: You know "base_8250_ports" is probably a bad variable name for the max entries in info_8250_port[] - _DEBUG_uart = &info_8250_port[0]; - _DEBUG_INITed = 1; - - // init the COM port. - // in DOSBox-X, the "log" mode will receive our text and print it into the log file - // on real hardware, our text will likely go over a null modem cable to another PC running a serial terminal program like PuTTY or minicom. - // if nothing is connected, then the bytes go off into the ether to get lost and life goes on. - uart_8250_enable_interrupt(_DEBUG_uart,0); // disable interrupts - uart_8250_set_FIFO(_DEBUG_uart,0x07); // enable FIFO (why not?), also clear xmit/recv FIFO buffers, set threshhold to 1 byte - uart_8250_set_MCR(_DEBUG_uart,3); // RTS and DTS on - uart_8250_set_line_control(_DEBUG_uart,UART_8250_LCR_8BIT | UART_8250_LCR_PARITY); // 8 bit 1 stop bit odd parity - uart_8250_set_baudrate(_DEBUG_uart,uart_8250_baud_to_divisor(_DEBUG_uart,9600)); // 9600 baud - } - - return _DEBUG_INITed; -} - -void _DEBUG(const char *msg) { - if (_DEBUG_uart != NULL) { - char c; - - while ((c=(*msg++)) != 0/*NUL*/) { - while (!uart_8250_can_write(_DEBUG_uart)); // wait for the UART to indicate readiness for our output - uart_8250_write(_DEBUG_uart,(uint8_t)c); // then write it - } - } -} - -static char _DEBUGF_TMP[256]; - -void _DEBUGF(const char *fmt,...) { - va_list va; - - va_start(va,fmt); - vsnprintf(_DEBUGF_TMP,sizeof(_DEBUGF_TMP),fmt,va); - _DEBUG(_DEBUGF_TMP); - va_end(va); -} -#endif - + +#include "src/16.h" + +// TODO: Could we also provide a build mode to emit debug to the "Bochs E9 hack?" +#ifdef DEBUGSERIAL +# include +# include +# include + +unsigned char _DEBUG_INITed = 0; +struct info_8250 *_DEBUG_uart = NULL; + +int _DEBUG_INIT() { + if (!_DEBUG_INITed) { + unsigned int i; + uint16_t port; + + if (!init_8250()) return 0; + + // what does the BIOS say the serial ports are? + probe_8250_bios_ports(); + for (i=0;i < bios_8250_ports;i++) { + port = get_8250_bios_port(i); + if (port == 0) continue; + probe_8250(port); + } + + // what about the standard serial ports? + for (i=0;i < (sizeof(standard_8250_ports)/sizeof(standard_8250_ports[0]));i++) { + port = standard_8250_ports[i]; + if (port == 0) continue; + probe_8250(port); + } + + // pick the first port, which is probably COM1 + if (base_8250_ports == 0) return 0; // FIXME: You know "base_8250_ports" is probably a bad variable name for the max entries in info_8250_port[] + _DEBUG_uart = &info_8250_port[0]; + _DEBUG_INITed = 1; + + // init the COM port. + // in DOSBox-X, the "log" mode will receive our text and print it into the log file + // on real hardware, our text will likely go over a null modem cable to another PC running a serial terminal program like PuTTY or minicom. + // if nothing is connected, then the bytes go off into the ether to get lost and life goes on. + uart_8250_enable_interrupt(_DEBUG_uart,0); // disable interrupts + uart_8250_set_FIFO(_DEBUG_uart,0x07); // enable FIFO (why not?), also clear xmit/recv FIFO buffers, set threshhold to 1 byte + uart_8250_set_MCR(_DEBUG_uart,3); // RTS and DTS on + uart_8250_set_line_control(_DEBUG_uart,UART_8250_LCR_8BIT | UART_8250_LCR_PARITY); // 8 bit 1 stop bit odd parity + uart_8250_set_baudrate(_DEBUG_uart,uart_8250_baud_to_divisor(_DEBUG_uart,9600)); // 9600 baud + } + + return _DEBUG_INITed; +} + +void _DEBUG(const char *msg) { + if (_DEBUG_uart != NULL) { + char c; + + while ((c=(*msg++)) != 0/*NUL*/) { + while (!uart_8250_can_write(_DEBUG_uart)); // wait for the UART to indicate readiness for our output + uart_8250_write(_DEBUG_uart,(uint8_t)c); // then write it + } + } +} + +static char _DEBUGF_TMP[256]; + +void _DEBUGF(const char *fmt,...) { + va_list va; + + va_start(va,fmt); + vsnprintf(_DEBUGF_TMP,sizeof(_DEBUGF_TMP),fmt,va); + _DEBUG(_DEBUGF_TMP); + va_end(va); +} +#endif + diff --git a/src/lib/16_dbg.h b/src/lib/16_dbg.h index 9aaf9644..58c5a05a 100755 --- a/src/lib/16_dbg.h +++ b/src/lib/16_dbg.h @@ -1,25 +1,25 @@ - -#ifndef _SRC_LIB_16_DBG -#define _SRC_LIB_16_DBG - -# ifdef DEBUGSERIAL -# include - -void _DEBUGF(const char *fmt,...); -void _DEBUG(const char *msg); -int _DEBUG_INIT(); -# else -static inline void _DEBUGF(const char *fmt,...) { - // NOTHING -} -static inline void _DEBUG(const char *msg) { - // NOTHING -} - -static inline int _DEBUG_INIT() { - // NOTHING - return -1; -} -# endif -#endif // _SRC_LIB_16_DBG - + +#ifndef _SRC_LIB_16_DBG +#define _SRC_LIB_16_DBG + +# ifdef DEBUGSERIAL +# include + +void _DEBUGF(const char *fmt,...); +void _DEBUG(const char *msg); +int _DEBUG_INIT(); +# else +static inline void _DEBUGF(const char *fmt,...) { + // NOTHING +} +static inline void _DEBUG(const char *msg) { + // NOTHING +} + +static inline int _DEBUG_INIT() { + // NOTHING + return -1; +} +# endif +#endif // _SRC_LIB_16_DBG + diff --git a/src/lib/16_hc.c b/src/lib/16_hc.c index 8743a38d..13dd3f0e 100755 --- a/src/lib/16_hc.c +++ b/src/lib/16_hc.c @@ -1,537 +1,537 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* - heap test stuff -*/ - -#include "src/lib/16_hc.h" - -#ifdef __BORLANDC__ -void * LargestFreeBlock(size_t* Size) -#endif -#ifdef __WATCOMC__ -void __near* LargestFreeBlock(size_t* Size) -#endif -{ - size_t s0, s1; -#ifdef __BORLANDC__ - void * p; -#endif -#ifdef __WATCOMC__ - void __near* p; -#endif - - s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); -#ifdef __BORLANDC__ - while (s0 && (p = malloc(s0)) == NULL) -#endif -#ifdef __WATCOMC__ - while (s0 && (p = _nmalloc(s0)) == NULL) -#endif - s0 >>= 1; - - if (p) -#ifdef __BORLANDC__ - free(p); -#endif -#ifdef __WATCOMC__ - _nfree(p); -#endif - - s1 = s0 >> 1; - while (s1) - { -#ifdef __BORLANDC__ - if ((p = malloc(s0 + s1)) != NULL) -#endif -#ifdef __WATCOMC__ - if ((p = _nmalloc(s0 + s1)) != NULL) -#endif - { - s0 += s1; -#ifdef __BORLANDC__ - free(p); -#endif -#ifdef __WATCOMC__ - _nfree(p); -#endif - } - s1 >>= 1; - } -#ifdef __BORLANDC__ - while (s0 && (p = malloc(s0)) == NULL) -#endif -#ifdef __WATCOMC__ - while (s0 && (p = _nmalloc(s0)) == NULL) -#endif - s0 ^= s0 & -s0; - - *Size = s0; - return p; -} - -size_t _coreleft(void) -{ - size_t total = 0; - void __near* pFirst = NULL; - void __near* pLast = NULL; - for(;;) - { - size_t largest; - void __near* p = (void __near *)LargestFreeBlock(&largest); - if (largest < sizeof(void __near*)) - { - if (p != NULL) -#ifdef __BORLANDC__ - free(p); -#endif -#ifdef __WATCOMC__ - _nfree(p); -#endif - break; - } - *(void __near* __near*)p = NULL; - total += largest; - if (pFirst == NULL) - pFirst = p; - - if (pLast != NULL) - *(void __near* __near*)pLast = p; - pLast = p; - } - - while (pFirst != NULL) - { - void __near* p = *(void __near* __near*)pFirst; -#ifdef __BORLANDC__ - free(pFirst); -#endif -#ifdef __WATCOMC__ - _nfree(pFirst); -#endif - pFirst = p; - } - return total; -} - -void far* LargestFarFreeBlock(size_t* Size) -{ - size_t s0, s1; - void far* p; - - s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); - while (s0 && (p = _fmalloc(s0)) == NULL) - s0 >>= 1; - - if (p) - _ffree(p); - - s1 = s0 >> 1; - while (s1) - { - if ((p = _fmalloc(s0 + s1)) != NULL) - { - s0 += s1; - _ffree(p); - } - s1 >>= 1; - } - while (s0 && (p = _fmalloc(s0)) == NULL) - s0 ^= s0 & -s0; - - *Size = s0; - return p; -} - -size_t _farcoreleft(void) -{ - size_t total = 0; - void far* pFirst = NULL; - void far* pLast = NULL; - for(;;) - { - size_t largest; - void far* p = LargestFarFreeBlock(&largest); - if (largest < sizeof(void far*)) - { - if (p != NULL) - _ffree(p); - break; - } - *(void far* far*)p = NULL; - total += largest; - if (pFirst == NULL) - pFirst = p; - - if (pLast != NULL) - *(void far* far*)pLast = p; - pLast = p; - } - - while (pFirst != NULL) - { - void far* p = *(void far* far*)pFirst; - _ffree(pFirst); - pFirst = p; - } - return total; -} - -#ifdef __WATCOMC__ -void huge* LargestHugeFreeBlock(size_t* Size) -{ - size_t s0, s1; - void huge* p; - - s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); - while (s0 && (p = halloc((dword)s0, 1)) == NULL) - s0 >>= 1; - - if (p) - hfree(p); - - s1 = s0 >> 1; - while (s1) - { - if ((p = halloc((dword)(s0 + s1), 1)) != NULL) - { - s0 += s1; - hfree(p); - } - s1 >>= 1; - } - while (s0 && (p = halloc((dword)s0, 1)) == NULL) - s0 ^= s0 & -s0; - - *Size = s0; - return p; -} - -size_t _hugecoreleft(void) -{ - size_t total = 0; - void huge* pFirst = NULL; - void huge* pLast = NULL; - for(;;) - { - size_t largest; - void huge* p = LargestHugeFreeBlock(&largest); - if (largest < sizeof(void huge*)) - { - if (p != NULL) - hfree(p); - break; - } - *(void huge* huge*)p = NULL; - total += largest; - if (pFirst == NULL) - pFirst = p; - - if (pLast != NULL) - *(void huge* huge*)pLast = p; - pLast = p; - } - - while (pFirst != NULL) - { - void huge* p = *(void huge* huge*)pFirst; - hfree(pFirst); - pFirst = p; - } - return total; -} - -/*void __based(__self)* LargestBasedFreeBlock(size_t* Size) -{ - __segment segu; - size_t s0, s1; - void __based(__self)* p; - - s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); - while (s0 && (p = _bmalloc(segu, s0)) == NULL) - s0 >>= 1; - - if (p) - _ffree(p); - - s1 = s0 >> 1; - while (s1) - { - if ((p = _bmalloc(segu, s0 + s1)) != NULL) - { - s0 += s1; - _ffree(p); - } - s1 >>= 1; - } - while (s0 && (p = _bmalloc(segu, s0)) == NULL) - s0 ^= s0 & -s0; - - *Size = s0; - return p; -} - -size_t _basedcoreleft(void) -{ - __segment segu; - size_t total = 0; - void __based(segu)* pFirst = NULL; - void __based(segu)* pLast = NULL; - // allocate based heap - segu = _bheapseg( 1024 ); - if( segu == _NULLSEG ) { - printf( "Unable to allocate based heap\n" ); - return 0; - //exit( 1 ); - } - else - - for(;;) - { - size_t largest; - void __based(segu)* p = LargestBasedFreeBlock(&largest); - if (largest < sizeof(void far*)) - { - if (p != NULL) - _ffree(p); - break; - } - *(void far* far*)p = NULL; - total += largest; - if (pFirst == NULL) - pFirst = p; - - if (pLast != NULL) - *(void far* far*)pLast = p; - pLast = p; - } - - while (pFirst != NULL) - { - void far* p = *(void far* far*)pFirst; - _ffree(pFirst); - pFirst = p; - } - return total; -}*/ - -size_t GetFreeSize(void) -{ - struct _heapinfo h_info; - int heap_status; - size_t h_free=0, h_total=0, h_used=0; - - h_info._pentry = NULL; - for(;;) { - heap_status = _heapwalk( &h_info ); - if( heap_status != _HEAPOK ) break; - if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size; - if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size; - h_total += h_info._size; - } - heapstat0(heap_status); - return h_free; -} - -size_t GetFarFreeSize(void) -{ - struct _heapinfo fh_info; - int heap_status; - size_t fh_free=0, fh_total=0, fh_used=0; - - fh_info._pentry = NULL; - for(;;) { - heap_status = _fheapwalk( &fh_info ); - if( heap_status != _HEAPOK ) break; - if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size; - if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size; - fh_total += fh_info._size; - } - heapstat0(heap_status); - return fh_free; -} - -size_t GetNearFreeSize(void) -{ - struct _heapinfo nh_info; - int heap_status; - size_t nh_free=0, nh_total=0, nh_used=0; - - nh_info._pentry = NULL; - for(;;) { - heap_status = _nheapwalk( &nh_info ); - if( heap_status != _HEAPOK ) break; - if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size; - if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size; - nh_total += nh_info._size; - } - heapstat0(heap_status); - return nh_free; -} - -void heapdump(global_game_variables_t *gvar) -{ - struct _heapinfo fh_info, nh_info, h_info; - int heap_status; - size_t h_free, nh_free, fh_free, h_total, nh_total, fh_total, h_used, nh_used, fh_used; - byte scratch[1024],str[16]; - - HC_OpenDebug(gvar); - - strcpy(scratch,"\n == default ==\n\n"); - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - h_info._pentry = NULL; - h_free=0; h_total=0; h_used=0; - for(;;) { - heap_status = _heapwalk( &h_info ); - if( heap_status != _HEAPOK ) break; - strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n"); - if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size; - if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size; - h_total += h_info._size; - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - } - heapstat(gvar, heap_status, &scratch); - - //near - strcpy(scratch,"\n == near ==\n\n"); - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - nh_info._pentry = NULL; - nh_free=0; nh_total=0; nh_used=0; - for(;;) { - heap_status = _nheapwalk( &nh_info ); - if( heap_status != _HEAPOK ) break; - strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)nh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(nh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n"); -/* printf( " %s block at %Fp of size %4.4X\n", -(nh_info._useflag == _USEDENTRY ? "USED" : "FREE"), -nh_info._pentry, nh_info._size );*/ - if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size; - if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size; - nh_total += nh_info._size; - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - } - heapstat(gvar, heap_status, &scratch); - - //far - strcpy(scratch,"\n == far ==\n\n"); - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - fh_info._pentry = NULL; - fh_free=0; fh_total=0; fh_used=0; - for(;;) { - heap_status = _fheapwalk( &fh_info ); - if( heap_status != _HEAPOK ) break; - strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)fh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(fh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n"); - /*printf( " %s block at %Fp of size %4.4X\n", -(fh_info._useflag == _USEDENTRY ? "USED" : "FREE"), -fh_info._pentry, fh_info._size );*/ - if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size; - if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size; - fh_total += fh_info._size; - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - } - heapstat(gvar, heap_status, &scratch); - - strcpy(scratch,"\n"); - strcat(scratch,kittengets(2,0,"Memory Type Total Used Free\n")); - strcat(scratch,"---------------- -------- -------- --------\n"); - printmeminfoline(&scratch, "Default", h_total, h_used, h_free); - printmeminfoline(&scratch, "Near", nh_total, nh_used, nh_free); - printmeminfoline(&scratch, "Far", fh_total, fh_used, fh_free); - strcat(scratch,"---------------- -------- -------- --------\n"); - strcat(scratch,"coreleft = "); ultoa((dword)_coreleft(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - strcat(scratch,"farcoreleft = "); ultoa((dword)_farcoreleft(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - strcat(scratch,"GetFreeSize = "); ultoa((dword)GetFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - strcat(scratch,"GetNearFreeSize = "); ultoa((dword)GetNearFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - strcat(scratch,"GetFarFreeSize = "); ultoa((dword)GetFarFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - strcat(scratch,"memavl = "); ultoa((dword)_memavl(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - strcat(scratch,"stackavail = "); ultoa((dword)stackavail(),str,10); strcat(scratch,str); strcat(scratch,"\n"); - write(gvar->handle.heaphandle,scratch,strlen(scratch)); - HC_CloseDebug(gvar); -} - -void heapstat(global_game_variables_t *gvar, int heap_status, byte *str) -{ - switch( heap_status ) { - case _HEAPEND: - strcpy((str),"OK - end of heap\n"); - break; - case _HEAPEMPTY: - strcpy((str),"OK - heap is empty\n"); - - break; - case _HEAPBADBEGIN: - strcpy((str),"ERROR - heap is damaged\n"); - break; - case _HEAPBADPTR: - strcpy((str),"ERROR - bad pointer to heap\n"); - break; - case _HEAPBADNODE: - strcpy((str),"ERROR - bad node in heap\n"); - } - write(gvar->handle.heaphandle,(str),strlen((str))); -} - -void heapstat0(int heap_status) -{ - switch( heap_status ) { - case _HEAPEND: - //printf("OK - end of heap\n"); - break; - case _HEAPEMPTY: - //printf("OK - heap is empty\n"); - break; - case _HEAPBADBEGIN: - printf("ERROR - heap is damaged\n"); - break; - case _HEAPBADPTR: - printf("ERROR - bad pointer to heap\n"); - break; - case _HEAPBADNODE: - printf("ERROR - bad node in heap\n"); - } -} -#endif -/* -============================ -= -= HC_OpenDebug / HC_CloseDebug -= -= Opens a binary file with the handle "heaphandle" -= -============================ -*/ -void HC_OpenDebug(global_game_variables_t *gvar) -{ -#ifdef __BORLANDC__ - unlink("heap.16b"); - gvar->handle.heaphandle = open("heap.16b", O_CREAT | O_WRONLY | O_TEXT); -#endif -#ifdef __WATCOMC__ - unlink("heap.16w"); - gvar->handle.heaphandle = open("heap.16w", O_CREAT | O_WRONLY | O_TEXT); -#endif -} - -void HC_CloseDebug(global_game_variables_t *gvar) -{ - close(gvar->handle.heaphandle); -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + heap test stuff +*/ + +#include "src/lib/16_hc.h" + +#ifdef __BORLANDC__ +void * LargestFreeBlock(size_t* Size) +#endif +#ifdef __WATCOMC__ +void __near* LargestFreeBlock(size_t* Size) +#endif +{ + size_t s0, s1; +#ifdef __BORLANDC__ + void * p; +#endif +#ifdef __WATCOMC__ + void __near* p; +#endif + + s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); +#ifdef __BORLANDC__ + while (s0 && (p = malloc(s0)) == NULL) +#endif +#ifdef __WATCOMC__ + while (s0 && (p = _nmalloc(s0)) == NULL) +#endif + s0 >>= 1; + + if (p) +#ifdef __BORLANDC__ + free(p); +#endif +#ifdef __WATCOMC__ + _nfree(p); +#endif + + s1 = s0 >> 1; + while (s1) + { +#ifdef __BORLANDC__ + if ((p = malloc(s0 + s1)) != NULL) +#endif +#ifdef __WATCOMC__ + if ((p = _nmalloc(s0 + s1)) != NULL) +#endif + { + s0 += s1; +#ifdef __BORLANDC__ + free(p); +#endif +#ifdef __WATCOMC__ + _nfree(p); +#endif + } + s1 >>= 1; + } +#ifdef __BORLANDC__ + while (s0 && (p = malloc(s0)) == NULL) +#endif +#ifdef __WATCOMC__ + while (s0 && (p = _nmalloc(s0)) == NULL) +#endif + s0 ^= s0 & -s0; + + *Size = s0; + return p; +} + +size_t _coreleft(void) +{ + size_t total = 0; + void __near* pFirst = NULL; + void __near* pLast = NULL; + for(;;) + { + size_t largest; + void __near* p = (void __near *)LargestFreeBlock(&largest); + if (largest < sizeof(void __near*)) + { + if (p != NULL) +#ifdef __BORLANDC__ + free(p); +#endif +#ifdef __WATCOMC__ + _nfree(p); +#endif + break; + } + *(void __near* __near*)p = NULL; + total += largest; + if (pFirst == NULL) + pFirst = p; + + if (pLast != NULL) + *(void __near* __near*)pLast = p; + pLast = p; + } + + while (pFirst != NULL) + { + void __near* p = *(void __near* __near*)pFirst; +#ifdef __BORLANDC__ + free(pFirst); +#endif +#ifdef __WATCOMC__ + _nfree(pFirst); +#endif + pFirst = p; + } + return total; +} + +void far* LargestFarFreeBlock(size_t* Size) +{ + size_t s0, s1; + void far* p; + + s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); + while (s0 && (p = _fmalloc(s0)) == NULL) + s0 >>= 1; + + if (p) + _ffree(p); + + s1 = s0 >> 1; + while (s1) + { + if ((p = _fmalloc(s0 + s1)) != NULL) + { + s0 += s1; + _ffree(p); + } + s1 >>= 1; + } + while (s0 && (p = _fmalloc(s0)) == NULL) + s0 ^= s0 & -s0; + + *Size = s0; + return p; +} + +size_t _farcoreleft(void) +{ + size_t total = 0; + void far* pFirst = NULL; + void far* pLast = NULL; + for(;;) + { + size_t largest; + void far* p = LargestFarFreeBlock(&largest); + if (largest < sizeof(void far*)) + { + if (p != NULL) + _ffree(p); + break; + } + *(void far* far*)p = NULL; + total += largest; + if (pFirst == NULL) + pFirst = p; + + if (pLast != NULL) + *(void far* far*)pLast = p; + pLast = p; + } + + while (pFirst != NULL) + { + void far* p = *(void far* far*)pFirst; + _ffree(pFirst); + pFirst = p; + } + return total; +} + +#ifdef __WATCOMC__ +void huge* LargestHugeFreeBlock(size_t* Size) +{ + size_t s0, s1; + void huge* p; + + s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); + while (s0 && (p = halloc((dword)s0, 1)) == NULL) + s0 >>= 1; + + if (p) + hfree(p); + + s1 = s0 >> 1; + while (s1) + { + if ((p = halloc((dword)(s0 + s1), 1)) != NULL) + { + s0 += s1; + hfree(p); + } + s1 >>= 1; + } + while (s0 && (p = halloc((dword)s0, 1)) == NULL) + s0 ^= s0 & -s0; + + *Size = s0; + return p; +} + +size_t _hugecoreleft(void) +{ + size_t total = 0; + void huge* pFirst = NULL; + void huge* pLast = NULL; + for(;;) + { + size_t largest; + void huge* p = LargestHugeFreeBlock(&largest); + if (largest < sizeof(void huge*)) + { + if (p != NULL) + hfree(p); + break; + } + *(void huge* huge*)p = NULL; + total += largest; + if (pFirst == NULL) + pFirst = p; + + if (pLast != NULL) + *(void huge* huge*)pLast = p; + pLast = p; + } + + while (pFirst != NULL) + { + void huge* p = *(void huge* huge*)pFirst; + hfree(pFirst); + pFirst = p; + } + return total; +} + +/*void __based(__self)* LargestBasedFreeBlock(size_t* Size) +{ + __segment segu; + size_t s0, s1; + void __based(__self)* p; + + s0 = ~(size_t)0 ^ (~(size_t)0 >> 1); + while (s0 && (p = _bmalloc(segu, s0)) == NULL) + s0 >>= 1; + + if (p) + _ffree(p); + + s1 = s0 >> 1; + while (s1) + { + if ((p = _bmalloc(segu, s0 + s1)) != NULL) + { + s0 += s1; + _ffree(p); + } + s1 >>= 1; + } + while (s0 && (p = _bmalloc(segu, s0)) == NULL) + s0 ^= s0 & -s0; + + *Size = s0; + return p; +} + +size_t _basedcoreleft(void) +{ + __segment segu; + size_t total = 0; + void __based(segu)* pFirst = NULL; + void __based(segu)* pLast = NULL; + // allocate based heap + segu = _bheapseg( 1024 ); + if( segu == _NULLSEG ) { + printf( "Unable to allocate based heap\n" ); + return 0; + //exit( 1 ); + } + else + + for(;;) + { + size_t largest; + void __based(segu)* p = LargestBasedFreeBlock(&largest); + if (largest < sizeof(void far*)) + { + if (p != NULL) + _ffree(p); + break; + } + *(void far* far*)p = NULL; + total += largest; + if (pFirst == NULL) + pFirst = p; + + if (pLast != NULL) + *(void far* far*)pLast = p; + pLast = p; + } + + while (pFirst != NULL) + { + void far* p = *(void far* far*)pFirst; + _ffree(pFirst); + pFirst = p; + } + return total; +}*/ + +size_t GetFreeSize(void) +{ + struct _heapinfo h_info; + int heap_status; + size_t h_free=0, h_total=0, h_used=0; + + h_info._pentry = NULL; + for(;;) { + heap_status = _heapwalk( &h_info ); + if( heap_status != _HEAPOK ) break; + if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size; + if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size; + h_total += h_info._size; + } + heapstat0(heap_status); + return h_free; +} + +size_t GetFarFreeSize(void) +{ + struct _heapinfo fh_info; + int heap_status; + size_t fh_free=0, fh_total=0, fh_used=0; + + fh_info._pentry = NULL; + for(;;) { + heap_status = _fheapwalk( &fh_info ); + if( heap_status != _HEAPOK ) break; + if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size; + if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size; + fh_total += fh_info._size; + } + heapstat0(heap_status); + return fh_free; +} + +size_t GetNearFreeSize(void) +{ + struct _heapinfo nh_info; + int heap_status; + size_t nh_free=0, nh_total=0, nh_used=0; + + nh_info._pentry = NULL; + for(;;) { + heap_status = _nheapwalk( &nh_info ); + if( heap_status != _HEAPOK ) break; + if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size; + if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size; + nh_total += nh_info._size; + } + heapstat0(heap_status); + return nh_free; +} + +void heapdump(global_game_variables_t *gvar) +{ + struct _heapinfo fh_info, nh_info, h_info; + int heap_status; + size_t h_free, nh_free, fh_free, h_total, nh_total, fh_total, h_used, nh_used, fh_used; + byte scratch[1024],str[16]; + + HC_OpenDebug(gvar); + + strcpy(scratch,"\n == default ==\n\n"); + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + h_info._pentry = NULL; + h_free=0; h_total=0; h_used=0; + for(;;) { + heap_status = _heapwalk( &h_info ); + if( heap_status != _HEAPOK ) break; + strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n"); + if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size; + if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size; + h_total += h_info._size; + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + } + heapstat(gvar, heap_status, &scratch); + + //near + strcpy(scratch,"\n == near ==\n\n"); + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + nh_info._pentry = NULL; + nh_free=0; nh_total=0; nh_used=0; + for(;;) { + heap_status = _nheapwalk( &nh_info ); + if( heap_status != _HEAPOK ) break; + strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)nh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(nh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n"); +/* printf( " %s block at %Fp of size %4.4X\n", +(nh_info._useflag == _USEDENTRY ? "USED" : "FREE"), +nh_info._pentry, nh_info._size );*/ + if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size; + if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size; + nh_total += nh_info._size; + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + } + heapstat(gvar, heap_status, &scratch); + + //far + strcpy(scratch,"\n == far ==\n\n"); + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + fh_info._pentry = NULL; + fh_free=0; fh_total=0; fh_used=0; + for(;;) { + heap_status = _fheapwalk( &fh_info ); + if( heap_status != _HEAPOK ) break; + strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)fh_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(fh_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n"); + /*printf( " %s block at %Fp of size %4.4X\n", +(fh_info._useflag == _USEDENTRY ? "USED" : "FREE"), +fh_info._pentry, fh_info._size );*/ + if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size; + if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size; + fh_total += fh_info._size; + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + } + heapstat(gvar, heap_status, &scratch); + + strcpy(scratch,"\n"); + strcat(scratch,kittengets(2,0,"Memory Type Total Used Free\n")); + strcat(scratch,"---------------- -------- -------- --------\n"); + printmeminfoline(&scratch, "Default", h_total, h_used, h_free); + printmeminfoline(&scratch, "Near", nh_total, nh_used, nh_free); + printmeminfoline(&scratch, "Far", fh_total, fh_used, fh_free); + strcat(scratch,"---------------- -------- -------- --------\n"); + strcat(scratch,"coreleft = "); ultoa((dword)_coreleft(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + strcat(scratch,"farcoreleft = "); ultoa((dword)_farcoreleft(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + strcat(scratch,"GetFreeSize = "); ultoa((dword)GetFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + strcat(scratch,"GetNearFreeSize = "); ultoa((dword)GetNearFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + strcat(scratch,"GetFarFreeSize = "); ultoa((dword)GetFarFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + strcat(scratch,"memavl = "); ultoa((dword)_memavl(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + strcat(scratch,"stackavail = "); ultoa((dword)stackavail(),str,10); strcat(scratch,str); strcat(scratch,"\n"); + write(gvar->handle.heaphandle,scratch,strlen(scratch)); + HC_CloseDebug(gvar); +} + +void heapstat(global_game_variables_t *gvar, int heap_status, byte *str) +{ + switch( heap_status ) { + case _HEAPEND: + strcpy((str),"OK - end of heap\n"); + break; + case _HEAPEMPTY: + strcpy((str),"OK - heap is empty\n"); + + break; + case _HEAPBADBEGIN: + strcpy((str),"ERROR - heap is damaged\n"); + break; + case _HEAPBADPTR: + strcpy((str),"ERROR - bad pointer to heap\n"); + break; + case _HEAPBADNODE: + strcpy((str),"ERROR - bad node in heap\n"); + } + write(gvar->handle.heaphandle,(str),strlen((str))); +} + +void heapstat0(int heap_status) +{ + switch( heap_status ) { + case _HEAPEND: + //printf("OK - end of heap\n"); + break; + case _HEAPEMPTY: + //printf("OK - heap is empty\n"); + break; + case _HEAPBADBEGIN: + printf("ERROR - heap is damaged\n"); + break; + case _HEAPBADPTR: + printf("ERROR - bad pointer to heap\n"); + break; + case _HEAPBADNODE: + printf("ERROR - bad node in heap\n"); + } +} +#endif +/* +============================ += += HC_OpenDebug / HC_CloseDebug += += Opens a binary file with the handle "heaphandle" += +============================ +*/ +void HC_OpenDebug(global_game_variables_t *gvar) +{ +#ifdef __BORLANDC__ + unlink("heap.16b"); + gvar->handle.heaphandle = open("heap.16b", O_CREAT | O_WRONLY | O_TEXT); +#endif +#ifdef __WATCOMC__ + unlink("heap.16w"); + gvar->handle.heaphandle = open("heap.16w", O_CREAT | O_WRONLY | O_TEXT); +#endif +} + +void HC_CloseDebug(global_game_variables_t *gvar) +{ + close(gvar->handle.heaphandle); +} diff --git a/src/lib/16_hc.h b/src/lib/16_hc.h index 4d0375e2..870d50c7 100755 --- a/src/lib/16_hc.h +++ b/src/lib/16_hc.h @@ -1,54 +1,54 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* - heap test stuff -*/ - -#ifndef __16HC__ -#define __16HC__ - -#include "src/lib/16_head.h" - -#ifdef __BORLANDC__ -void * LargestFreeBlock(size_t* Size); -#endif -#ifdef __WATCOMC__ -void __near* LargestFreeBlock(size_t* Size); -#endif -size_t _coreleft(void); -void far* LargestFarFreeBlock(size_t* Size); -size_t _farcoreleft(void); -void huge* LargestHugeFreeBlock(size_t* Size); -size_t _hugecoreleft(void); -//void __based(__self)* LargestBasedFreeBlock(size_t* Size); -//size_t _basedcoreleft(void); -size_t GetFreeSize(void); -size_t GetFarFreeSize(void); -size_t GetNearFreeSize(void); -void heapdump(global_game_variables_t *gvar); -void heapstat(global_game_variables_t *gvar, int heap_status, byte *str); -void heapstat0(int heap_status); - -void HC_OpenDebug(global_game_variables_t *gvar); -void HC_CloseDebug(global_game_variables_t *gvar); - -#endif /* __16HC__ */ +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + heap test stuff +*/ + +#ifndef __16HC__ +#define __16HC__ + +#include "src/lib/16_head.h" + +#ifdef __BORLANDC__ +void * LargestFreeBlock(size_t* Size); +#endif +#ifdef __WATCOMC__ +void __near* LargestFreeBlock(size_t* Size); +#endif +size_t _coreleft(void); +void far* LargestFarFreeBlock(size_t* Size); +size_t _farcoreleft(void); +void huge* LargestHugeFreeBlock(size_t* Size); +size_t _hugecoreleft(void); +//void __based(__self)* LargestBasedFreeBlock(size_t* Size); +//size_t _basedcoreleft(void); +size_t GetFreeSize(void); +size_t GetFarFreeSize(void); +size_t GetNearFreeSize(void); +void heapdump(global_game_variables_t *gvar); +void heapstat(global_game_variables_t *gvar, int heap_status, byte *str); +void heapstat0(int heap_status); + +void HC_OpenDebug(global_game_variables_t *gvar); +void HC_CloseDebug(global_game_variables_t *gvar); + +#endif /* __16HC__ */ diff --git a/src/lib/16_head.h b/src/lib/16_head.h index b3423ed0..0155c81e 100755 --- a/src/lib/16_head.h +++ b/src/lib/16_head.h @@ -152,6 +152,7 @@ static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */ extern int profilehandle,debughandle; //make it into game global #define __DEBUG__ +#define __DEBUG_PM__ #define nil ((void *)0) #ifdef __BORLANDC__ @@ -198,6 +199,7 @@ int US_CheckParm(char *parm,char **strings); #ifdef __BORLANDC__ void Quit (char *error); #endif +void XMS_CALL(byte v, global_game_variables_t *gvar); byte dirchar(byte in); #endif/*_LIBHEAD_H_*/ diff --git a/src/lib/16_map.c b/src/lib/16_map.c index 8e2d65b2..d697142d 100755 --- a/src/lib/16_map.c +++ b/src/lib/16_map.c @@ -1,156 +1,156 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "16_map.h" - -// Ideally, preprocess json during compilation and read serialized data - -int jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && - strncmp(json + tok->start, s, tok->end - tok->start) == 0) { - return 0; - } - return -1; -} - -void extract_map(const char *js, jsmntok_t *t, size_t count, map_t *map) { - int i, j, k, indent, inner_end; - bitmap_t bp; - char *s; - i = 0; - while(idata = malloc(sizeof(byte*) * t[i].size); - inner_end = t[i].end; - k = 0; - while(t[i].start < inner_end) { - printf("%d, %d\n", t[i].start, inner_end); - if(jsoneq(js, &(t[i]), "data") == 0) { - #ifdef DEBUG_MAPVAR - printf("Layer %d data: [", k); - #endif - map->data[k] = malloc(sizeof(byte) * t[i+1].size); - for(j = 0; j < t[i+1].size; j++) { - map->data[k][j] = (byte)atoi(js + t[i+2+j].start); - #ifdef DEBUG_MAPVAR - printf("%d, ", map->data[k][j]); - #endif - } - i += j + 2; - k++; - #ifdef DEBUG_MAPVAR - puts("]"); - #endif - } - else{ - i++; - } - } - } - if(jsoneq(js, &(t[i]), "tilesets") == 0) { - i++; - map->tiles = malloc(sizeof(tiles_t*) * t[i].size); - inner_end = t[i].end; - k = 0; - while(t[i].start < inner_end) { - if(jsoneq(js, &(t[i]), "image") == 0) { - //fix this to be far~ - map->tiles[k] = malloc(sizeof(tiles_t)); - map->tiles[k]->btdata = malloc(sizeof(bitmap_t)); - map->tiles[k]->tileHeight = 16; - map->tiles[k]->tileWidth = 16; - map->tiles[k]->rows = 1; - map->tiles[k]->cols = 1; - map->tiles[k]->debug_text=false; - //Fix to load tileset specified. - //And move to vrs, probably - bp = bitmapLoadPcx("data/ed.pcx"); - map->tiles[k]->btdata = &bp; - k++; - } - i++; - } - } - - if (jsoneq(js, &(t[i]), "height") == 0 && indent<=1) { - map->height = atoi(js + t[i+1].start); - #ifdef DEBUG_MAPVAR - printf("Height: %d\n", map->height); - #endif - i++; - } - else if(jsoneq(js, &(t[i]), "width") == 0 && indent<=1) { - map->width = atoi(js + t[i+1].start); - #ifdef DEBUG_MAPVAR - printf("Width: %d\n", map->width); - #endif - i++; - } - i++; - } -} - -int loadmap(char *mn, map_t *map) { - char *js; - - jsmn_parser p; - jsmntok_t *tok = NULL; - size_t tokcount, file_s; - - FILE *fh = fopen(mn, "r"); - int status; - - /* Prepare parser */ - jsmn_init(&p); - - file_s = filesize(fh); - js = malloc(file_s); - if(js == NULL) { - fprintf(stderr, "malloc(): errno = %d", 2); - fclose(fh); - return 3; - } - if(fread(js, 1, file_s, fh) != file_s) { - fprintf(stderr, "Map read error"); - free(js); - fclose(fh); - return 1; - } - tokcount = jsmn_parse(&p, js, file_s, NULL, 0); - tok = malloc(tokcount*sizeof(jsmntok_t)); - printf("Allocated %d tokens", tokcount); - jsmn_init(&p); - if((status = jsmn_parse(&p, js, file_s, tok, tokcount)) < 0) - { - printf("Error: %d\n", status); - return status; - } - else if(status != tokcount) { printf("Warning: used %d tok\n", status);} - extract_map(js, tok, tokcount, map); - - free(js); - free(tok); - fclose(fh); - - return 0; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "16_map.h" + +// Ideally, preprocess json during compilation and read serialized data + +int jsoneq(const char *json, jsmntok_t *tok, const char *s) { + if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +void extract_map(const char *js, jsmntok_t *t, size_t count, map_t *map) { + int i, j, k, indent, inner_end; + bitmap_t bp; + char *s; + i = 0; + while(idata = malloc(sizeof(byte*) * t[i].size); + inner_end = t[i].end; + k = 0; + while(t[i].start < inner_end) { + printf("%d, %d\n", t[i].start, inner_end); + if(jsoneq(js, &(t[i]), "data") == 0) { + #ifdef DEBUG_MAPVAR + printf("Layer %d data: [", k); + #endif + map->data[k] = malloc(sizeof(byte) * t[i+1].size); + for(j = 0; j < t[i+1].size; j++) { + map->data[k][j] = (byte)atoi(js + t[i+2+j].start); + #ifdef DEBUG_MAPVAR + printf("%d, ", map->data[k][j]); + #endif + } + i += j + 2; + k++; + #ifdef DEBUG_MAPVAR + puts("]"); + #endif + } + else{ + i++; + } + } + } + if(jsoneq(js, &(t[i]), "tilesets") == 0) { + i++; + map->tiles = malloc(sizeof(tiles_t*) * t[i].size); + inner_end = t[i].end; + k = 0; + while(t[i].start < inner_end) { + if(jsoneq(js, &(t[i]), "image") == 0) { + //fix this to be far~ + map->tiles[k] = malloc(sizeof(tiles_t)); + map->tiles[k]->btdata = malloc(sizeof(bitmap_t)); + map->tiles[k]->tileHeight = 16; + map->tiles[k]->tileWidth = 16; + map->tiles[k]->rows = 1; + map->tiles[k]->cols = 1; + map->tiles[k]->debug_text=false; + //Fix to load tileset specified. + //And move to vrs, probably + bp = bitmapLoadPcx("data/ed.pcx"); + map->tiles[k]->btdata = &bp; + k++; + } + i++; + } + } + + if (jsoneq(js, &(t[i]), "height") == 0 && indent<=1) { + map->height = atoi(js + t[i+1].start); + #ifdef DEBUG_MAPVAR + printf("Height: %d\n", map->height); + #endif + i++; + } + else if(jsoneq(js, &(t[i]), "width") == 0 && indent<=1) { + map->width = atoi(js + t[i+1].start); + #ifdef DEBUG_MAPVAR + printf("Width: %d\n", map->width); + #endif + i++; + } + i++; + } +} + +int loadmap(char *mn, map_t *map) { + char *js; + + jsmn_parser p; + jsmntok_t *tok = NULL; + size_t tokcount, file_s; + + FILE *fh = fopen(mn, "r"); + int status; + + /* Prepare parser */ + jsmn_init(&p); + + file_s = filesize(fh); + js = malloc(file_s); + if(js == NULL) { + fprintf(stderr, "malloc(): errno = %d", 2); + fclose(fh); + return 3; + } + if(fread(js, 1, file_s, fh) != file_s) { + fprintf(stderr, "Map read error"); + free(js); + fclose(fh); + return 1; + } + tokcount = jsmn_parse(&p, js, file_s, NULL, 0); + tok = malloc(tokcount*sizeof(jsmntok_t)); + printf("Allocated %d tokens", tokcount); + jsmn_init(&p); + if((status = jsmn_parse(&p, js, file_s, tok, tokcount)) < 0) + { + printf("Error: %d\n", status); + return status; + } + else if(status != tokcount) { printf("Warning: used %d tok\n", status);} + extract_map(js, tok, tokcount, map); + + free(js); + free(tok); + fclose(fh); + + return 0; +} diff --git a/src/lib/16_mm.c b/src/lib/16_mm.c index 9333d380..5f5b6444 100755 --- a/src/lib/16_mm.c +++ b/src/lib/16_mm.c @@ -1,1821 +1,1808 @@ -/* Catacomb Apocalypse Source Code - * Copyright (C) 1993-2014 Flat Rock Software - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -// NEWMM.C - -/* -============================================================================= - - ID software memory manager - -------------------------- - -Primary coder: John Carmack - -RELIES ON ---------- -Quit (char *error) function - - -WORK TO DO ----------- -MM_SizePtr to change the size of a given pointer - -Multiple purge levels utilized - -EMS / XMS unmanaged routines - -============================================================================= -*/ -/* - -Open Watcom port by sparky4 - -*/ -#include "src/lib/16_mm.h" -#include "src/lib/16_ca.h" -#pragma hdrstop - -#pragma warn -pro -#pragma warn -use - -/* -============================================================================= - - GLOBAL VARIABLES - -============================================================================= -*/ - -void (* beforesort) (void); -void (* aftersort) (void); -void (* XMSaddr) (void); // far pointer to XMS driver - -/* -============================================================================= - - LOCAL VARIABLES - -============================================================================= -*/ - -static char *ParmStringsexmm[] = {"noems","noxms",""}; - -/* -====================== -= -= MML_CheckForEMS -= -= Routine from p36 of Extending DOS -= -======================= -*/ - -boolean MML_CheckForEMS(void) -{ - boolean emmcfems; - static char emmname[] = "EMMXXXX0"; //fix by andrius4669 - __asm { - mov dx,OFFSET emmname //fix by andrius4669 - mov ax,0x3d00 - int 0x21 // try to open EMMXXXX0 device - jc error - - mov bx,ax - mov ax,0x4400 - - int 0x21 // get device info - jc error - - and dx,0x80 - jz error - - mov ax,0x4407 - - int 0x21 // get status - jc error - or al,al - jz error - - mov ah,0x3e - int 0x21 // close handle - jc error - // - // EMS is good - // - mov emmcfems,1 - jmp End -#ifdef __BORLANDC__ - } -#endif - error: -#ifdef __BORLANDC__ - __asm { -#endif - // - // EMS is bad - // - mov emmcfems,0 -#ifdef __BORLANDC__ - } -#endif - End: -#ifdef __WATCOMC__ - } -#endif - return(emmcfems); -} - - -/* -====================== -= -= MML_SetupEMS -= -======================= -*/ - -byte MML_SetupEMS(global_game_variables_t *gvar) -{ - byte str[160]; - byte err; - boolean errorflag=false; - - unsigned int EMSVer = 0; - //byte EMS_status; - unsigned totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle; - totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0; - - __asm { - mov ah,EMS_STATUS - int EMS_INT // make sure EMS hardware is present - or ah,ah - //mov [EMS_status],ah - jnz error - - mov ah,EMS_VERSION - int EMS_INT - or ah,ah - jnz error - mov [EMSVer],ax // set EMSVer - cmp al,0x32 // only work on ems 3.2 or greater - jb error - - mov ah,EMS_GETFRAME - int EMS_INT // find the page frame address - or ah,ah - jnz error - mov [EMSPageFrame],bx - - mov ah,EMS_GETPAGES - int EMS_INT // find out how much EMS is there - or ah,ah - jnz error - mov [totalEMSpages],dx - mov [freeEMSpages],bx - or bx,bx - jz noEMS // no EMS at all to allocate - //EXPAND DONG!!!! - cmp [EMSVer],0x40 - jb low - cmp bx,[freeEMSpages] - jle getpages - mov bx,[freeEMSpages] - jmp getpages -#ifdef __BORLANDC__ - } -#endif - low: -#ifdef __BORLANDC__ - __asm { -#endif - cmp bx,4 - jle getpages // there is only 1,2,3,or 4 pages - mov bx,4 // we can't use more than 4 pages -#ifdef __BORLANDC__ - } -#endif - getpages: -#ifdef __BORLANDC__ - __asm { -#endif - mov [EMSpagesmapped],bx - mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS - int EMS_INT - or ah,ah - jnz error - mov [EMSHandle],dx - jmp End -#ifdef __BORLANDC__ - } -#endif - error: -#ifdef __BORLANDC__ - __asm { -#endif - mov err,ah - mov errorflag,1 - jmp End -#ifdef __BORLANDC__ - } -#endif -noEMS: -End: -#ifdef __WATCOMC__ - } -#endif - if(errorflag==true) - { - strcpy(str,"MM_SetupEMS: EMS error "); - MM_EMSerr(str, err); - printf("%s\n",str); - return err; - } - gvar->pm.emm.totalEMSpages=totalEMSpages; - gvar->pm.emm.freeEMSpages=freeEMSpages; - gvar->pm.emm.EMSPageFrame=EMSPageFrame; - gvar->pm.emm.EMSpagesmapped=EMSpagesmapped; - gvar->pm.emm.EMSHandle=EMSHandle; - gvar->pm.emm.EMSVer=EMSVer; - return 0; -} - - -/* -====================== -= -= MML_ShutdownEMS -= -======================= -*/ - -void MML_ShutdownEMS(global_game_variables_t *gvar) -{ - boolean errorflag=false; - unsigned EMSHandle=gvar->pm.emm.EMSHandle; - - if(!EMSHandle) - return; - __asm { - mov ah,EMS_FREEPAGES - mov dx,[EMSHandle] - int EMS_INT - or ah,ah - jz ok - mov errorflag,1 -#ifdef __BORLANDC__ - } -#endif - ok: -#ifdef __WATCOMC__ - } -#endif - if(errorflag==true) - Quit("MML_ShutdownEMS: Error freeing EMS!\n"); //++++ add something -} - -/* -==================== -= -= MM_MapEMS -= -= Maps the 64k of EMS used by memory manager into the page frame -= for general use. This only needs to be called if you are keeping -= other things in EMS. -= -==================== -*/ - -byte MM_MapEMS(global_game_variables_t *gvar) -{ - byte str[160]; - unsigned EMSHandle; - byte err; - boolean errorflag=false; - int i; - EMSHandle=gvar->pm.emm.EMSHandle; - - for (i=0;i<4/*MAPPAGES*/;i++) - { - __asm { - mov ah,EMS_MAPPAGE - mov bx,[i] // logical page - mov al,bl // physical page - mov dx,[EMSHandle] // handle - int EMS_INT - or ah,ah - jnz error - jmp End -#ifdef __BORLANDC__ - } -#endif - error: -#ifdef __BORLANDC__ - __asm { -#endif - mov err,ah - mov errorflag,1 -#ifdef __BORLANDC__ - } -#endif - End: -#ifdef __WATCOMC__ - } -#endif - if(errorflag==true) - { - strcpy(str,"MM_MapEMS: EMS error "); - MM_EMSerr(str, err); - printf("%s\n",str); - return err; - } - } - gvar->mmi.EMSmem = (i)*0x4000lu; - //printf(" gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem); - return 0; -} - -byte MM_MapXEMS(global_game_variables_t *gvar) -{ -//SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle) - - //Maps up to 4 logical EMS pages to physical pages in the page frame, where: - //PhysicalStart = Physical page first logical page is mapped to - //LogicalStart = First logical page to map - //NumPages = Number of pages to map (1 to 4) - //Handle = EMS handle logical pages are allocated to - - /*//Create a buffer containing the page information -// FOR x = 0 TO NumPages - 1 -// MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x) -// NEXT*/ - -// Regs.ax = 0x5000 //Map the pages in the buffer -// Regs.cx = NumPages //to the pageframe -// Regs.dx = Handle -// Regs.ds = VARSEG(MapInfo$) -// Regs.si = SADD(MapInfo$) -// InterruptX 0x67, Regs, Regs -// EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100 //Store the status code - -//END SUB - byte str[160]; - byte err; - word EMSHandle; - boolean errorflag=false; - int i; - EMSHandle=gvar->pm.emm.EMSHandle; - - if(gvar->pm.emm.EMSVer<0x40) - return 5; - - for (i=0;immi.EMSmem = (i)*0x4000lu; - return 0; -} - -//========================================================================== - -/* -====================== -= -= MML_CheckForXMS -= -= Check for XMM driver -= -======================= -*/ - -boolean MML_CheckForXMS(global_game_variables_t *gvar) -{ - boolean errorflag=false; - gvar->mm.numUMBs = 0; - - __asm { - mov ax,0x4300 - int 0x2f // query status of installed diver - cmp al,0x80 - je good - mov errorflag,1 -#ifdef __BORLANDC__ - } -#endif - good: -#ifdef __WATCOMC__ - } -#endif - if(errorflag==true) return false; - else return true; -} - - -/* -====================== -= -= MML_SetupXMS -= -= Try to allocate all upper memory block -= -======================= -*/ - -void MML_SetupXMS(global_game_variables_t *gvar) -{ - word base,size; - - - __asm { - mov ax,0x4310 - int 0x2f - mov [WORD PTR XMSaddr],bx - mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver - } -getmemory: - __asm { - mov ah,XMS_ALLOCUMB - mov dx,0xffff // try for largest block possible - //mov ax,dx // Set available Kbytes. - call [DWORD PTR XMSaddr] - or ax,ax - jnz gotone - - cmp bl,0xb0 // error: smaller UMB is available - jne done; - - mov ah,XMS_ALLOCUMB - call [DWORD PTR XMSaddr] // DX holds largest available UMB - or ax,ax - jz done // another error... -#ifdef __BORLANDC__ - } -#endif - gotone: -#ifdef __BORLANDC__ - __asm { -#endif - mov [base],bx - mov [size],dx -#ifdef __BORLANDC__ - } -#endif - done: -#ifdef __WATCOMC__ - } -#endif -// printf("base=%u ", base); printf("size=%u\n", size); - MML_UseSpace(base,size, gvar); - gvar->mmi.XMSmem += size*16; - gvar->mm.UMBbase[gvar->mm.numUMBs] = base; - gvar->mm.numUMBs++; - if(gvar->mm.numUMBs < MAXUMBS) - goto getmemory; -} - - -/* -====================== -= -= MML_ShutdownXMS -= -====================== -*/ - -void MML_ShutdownXMS(global_game_variables_t *gvar) -{ - int i; - unsigned base; - - for (i=0;imm.numUMBs;i++) - { - base = gvar->mm.UMBbase[i]; - __asm { - mov ah,XMS_FREEUMB - mov dx,[base] - call [DWORD PTR XMSaddr] - } - } -} - -//========================================================================== - -/* -====================== -= -= MML_UseSpace -= -= Marks a range of paragraphs as usable by the memory manager -= This is used to mark space for the near heap, far heap, ems page frame, -= and upper memory blocks -= -====================== -*/ - -/*void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan,huge *last; - word segm=1; - word oldend; - dword segmlen; - dword extra; - - scan = last = gvar->mm.mmhead; - gvar->mm.mmrover = gvar->mm.mmhead; // reset rover to start of memory - -// -// search for the block that contains the range of segments -// - while(scan->start+scan->length < segstart) - { - last = scan; - scan = scan->next; - } - -// -// take the given range out of the block -// - oldend = scan->start + scan->length; - extra = oldend - (segstart+seglength); - - segmlen=extra; - - //++++emsver stuff! - if(segm>1)/// || extra>=0x10000lu) - //if(extra>0xfffflu) - { - scan->blob=segm; - - //MML_UseSpace(segstart, seglength, gvar); - - printf("MML_UseSpace: Segment spans two blocks!\n"); - //} - printf("segm=%u ", segm); - printf("ex=%lu ", extra); - printf("old=%u ", oldend); - printf("start+seglen=%lu\n", segstart+seglength); - printf("segsta=%x ", segstart); - printf("len=%lu ", scan->length); - printf("seglen=%lu ", seglength); - printf("segmlen=%lu\n", segmlen); - } -//++++todo: linked list of segment! - if(segstart == scan->start) - { - last->next = scan->next; // unlink block - FREEBLOCK(scan); - scan = last; - } - else - scan->length = segstart-scan->start; // shorten block - - if(extra > 0) - { - GETNEWBLOCK; - gvar->mm.mmnew->useptr = NULL; - - gvar->mm.mmnew->next = scan->next; - scan->next = gvar->mm.mmnew; - gvar->mm.mmnew->start = segstart+seglength; - gvar->mm.mmnew->length = extra; - gvar->mm.mmnew->attributes = LOCKBIT; - }//else if(segm>0) goto segu; - -}*/ -void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar) -{ - mmblocktype far *scan,far *last; - word oldend; - sdword extra; - //word segm=1; - - scan = last = gvar->mm.mmhead; - gvar->mm.mmrover = gvar->mm.mmhead; // reset rover to start of memory - -// -// search for the block that contains the range of segments -// - while (scan->start+scan->length < segstart) - { - last = scan; - scan = scan->next; - } - -// -// find out how many blocks it spans! -// - /*for(;seglength>=0x10000;seglength-=0xFFFF) - { - //printf(" seglen=%lu\n", segmlen); - segm++; - }*/ - -// -// take the given range out of the block -// - oldend = scan->start + scan->length; - extra = oldend - (segstart+((unsigned)seglength)); - if (extra < 0) - { - printf("========================================\n"); - printf("start=%x ", scan->start); - printf("old=%u ", oldend); - printf("start+seglen=%lu\n", segstart+seglength); - printf("segsta=%x ", segstart); - printf("len=%lu ", scan->length); - printf("seglen=%lu ", seglength); - printf("\n"); - printf("MML_UseSpace: Segment spans two blocks! %d\n", extra); - printf("========================================\n"); - //return; - } - - if (segstart == scan->start) - { - last->next = scan->next; // unlink block - FREEBLOCK(scan); - scan = last; - } - else - scan->length = segstart-scan->start; // shorten block - - if (extra > 0) - { - GETNEWBLOCK; - gvar->mm.mmnew->useptr = NULL; - - gvar->mm.mmnew->next = scan->next; - scan->next = gvar->mm.mmnew; - gvar->mm.mmnew->start = segstart+seglength; - gvar->mm.mmnew->length = extra; - gvar->mm.mmnew->attributes = LOCKBIT; - } - -} - -//========================================================================== - -/* -==================== -= -= MML_ClearBlock -= -= We are out of blocks, so free a purgable block -= -==================== -*/ - -void MML_ClearBlock(global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan,huge *last; - mmblocktype far *scan,far *last; - - scan = gvar->mm.mmhead->next; - - while(scan) - { - if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS)) - { - MM_FreePtr(scan->useptr, gvar); - return; - } - scan = scan->next; - } - - printf("MM_ClearBlock: No purgable blocks!\n"); -} - - -//========================================================================== - -/* -=================== -= -= MM_Startup -= -= Grabs all space from turbo with malloc/farmalloc -= Allocates bufferseg misc buffer -= -=================== -*/ - -void MM_Startup(global_game_variables_t *gvar) -{ - int i; - //dword length,seglength; - dword length; word seglength; - //huge void huge *start; - void far *start; - word segstart;//,endfree; - //memptr *peeonself; - - if(gvar->mm.mmstarted) - MM_Shutdown(gvar); - - gvar->mm.mmstarted = true; - gvar->mm.bombonerror = true; - -// -// set up the linked list (everything in the free list; -// - gvar->mm.mmhead = NULL; - gvar->mm.mmfree = &(gvar->mm.mmblocks[0]); - for(i=0;imm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]); - } - gvar->mm.mmblocks[i].next = NULL; - -// -// locked block of all memory until we punch out free space -// - GETNEWBLOCK; - gvar->mm.mmhead = gvar->mm.mmnew; // this will allways be the first node - gvar->mm.mmnew->start = 0; - gvar->mm.mmnew->length = 0xffff; - gvar->mm.mmnew->attributes = LOCKBIT; - gvar->mm.mmnew->next = NULL; - //gvar->mm.mmnew->useptr = peeonself; - gvar->mm.mmrover = gvar->mm.mmhead; - - //printf(" %x\n", peeonself); - //printf(" %x\n", *peeonself); -// -// get all available near conventional memory segments -// -#ifdef __WATCOMC__ - _nheapgrow(); - length=(dword)_memavl();//(dword)GetFreeSize(); - //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length)); - start = (void far *)(gvar->mm.nearheap = _nmalloc(length)); -#endif -#ifdef __BORLANDC__ - length=coreleft(); - //huge start = (void huge *)(gvar->mm.nearheap = malloc(length)); - start = (void far *)(gvar->mm.nearheap = malloc(length)); -#endif - length -= 16-(FP_OFF(start)&15); - length -= SAVENEARHEAP; - seglength = length / 16; // now in paragraphs - segstart = FP_SEG(start)+(FP_OFF(start)+15)/16; - MML_UseSpace(segstart,seglength, gvar); - gvar->mmi.nearheap = length; - //printf("start=%Fp segstart=%x seglen=%lu len=%lu\n", start, segstart, seglength, length); - -// -// get all available far conventional memory segments -// - //printf("_FARCORELEFT %lu\n", _FCORELEFT); -#ifdef __WATCOMC__ - _fheapgrow(); -#endif -#ifdef __BORLANDC__ - printf("farcoreleft() %lu\n", farcoreleft()); - printf("(farcoreleft()+32)-_FCORELEFT %d\n", (sword)((farcoreleft()+32)-_FCORELEFT)); -#endif - length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL; - start = gvar->mm.farheap = _fmalloc(length); - //start = gvar->mm.farheap = halloc(length, 1); - length -= 16-(FP_OFF(start)&15); - length -= SAVEFARHEAP; - seglength = length / 16; // now in paragraphs - segstart = FP_SEG(start)+(FP_OFF(start)+15)/16; - MML_UseSpace(segstart,seglength, gvar); - gvar->mmi.farheap = length; - //printf("start=%Fp segstart=%x seglen=%lu len=%lu\n", start, segstart, seglength, length); - - gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap; - -// -// detect EMS and allocate up to 64K at page frame -// - gvar->mmi.EMSmem = 0; -//goto emsskip; //0000 - for(i = 1;i < -#ifdef __WATCOMC__ - __argc -#endif -#ifdef __BORLANDC__ - _argc -#endif - ;i++) - { - if(US_CheckParm( -#ifdef __WATCOMC__ - __argv[i] -#endif -#ifdef __BORLANDC__ - _argv[i] -#endif - ,ParmStringsexmm) == 0) - goto emsskip; // param NOEMS - } - if(MML_CheckForEMS()) - { - MML_SetupEMS(gvar); // allocate space - //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT! - MML_UseSpace(gvar->pm.emm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar); - //if(gvar->pm.emm.EMSVer<0x40) - MM_MapEMS(gvar); // map in used pages - //else - //MM_MapXEMS(gvar); // map in used pages - } - -// -// detect XMS and get upper memory blocks -// -emsskip: - gvar->mmi.XMSmem = 0; -goto xmsskip;//0000 - for(i = 1;i < -#ifdef __WATCOMC__ - __argc -#endif -#ifdef __BORLANDC__ - _argc -#endif - ;i++) - { - if(US_CheckParm( -#ifdef __WATCOMC__ - __argv[i] -#endif -#ifdef __BORLANDC__ - _argv[i] -#endif - ,ParmStringsexmm) == 0) - goto xmsskip; // param NOXMS - } - if(MML_CheckForXMS(gvar)) - { - MML_SetupXMS(gvar); // allocate as many UMBs as possible - } - -// -// allocate the misc buffer -// -xmsskip: - gvar->mm.mmrover = gvar->mm.mmhead; // start looking for space after low block - - MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar); -} - -//========================================================================== - -/* -==================== -= -= MM_Shutdown -= -= Frees all conventional, EMS, and XMS allocated -= -==================== -*/ - -void MM_Shutdown(global_game_variables_t *gvar) -{ - if(!(gvar->mm.mmstarted)) - return; - - _ffree(gvar->mm.farheap);// printf(" far freed\n"); -#ifdef __WATCOMC__ - _nfree(gvar->mm.nearheap);// printf(" near freed\n"); -#endif -#ifdef __BORLANDC__ - free(gvar->mm.nearheap);// printf(" near freed\n"); -#endif - if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf(" EMS freed\n"); } - if(MML_CheckForXMS(gvar)){ MML_ShutdownXMS(gvar); }//printf(" XMS freed\n"); } -} - -//========================================================================== - -/* -==================== -= -= MM_GetPtr -= -= Allocates an unlocked, unpurgable block -= -==================== -*/ - -void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next; - mmblocktype far *scan,far *lastscan,far *endscan,far *purge,far *next; - int search; - unsigned needed,startseg; - - needed = (size+15)/16; // convert size from bytes to paragraphs - - GETNEWBLOCK; // fill in start and next after a spot is found - gvar->mm.mmnew->length = needed; - gvar->mm.mmnew->useptr = baseptr; - //if(gvar->mm.mmnew->useptr==NULL){ -#ifdef __DEBUG__ - printf(" MM_GetPtr\n"); - printf(" baseptr=%04x ", baseptr); printf("useptr=%04x\n", gvar->mm.mmnew->useptr); - printf(" *baseptr=%04x ", *baseptr); printf("*useptr=%04x\n", *(gvar->mm.mmnew->useptr)); - printf(" *baseptr=%Fp ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr)); -#endif - //exit(-5); } - gvar->mm.mmnew->attributes = BASEATTRIBUTES; - -//tryagain: - for (search = 0; search<3; search++) - { - // - // first search: try to allocate right after the rover, then on up - // second search: search from the head pointer up to the rover - // third search: compress memory, then scan from start - if (search == 1 && gvar->mm.mmrover == gvar->mm.mmhead) - search++; - - switch (search) - { - case 0: - lastscan = gvar->mm.mmrover; - scan = gvar->mm.mmrover->next; - endscan = NULL; - break; - case 1: - lastscan = gvar->mm.mmhead; - scan = gvar->mm.mmhead->next; - endscan = gvar->mm.mmrover; - break; - case 2: - MM_SortMem (gvar); - lastscan = gvar->mm.mmhead; - scan = gvar->mm.mmhead->next; - endscan = NULL; - break; - } - - startseg = lastscan->start + lastscan->length; - - while (scan != endscan) - { - if (scan->start - startseg >= needed) - { - // - // got enough space between the end of lastscan and - // the start of scan, so throw out anything in the middle - // and allocate the new block - // - purge = lastscan->next; - lastscan->next = gvar->mm.mmnew; - gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg; - gvar->mm.mmnew->next = scan; - while ( purge != scan) - { // free the purgable block - next = purge->next; - FREEBLOCK(purge); - purge = next; // purge another if not at scan - } - gvar->mm.mmrover = gvar->mm.mmnew; - return; // good allocation! - } - - // - // if this block is purge level zero or locked, skip past it - // - if ( (scan->attributes & LOCKBIT) - || !(scan->attributes & PURGEBITS) ) - { - lastscan = scan; - startseg = lastscan->start + lastscan->length; - } - - - scan=scan->next; // look at next line - } - } - - if (gvar->mm.bombonerror) - { -#ifdef __WATCOMC__ - //heapdump(); -#endif - printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap)); - printf("for stability reasons the program will shut down! wwww\n"); - MM_Shutdown(gvar); - exit(-1); - } - else - gvar->mm.mmerror = true; -} - -//========================================================================== - -/* -==================== -= -= MM_FreePtr -= -= Allocates an unlocked, unpurgable block -= -==================== -*/ - -void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan,huge *last; - mmblocktype far *scan,far *last; - - last = gvar->mm.mmhead; - scan = last->next; - - if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block - gvar->mm.mmrover = gvar->mm.mmhead; - - while(scan->useptr != baseptr && scan) - { - last = scan; - scan = scan->next; - } - - if(!scan) - { - printf("MM_FreePtr: Block not found!\n"); - return; - } - - last->next = scan->next; - - FREEBLOCK(scan); -} -//========================================================================== - -/* -===================== -= -= MM_SetPurge -= -= Sets the purge level for a block (locked blocks cannot be made purgable) -= -===================== -*/ - -void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar) -{ - //huge mmblocktype huge *start; - mmblocktype far *start; - - start = gvar->mm.mmrover; - - do - { - if(gvar->mm.mmrover->useptr == baseptr) - break; - - gvar->mm.mmrover = gvar->mm.mmrover->next; - - if(!gvar->mm.mmrover) - gvar->mm.mmrover = gvar->mm.mmhead; - else if(gvar->mm.mmrover == start) - { - //Quit("MM_SetPurge: Block not found!"); - printf("%Fp %u\n", start->start, start->length); - printf("MM_SetPurge: Block not found!\n"); - exit(1); - return; - } - - } while(1); - - gvar->mm.mmrover->attributes &= ~PURGEBITS; - gvar->mm.mmrover->attributes |= purge; -} - -//========================================================================== - -/* -===================== -= -= MM_SetLock -= -= Locks / unlocks the block -= -===================== -*/ - -void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar) -{ - //huge mmblocktype huge *start; - mmblocktype far *start; - - start = gvar->mm.mmrover; - - do - { - if(gvar->mm.mmrover->useptr == baseptr) - break; - - gvar->mm.mmrover = gvar->mm.mmrover->next; - - if(!gvar->mm.mmrover) - gvar->mm.mmrover = gvar->mm.mmhead; - else if(gvar->mm.mmrover == start) - { - Quit("MM_SetLock: Block not found!"); - //return; - } - - } while(1); - - gvar->mm.mmrover->attributes &= ~LOCKBIT; - gvar->mm.mmrover->attributes |= locked*LOCKBIT; -} - -//========================================================================== - -/* -===================== -= -= MM_SortMem -= -= Throws out all purgable stuff and compresses movable blocks -= -===================== -*/ - -void MM_SortMem(global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan,huge *last,huge *next; - mmblocktype far *scan,far *last,far *next; - unsigned start,length,source,dest,oldborder; - int playing; - - // - // lock down a currently playing sound - // -/*++++ playing = SD_SoundPlaying (); - if(playing) - { - switch (SoundMode) - { - case sdm_PC: - playing += STARTPCSOUNDS; - break; - case sdm_AdLib: - playing += STARTADLIBSOUNDS; - break; - } - MM_SetLock(&(memptr)audiosegs[playing],true); - } - - - SD_StopSound();*/ -// oldborder = bordercolor; -// VW_ColorBorder (15); - - if(beforesort) - beforesort(); - - scan = gvar->mm.mmhead; - - last = NULL; // shut up compiler warning - - while(scan) - { - if(scan->attributes & LOCKBIT) - { - // - // block is locked, so try to pile later blocks right after it - // - start = scan->start + scan->length; - } - else - { - if(scan->attributes & PURGEBITS) - { - // - // throw out the purgable block - // - next = scan->next; - FREEBLOCK(scan); - //MM_FreeBlock(scan, gvar); - last->next = next; - scan = next; - continue; - } - else - { - // - // push the non purgable block on top of the last moved block - // - if(scan->start != start) - { - length = scan->length; - source = scan->start; - dest = start; - while(length > 0xf00) - { - movedata(source,0,dest,0,0xf00*16); - length -= 0xf00; - source += 0xf00; - dest += 0xf00; - } - movedata(source,0,dest,0,length*16); - - scan->start = start; - *(unsigned *)scan->useptr = start; - } - start = scan->start + scan->length; - } - } - - last = scan; - scan = scan->next; // go to next block - } - - gvar->mm.mmrover = gvar->mm.mmhead; - - if(aftersort) - aftersort(); - -// VW_ColorBorder (oldborder); - -/*++++ if(playing) - MM_SetLock(&(memptr)audiosegs[playing],false);*/ -} - -//========================================================================== - -/* -===================== -= -= MM_ShowMemory -= -===================== -*/ - -void MM_ShowMemory(global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan; - mmblocktype far *scan; - word temp; - sdword end,owner; - //word chx,chy; - word w; - //dword wwww; - byte scratch[160],scratch0[4096],scratch1[160],str[16]; - //byte d = '#'; -//**** VW_SetDefaultColors(); -//**** VW_SetLineWidth(40); -//++++mh temp = bufferofs; -//++++mh bufferofs = 0; -//**** VW_SetScreen (0,0); - scan = gvar->mm.mmhead; - end = -1; - - CA_OpenDebug (gvar); - w=0; - while(scan) - { - strcpy(scratch, AARESET); - if(scan->attributes & PURGEBITS) - strcpy(scratch0, AAMAGENTA); // dark purple = purgable - else - strcpy(scratch0, AABLUE); // medium blue = non purgable - if(scan->attributes & LOCKBIT) - strcpy(scratch0, AARED); // red = locked - if(scan->start<=end) - { - printf("\nend==%d\n\n", end); - strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n"); - strcat(scratch, "End's Size: "); - ultoa (end,str,10); - strcat (scratch,str); - strcat(scratch, "\nscan->start's Size: "); - ultoa (scan->start,str,10); - strcat (scratch,str); - write(gvar->handle.debughandle,scratch,strlen(scratch)); - //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n"); - break; - } - end = scan->start+(scan->length)-1; -//++++ chy = scan->start/320; -//++++ chx = scan->start%320; - //modexhlin(page, scan->start, (unsigned)end, chy, color); - //for(chx=scan->start;chx+4>=(word)end;chx+=4) - //{ -//++++ modexClearRegion(page, chx, chy, 4, 4, color); - //} -//++++ VW_Hlin(scan->start,(unsigned)end,0,color); - for(w=(scan->start)/80;w<=end/80;w++) - { - //printf("+ %u %lu\n", w, scan->length); - strcat(scratch0, "+"); - } - //++==++==optional strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_"); -//++++ VW_Plot(scan->start,0,15); -//++++ modexClearRegion(page, chx, chy, 4, 4, 15); -//++++ VW_Hlin(end+1,scan->next->start,0,0); // black = free - - //wwww=(dword)(scan->next->start)-(dword)scan->start; - //wwww=(dword)scan->start+(dword)(scan->next->start); - if (scan->next && scan->next->start >= end+1) - { - strcat(scratch0, AARESET); - //++==++==optional strcat(scratch0, "\n"); - strcat(scratch0,AAGREEN); - for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++) - //for(w=(wwww)/80;w<=((end+1)/80);w++) - //for(w=(end+1)/80;w<=((wwww)/80);w++) - { - //printf("0 %x %u %lu\n", scan->next->start, w, scan->length); - strcat(scratch0,"0"); - } - //printf("==================\n"); - //printf("w=%u wwww=%lu start=%04x next=%04x end=%lu\n", w/80, wwww/80, scan->start, (scan->next->start), end+1); - //printf("==================\n"); - strcat(scratch0, "\n"); - //getch(); - }/*else {//if(scan->next->start <= scan->start){ - scan->next->start=scan->start+0x1000; - wwww=(dword)(scan->next->start)-(dword)scan->start; - strcat(scratch0, AARESET); - strcat(scratch0, "\n"); - strcat(scratch0,AAGREEN); - for(w=(end+1);w<=(0x1000/80);w++) - { - //printf("0 %x %x %u\n", scan->start, w); - strcat(scratch0,"0"); - } - printf("================\n"); - printf("w=%x start=%x next=%x end=%u %lu\n", w, scan->start, (scan->next->start), end+1, wwww); - printf("================\n"); - getch(); - }*/ - strcat(scratch0, AARESET); - //strcat(scratch0,"\n"); - //for(chx=scan->next->start;chx+4>=(word)end+1;chx+=4) - //{ -// chx+=scan->next->start; -// modexClearRegion(page, chx, chy, 4, 4, 2); - //} - //modexhlin(page, end+1,scan->next->start, chy, 0); -/* y = scan->start/320; - x = scan->start%320; - VW_Hlin(x,x+end,y,color); - VW_Plot(x,y,15);*/ -//++++ VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free - strcat(scratch,"Seg:"); - ultoa (scan->start,str,16); - strcat (scratch,str); - strcat (scratch,"\tSize:"); - ultoa ((unsigned)scan->length,str,10); - strcat (scratch,str); - strcat (scratch,"\tOwner:0x"); - owner = (unsigned)scan->useptr; - ultoa (owner,str,16); - strcat (scratch,str); - strcat (scratch,"\n"); - write(gvar->handle.debughandle,scratch,strlen(scratch)); - write(gvar->handle.debughandle,scratch0,strlen(scratch0)); -//modexprint(page, chx, chy, 1, 0, 24, &scratch); -//++++chy+=4; -//fprintf(stdout, "%s", scratch); - - scan = scan->next; - } - /*strcpy(scratch1, AARESET); - strcat(scratch1, "========================================\n"); - strcat(scratch1, "near= "); - ultoa (*(gvar->mm.nearheap),str,10); - strcat (scratch1,str); - strcat(scratch1, " far= "); - ultoa (*(gvar->mm.farheap),str,10); - strcat (scratch1,str); - strcat(scratch1, "\n"); - //strcat(scratch1, "&near= %Fp ", &(gvar->mm.nearheap)); - //strcat(scratch1, "&far= %Fp", &(gvar->mm.farheap)); - //strcat(scratch1, "\n"); - strcat(scratch1, "========================================\n"); - write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/ - - - CA_CloseDebug (gvar); - -//++++mh IN_Ack(); -//**** VW_SetLineWidth(64); -//++++mh bufferofs = temp; -} - -//========================================================================== - -/* -===================== -= -= MM_DumpData -= -===================== -*/ - -void MM_DumpData(global_game_variables_t *gvar) -{ - //huge mmblocktype huge *scan,huge *best; - mmblocktype far *scan,far *best; - long lowest,oldlowest; - word owner; - byte lock,purge; - FILE *dumpfile; - - free(gvar->mm.nearheap); -#ifdef __BORLANDC__ - dumpfile = fopen ("mmdump.16b","w"); -#endif -#ifdef __WATCOMC__ - dumpfile = fopen ("mmdump.16w","w"); -#endif - if (!dumpfile){ - printf("MM_DumpData: Couldn't open MMDUMP.16!\n"); - return; - } - - lowest = -1; - do - { - oldlowest = lowest; - lowest = 0xffff; - - scan = gvar->mm.mmhead; - while (scan) - { - owner = (unsigned)scan->useptr; - - if (owner && owner oldlowest) - { - best = scan; - lowest = owner; - } - - scan = scan->next; - } - - if (lowest != 0xffff) - { - if (best->attributes & PURGEBITS) - purge = 'P'; - else - purge = '-'; - if (best->attributes & LOCKBIT) - lock = 'L'; - else - lock = '-'; - fprintf (dumpfile,"0x%p (%c%c) = %u\n" - ,(unsigned)lowest,lock,purge,best->length); - } - - } while (lowest != 0xffff); - - fclose(dumpfile); - printf("MMDUMP.16 created.\n"); -} - -//========================================================================== - - -/* -====================== -= -= MM_UnusedMemory -= -= Returns the total free space without purging -= -====================== -*/ - -dword MM_UnusedMemory(global_game_variables_t *gvar) -{ - dword free; - //huge mmblocktype huge *scan; - mmblocktype far *scan; - - free = 0; - scan = gvar->mm.mmhead; - - while(scan->next) - { - free += scan->next->start - (scan->start + scan->length); - scan = scan->next; - } - - return free*16lu; -// return free; -} - -//========================================================================== - - -/* -====================== -= -= MM_TotalFree -= -= Returns the total free space with purging -= -====================== -*/ - -dword MM_TotalFree(global_game_variables_t *gvar) -{ - dword free; - //huge mmblocktype huge *scan; - mmblocktype far *scan; - - free = 0; - scan = gvar->mm.mmhead; - - while(scan->next) - { - if((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT)) - free += scan->length; - free += scan->next->start - (scan->start + scan->length); - scan = scan->next; - } - - return free*16lu; -// return free; -} - -//========================================================================== - -/* -===================== -= -= MM_Report -= -===================== -*/ - -void MM_Report_(global_game_variables_t *gvar) -{ - printf("========================================\n"); - printf(" MM_Report\n"); - printf("========================================\n"); - if(MML_CheckForEMS()) - { - printf(" LIMEMS\n"); - printf(" EMM v%x.%x available\n", gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F); - printf(" totalEMSpages: %u ", gvar->pm.emm.totalEMSpages); printf("freeEMSpages: %u\n", gvar->pm.emm.freeEMSpages); - printf(" EMSPageFrame: %x\n", gvar->pm.emm.EMSPageFrame); - } - if(MML_CheckForXMS(gvar)) - { - printf(" XMS\n"); - printf(" XMSaddr: %X\n", *XMSaddr); - } - printf("near: %lu ", gvar->mmi.nearheap); printf("far: %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS()) - printf("EMSmem: %lu ", gvar->mmi.EMSmem); if(MML_CheckForXMS(gvar)) printf("XMSmem: %lu", gvar->mmi.XMSmem); printf("\n"); - //printf("mainmem: %lu\n", gvar->mmi.mainmem); - printf("Total convmem: %lu ", gvar->mmi.mainmem); printf("TotalFree: %lu ", MM_TotalFree(gvar)); printf("TotalUsed: %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem); - printf(" UnusedMemory: %lu\n", MM_UnusedMemory(gvar)); -} - -//========================================================================== - -/* -===================== -= -= MM_EMSerr -= -===================== -*/ - -void MM_EMSerr(byte *stri, byte err) -{ - //Returns a text string describing the error code in EMS.Error. - switch(err) - { - case 0x0: - strcat(stri, "successful"); - break; - case 0x80: - strcat(stri, "internal error"); - break; - case 0x81: - strcat(stri, "hardware malfunction"); - break; - case 0x82: - strcat(stri, "busy .. retry later"); - break; - case 0x83: - strcat(stri, "invalid handle"); - break; - case 0x84: - strcat(stri, "undefined function requested by application"); - break; - case 0x85: - strcat(stri, "no more handles available"); - break; - case 0x86: - strcat(stri, "error in save or restore of mapping context"); - break; - case 0x87: - strcat(stri, "insufficient memory pages in system"); - break; - case 0x88: - strcat(stri, "insufficient memory pages available"); - break; - case 0x89: - strcat(stri, "zero pages requested"); - break; - case 0x8A: - strcat(stri, "invalid logical page number encountered"); - break; - case 0x8B: - strcat(stri, "invalid physical page number encountered"); - break; - case 0x8C: - strcat(stri, "page-mapping hardware state save area is full"); - break; - case 0x8D: - strcat(stri, "save of mapping context failed"); - break; - case 0x8E: - strcat(stri, "restore of mapping context failed"); - break; - case 0x8F: - strcat(stri, "undefined subfunction"); - break; - case 0x90: - strcat(stri, "undefined attribute type"); - break; - case 0x91: - strcat(stri, "feature not supported"); - break; - case 0x92: - strcat(stri, "successful, but a portion of the source region has been overwritten"); - break; - case 0x93: - strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle"); - break; - case 0x94: - strcat(stri, "conventional and expanded memory regions overlap"); - break; - case 0x95: - strcat(stri, "offset within logical page exceeds size of logical page"); - break; - case 0x96: - strcat(stri, "region length exceeds 1 MB"); - break; - case 0x97: - strcat(stri, "source and destination EMS regions have same handle and overlap"); - break; - case 0x98: - strcat(stri, "memory source or destination type undefined"); - break; - case 0x9A: - strcat(stri, "specified alternate map register or DMA register set not supported"); - break; - case 0x9B: - strcat(stri, "all alternate map register or DMA register sets currently allocated"); - break; - case 0x9C: - strcat(stri, "alternate map register or DMA register sets not supported"); - break; - case 0x9D: - strcat(stri, "undefined or unallocated alternate map register or DMA register set"); - break; - case 0x9E: - strcat(stri, "dedicated DMA channels not supported"); - break; - case 0x9F: - strcat(stri, "specified dedicated DMA channel not supported"); - break; - case 0xA0: - strcat(stri, "no such handle name"); - break; - case 0xA1: - strcat(stri, "a handle found had no name, or duplicate handle name"); - break; - case 0xA2: - strcat(stri, "attempted to wrap around 1M conventional address space"); - break; - case 0xA3: - strcat(stri, "source array corrupted"); - break; - case 0xA4: - strcat(stri, "operating system denied access"); - break; - default: - strcat(stri, "undefined error"); - } -} - -//========================================================================== - -/* -===================== -= -= MM_BombOnError -= -===================== -*/ - -void MM_BombOnError(boolean bomb, global_game_variables_t *gvar) -{ - gvar->mm.bombonerror = bomb; -} - -/*void MM_GetNewBlock(global_game_variables_t *gvar) -{ - if(!gvar->mm.mmfree) - MML_ClearBlock(gvar); - gvar->mm.mmnew=gvar->mm.mmfree; - gvar->mm.mmfree=gvar->mm.mmfree->next; - if(!(gvar->mm.mmnew=gvar->mm.mmfree)) - { - printf("MM_GETNEWBLOCK: No free blocks!\n"); - return; - } - gvar->mm.mmfree=gvar->mm.mmfree->next; -} - -void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar) -{ - x->useptr=NULL; - x->next=gvar->mm.mmfree; - gvar->mm.mmfree=x; -}*/ - -/*void MM_seguin(void) -{ - __asm { - push ds - mov ax,ds - inc ax - mov ds,ax - } -} - -void MM_segude(void) -{ - __asm { - pop ds - } -}*/ - -/* -pull data from far and put it into ds var -mov ax,es:si -mov x,ax -*/ -/* -ss stack segment -sp top of stack -bp bottem of stack -*/ +/* Catacomb Apocalypse Source Code + * Copyright (C) 1993-2014 Flat Rock Software + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// NEWMM.C + +/* +============================================================================= + + ID software memory manager + -------------------------- + +Primary coder: John Carmack + +RELIES ON +--------- +Quit (char *error) function + + +WORK TO DO +---------- +MM_SizePtr to change the size of a given pointer + +Multiple purge levels utilized + +EMS / XMS unmanaged routines + +============================================================================= +*/ +/* + +Open Watcom port by sparky4 + +*/ +#include "src/lib/16_mm.h" +#include "src/lib/16_ca.h" +#pragma hdrstop + +#pragma warn -pro +#pragma warn -use + +/* +============================================================================= + + GLOBAL VARIABLES + +============================================================================= +*/ + +void (* beforesort) (void); +void (* aftersort) (void); +void (* XMSaddr) (void); // far pointer to XMS driver + +/* +============================================================================= + + LOCAL VARIABLES + +============================================================================= +*/ + +/* +====================== += += MML_CheckForEMS += += Routine from p36 of Extending DOS += +======================= +*/ + +boolean MML_CheckForEMS(void) +{ + boolean emmcfems; + static char emmname[] = "EMMXXXX0"; //fix by andrius4669 + __asm { + mov dx,OFFSET emmname //fix by andrius4669 + mov ax,0x3d00 + int 0x21 // try to open EMMXXXX0 device + jc error + + mov bx,ax + mov ax,0x4400 + + int 0x21 // get device info + jc error + + and dx,0x80 + jz error + + mov ax,0x4407 + + int 0x21 // get status + jc error + or al,al + jz error + + mov ah,0x3e + int 0x21 // close handle + jc error + // + // EMS is good + // + mov emmcfems,1 + jmp End +#ifdef __BORLANDC__ + } +#endif + error: +#ifdef __BORLANDC__ + __asm { +#endif + // + // EMS is bad + // + mov emmcfems,0 +#ifdef __BORLANDC__ + } +#endif + End: +#ifdef __WATCOMC__ + } +#endif + return(emmcfems); +} + + +/* +====================== += += MML_SetupEMS += +======================= +*/ + +byte MML_SetupEMS(global_game_variables_t *gvar) +{ + byte str[160]; + byte err; + boolean errorflag=false; + + unsigned int EMSVer = 0; + //byte EMS_status; + unsigned totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle; + totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0; + + __asm { + mov ah,EMS_STATUS + int EMS_INT // make sure EMS hardware is present + or ah,ah + //mov [EMS_status],ah + jnz error + + mov ah,EMS_VERSION + int EMS_INT + or ah,ah + jnz error + mov [EMSVer],ax // set EMSVer + cmp al,0x32 // only work on ems 3.2 or greater + jb error + + mov ah,EMS_GETFRAME + int EMS_INT // find the page frame address + or ah,ah + jnz error + mov [EMSPageFrame],bx + + mov ah,EMS_GETPAGES + int EMS_INT // find out how much EMS is there + or ah,ah + jnz error + mov [totalEMSpages],dx + mov [freeEMSpages],bx + or bx,bx + jz noEMS // no EMS at all to allocate + //EXPAND DONG!!!! + cmp [EMSVer],0x40 + jb low + cmp bx,[freeEMSpages] + jle getpages + mov bx,[freeEMSpages] + jmp getpages +#ifdef __BORLANDC__ + } +#endif + low: +#ifdef __BORLANDC__ + __asm { +#endif + cmp bx,4 + jle getpages // there is only 1,2,3,or 4 pages + mov bx,4 // we can't use more than 4 pages +#ifdef __BORLANDC__ + } +#endif + getpages: +#ifdef __BORLANDC__ + __asm { +#endif + mov [EMSpagesmapped],bx + mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS + int EMS_INT + or ah,ah + jnz error + mov [EMSHandle],dx + jmp End +#ifdef __BORLANDC__ + } +#endif + error: +#ifdef __BORLANDC__ + __asm { +#endif + mov err,ah + mov errorflag,1 + jmp End +#ifdef __BORLANDC__ + } +#endif +noEMS: +End: +#ifdef __WATCOMC__ + } +#endif + if(errorflag==true) + { + strcpy(str,"MM_SetupEMS: EMS error "); + MM_EMSerr(str, err); + printf("%s\n",str); + return err; + } + gvar->pm.emm.totalEMSpages=totalEMSpages; + gvar->pm.emm.freeEMSpages=freeEMSpages; + gvar->pm.emm.EMSPageFrame=EMSPageFrame; + gvar->pm.emm.EMSpagesmapped=EMSpagesmapped; + gvar->pm.emm.EMSHandle=EMSHandle; + gvar->pm.emm.EMSVer=EMSVer; + return 0; +} + + +/* +====================== += += MML_ShutdownEMS += +======================= +*/ + +void MML_ShutdownEMS(global_game_variables_t *gvar) +{ + boolean errorflag=false; + unsigned EMSHandle=gvar->pm.emm.EMSHandle; + + if(!EMSHandle) + return; + __asm { + mov ah,EMS_FREEPAGES + mov dx,[EMSHandle] + int EMS_INT + or ah,ah + jz ok + mov errorflag,1 +#ifdef __BORLANDC__ + } +#endif + ok: +#ifdef __WATCOMC__ + } +#endif + if(errorflag==true) + Quit("MML_ShutdownEMS: Error freeing EMS!\n"); //++++ add something +} + +/* +==================== += += MM_MapEMS += += Maps the 64k of EMS used by memory manager into the page frame += for general use. This only needs to be called if you are keeping += other things in EMS. += +==================== +*/ + +byte MM_MapEMS(global_game_variables_t *gvar) +{ + byte str[160]; + unsigned EMSHandle; + byte err; + boolean errorflag=false; + int i; + EMSHandle=gvar->pm.emm.EMSHandle; + + for (i=0;i<4/*MAPPAGES*/;i++) + { + __asm { + mov ah,EMS_MAPPAGE + mov bx,[i] // logical page + mov al,bl // physical page + mov dx,[EMSHandle] // handle + int EMS_INT + or ah,ah + jnz error + jmp End +#ifdef __BORLANDC__ + } +#endif + error: +#ifdef __BORLANDC__ + __asm { +#endif + mov err,ah + mov errorflag,1 +#ifdef __BORLANDC__ + } +#endif + End: +#ifdef __WATCOMC__ + } +#endif + if(errorflag==true) + { + strcpy(str,"MM_MapEMS: EMS error "); + MM_EMSerr(str, err); + printf("%s\n",str); + return err; + } + } + gvar->mmi.EMSmem = (i)*0x4000lu; + //printf(" gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem); + return 0; +} + +byte MM_MapXEMS(global_game_variables_t *gvar) +{ +//SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle) + + //Maps up to 4 logical EMS pages to physical pages in the page frame, where: + //PhysicalStart = Physical page first logical page is mapped to + //LogicalStart = First logical page to map + //NumPages = Number of pages to map (1 to 4) + //Handle = EMS handle logical pages are allocated to + + /*//Create a buffer containing the page information +// FOR x = 0 TO NumPages - 1 +// MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x) +// NEXT*/ + +// Regs.ax = 0x5000 //Map the pages in the buffer +// Regs.cx = NumPages //to the pageframe +// Regs.dx = Handle +// Regs.ds = VARSEG(MapInfo$) +// Regs.si = SADD(MapInfo$) +// InterruptX 0x67, Regs, Regs +// EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100 //Store the status code + +//END SUB + byte str[160]; + byte err; + word EMSHandle; + boolean errorflag=false; + int i; + EMSHandle=gvar->pm.emm.EMSHandle; + + if(gvar->pm.emm.EMSVer<0x40) + return 5; + + for (i=0;immi.EMSmem = (i)*0x4000lu; + return 0; +} + +//========================================================================== + +/* +====================== += += MML_CheckForXMS += += Check for XMM driver += +======================= +*/ + +boolean MML_CheckForXMS(global_game_variables_t *gvar) +{ + boolean errorflag=false; + gvar->mm.numUMBs = 0; + + __asm { + mov ax,0x4300 + int 0x2f // query status of installed diver + cmp al,0x80 + je good + mov errorflag,1 +#ifdef __BORLANDC__ + } +#endif + good: +#ifdef __WATCOMC__ + } +#endif + if(errorflag==true) return false; + else return true; +} + + +/* +====================== += += MML_SetupXMS += += Try to allocate all upper memory block += +======================= +*/ + +void MML_SetupXMS(global_game_variables_t *gvar) +{ + word base,size; + + + __asm { + mov ax,0x4310 + int 0x2f + mov [WORD PTR XMSaddr],bx + mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver + } +getmemory: + __asm { + mov ah,XMS_ALLOCUMB + mov dx,0xffff // try for largest block possible + //mov ax,dx // Set available Kbytes. + call [DWORD PTR XMSaddr] + or ax,ax + jnz gotone + + cmp bl,0xb0 // error: smaller UMB is available + jne done; + + mov ah,XMS_ALLOCUMB + call [DWORD PTR XMSaddr] // DX holds largest available UMB + or ax,ax + jz done // another error... +#ifdef __BORLANDC__ + } +#endif + gotone: +#ifdef __BORLANDC__ + __asm { +#endif + mov [base],bx + mov [size],dx +#ifdef __BORLANDC__ + } +#endif + done: +#ifdef __WATCOMC__ + } +#endif +// printf("base=%u ", base); printf("size=%u\n", size); + MML_UseSpace(base,size, gvar); + gvar->mmi.XMSmem += size*16; + gvar->mm.UMBbase[gvar->mm.numUMBs] = base; + gvar->mm.numUMBs++; + if(gvar->mm.numUMBs < MAXUMBS) + goto getmemory; +} + + +/* +====================== += += MML_ShutdownXMS += +====================== +*/ + +void MML_ShutdownXMS(global_game_variables_t *gvar) +{ + int i; + unsigned base; + + for (i=0;imm.numUMBs;i++) + { + base = gvar->mm.UMBbase[i]; + __asm { + mov ah,XMS_FREEUMB + mov dx,[base] + call [DWORD PTR XMSaddr] + } + } +} + +//========================================================================== + +/* +====================== += += MML_UseSpace += += Marks a range of paragraphs as usable by the memory manager += This is used to mark space for the near heap, far heap, ems page frame, += and upper memory blocks += +====================== +*/ + +/*void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan,huge *last; + word segm=1; + word oldend; + dword segmlen; + dword extra; + + scan = last = gvar->mm.mmhead; + gvar->mm.mmrover = gvar->mm.mmhead; // reset rover to start of memory + +// +// search for the block that contains the range of segments +// + while(scan->start+scan->length < segstart) + { + last = scan; + scan = scan->next; + } + +// +// take the given range out of the block +// + oldend = scan->start + scan->length; + extra = oldend - (segstart+seglength); + + segmlen=extra; + + //++++emsver stuff! + if(segm>1)/// || extra>=0x10000lu) + //if(extra>0xfffflu) + { + scan->blob=segm; + + //MML_UseSpace(segstart, seglength, gvar); + + printf("MML_UseSpace: Segment spans two blocks!\n"); + //} + printf("segm=%u ", segm); + printf("ex=%lu ", extra); + printf("old=%u ", oldend); + printf("start+seglen=%lu\n", segstart+seglength); + printf("segsta=%x ", segstart); + printf("len=%lu ", scan->length); + printf("seglen=%lu ", seglength); + printf("segmlen=%lu\n", segmlen); + } +//++++todo: linked list of segment! + if(segstart == scan->start) + { + last->next = scan->next; // unlink block + FREEBLOCK(scan); + scan = last; + } + else + scan->length = segstart-scan->start; // shorten block + + if(extra > 0) + { + GETNEWBLOCK; + gvar->mm.mmnew->useptr = NULL; + + gvar->mm.mmnew->next = scan->next; + scan->next = gvar->mm.mmnew; + gvar->mm.mmnew->start = segstart+seglength; + gvar->mm.mmnew->length = extra; + gvar->mm.mmnew->attributes = LOCKBIT; + }//else if(segm>0) goto segu; + +}*/ +void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar) +{ + mmblocktype far *scan,far *last; + word oldend; + sdword extra; + //word segm=1; + + scan = last = gvar->mm.mmhead; + gvar->mm.mmrover = gvar->mm.mmhead; // reset rover to start of memory + +// +// search for the block that contains the range of segments +// + while (scan->start+scan->length < segstart) + { + last = scan; + scan = scan->next; + } + +// +// find out how many blocks it spans! +// + /*for(;seglength>=0x10000;seglength-=0xFFFF) + { + //printf(" seglen=%lu\n", segmlen); + segm++; + }*/ + +// +// take the given range out of the block +// + oldend = scan->start + scan->length; + extra = oldend - (segstart+((unsigned)seglength)); + if (extra < 0) + { + printf("========================================\n"); + printf("start=%x ", scan->start); + printf("old=%u ", oldend); + printf("start+seglen=%lu\n", segstart+seglength); + printf("segsta=%x ", segstart); + printf("len=%lu ", scan->length); + printf("seglen=%lu ", seglength); + printf("\n"); + printf("MML_UseSpace: Segment spans two blocks! %d\n", extra); + printf("========================================\n"); + //return; + } + + if (segstart == scan->start) + { + last->next = scan->next; // unlink block + FREEBLOCK(scan); + scan = last; + } + else + scan->length = segstart-scan->start; // shorten block + + if (extra > 0) + { + GETNEWBLOCK; + gvar->mm.mmnew->useptr = NULL; + + gvar->mm.mmnew->next = scan->next; + scan->next = gvar->mm.mmnew; + gvar->mm.mmnew->start = segstart+seglength; + gvar->mm.mmnew->length = extra; + gvar->mm.mmnew->attributes = LOCKBIT; + } + +} + +//========================================================================== + +/* +==================== += += MML_ClearBlock += += We are out of blocks, so free a purgable block += +==================== +*/ + +void MML_ClearBlock(global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan,huge *last; + mmblocktype far *scan,far *last; + + scan = gvar->mm.mmhead->next; + + while(scan) + { + if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS)) + { + MM_FreePtr(scan->useptr, gvar); + return; + } + scan = scan->next; + } + + printf("MM_ClearBlock: No purgable blocks!\n"); +} + + +//========================================================================== + +/* +=================== += += MM_Startup += += Grabs all space from turbo with malloc/farmalloc += Allocates bufferseg misc buffer += +=================== +*/ + +void MM_Startup(global_game_variables_t *gvar) +{ + int i; + //dword length,seglength; + dword length; + //huge void huge *start; + void far *start; + word segstart,seglength,endfree; + //memptr *peeonself; + + if(gvar->mm.mmstarted) + MM_Shutdown(gvar); + + + gvar->mm.mmstarted = true; + gvar->mm.bombonerror = true; +// +// set up the linked list (everything in the free list; +// + gvar->mm.mmhead = NULL; + gvar->mm.mmfree = &(gvar->mm.mmblocks[0]); + for(i=0;imm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]); + } + gvar->mm.mmblocks[i].next = NULL; + +// +// locked block of all memory until we punch out free space +// + GETNEWBLOCK; + gvar->mm.mmhead = gvar->mm.mmnew; // this will allways be the first node + gvar->mm.mmnew->start = 0; + gvar->mm.mmnew->length = 0xffff; + gvar->mm.mmnew->attributes = LOCKBIT; + gvar->mm.mmnew->next = NULL; + //gvar->mm.mmnew->useptr = peeonself; + gvar->mm.mmrover = gvar->mm.mmhead; + + //printf(" %x\n", peeonself); + //printf(" %x\n", *peeonself); +// +// get all available near conventional memory segments +// +#ifdef __WATCOMC__ + _nheapgrow(); + length=(dword)_memavl();//(dword)GetFreeSize(); + //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length)); + start = (void far *)(gvar->mm.nearheap = _nmalloc(length)); +#endif +#ifdef __BORLANDC__ + length=coreleft(); + //huge start = (void huge *)(gvar->mm.nearheap = malloc(length)); + start = (void far *)(gvar->mm.nearheap = malloc(length)); + printf("Borland C unique function\n"); + printf(" coreleft() %lu\n", coreleft()); +#endif + length -= 16-(FP_OFF(start)&15); + length -= SAVENEARHEAP; + seglength = length / 16; // now in paragraphs + segstart = FP_SEG(start)+(FP_OFF(start)+15)/16; + MML_UseSpace(segstart,seglength, gvar); + gvar->mmi.nearheap = length; + //printf("start=%Fp segstart=%x seglen=%lu len=%lu\n", start, segstart, seglength, length); + +// +// get all available far conventional memory segments +// + //printf("_FARCORELEFT %lu\n", _FCORELEFT); +#ifdef __WATCOMC__ + _fheapgrow(); +#endif +#ifdef __BORLANDC__ + printf(" farcoreleft() %lu\n", farcoreleft()); + printf(" (farcoreleft()+32)-_FCORELEFT %d\n", (sword)((farcoreleft()+32)-_FCORELEFT)); +#endif + length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL; + start = gvar->mm.farheap = _fmalloc(length); + //start = gvar->mm.farheap = halloc(length, 1); + length -= 16-(FP_OFF(start)&15); + length -= SAVEFARHEAP; + seglength = length / 16; // now in paragraphs + segstart = FP_SEG(start)+(FP_OFF(start)+15)/16; + MML_UseSpace(segstart,seglength, gvar); + gvar->mmi.farheap = length; + gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap; + //printf("start=%Fp segstart=%x seglen=%lu len=%lu\n", start, segstart, seglength, length); + +goto xmsskip; //INFO: 16_PM dose this job better + +// +// detect EMS and allocate up to 64K at page frame +// + gvar->mmi.EMSmem = 0; +//goto emsskip; //0000 + if(MML_CheckForEMS()) + { + MML_SetupEMS(gvar); // allocate space + //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT! + MML_UseSpace(gvar->pm.emm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar); + //if(gvar->pm.emm.EMSVer<0x40) + MM_MapEMS(gvar); // map in used pages + //else + //MM_MapXEMS(gvar); // map in used pages + } + +// +// detect XMS and get upper memory blocks +// +//emsskip: + gvar->mmi.XMSmem = 0; +//goto xmsskip;//0000 + if(MML_CheckForXMS(gvar)) + { + MML_SetupXMS(gvar); // allocate as many UMBs as possible + } + +// +// allocate the misc buffer +// +xmsskip: + gvar->mm.mmrover = gvar->mm.mmhead; // start looking for space after low block + + MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar); +} + +//========================================================================== + +/* +==================== += += MM_Shutdown += += Frees all conventional, EMS, and XMS allocated += +==================== +*/ + +void MM_Shutdown(global_game_variables_t *gvar) +{ + if(!(gvar->mm.mmstarted)) + return; + + _ffree(gvar->mm.farheap);// printf(" far freed\n"); +#ifdef __WATCOMC__ + _nfree(gvar->mm.nearheap);// printf(" near freed\n"); +#endif +#ifdef __BORLANDC__ + free(gvar->mm.nearheap);// printf(" near freed\n"); +#endif + if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf(" EMS freed\n"); } + if(MML_CheckForXMS(gvar)){ MML_ShutdownXMS(gvar); }//printf(" XMS freed\n"); } +} + +//========================================================================== + +/* +==================== += += MM_GetPtr += += Allocates an unlocked, unpurgable block += +==================== +*/ + +void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next; + mmblocktype far *scan,far *lastscan,far *endscan,far *purge,far *next; + int search; + unsigned needed,startseg; + + needed = (size+15)/16; // convert size from bytes to paragraphs + + GETNEWBLOCK; // fill in start and next after a spot is found + gvar->mm.mmnew->length = needed; + gvar->mm.mmnew->useptr = baseptr; + //if(gvar->mm.mmnew->useptr==NULL){ +#ifdef __DEBUG__ + printf(" MM_GetPtr\n"); + printf(" baseptr=%04x ", baseptr); printf("useptr=%04x\n", gvar->mm.mmnew->useptr); + printf(" *baseptr=%04x ", *baseptr); printf("*useptr=%04x\n", *(gvar->mm.mmnew->useptr)); + printf(" *baseptr=%Fp ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr)); +#endif + //exit(-5); } + gvar->mm.mmnew->attributes = BASEATTRIBUTES; + +//tryagain: + for (search = 0; search<3; search++) + { + // + // first search: try to allocate right after the rover, then on up + // second search: search from the head pointer up to the rover + // third search: compress memory, then scan from start + if (search == 1 && gvar->mm.mmrover == gvar->mm.mmhead) + search++; + + switch (search) + { + case 0: + lastscan = gvar->mm.mmrover; + scan = gvar->mm.mmrover->next; + endscan = NULL; + break; + case 1: + lastscan = gvar->mm.mmhead; + scan = gvar->mm.mmhead->next; + endscan = gvar->mm.mmrover; + break; + case 2: + MM_SortMem (gvar); + lastscan = gvar->mm.mmhead; + scan = gvar->mm.mmhead->next; + endscan = NULL; + break; + } + + startseg = lastscan->start + lastscan->length; + + while (scan != endscan) + { + if (scan->start - startseg >= needed) + { + // + // got enough space between the end of lastscan and + // the start of scan, so throw out anything in the middle + // and allocate the new block + // + purge = lastscan->next; + lastscan->next = gvar->mm.mmnew; + gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg; + gvar->mm.mmnew->next = scan; + while ( purge != scan) + { // free the purgable block + next = purge->next; + FREEBLOCK(purge); + purge = next; // purge another if not at scan + } + gvar->mm.mmrover = gvar->mm.mmnew; + return; // good allocation! + } + + // + // if this block is purge level zero or locked, skip past it + // + if ( (scan->attributes & LOCKBIT) + || !(scan->attributes & PURGEBITS) ) + { + lastscan = scan; + startseg = lastscan->start + lastscan->length; + } + + + scan=scan->next; // look at next line + } + } + + if (gvar->mm.bombonerror) + { +#ifdef __WATCOMC__ + //heapdump(); +#endif + printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap)); + printf("for stability reasons the program will shut down! wwww\n"); + MM_Shutdown(gvar); + exit(-1); + } + else + gvar->mm.mmerror = true; +} + +//========================================================================== + +/* +==================== += += MM_FreePtr += += Allocates an unlocked, unpurgable block += +==================== +*/ + +void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan,huge *last; + mmblocktype far *scan,far *last; + + last = gvar->mm.mmhead; + scan = last->next; + + if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block + gvar->mm.mmrover = gvar->mm.mmhead; + + while(scan->useptr != baseptr && scan) + { + last = scan; + scan = scan->next; + } + + if(!scan) + { + printf("MM_FreePtr: Block not found!\n"); + return; + } + + last->next = scan->next; + + FREEBLOCK(scan); +} +//========================================================================== + +/* +===================== += += MM_SetPurge += += Sets the purge level for a block (locked blocks cannot be made purgable) += +===================== +*/ + +void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar) +{ + mmblocktype huge *start; + //mmblocktype far *start; + + start = gvar->mm.mmrover; + + do + { + if(gvar->mm.mmrover->useptr == baseptr) + break; + + gvar->mm.mmrover = gvar->mm.mmrover->next; + + if(!gvar->mm.mmrover) + gvar->mm.mmrover = gvar->mm.mmhead; + else if(gvar->mm.mmrover == start) + { +#ifdef __DEBUG_PM__ + printf("\n\nstart->useptr gvar->mm.mmhead->useptr\n"); + printf(" %Fp %Fp\n", start->useptr, gvar->mm.mmhead->useptr); + printf("& %Fp %Fp\n", &(start->useptr), &(gvar->mm.mmhead->useptr)); + printf("baseptr gvar->mm.mmrover->useptr\n"); + printf(" %Fp %Fp\n", baseptr, gvar->mm.mmrover->useptr); + printf("& %Fp %Fp\n", &(baseptr), &(gvar->mm.mmrover->useptr)); + printf("* %Fp %Fp\n", *(baseptr), *(gvar->mm.mmrover->useptr)); + printf("start gvar->mm.mmrover gvar->mm.mmrover->next\n"); + printf(" %Fp %Fp %Fp\n", start, gvar->mm.mmrover, gvar->mm.mmrover->next); + printf("& %Fp %Fp %Fp\n", &start, &gvar->mm.mmrover, gvar->mm.mmrover->next); + getch(); + MM_ShowMemory(gvar); + MM_DumpData(gvar); + MM_Report_(gvar); + getch(); +#endif + Quit("MM_SetPurge: Block not found!"); + return; + } + + } while(1); + + gvar->mm.mmrover->attributes &= ~PURGEBITS; + gvar->mm.mmrover->attributes |= purge; +} + +//========================================================================== + +/* +===================== += += MM_SetLock += += Locks / unlocks the block += +===================== +*/ + +void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar) +{ + //huge mmblocktype huge *start; + mmblocktype far *start; + + start = gvar->mm.mmrover; + + do + { + if(gvar->mm.mmrover->useptr == baseptr) + break; + + gvar->mm.mmrover = gvar->mm.mmrover->next; + + if(!gvar->mm.mmrover) + gvar->mm.mmrover = gvar->mm.mmhead; + else if(gvar->mm.mmrover == start) + { + Quit("MM_SetLock: Block not found!"); + //return; + } + + } while(1); + + gvar->mm.mmrover->attributes &= ~LOCKBIT; + gvar->mm.mmrover->attributes |= locked*LOCKBIT; +} + +//========================================================================== + +/* +===================== += += MM_SortMem += += Throws out all purgable stuff and compresses movable blocks += +===================== +*/ + +void MM_SortMem(global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan,huge *last,huge *next; + mmblocktype far *scan,far *last,far *next; + unsigned start,length,source,dest,oldborder; + int playing; + + // + // lock down a currently playing sound + // +/*++++ playing = SD_SoundPlaying (); + if(playing) + { + switch (SoundMode) + { + case sdm_PC: + playing += STARTPCSOUNDS; + break; + case sdm_AdLib: + playing += STARTADLIBSOUNDS; + break; + } + MM_SetLock(&(memptr)audiosegs[playing],true); + } + + + SD_StopSound();*/ +// oldborder = bordercolor; +// VW_ColorBorder (15); + + if(beforesort) + beforesort(); + + scan = gvar->mm.mmhead; + + last = NULL; // shut up compiler warning + + while(scan) + { + if(scan->attributes & LOCKBIT) + { + // + // block is locked, so try to pile later blocks right after it + // + start = scan->start + scan->length; + } + else + { + if(scan->attributes & PURGEBITS) + { + // + // throw out the purgable block + // + next = scan->next; + FREEBLOCK(scan); + //MM_FreeBlock(scan, gvar); + last->next = next; + scan = next; + continue; + } + else + { + // + // push the non purgable block on top of the last moved block + // + if(scan->start != start) + { + length = scan->length; + source = scan->start; + dest = start; + while(length > 0xf00) + { + movedata(source,0,dest,0,0xf00*16); + length -= 0xf00; + source += 0xf00; + dest += 0xf00; + } + movedata(source,0,dest,0,length*16); + + scan->start = start; + *(unsigned *)scan->useptr = start; + } + start = scan->start + scan->length; + } + } + + last = scan; + scan = scan->next; // go to next block + } + + gvar->mm.mmrover = gvar->mm.mmhead; + + if(aftersort) + aftersort(); + +// VW_ColorBorder (oldborder); + +/*++++ if(playing) + MM_SetLock(&(memptr)audiosegs[playing],false);*/ +} + +//========================================================================== + +/* +===================== += += MM_ShowMemory += +===================== +*/ + +void MM_ShowMemory(global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan; + mmblocktype far *scan; + word temp; + sdword end,owner; + //word chx,chy; + word w; + //dword wwww; + byte scratch[160],scratch0[4096],scratch1[160],str[16]; + //byte d = '#'; +//**** VW_SetDefaultColors(); +//**** VW_SetLineWidth(40); +//++++mh temp = bufferofs; +//++++mh bufferofs = 0; +//**** VW_SetScreen (0,0); + scan = gvar->mm.mmhead; + end = -1; + + CA_OpenDebug (gvar); + w=0; + while(scan) + { + strcpy(scratch, AARESET); + if(scan->attributes & PURGEBITS) + strcpy(scratch0, AAMAGENTA); // dark purple = purgable + else + strcpy(scratch0, AABLUE); // medium blue = non purgable + if(scan->attributes & LOCKBIT) + strcpy(scratch0, AARED); // red = locked + if(scan->start<=end) + { + printf("\nend==%d\n\n", end); + strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n"); + strcat(scratch, "End's Size: "); + ultoa (end,str,10); + strcat (scratch,str); + strcat(scratch, "\nscan->start's Size: "); + ultoa (scan->start,str,10); + strcat (scratch,str); + write(gvar->handle.debughandle,scratch,strlen(scratch)); + //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n"); + break; + } + end = scan->start+(scan->length)-1; +//++++ chy = scan->start/320; +//++++ chx = scan->start%320; + //modexhlin(page, scan->start, (unsigned)end, chy, color); + //for(chx=scan->start;chx+4>=(word)end;chx+=4) + //{ +//++++ modexClearRegion(page, chx, chy, 4, 4, color); + //} +//++++ VW_Hlin(scan->start,(unsigned)end,0,color); + for(w=(scan->start)/80;w<=end/80;w++) + { + //printf("+ %u %lu\n", w, scan->length); + strcat(scratch0, "+"); + } + //++==++==optional strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_"); +//++++ VW_Plot(scan->start,0,15); +//++++ modexClearRegion(page, chx, chy, 4, 4, 15); +//++++ VW_Hlin(end+1,scan->next->start,0,0); // black = free + + //wwww=(dword)(scan->next->start)-(dword)scan->start; + //wwww=(dword)scan->start+(dword)(scan->next->start); + if (scan->next && scan->next->start >= end+1) + { + strcat(scratch0, AARESET); + //++==++==optional strcat(scratch0, "\n"); + strcat(scratch0,AAGREEN); + for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++) + //for(w=(wwww)/80;w<=((end+1)/80);w++) + //for(w=(end+1)/80;w<=((wwww)/80);w++) + { + //printf("0 %x %u %lu\n", scan->next->start, w, scan->length); + strcat(scratch0,"0"); + } + //printf("==================\n"); + //printf("w=%u wwww=%lu start=%04x next=%04x end=%lu\n", w/80, wwww/80, scan->start, (scan->next->start), end+1); + //printf("==================\n"); + strcat(scratch0, "\n"); + //getch(); + }/*else {//if(scan->next->start <= scan->start){ + scan->next->start=scan->start+0x1000; + wwww=(dword)(scan->next->start)-(dword)scan->start; + strcat(scratch0, AARESET); + strcat(scratch0, "\n"); + strcat(scratch0,AAGREEN); + for(w=(end+1);w<=(0x1000/80);w++) + { + //printf("0 %x %x %u\n", scan->start, w); + strcat(scratch0,"0"); + } + printf("================\n"); + printf("w=%x start=%x next=%x end=%u %lu\n", w, scan->start, (scan->next->start), end+1, wwww); + printf("================\n"); + getch(); + }*/ + strcat(scratch0, AARESET); + //strcat(scratch0,"\n"); + //for(chx=scan->next->start;chx+4>=(word)end+1;chx+=4) + //{ +// chx+=scan->next->start; +// modexClearRegion(page, chx, chy, 4, 4, 2); + //} + //modexhlin(page, end+1,scan->next->start, chy, 0); +/* y = scan->start/320; + x = scan->start%320; + VW_Hlin(x,x+end,y,color); + VW_Plot(x,y,15);*/ +//++++ VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free + strcat(scratch,"Seg:"); + ultoa (scan->start,str,16); + strcat (scratch,str); + strcat (scratch,"\tSize:"); + ultoa ((unsigned)scan->length,str,10); + strcat (scratch,str); + strcat (scratch,"\tOwner:0x"); + owner = (unsigned)scan->useptr; + ultoa (owner,str,16); + strcat (scratch,str); + strcat (scratch,"\n"); + write(gvar->handle.debughandle,scratch,strlen(scratch)); + write(gvar->handle.debughandle,scratch0,strlen(scratch0)); +//modexprint(page, chx, chy, 1, 0, 24, &scratch); +//++++chy+=4; +//fprintf(stdout, "%s", scratch); + + scan = scan->next; + } + /*strcpy(scratch1, AARESET); + strcat(scratch1, "========================================\n"); + strcat(scratch1, "near= "); + ultoa (*(gvar->mm.nearheap),str,10); + strcat (scratch1,str); + strcat(scratch1, " far= "); + ultoa (*(gvar->mm.farheap),str,10); + strcat (scratch1,str); + strcat(scratch1, "\n"); + //strcat(scratch1, "&near= %Fp ", &(gvar->mm.nearheap)); + //strcat(scratch1, "&far= %Fp", &(gvar->mm.farheap)); + //strcat(scratch1, "\n"); + strcat(scratch1, "========================================\n"); + write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/ + + + CA_CloseDebug (gvar); + +//++++mh IN_Ack(); +//**** VW_SetLineWidth(64); +//++++mh bufferofs = temp; +} + +//========================================================================== + +/* +===================== += += MM_DumpData += +===================== +*/ + +void MM_DumpData(global_game_variables_t *gvar) +{ + //huge mmblocktype huge *scan,huge *best; + mmblocktype far *scan,far *best; + long lowest,oldlowest; + word owner; + byte lock,purge; + FILE *dumpfile; + + free(gvar->mm.nearheap); +#ifdef __BORLANDC__ + dumpfile = fopen ("mmdump.16b","w"); +#endif +#ifdef __WATCOMC__ + dumpfile = fopen ("mmdump.16w","w"); +#endif + if (!dumpfile){ + printf("MM_DumpData: Couldn't open MMDUMP.16!\n"); + return; + } + + lowest = -1; + do + { + oldlowest = lowest; + lowest = 0xffff; + + scan = gvar->mm.mmhead; + while (scan) + { + owner = (unsigned)scan->useptr; + + if (owner && owner oldlowest) + { + best = scan; + lowest = owner; + } + + scan = scan->next; + } + + if (lowest != 0xffff) + { + if (best->attributes & PURGEBITS) + purge = 'P'; + else + purge = '-'; + if (best->attributes & LOCKBIT) + lock = 'L'; + else + lock = '-'; + fprintf (dumpfile,"0x%p (%c%c) = %u\n" + ,(unsigned)lowest,lock,purge,best->length); + } + + } while (lowest != 0xffff); + + fclose(dumpfile); + printf("MMDUMP.16 created.\n"); +} + +//========================================================================== + + +/* +====================== += += MM_UnusedMemory += += Returns the total free space without purging += +====================== +*/ + +dword MM_UnusedMemory(global_game_variables_t *gvar) +{ + dword free; + //huge mmblocktype huge *scan; + mmblocktype far *scan; + + free = 0; + scan = gvar->mm.mmhead; + + while(scan->next) + { + free += scan->next->start - (scan->start + scan->length); + scan = scan->next; + } + + return free*16lu; +// return free; +} + +//========================================================================== + + +/* +====================== += += MM_TotalFree += += Returns the total free space with purging += +====================== +*/ + +dword MM_TotalFree(global_game_variables_t *gvar) +{ + dword free; + //huge mmblocktype huge *scan; + mmblocktype far *scan; + + free = 0; + scan = gvar->mm.mmhead; + + while(scan->next) + { + if((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT)) + free += scan->length; + free += scan->next->start - (scan->start + scan->length); + scan = scan->next; + } + + return free*16lu; +// return free; +} + +//========================================================================== + +/* +===================== += += MM_Report += +===================== +*/ + +void MM_Report_(global_game_variables_t *gvar) +{ + printf("========================================\n"); + printf(" MM_Report\n"); + printf("========================================\n"); + if(MML_CheckForEMS()) + { + printf(" LIMEMS\n"); + printf(" EMM v%x.%x available\n", gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F); + printf(" totalEMSpages: %u ", gvar->pm.emm.totalEMSpages); printf("freeEMSpages: %u\n", gvar->pm.emm.freeEMSpages); + printf(" EMSPageFrame: %x\n", gvar->pm.emm.EMSPageFrame); + } + if(MML_CheckForXMS(gvar)) + { + printf(" XMS\n"); + printf(" XMSaddr: %X\n", *XMSaddr); + } + printf("near: %lu ", gvar->mmi.nearheap); printf("far: %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS()) + printf("EMSmem: %lu ", gvar->mmi.EMSmem); if(MML_CheckForXMS(gvar)) printf("XMSmem: %lu", gvar->mmi.XMSmem); printf("\n"); + //printf("mainmem: %lu\n", gvar->mmi.mainmem); + printf("Total convmem: %lu ", gvar->mmi.mainmem); printf("TotalFree: %lu ", MM_TotalFree(gvar)); printf("TotalUsed: %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem); + printf(" UnusedMemory: %lu\n", MM_UnusedMemory(gvar)); +} + +//========================================================================== + +/* +===================== += += MM_EMSerr += +===================== +*/ + +void MM_EMSerr(byte *stri, byte err) +{ + //Returns a text string describing the error code in EMS.Error. + switch(err) + { + case 0x0: + strcat(stri, "successful"); + break; + case 0x80: + strcat(stri, "internal error"); + break; + case 0x81: + strcat(stri, "hardware malfunction"); + break; + case 0x82: + strcat(stri, "busy .. retry later"); + break; + case 0x83: + strcat(stri, "invalid handle"); + break; + case 0x84: + strcat(stri, "undefined function requested by application"); + break; + case 0x85: + strcat(stri, "no more handles available"); + break; + case 0x86: + strcat(stri, "error in save or restore of mapping context"); + break; + case 0x87: + strcat(stri, "insufficient memory pages in system"); + break; + case 0x88: + strcat(stri, "insufficient memory pages available"); + break; + case 0x89: + strcat(stri, "zero pages requested"); + break; + case 0x8A: + strcat(stri, "invalid logical page number encountered"); + break; + case 0x8B: + strcat(stri, "invalid physical page number encountered"); + break; + case 0x8C: + strcat(stri, "page-mapping hardware state save area is full"); + break; + case 0x8D: + strcat(stri, "save of mapping context failed"); + break; + case 0x8E: + strcat(stri, "restore of mapping context failed"); + break; + case 0x8F: + strcat(stri, "undefined subfunction"); + break; + case 0x90: + strcat(stri, "undefined attribute type"); + break; + case 0x91: + strcat(stri, "feature not supported"); + break; + case 0x92: + strcat(stri, "successful, but a portion of the source region has been overwritten"); + break; + case 0x93: + strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle"); + break; + case 0x94: + strcat(stri, "conventional and expanded memory regions overlap"); + break; + case 0x95: + strcat(stri, "offset within logical page exceeds size of logical page"); + break; + case 0x96: + strcat(stri, "region length exceeds 1 MB"); + break; + case 0x97: + strcat(stri, "source and destination EMS regions have same handle and overlap"); + break; + case 0x98: + strcat(stri, "memory source or destination type undefined"); + break; + case 0x9A: + strcat(stri, "specified alternate map register or DMA register set not supported"); + break; + case 0x9B: + strcat(stri, "all alternate map register or DMA register sets currently allocated"); + break; + case 0x9C: + strcat(stri, "alternate map register or DMA register sets not supported"); + break; + case 0x9D: + strcat(stri, "undefined or unallocated alternate map register or DMA register set"); + break; + case 0x9E: + strcat(stri, "dedicated DMA channels not supported"); + break; + case 0x9F: + strcat(stri, "specified dedicated DMA channel not supported"); + break; + case 0xA0: + strcat(stri, "no such handle name"); + break; + case 0xA1: + strcat(stri, "a handle found had no name, or duplicate handle name"); + break; + case 0xA2: + strcat(stri, "attempted to wrap around 1M conventional address space"); + break; + case 0xA3: + strcat(stri, "source array corrupted"); + break; + case 0xA4: + strcat(stri, "operating system denied access"); + break; + default: + strcat(stri, "undefined error"); + } +} + +//========================================================================== + +/* +===================== += += MM_BombOnError += +===================== +*/ + +void MM_BombOnError(boolean bomb, global_game_variables_t *gvar) +{ + gvar->mm.bombonerror = bomb; +} + +/*void MM_GetNewBlock(global_game_variables_t *gvar) +{ + if(!gvar->mm.mmfree) + MML_ClearBlock(gvar); + gvar->mm.mmnew=gvar->mm.mmfree; + gvar->mm.mmfree=gvar->mm.mmfree->next; + if(!(gvar->mm.mmnew=gvar->mm.mmfree)) + { + printf("MM_GETNEWBLOCK: No free blocks!\n"); + return; + } + gvar->mm.mmfree=gvar->mm.mmfree->next; +} + +void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar) +{ + x->useptr=NULL; + x->next=gvar->mm.mmfree; + gvar->mm.mmfree=x; +}*/ + +void XMS_CALL(byte v, global_game_variables_t *gvar) +{ + XMSD; + //XMSDriver=gvar->pm.xmm.XMSDriver; + __asm { + mov v,ah + call [WORD PTR XMSDriver] + } +} + +/*void MM_seguin(void) +{ + __asm { + push ds + mov ax,ds + inc ax + mov ds,ax + } +} + +void MM_segude(void) +{ + __asm { + pop ds + } +}*/ + +/* +pull data from far and put it into ds var +mov ax,es:si +mov x,ax +*/ +/* +ss stack segment +sp top of stack +bp bottem of stack +*/ diff --git a/src/lib/16_mm.h b/src/lib/16_mm.h index 206a3c8b..d351abfa 100755 --- a/src/lib/16_mm.h +++ b/src/lib/16_mm.h @@ -1,220 +1,212 @@ -/* Catacomb Apocalypse Source Code - * Copyright (C) 1993-2014 Flat Rock Software - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -// ID_MM.H - -#ifndef __16_EXMM__ -#define __16_EXMM__ - -#include -#include -#include "src/lib/16_head.h" -#include "src/lib/16_hc.h" -#include "src/lib/16_lib.h" -//++++mh #include "src/lib/16_in.h" - - -#ifdef __DEBUG__ // 1 == Debug/Dev ; 0 == Production/final -#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%lu bytes\n" -#else -#define OUT_OF_MEM_MSG "\npee\n" -#endif - -//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!") ;mmfree=mmfree->next;} -#define GETNEWBLOCK {if(!gvar->mm.mmfree)MML_ClearBlock(gvar);gvar->mm.mmnew=gvar->mm.mmfree;gvar->mm.mmfree=gvar->mm.mmfree->next;} - -#define FREEBLOCK(x) {*x->useptr=NULL;x->next=gvar->mm.mmfree;gvar->mm.mmfree=x;} - -#define SAVENEARHEAP 0x200 // space to leave in data segment -#define SAVEFARHEAP 0//x400 // space to leave in far heap - -#define BUFFERSIZE 0x1000 // miscelanious, allways available buffer - -//moved to typdefst -//#define MAXBLOCKS 1024 - - - -//-------- - -#define EMS_INT 0x67 - -#define EMS_STATUS 0x40 -#define EMS_GETFRAME 0x41 -#define EMS_GETPAGES 0x42 -#define EMS_ALLOCPAGES 0x43 -#define EMS_MAPPAGE 0x44 -#define EMS_MAPXPAGE 0x50 -#define EMS_FREEPAGES 0x45 -#define EMS_VERSION 0x46 - -//-------- - -#define XMS_INT 0x2f -#define XMSD dword XMSDriver=gvar->pm.xmm.XMSDriver; -inline void XMS_CALL(byte v, global_game_variables_t *gvar) -{ - XMSD; - XMSDriver=gvar->pm.xmm.XMSDriver; - __asm { - mov v,ah - call [WORD PTR XMSDriver] - } -} - -#define XMS_VERSION 0x00 - -#define XMS_ALLOCHMA 0x01 -#define XMS_FREEHMA 0x02 - -#define XMS_GENABLEA20 0x03 -#define XMS_GDISABLEA20 0x04 -#define XMS_LENABLEA20 0x05 -#define XMS_LDISABLEA20 0x06 -#define XMS_QUERYA20 0x07 - -#define XMS_QUERYFREE 0x08 -#define XMS_ALLOC 0x09 -#define XMS_FREE 0x0A -#define XMS_MOVE 0x0B -#define XMS_LOCK 0x0C -#define XMS_UNLOCK 0x0D -#define XMS_GETINFO 0x0E -#define XMS_RESIZE 0x0F - -#define XMS_ALLOCUMB 0x10 -#define XMS_FREEUMB 0x11 - -//========================================================================== - -//moved to typdefst -/*typedef struct -{ - dword nearheap,farheap,EMSmem,XMSmem,mainmem; -} mminfotype;*/ - -//========================================================================== - -extern void (* beforesort) (void); -extern void (* aftersort) (void); -extern void (* XMSaddr) (void); // far pointer to XMS driver - -//========================================================================== - -/* -============================================================================= - - LOCAL INFO - -============================================================================= -*/ - -#define LOCKBIT 0x80 // if set in attributes, block cannot be moved -#define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first -#define PURGEMASK 0xfffc -#define BASEATTRIBUTES 0 // unlocked, non purgable - -//moved to typedefst -//#define MAXUMBS 12 -#define MAPPAGES 4//gvar->mm.EMSpagesmapped - -//moved to typdefst -/*typedef struct mmblockstruct -{ - word start,length; - //word start; dword length; - word blob; //for data larger than 64k - unsigned attributes; - memptr *useptr; // pointer to the segment start - //huge struct mmblockstruct huge *next; - struct mmblockstruct far *next; -} mmblocktype; - - -typedef struct -{ - memptr bufferseg; - boolean mmstarted, bombonerror, mmerror; - //huge void huge *farheap; - void far *farheap; -#ifdef __BORLANDC__ - void *nearheap; -#endif -#ifdef __WATCOMC__ - void __near *nearheap; -#endif - //byte EMS_status; - unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle; - unsigned int EMSVer; - word numUMBs,UMBbase[MAXUMBS]; - //dword numUMBs,UMBbase[MAXUMBS]; - //huge mmblocktype huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew; - mmblocktype far mmblocks[MAXBLOCKS],far *mmhead,far *mmfree,far *mmrover,far *mmnew; -} mminfo_t;*/ - -/* -============================================================================= - - GLOBAL VARIABLES - -============================================================================= -*/ - - -/* -============================================================================= - - LOCAL VARIABLES - -============================================================================= -*/ - -//========================================================================== - -boolean MML_CheckForEMS(void); -//byte MML_SetupEMS(mminfo_t *mm); -//void MML_ShutdownEMS(mminfo_t *mm); -byte MM_MapEMS(global_game_variables_t *gvar); -byte MM_MapXEMS(global_game_variables_t *gvar); -//boolean MML_CheckForXMS(mminfo_t *mm); -//void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi); -//void MML_ShutdownXMS(mminfo_t *mm); -void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar); -void MML_ClearBlock(global_game_variables_t *gvar); - -void MM_Startup(global_game_variables_t *gvar); -void MM_Shutdown(global_game_variables_t *gvar); - -void MM_GetPtr(memptr *baseptr,dword size, global_game_variables_t *gvar); -void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar); -void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar); -void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar); -void MM_SortMem(global_game_variables_t *gvar); -void MM_ShowMemory(global_game_variables_t *gvar); -void MM_DumpData(global_game_variables_t *gvar); -dword MM_UnusedMemory(global_game_variables_t *gvar); -dword MM_TotalFree(global_game_variables_t *gvar); -void MM_Report_(global_game_variables_t *gvar); -/*static */void MM_EMSerr(byte *stri, byte err); -void MM_BombOnError(boolean bomb, global_game_variables_t *gvar); -//void MM_GetNewBlock(mminfo_t *mm); -//void MM_FreeBlock(mmblocktype *x, mminfo_t *mm); - -//========================================================================== - -#endif +/* Catacomb Apocalypse Source Code + * Copyright (C) 1993-2014 Flat Rock Software + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// ID_MM.H + +#ifndef __16_EXMM__ +#define __16_EXMM__ + +#include +#include +#include "src/lib/16_head.h" +#include "src/lib/16_hc.h" +#include "src/lib/16_lib.h" +//++++mh #include "src/lib/16_in.h" + + +#ifdef __DEBUG__ // 1 == Debug/Dev ; 0 == Production/final +#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%lu bytes\n" +#else +#define OUT_OF_MEM_MSG "\npee\n" +#endif + +//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!") ;mmfree=mmfree->next;} +#define GETNEWBLOCK {if(!gvar->mm.mmfree)MML_ClearBlock(gvar);gvar->mm.mmnew=gvar->mm.mmfree;gvar->mm.mmfree=gvar->mm.mmfree->next;} + +#define FREEBLOCK(x) {*x->useptr=NULL;x->next=gvar->mm.mmfree;gvar->mm.mmfree=x;} + +#define SAVENEARHEAP 0x200 // space to leave in data segment +#define SAVEFARHEAP 0//x400 // space to leave in far heap + +#define BUFFERSIZE 0x1000 // miscelanious, allways available buffer + +//moved to typdefst +//#define MAXBLOCKS 1024 + + + +//-------- + +#define EMS_INT 0x67 + +#define EMS_STATUS 0x40 +#define EMS_GETFRAME 0x41 +#define EMS_GETPAGES 0x42 +#define EMS_ALLOCPAGES 0x43 +#define EMS_MAPPAGE 0x44 +#define EMS_MAPXPAGE 0x50 +#define EMS_FREEPAGES 0x45 +#define EMS_VERSION 0x46 + +//-------- + +#define XMS_INT 0x2f +#define XMSD dword XMSDriver=gvar->pm.xmm.XMSDriver; + +#define XMS_VERSION 0x00 + +#define XMS_ALLOCHMA 0x01 +#define XMS_FREEHMA 0x02 + +#define XMS_GENABLEA20 0x03 +#define XMS_GDISABLEA20 0x04 +#define XMS_LENABLEA20 0x05 +#define XMS_LDISABLEA20 0x06 +#define XMS_QUERYA20 0x07 + +#define XMS_QUERYFREE 0x08 +#define XMS_ALLOC 0x09 +#define XMS_FREE 0x0A +#define XMS_MOVE 0x0B +#define XMS_LOCK 0x0C +#define XMS_UNLOCK 0x0D +#define XMS_GETINFO 0x0E +#define XMS_RESIZE 0x0F + +#define XMS_ALLOCUMB 0x10 +#define XMS_FREEUMB 0x11 + +//========================================================================== + +//moved to typdefst +/*typedef struct +{ + dword nearheap,farheap,EMSmem,XMSmem,mainmem; +} mminfotype;*/ + +//========================================================================== + +extern void (* beforesort) (void); +extern void (* aftersort) (void); +extern void (* XMSaddr) (void); // far pointer to XMS driver + +//========================================================================== + +/* +============================================================================= + + LOCAL INFO + +============================================================================= +*/ + +#define LOCKBIT 0x80 // if set in attributes, block cannot be moved +#define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first +#define PURGEMASK 0xfffc +#define BASEATTRIBUTES 0 // unlocked, non purgable + +//moved to typedefst +//#define MAXUMBS 12 +#define MAPPAGES 4//gvar->mm.EMSpagesmapped + +//moved to typdefst +/*typedef struct mmblockstruct +{ + word start,length; + //word start; dword length; + word blob; //for data larger than 64k + unsigned attributes; + memptr *useptr; // pointer to the segment start + //huge struct mmblockstruct huge *next; + struct mmblockstruct far *next; +} mmblocktype; + + +typedef struct +{ + memptr bufferseg; + boolean mmstarted, bombonerror, mmerror; + //huge void huge *farheap; + void far *farheap; +#ifdef __BORLANDC__ + void *nearheap; +#endif +#ifdef __WATCOMC__ + void __near *nearheap; +#endif + //byte EMS_status; + unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle; + unsigned int EMSVer; + word numUMBs,UMBbase[MAXUMBS]; + //dword numUMBs,UMBbase[MAXUMBS]; + //huge mmblocktype huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew; + mmblocktype far mmblocks[MAXBLOCKS],far *mmhead,far *mmfree,far *mmrover,far *mmnew; +} mminfo_t;*/ + +/* +============================================================================= + + GLOBAL VARIABLES + +============================================================================= +*/ + + +/* +============================================================================= + + LOCAL VARIABLES + +============================================================================= +*/ + +//========================================================================== + +boolean MML_CheckForEMS(void); +//byte MML_SetupEMS(mminfo_t *mm); +//void MML_ShutdownEMS(mminfo_t *mm); +byte MM_MapEMS(global_game_variables_t *gvar); +byte MM_MapXEMS(global_game_variables_t *gvar); +//boolean MML_CheckForXMS(mminfo_t *mm); +//void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi); +//void MML_ShutdownXMS(mminfo_t *mm); +void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar); +void MML_ClearBlock(global_game_variables_t *gvar); + +void MM_Startup(global_game_variables_t *gvar); +void MM_Shutdown(global_game_variables_t *gvar); + +void MM_GetPtr(memptr *baseptr,dword size, global_game_variables_t *gvar); +void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar); +void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar); +void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar); +void MM_SortMem(global_game_variables_t *gvar); +void MM_ShowMemory(global_game_variables_t *gvar); +void MM_DumpData(global_game_variables_t *gvar); +dword MM_UnusedMemory(global_game_variables_t *gvar); +dword MM_TotalFree(global_game_variables_t *gvar); +void MM_Report_(global_game_variables_t *gvar); +/*static */void MM_EMSerr(byte *stri, byte err); +void MM_BombOnError(boolean bomb, global_game_variables_t *gvar); +//void MM_GetNewBlock(mminfo_t *mm); +//void MM_FreeBlock(mmblocktype *x, mminfo_t *mm); +void XMS_CALL(byte v, global_game_variables_t *gvar); + +//========================================================================== + +#endif diff --git a/src/lib/16_pm.c b/src/lib/16_pm.c index 8ebf0ec0..ea11ac48 100755 --- a/src/lib/16_pm.c +++ b/src/lib/16_pm.c @@ -137,62 +137,51 @@ PML_MapEMS(word logical, byte physical, global_game_variables_t *gvar) boolean PML_StartupEMS(global_game_variables_t *gvar) { - boolean emmcfems; - int i; long size; + boolean errorflag; gvar->pm.emm.EMSPresent = false; // Assume that we'll fail gvar->pm.emm.EMSAvail = 0; - emmcfems=0; + errorflag=0; + _DX = (word)EMMDriverName; + _AX = 0x3d00; + geninterrupt(0x21); // try to open EMMXXXX0 device __asm { - //_DX = (word)EMMDriverName; - //_AX = 0x3d00; - //geninterrupt(0x21); // try to open EMMXXXX0 device - mov dx,OFFSET EMMDriverName - mov ax,0x3d00 - int 0x21 // try to open EMMXXXX0 device - jnc gothandle - //fail - mov emmcfems,1 - jmp Aend -#ifdef __BORLANDC__ + jnc gothandle + mov errorflag,1 + gothandle: } -#endif + if(errorflag) + goto error; -gothandle: -#ifdef __BORLANDC__ +//gothandle: + _BX = _AX; + _AX = 0x4400; + geninterrupt(0x21); // get device info __asm { -#endif - //_BX = _AX; - //_AX = 0x4400; - //geninterrupt(0x21); // get device info - mov bx,ax - mov ax,0x4400 - int 0x21 // get device info jnc gotinfo - //fail - mov emmcfems,1 - jmp Aend -#ifdef __BORLANDC__ - } -#endif -Aend: -gotinfo: -#ifndef __BORLANDC__ + mov errorflag,1 + gotinfo: } -#endif - if(emmcfems!=0) goto error; - __asm and dx,0x80 + if(errorflag) + goto error; + +//gotinfo: +__asm and dx,0x80 if (!_DX) goto error; _AX = 0x4407; geninterrupt(0x21); // get status - __asm mov emmcfems,1 - if(emmcfems!=0) goto error; - + __asm { + jc error + jmp end + error: + mov errorflag,1 + end: + } if (!_AL) goto error; @@ -256,11 +245,16 @@ error: void PML_ShutdownEMS(global_game_variables_t *gvar) { + word EMSHandle; + EMSHandle=gvar->pm.emm.EMSHandle; + if (gvar->pm.emm.EMSPresent) { - _AH=EMS_FREEPAGES; - _AX=gvar->pm.emm.EMSHandle; - geninterrupt(EMS_INT); + __asm { + mov ah,EMS_FREEPAGES + mov dx,[EMSHandle] + int EMS_INT + } if (_AH) { Quit("PML_ShutdownEMS: Error freeing EMS\n"); @@ -435,8 +429,15 @@ PM_SetMainMemPurge(int level, global_game_variables_t *gvar) int i; for (i = 0;i < PMMaxMainMem;i++) + { +#ifdef __DEBUG_PM__ + printf("PM_SetMainMemPurge() info of gvar->pm.mm.MainMemPages[i]\n"); + printf(" %Fp, %Fp\n", gvar->pm.mm.MainMemPages[i], (gvar->pm.mm.MainMemPages[i])); + printf("& %Fp, %Fp\n", &gvar->pm.mm.MainMemPages[i], &(gvar->pm.mm.MainMemPages[i])); +#endif if (gvar->pm.mm.MainMemPages[i]) - MM_SetPurge(&gvar->pm.mm.MainMemPages[i],level, gvar); + MM_SetPurge((gvar->pm.mm.MainMemPages[i]),level, gvar); + } } // diff --git a/src/lib/16_sprit.c b/src/lib/16_sprit.c index c5158dc5..c59590ce 100755 --- a/src/lib/16_sprit.c +++ b/src/lib/16_sprit.c @@ -1,118 +1,118 @@ -#include "src/lib/16_sprit.h" - -char* get_curr_anim_name(struct sprite *spri) -{ - // Retrive animation name list - struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; - uint32_t huge *anim_names_offsets = (uint32_t huge *) - ((byte huge *)vrs + - vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_NAME_LIST]); - - return (char *)(vrs + anim_names_offsets[spri->curr_anim]); -} - -void init_anim(struct sprite *spri, int anim_index) -{ - struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; - uint32_t huge *anim_lists_offsets = (uint32_t huge *) - ((byte huge *)vrs + - vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_LIST]); - struct vrs_animation_list_entry_t huge *anim_list = (struct vrs_animation_list_entry_t huge *) - ((byte huge *)vrs + - anim_lists_offsets[anim_index]); - - // Upon new animation, start from the first sprite in it - spri->curr_anim = anim_index; - spri->curr_anim_spri = 0; - spri->curr_spri_id = anim_list[0].sprite_id; - spri->delay = anim_list[0].delay; - - spri->curr_anim_list = anim_list; -} - - -int set_anim_by_id(struct sprite *spri, int anim_id) -{ - int new_anim_index = 0; - int iter_id; - struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; - // Retruve animation ids list - uint16_t huge *anim_ids = (uint16_t huge *) - ((byte huge *)vrs + - vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]); - - // Loop through animation id untill match or end of list - while(iter_id = anim_ids[new_anim_index]) - { - // Return on successful match - if (iter_id == anim_id) - { - init_anim(spri, new_anim_index); - return 0; - } - new_anim_index++; - } - return -1; -} - -void print_anim_ids(struct sprite *spri) -{ - int new_anim_index = 0; - int iter_id; - struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; - // Retruve animation ids list - uint16_t huge *anim_ids = (uint16_t huge *) - ((byte huge *)vrs + - vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]); - - if(!anim_ids[new_anim_index]) - exit(3); - // Loop through animation id untill match or end of list - while(iter_id = anim_ids[new_anim_index]) - { - // Return on successful match - new_anim_index++; - } -} - - -void animate_spri(struct sprite *spri) -{ - int i; - // Events go here - - // Draw sprite - i = get_vrl_by_id(spri->spritesheet, spri->curr_spri_id, spri->sprite_vrl_cont); - if(i < 0) - { - printf("Error retriving required sprite"); - exit(-1); - } - draw_vrl1_vgax_modex( spri->x, spri->y, - spri->sprite_vrl_cont->vrl_header, spri->sprite_vrl_cont->line_offsets, - spri->sprite_vrl_cont->buffer + sizeof(struct vrl1_vgax_header), - spri->sprite_vrl_cont->data_size); - - // Depending on delay, update indices - switch(spri->delay){ - // Delay = 0 means that sprite should loop. Nothing to change here - case 0: - break; - - // Delay = 1 means that on next time unit sprite should be changed - case 1: - spri->curr_anim_spri++; - - // If we hit the end of an animation sequence, restart it - if(!(spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id)){ - spri->curr_anim_spri = 0; - spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id; - } - spri->delay = spri->curr_anim_list[spri->curr_anim_spri].delay; - - // Delay > 1 means that we should not change sprite yet. Decrease delay - default: - spri->delay--; - break; - } -} +#include "src/lib/16_sprit.h" + +char* get_curr_anim_name(struct sprite *spri) +{ + // Retrive animation name list + struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; + uint32_t huge *anim_names_offsets = (uint32_t huge *) + ((byte huge *)vrs + + vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_NAME_LIST]); + + return (char *)(vrs + anim_names_offsets[spri->curr_anim]); +} + +void init_anim(struct sprite *spri, int anim_index) +{ + struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; + uint32_t huge *anim_lists_offsets = (uint32_t huge *) + ((byte huge *)vrs + + vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_LIST]); + struct vrs_animation_list_entry_t huge *anim_list = (struct vrs_animation_list_entry_t huge *) + ((byte huge *)vrs + + anim_lists_offsets[anim_index]); + + // Upon new animation, start from the first sprite in it + spri->curr_anim = anim_index; + spri->curr_anim_spri = 0; + spri->curr_spri_id = anim_list[0].sprite_id; + spri->delay = anim_list[0].delay; + + spri->curr_anim_list = anim_list; +} + + +int set_anim_by_id(struct sprite *spri, int anim_id) +{ + int new_anim_index = 0; + int iter_id; + struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; + // Retruve animation ids list + uint16_t huge *anim_ids = (uint16_t huge *) + ((byte huge *)vrs + + vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]); + + // Loop through animation id untill match or end of list + while(iter_id = anim_ids[new_anim_index]) + { + // Return on successful match + if (iter_id == anim_id) + { + init_anim(spri, new_anim_index); + return 0; + } + new_anim_index++; + } + return -1; +} + +void print_anim_ids(struct sprite *spri) +{ + int new_anim_index = 0; + int iter_id; + struct vrs_header huge *vrs = spri->spritesheet->vrs_hdr; + // Retruve animation ids list + uint16_t huge *anim_ids = (uint16_t huge *) + ((byte huge *)vrs + + vrs->offset_table[VRS_HEADER_OFFSET_ANIMATION_ID_LIST]); + + if(!anim_ids[new_anim_index]) + exit(3); + // Loop through animation id untill match or end of list + while(iter_id = anim_ids[new_anim_index]) + { + // Return on successful match + new_anim_index++; + } +} + + +void animate_spri(struct sprite *spri) +{ + int i; + // Events go here + + // Draw sprite + i = get_vrl_by_id(spri->spritesheet, spri->curr_spri_id, spri->sprite_vrl_cont); + if(i < 0) + { + printf("Error retriving required sprite"); + exit(-1); + } + draw_vrl1_vgax_modex( spri->x, spri->y, + spri->sprite_vrl_cont->vrl_header, spri->sprite_vrl_cont->line_offsets, + spri->sprite_vrl_cont->buffer + sizeof(struct vrl1_vgax_header), + spri->sprite_vrl_cont->data_size); + + // Depending on delay, update indices + switch(spri->delay){ + // Delay = 0 means that sprite should loop. Nothing to change here + case 0: + break; + + // Delay = 1 means that on next time unit sprite should be changed + case 1: + spri->curr_anim_spri++; + + // If we hit the end of an animation sequence, restart it + if(!(spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id)){ + spri->curr_anim_spri = 0; + spri->curr_spri_id = spri->curr_anim_list[spri->curr_anim_spri].sprite_id; + } + spri->delay = spri->curr_anim_list[spri->curr_anim_spri].delay; + + // Delay > 1 means that we should not change sprite yet. Decrease delay + default: + spri->delay--; + break; + } +} diff --git a/src/lib/16_sprit.h b/src/lib/16_sprit.h index a93838ac..555e8d1c 100755 --- a/src/lib/16_sprit.h +++ b/src/lib/16_sprit.h @@ -1,74 +1,74 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef __16_SPRI__ -#define __16_SPRI__ - -#include "src/lib/16_vrs.h" -#include "src/lib/typdefst.h" - -struct sprite -{ - // VRS container from which we will extract animation and image data - struct vrs_container *spritesheet; - // Container for a vrl sprite - struct vrl_container *sprite_vrl_cont; - // Current sprite id - int curr_spri_id; - // Index of a current sprite in an animation sequence - int curr_anim_spri; - // Current animation sequence - struct vrs_animation_list_entry_t *curr_anim_list; - // Index of current animation in relevant VRS offsets table - int curr_anim; - // Delay in time units untill we should change sprite - int delay; - // Position of sprite on screen - int x, y; -}; - -/* Retrive current animation name of sprite -* In: -* + struct sprite *spri - sprite to retrive current animation sequence name from -* Out: -* + char* - animation sequence name -*/ -char* get_curr_anim_name(struct sprite *spri); - -/* Change sprite's current animation to the one given by id - * In: - * struct sprite *spri - sprite to manipulate on - * int id - id of a new animation sequence of th sprite - * Out: - * int - 0 on success, -1 on error - */ -int set_anim_by_id(struct sprite *spri, int id); - -/* Animate sprite, triggering any events and changing indices if necessary - * NB: if you want to change animation sequence after a specific sprite is shown, you should call animate_spri first - * In: - * + struct sprite *spri - sprite to animate - */ -void animate_spri(struct sprite *spri); - -void print_anim_ids(struct sprite *spri); - -#endif +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __16_SPRI__ +#define __16_SPRI__ + +#include "src/lib/16_vrs.h" +#include "src/lib/typdefst.h" + +struct sprite +{ + // VRS container from which we will extract animation and image data + struct vrs_container *spritesheet; + // Container for a vrl sprite + struct vrl_container *sprite_vrl_cont; + // Current sprite id + int curr_spri_id; + // Index of a current sprite in an animation sequence + int curr_anim_spri; + // Current animation sequence + struct vrs_animation_list_entry_t *curr_anim_list; + // Index of current animation in relevant VRS offsets table + int curr_anim; + // Delay in time units untill we should change sprite + int delay; + // Position of sprite on screen + int x, y; +}; + +/* Retrive current animation name of sprite +* In: +* + struct sprite *spri - sprite to retrive current animation sequence name from +* Out: +* + char* - animation sequence name +*/ +char* get_curr_anim_name(struct sprite *spri); + +/* Change sprite's current animation to the one given by id + * In: + * struct sprite *spri - sprite to manipulate on + * int id - id of a new animation sequence of th sprite + * Out: + * int - 0 on success, -1 on error + */ +int set_anim_by_id(struct sprite *spri, int id); + +/* Animate sprite, triggering any events and changing indices if necessary + * NB: if you want to change animation sequence after a specific sprite is shown, you should call animate_spri first + * In: + * + struct sprite *spri - sprite to animate + */ +void animate_spri(struct sprite *spri); + +void print_anim_ids(struct sprite *spri); + +#endif diff --git a/src/lib/16_vrs.c b/src/lib/16_vrs.c index 5dc525e1..595489d6 100755 --- a/src/lib/16_vrs.c +++ b/src/lib/16_vrs.c @@ -1,139 +1,139 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#include "src/lib/16_vrs.h" -#include "src/lib/typdefst.h" - -// Read .vrs file into far memory -int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont){ - int fd; - dword size; -#ifdef __WATCOMC__ - __segment seg; - void __based(seg)* bigbuffer; -#endif -#ifdef __BORLANDC__ - memptr bigbuffer; -#endif - byte huge *buffer; - vrl1_vgax_offset_t **vrl_line_offsets; - uint32_t huge *vrl_headers_offsets; - uint16_t huge *vrl_id_iter; - uint32_t vrl_size; - int num_of_vrl, i; - struct vrl1_vgax_header huge *curr_vrl; - int success; - - // Open filename, get size of file, - // populate the vrs_container if all tests pass - fd = open(filename, O_RDONLY|O_BINARY); - // Insert sanity cheks later - size = lseek(fd, 0, SEEK_END); - buffer = malloc(size); - lseek(fd, 0, SEEK_SET); - read(fd, buffer, size); - close(fd); - if(!success) - { - fprintf(stderr, "Unablee to load file"); - exit(3); - } - vrs_cont->data_size = size - sizeof(struct vrs_header); - vrs_cont->buffer = buffer; - - // Calculate vrl offsets - - // Count sprites - vrl_id_iter = (uint16_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]); - while(vrl_id_iter[num_of_vrl]){ - num_of_vrl++; - } - // Allocate memory for vrl line offsets table - vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl); - - vrl_headers_offsets = (uint32_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]); - // Calculate line offsets for each vrl - for(i = 0; i < num_of_vrl; i++){ - curr_vrl = (struct vrl1_vgax_header huge *)(buffer + vrl_headers_offsets[i]); - - // Calc. vrl size as (next_offset - curr_offset) - if (i != num_of_vrl - 1){ - vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); - } - // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset) - else{ - vrl_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); - } - vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size); - } - vrs_cont->vrl_line_offsets = vrl_line_offsets; - return 0; -} - -// Seek and return a specified .vrl blob from .vrs blob in far memory -int get_vrl_by_id(struct vrs_container /*huge*/ *vrs_cont, uint16_t id, struct vrl_container *vrl_cont){ - uint16_t huge *ids; - uint32_t huge *vrl_offs_list; - int counter = 0; - - // If id is invalid, return -1 - if(id == 0){ - // Probably add an error message? - return -1; - } - - // Get id list from .vrs blob (base + offset) - ids = (uint16_t huge*)(vrs_cont->buffer + - vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]); - - // Loop through the id list until we found the right one or hit the end of the list - // Counter is keeping track of the offset(in ids/vrl blobs) - while(ids[counter] != id && ids[counter]){ - counter++; - } - // Return -2 if we couldn't find the requested id - if(!ids[counter]){ - // Error message? - return -2; - } - - // Get vrl offsets list from .vrs blob (base + offset) - vrl_offs_list = (uint32_t huge *)(vrs_cont->buffer + - vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]); - - // Get vrl_header from .vrs (base + offset from vrl_list) - // Counter is number of vrls to skip (ids and vrls are aligned according to the .vrs specification) - vrl_cont->vrl_header = (struct vrl1_vgax_header huge *)(vrs_cont->buffer + vrl_offs_list[counter]); - - // Get .vrl size by integer arithmetics (next vrl offset - current vrl offset) - if(ids[counter+1]){ - vrl_cont->data_size = vrl_offs_list[counter+1] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header); - } - // If we are retriving the last vrl, size is ids_list offset - current vrl offset, as next vrl offs is 0 - else{ - vrl_cont->data_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header); - } - - // Retrive line offsets form .vrs - vrl_cont->line_offsets = vrs_cont->vrl_line_offsets[counter]; - - return 0; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#include "src/lib/16_vrs.h" +#include "src/lib/typdefst.h" + +// Read .vrs file into far memory +int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont){ + int fd; + dword size; +#ifdef __WATCOMC__ + __segment seg; + void __based(seg)* bigbuffer; +#endif +#ifdef __BORLANDC__ + memptr bigbuffer; +#endif + byte huge *buffer; + vrl1_vgax_offset_t **vrl_line_offsets; + uint32_t huge *vrl_headers_offsets; + uint16_t huge *vrl_id_iter; + uint32_t vrl_size; + int num_of_vrl, i; + struct vrl1_vgax_header huge *curr_vrl; + int success; + + // Open filename, get size of file, + // populate the vrs_container if all tests pass + fd = open(filename, O_RDONLY|O_BINARY); + // Insert sanity cheks later + size = lseek(fd, 0, SEEK_END); + buffer = malloc(size); + lseek(fd, 0, SEEK_SET); + read(fd, buffer, size); + close(fd); + if(!success) + { + fprintf(stderr, "Unablee to load file"); + exit(3); + } + vrs_cont->data_size = size - sizeof(struct vrs_header); + vrs_cont->buffer = buffer; + + // Calculate vrl offsets + + // Count sprites + vrl_id_iter = (uint16_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]); + while(vrl_id_iter[num_of_vrl]){ + num_of_vrl++; + } + // Allocate memory for vrl line offsets table + vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl); + + vrl_headers_offsets = (uint32_t huge *)(buffer + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]); + // Calculate line offsets for each vrl + for(i = 0; i < num_of_vrl; i++){ + curr_vrl = (struct vrl1_vgax_header huge *)(buffer + vrl_headers_offsets[i]); + + // Calc. vrl size as (next_offset - curr_offset) + if (i != num_of_vrl - 1){ + vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); + } + // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset) + else{ + vrl_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); + } + vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size); + } + vrs_cont->vrl_line_offsets = vrl_line_offsets; + return 0; +} + +// Seek and return a specified .vrl blob from .vrs blob in far memory +int get_vrl_by_id(struct vrs_container /*huge*/ *vrs_cont, uint16_t id, struct vrl_container *vrl_cont){ + uint16_t huge *ids; + uint32_t huge *vrl_offs_list; + int counter = 0; + + // If id is invalid, return -1 + if(id == 0){ + // Probably add an error message? + return -1; + } + + // Get id list from .vrs blob (base + offset) + ids = (uint16_t huge*)(vrs_cont->buffer + + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]); + + // Loop through the id list until we found the right one or hit the end of the list + // Counter is keeping track of the offset(in ids/vrl blobs) + while(ids[counter] != id && ids[counter]){ + counter++; + } + // Return -2 if we couldn't find the requested id + if(!ids[counter]){ + // Error message? + return -2; + } + + // Get vrl offsets list from .vrs blob (base + offset) + vrl_offs_list = (uint32_t huge *)(vrs_cont->buffer + + vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]); + + // Get vrl_header from .vrs (base + offset from vrl_list) + // Counter is number of vrls to skip (ids and vrls are aligned according to the .vrs specification) + vrl_cont->vrl_header = (struct vrl1_vgax_header huge *)(vrs_cont->buffer + vrl_offs_list[counter]); + + // Get .vrl size by integer arithmetics (next vrl offset - current vrl offset) + if(ids[counter+1]){ + vrl_cont->data_size = vrl_offs_list[counter+1] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header); + } + // If we are retriving the last vrl, size is ids_list offset - current vrl offset, as next vrl offs is 0 + else{ + vrl_cont->data_size = vrs_cont->vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_offs_list[counter] - sizeof(struct vrl1_vgax_header); + } + + // Retrive line offsets form .vrs + vrl_cont->line_offsets = vrs_cont->vrl_line_offsets[counter]; + + return 0; +} diff --git a/src/lib/16_vrs.h b/src/lib/16_vrs.h index 381b7108..cdeb81a0 100755 --- a/src/lib/16_vrs.h +++ b/src/lib/16_vrs.h @@ -1,78 +1,78 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef __16_VRS__ -#define __16_VRS__ - -#include "src/lib/modex16.h" -#include "src/lib/typdefst.h" -//#include -//#include -#include -#include "src/lib/16_ca.h" - -struct vrs_container{ - // Size of a .vrs lob in memory - // minus header - dword data_size; - union{ - byte huge *buffer; - struct vrs_header huge *vrs_hdr; - }; - // Array of corresponding vrl line offsets - vrl1_vgax_offset_t **vrl_line_offsets; -}; - -struct vrl_container{ - // Size of a .vrl blob in memory - // minus header - dword data_size; - union{ - byte huge *buffer; - struct vrl1_vgax_header huge *vrl_header; - }; - // Pointer to a corresponding vrl line offsets struct - vrl1_vgax_offset_t *line_offsets; -}; - -/* Read .vrs file into memory -* In: -* + char *filename - name of the file to load -* + struct vrs_container *vrs_cont - pointer to the vrs_container -* to load the file into -* Out: -* + int - 0 on succes, 1 on failure -*/ -int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont); - -/* Seek and return a specified .vrl blob from .vrs blob in memory -* In: -* + struct vrs_container *vrs_cont - pointer to the vrs_container -* with a loaded .vrs file -* + uint16_t id - id of the vrl to retrive -* + struct vrl_container * vrl_cont - pointer to vrl_container to load to -* Out: -* int - operation status -* to the requested .vrl blob -*/ -int get_vrl_by_id(struct vrs_container *vrs_cont, uint16_t id, struct vrl_container * vrl_cont); - -#endif +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __16_VRS__ +#define __16_VRS__ + +#include "src/lib/modex16.h" +#include "src/lib/typdefst.h" +//#include +//#include +#include +#include "src/lib/16_ca.h" + +struct vrs_container{ + // Size of a .vrs lob in memory + // minus header + dword data_size; + union{ + byte huge *buffer; + struct vrs_header huge *vrs_hdr; + }; + // Array of corresponding vrl line offsets + vrl1_vgax_offset_t **vrl_line_offsets; +}; + +struct vrl_container{ + // Size of a .vrl blob in memory + // minus header + dword data_size; + union{ + byte huge *buffer; + struct vrl1_vgax_header huge *vrl_header; + }; + // Pointer to a corresponding vrl line offsets struct + vrl1_vgax_offset_t *line_offsets; +}; + +/* Read .vrs file into memory +* In: +* + char *filename - name of the file to load +* + struct vrs_container *vrs_cont - pointer to the vrs_container +* to load the file into +* Out: +* + int - 0 on succes, 1 on failure +*/ +int read_vrs(global_game_variables_t *gvar, char *filename, struct vrs_container *vrs_cont); + +/* Seek and return a specified .vrl blob from .vrs blob in memory +* In: +* + struct vrs_container *vrs_cont - pointer to the vrs_container +* with a loaded .vrs file +* + uint16_t id - id of the vrl to retrive +* + struct vrl_container * vrl_cont - pointer to vrl_container to load to +* Out: +* int - operation status +* to the requested .vrl blob +*/ +int get_vrl_by_id(struct vrs_container *vrs_cont, uint16_t id, struct vrl_container * vrl_cont); + +#endif diff --git a/src/lib/_croll16.c b/src/lib/_croll16.c index 2dc6f5aa..e152ce18 100755 --- a/src/lib/_croll16.c +++ b/src/lib/_croll16.c @@ -1,925 +1,925 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* - scroll16 library~ -*/ -#include "src/lib/scroll16.h" -#include "src/lib/16_sprite.h" - -void walk(map_view_t *pip, player_t *player, word pn) -{ - #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1; - //printf("player[%d].d=%d\n", pn, player[pn].d); - switch(player[pn].d) - { - //no direction - case 2: - //0000pip[0].video->startclk = (*clockw); - break; - //right movement - case 3: - //printf("pip[0].page->tilesw=%d ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw); - if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && - !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollRight(pip, player, 3, pn); - ScrollRight(pip, player, 2, pn); - mapScrollRight(pip, player, !(pip[0].video->p), pn); - mapScrollRight(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } - } - else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].x+=(player[pn].speed); - animatePlayer(pip, player, pn, 0); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); -#ifdef SPRITE - //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 16, 32, PLAYERBMPDATA); - animate_spri(player[pn].spri); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 14); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx+1; - player[pn].triggery = player[pn].ty; - break; - - //left movement - case 1: - if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && - !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollLeft(pip, player, 3, pn); - ScrollLeft(pip, player, 2, pn); - mapScrollLeft(pip, player, !(pip[0].video->p), pn); - mapScrollLeft(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } - } - else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].x-=(player[pn].speed); - animatePlayer(pip, player, pn, 0); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); -#ifdef SPRITE - //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 96, 16, 32, PLAYERBMPDATA); - animate_spri(player[pn].spri); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 10); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx-1; - player[pn].triggery = player[pn].ty; - break; - - //down movement - case 4: - if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && - !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollDown(pip, player, 3, pn); - ScrollDown(pip, player, 2, pn); - mapScrollDown(pip, player, !(pip[0].video->p), pn); - mapScrollDown(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } - } - else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].y+=(player[pn].speed); - animatePlayer(pip, player, pn, 0); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); -#ifdef SPRITE - //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 64, 16, 32, PLAYERBMPDATA); - animate_spri(player[pn].spri); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 9); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx; - player[pn].triggery = player[pn].ty+1; - break; - - //up movement - case 0: - if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && - !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollUp(pip, player, 3, pn); - ScrollUp(pip, player, 2, pn); - mapScrollUp(pip, player, !(pip[0].video->p), pn); - mapScrollUp(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } - } - else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].y-=(player[pn].speed); - animatePlayer(pip, player, 0, pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); -#ifdef SPRITE - //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 0, 16, 32, PLAYERBMPDATA); - animate_spri(player[pn].spri); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 12); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx; - player[pn].triggery = player[pn].ty-1; - break; - } -} - -//panning page -void panpagemanual(map_view_t *pip, player_t *player, word pn) -{ - switch(player[pn].d) - { - //right movement - case 3: - if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dx+=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; } - } - break; - - //left movement - case 1: - if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dx-=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; } - } - break; - - //down movement - case 4: - if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dy+=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; } - } - break; - - //up movement - case 0: - if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dy-=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; } - } - break; - } - //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q); -} - -/*map_t -allocMap(int w, int h) { - map_t result; - - result.width =w; - result.height=h; - result.data = malloc(sizeof(byte) * w * h); - //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024); - if(isEMS() || checkEMS()) - { - XMOVE mm; - //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map)) - mm.length=sizeof(result); - mm.sourceH=0; - mm.sourceOff=ptr2long(&result); - mm.destH=emmhandle; - mm.destOff=0; - ist = move_emem(&mm); - if(!ist){ dealloc_emem(emmhandle); exit(5); } - printf("%d\n", coretotalEMS()); - } - - return result; -}*/ - -/*void -initMap(map_t *map) { - // just a place holder to fill out an alternating pattern - int x, y, xx, yy; - int i, q; -// int tile = 1; - //if(!isEMS() || !checkEMS()) -// map->tiles = malloc(sizeof(tiles_t)); - //else - // map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t)); - - //create the tile set - //if(!isEMS() || !checkEMS()) -// map->tiles->data = malloc(sizeof(bitmap_t)); - //else - // map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t)); -// map->tiles->data->width = (TILEWH); -// map->tiles->data->height= TILEWH; - //if(!isEMS() || !checkEMS()) -// map->tiles->data->data = malloc((TILEWH*2)*TILEWH); - //else - // map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH); -// map->tiles->tileHeight = TILEWH; -// map->tiles->tileWidth =TILEWH; -// map->tiles->rows = 1; -// map->tiles->cols = 1;//2; - - q=0; - //for(y=0; yheight; y++) { - //for(x=0; xwidth; x++) { - i=0; - for(yy=0; yytiles->data->data[i+1] = map->data[q];//28;//0x24; -// printf("[%d]", map->tiles->data->data[i]); - //}else{ - //map->tiles->data->data[i] = map->data[q];//0;//0x34; - //printf("]%d[==[%d]", i, map->tiles->data->data[i]); - //} - i++; - } -// printf("\n"); - } -// printf("[%d]", map->data[q]); - q++; -// } - //printf("\n\n"); -// } - - i=0; - for(y=0; yheight; y++) { - for(x=0; xwidth; x++) { -// map->data[i]=255; - printf("[%d]", map->data[i]); - //tile = tile ? 0 : 1; - i++; - } - //tile = tile ? 0 : 1; - } -}*/ - -void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* increment the pixel position and update the page */ - mv[id].page->dx += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx >= mv[id].dxThresh ) - { - /* go forward one tile */ - mv[id].tx++; - /* Snap the origin forward */ - mv[id].page->data += 4; - - mv[id].page->dx = mv[id].map->tiles->tileWidth; - } - - /* draw the next column */ - x= mv[0].page->sw + mv[id].map->tiles->tileWidth; - if(player[plid].q%4) - if(id==0) - mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); - mv[0].video->r=1; -} - - -void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* decrement the pixel position and update the page */ - mv[id].page->dx -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx == 0) - { - /* go backward one tile */ - mv[id].tx--; - /* Snap the origin backward */ - mv[id].page->data -= 4; - - mv[id].page->dx = mv[id].map->tiles->tileWidth; - } - - /* draw the next column */ - x= 0; - if(player[plid].q%4) - if(id==0) - mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); - mv[0].video->r=1; -} - - -void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* decrement the pixel position and update the page */ - mv[id].page->dy -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy == 0 ) - { - /* go down one tile */ - mv[id].ty--; - /* Snap the origin downward */ - mv[id].page->data -= mv[id].page->pi; - - mv[id].page->dy = mv[id].map->tiles->tileHeight; - } - - /* draw the next row */ - y= 0; - if(player[plid].q%3) - if(id==0) - mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); - mv[0].video->r=1; -} - -void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* increment the pixel position and update the page */ - mv[id].page->dy += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy >= mv[id].dyThresh ) - { - /* go down one tile */ - mv[id].ty++; - /* Snap the origin downward */ - mv[id].page->data += mv[id].page->pi; - - mv[id].page->dy = mv[id].map->tiles->tileHeight; - } - - /* draw the next row */ - y= mv[0].page->sh + mv[id].map->tiles->tileHeight; - if(player[plid].q%3) - if(id==0) - mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); - mv[0].video->r=1; -} - - -//TODO finish this wwww -void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid) -{ - /* increment the pixel position and update the page */ - mv[id].page->dx += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx >= mv[0].dxThresh ) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin forward */ - mv[id].page->data += 4; - mv[id].page->dx = mv[0].map->tiles->tileWidth; - } -} - -void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid) -{ - /* decrement the pixel position and update the page */ - mv[id].page->dx -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx == 0) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin backward */ - mv[id].page->data -= 4; - mv[id].page->dx = mv[0].map->tiles->tileWidth; - } -} - -void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid) -{ - /* decrement the pixel position and update the page */ - mv[id].page->dy -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy == 0) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin backward */ - mv[id].page->data -= mv[id].page->pi; - mv[id].page->dy = mv[0].map->tiles->tileWidth; - } -} - -void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid) -{ - /* increment the pixel position and update the page */ - mv[id].page->dy += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy >= mv[0].dxThresh ) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin forward */ - mv[id].page->data += mv[id].page->pi; - mv[id].page->dy = mv[0].map->tiles->tileWidth; - } -} - -sword chkmap(map_t *map, word q) -{ -// bitmap_t bp; - static byte x[(MAPW*MAPH)+1] = -{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 }; -/*1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, \ -5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, \ -0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4 };*/ - //check for failed to load map - if((map->width == map->height == 0) && (q>0)) - { - //initiate a null map! - map->width=MAPW;///2; - map->height=MAPH;///2; -// map->data = malloc(((map->width*map->height)+1)*sizeof(byte)); - map->data = &x; - map->tiles = malloc(sizeof(tiles_t)); - //fix this to be far~ -// bp = bitmapLoadPcx("data/ed.pcx"); -// map->tiles->data = &bp; - map->tiles->debug_data = map->data; - map->tiles->tileHeight = 16; - map->tiles->tileWidth = 16; - map->tiles->rows = 1; - map->tiles->cols = 1; - map->tiles->debug_text = true; - } - else map->tiles->debug_text = false; - return 0; -} - -//TODO: player position here -void mapGoTo(map_view_t *mv, int tx, int ty) -{ - int px, py; - unsigned int i; - - /* set up the coordinates */ - mv[0].tx = mv[1].tx = tx; - mv[0].ty = mv[1].ty = ty; - mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth; - mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight; - - /* set up the thresholds */ - mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2; - mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2; - - /* draw the tiles */ - modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0); - py=0; - i=mv[0].ty * mv[0].map->width + mv[0].tx; - for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) { - mapDrawWRow(&mv[0], tx-1, ty, py); - i+=mv->map->width - tx; - } - if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height); -// { -// unsigned int k,j,o; -// /* fill screen with a distinctive pattern */ -// for (k=0;k < vga_state.vga_width;k++) { -// o = k >> 2; -// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); -// for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride) -// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! -// } -// } - modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 16, 32); -} - -void near -mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) -{ - word rx; - word ry; - word textx=0; - word texty=0; - //if(i==0) i=2; - if(i==0) - { - //wwww - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color! - } - else - { - rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth); - ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight); -////0000printf("i=%d\n", i); - switch(t->debug_text) - { - case 0: -#ifndef TILERENDER - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1)); - //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i])); -#else - PBUFBFUN (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); - /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ - //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - //modexDrawBmpRegion (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); -#endif - break; - case 1: - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1); - //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data)); - /*for(texty=0; texty<2; texty++) - { - for(textx=0; textx<2; textx++) - {*/ -// modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data)); -/* } - }*/ - break; - } - } -} - -void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset) -{ - word x; - int i; - poopoffset%=p[0].speed; -//printf("y: %d\n", poopoffset); - /* the position within the map array */ - i=ty * mv->map->width + tx; - for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { - if(i>=0) { - /* we are in the map, so copy! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i++; /* next! */ - } -} - -void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset) -{ - int y; - int i; - poopoffset%=p[0].speed; -//printf("x: %d\n", poopoffset); - /* location in the map array */ - i=ty * mv->map->width + tx; - - /* We'll copy all of the columns in the screen, - i + 1 row above and one below */ - for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { - if(i>=0) { - /* we are in the map, so copy away! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i += mv->map->width; - } -} - -void mapDrawWRow(map_view_t *mv, int tx, int ty, word y) -{ - word x; - int i; - - /* the position within the map array */ - i=ty * mv->map->width + tx; - for(x=0; xpage->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { - if(i>=0) { - /* we are in the map, so copy! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i++; /* next! */ - } -} - -void mapDrawWCol(map_view_t *mv, int tx, int ty, word x) -{ - int y; - int i; - - /* location in the map array */ - i=ty * mv->map->width + tx; - - /* We'll copy all of the columns in the screen, - i + 1 row above and one below */ - for(y=0; ypage->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { - if(i>=0) { - /* we are in the map, so copy away! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i += mv->map->width; - } -} - -/*void qclean() -{ - //setkb(0); -}*/ - -unsigned char shinku_fps_indicator_page = 2; -boolean pageflipflop = 1; -boolean pageploop = 1; - -/* sync */ -void shinku(global_game_variables_t *gv) -{ - word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen - word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen - word w = 64, h = 8, col = 7, bgcol = 0, type = 1; - byte o,o2,i; - //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4); - /* block copy to visible RAM from offscreen */ -// vga_setup_wm1_block_copy(); -// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h); -// o = *(gv->video.page[2].data); // source offscreen -// o2 = *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) -// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ -// vga_restore_rm0wm0(); - if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second)) - { - sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv)); - //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45); - modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee); - gv->kurokku.tiku=0; - /* block copy to visible RAM from offscreen */ -// vga_setup_wm1_block_copy(); -// o = *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen -// o2 = *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) -// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); -// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ -// vga_restore_rm0wm0(); - }else //copy dat sheet - gv->kurokku.tiku++; - - switch(gv->kurokku.fpscap) - { - case 0: - //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!"); - gv->kurokku.frames_per_second=1; - break; - case 1: - //turn this off if XT - //modexWaitBorder(); - vga_wait_for_vsync(); - gv->kurokku.frames_per_second=60; - break; - } - if(pageflipflop){ - if(gv->video.r){ - //vga_setup_wm1_block_copy(); - //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize); - //vga_restore_rm0wm0(); - if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height); - modexShowPage(&(gv->video.page[gv->video.p])); - if(!pageploop) gv->video.p=!gv->video.p; - gv->video.r=!gv->video.r; - //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2; - } - } -} - -void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch) -{ - sword x = player[pn].x; - sword y = player[pn].y; - sword bx = x+16; //buffer's x - sword by = y+16; //buffer's y - word dire=32; //direction - sword qq; //scroll offset - word ls = player[pn].persist_aniframe; - - switch(scrollswitch) - { - case 0: - qq = 0; - break; - default: - qq = ((player[pn].q)*(player[pn].speed)); - break; - } - //x-=4; - y-=pip[0].map->tiles->tileHeight; - switch (player[pn].d) - { - case 0: - //up - dire*=player[pn].d; - y-=qq; - by-=4; - break; - case 3: - // right - dire*=(player[pn].d-2); - x+=qq; - bx+=4; - break; - case 2: - break; - case 4: - //down - dire*=(player[pn].d-2); - y+=qq; - by+=4; - break; - case 1: - //left - dire*=(player[pn].d+2); - x-=qq; - bx-=4; - break; - } - -#ifdef SPRITE -//#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 32, dire, 16, 32, PLAYERBMPDATA); -//#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32, PLAYERBMPDATA); -//#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 16, 32, PLAYERBMPDATA); -//#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32, PLAYERBMPDATA); -#define FRAME1 animate_spri(player[pn].spri); -#define FRAME2 animate_spri(player[pn].spri); -#define FRAME3 animate_spri(player[pn].spri); -#define FRAME4 animate_spri(player[pn].spri); -#else -#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 2+dire); -#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire); -#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, dire); -#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire); -#endif - if(!pageflipflop) - modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36); - else{ - //copy old bg to page0 - //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0, 20, 36); - //update buffer - //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 20, 36); - } -//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height); - //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36); - /*modexCopyPageRegion(pip[pip->video->p].page, - pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/ -// else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40); - switch(ls) - { - case 1: - FRAME1 - break; - case 2: - FRAME2 - break; - case 3: - FRAME3 - break; - case 4: - FRAME4 - break; - } -// if(2>ls && ls>=1) { FRAME1 }else -// if(3>ls && ls>=2) { FRAME2 }else -// if(4>ls && ls>=3) { FRAME3 }else -// if(5>ls && ls>=4) { FRAME4 } - //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 16, 32); - //printf("x=%d y=%d bx=%d by=%d\n", x, y, bx, by); - pip->video->r=1; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + scroll16 library~ +*/ +#include "src/lib/scroll16.h" +#include "src/lib/16_sprite.h" + +void walk(map_view_t *pip, player_t *player, word pn) +{ + #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1; + //printf("player[%d].d=%d\n", pn, player[pn].d); + switch(player[pn].d) + { + //no direction + case 2: + //0000pip[0].video->startclk = (*clockw); + break; + //right movement + case 3: + //printf("pip[0].page->tilesw=%d ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw); + if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && + !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollRight(pip, player, 3, pn); + ScrollRight(pip, player, 2, pn); + mapScrollRight(pip, player, !(pip[0].video->p), pn); + mapScrollRight(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } + } + else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].x+=(player[pn].speed); + animatePlayer(pip, player, pn, 0); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); +#ifdef SPRITE + //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 16, 32, PLAYERBMPDATA); + animate_spri(player[pn].spri); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 14); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx+1; + player[pn].triggery = player[pn].ty; + break; + + //left movement + case 1: + if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && + !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollLeft(pip, player, 3, pn); + ScrollLeft(pip, player, 2, pn); + mapScrollLeft(pip, player, !(pip[0].video->p), pn); + mapScrollLeft(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } + } + else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].x-=(player[pn].speed); + animatePlayer(pip, player, pn, 0); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); +#ifdef SPRITE + //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 96, 16, 32, PLAYERBMPDATA); + animate_spri(player[pn].spri); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 10); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx-1; + player[pn].triggery = player[pn].ty; + break; + + //down movement + case 4: + if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && + !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollDown(pip, player, 3, pn); + ScrollDown(pip, player, 2, pn); + mapScrollDown(pip, player, !(pip[0].video->p), pn); + mapScrollDown(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } + } + else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].y+=(player[pn].speed); + animatePlayer(pip, player, pn, 0); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); +#ifdef SPRITE + //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 64, 16, 32, PLAYERBMPDATA); + animate_spri(player[pn].spri); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 9); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx; + player[pn].triggery = player[pn].ty+1; + break; + + //up movement + case 0: + if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && + !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollUp(pip, player, 3, pn); + ScrollUp(pip, player, 2, pn); + mapScrollUp(pip, player, !(pip[0].video->p), pn); + mapScrollUp(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } + } + else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].y-=(player[pn].speed); + animatePlayer(pip, player, 0, pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 16, 32); +#ifdef SPRITE + //PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 16, 0, 16, 32, PLAYERBMPDATA); + animate_spri(player[pn].spri); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 16, 32, 12); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx; + player[pn].triggery = player[pn].ty-1; + break; + } +} + +//panning page +void panpagemanual(map_view_t *pip, player_t *player, word pn) +{ + switch(player[pn].d) + { + //right movement + case 3: + if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dx+=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; } + } + break; + + //left movement + case 1: + if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dx-=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; } + } + break; + + //down movement + case 4: + if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dy+=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; } + } + break; + + //up movement + case 0: + if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dy-=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; } + } + break; + } + //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q); +} + +/*map_t +allocMap(int w, int h) { + map_t result; + + result.width =w; + result.height=h; + result.data = malloc(sizeof(byte) * w * h); + //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024); + if(isEMS() || checkEMS()) + { + XMOVE mm; + //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map)) + mm.length=sizeof(result); + mm.sourceH=0; + mm.sourceOff=ptr2long(&result); + mm.destH=emmhandle; + mm.destOff=0; + ist = move_emem(&mm); + if(!ist){ dealloc_emem(emmhandle); exit(5); } + printf("%d\n", coretotalEMS()); + } + + return result; +}*/ + +/*void +initMap(map_t *map) { + // just a place holder to fill out an alternating pattern + int x, y, xx, yy; + int i, q; +// int tile = 1; + //if(!isEMS() || !checkEMS()) +// map->tiles = malloc(sizeof(tiles_t)); + //else + // map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t)); + + //create the tile set + //if(!isEMS() || !checkEMS()) +// map->tiles->data = malloc(sizeof(bitmap_t)); + //else + // map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t)); +// map->tiles->data->width = (TILEWH); +// map->tiles->data->height= TILEWH; + //if(!isEMS() || !checkEMS()) +// map->tiles->data->data = malloc((TILEWH*2)*TILEWH); + //else + // map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH); +// map->tiles->tileHeight = TILEWH; +// map->tiles->tileWidth =TILEWH; +// map->tiles->rows = 1; +// map->tiles->cols = 1;//2; + + q=0; + //for(y=0; yheight; y++) { + //for(x=0; xwidth; x++) { + i=0; + for(yy=0; yytiles->data->data[i+1] = map->data[q];//28;//0x24; +// printf("[%d]", map->tiles->data->data[i]); + //}else{ + //map->tiles->data->data[i] = map->data[q];//0;//0x34; + //printf("]%d[==[%d]", i, map->tiles->data->data[i]); + //} + i++; + } +// printf("\n"); + } +// printf("[%d]", map->data[q]); + q++; +// } + //printf("\n\n"); +// } + + i=0; + for(y=0; yheight; y++) { + for(x=0; xwidth; x++) { +// map->data[i]=255; + printf("[%d]", map->data[i]); + //tile = tile ? 0 : 1; + i++; + } + //tile = tile ? 0 : 1; + } +}*/ + +void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* increment the pixel position and update the page */ + mv[id].page->dx += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx >= mv[id].dxThresh ) + { + /* go forward one tile */ + mv[id].tx++; + /* Snap the origin forward */ + mv[id].page->data += 4; + + mv[id].page->dx = mv[id].map->tiles->tileWidth; + } + + /* draw the next column */ + x= mv[0].page->sw + mv[id].map->tiles->tileWidth; + if(player[plid].q%4) + if(id==0) + mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); + mv[0].video->r=1; +} + + +void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* decrement the pixel position and update the page */ + mv[id].page->dx -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx == 0) + { + /* go backward one tile */ + mv[id].tx--; + /* Snap the origin backward */ + mv[id].page->data -= 4; + + mv[id].page->dx = mv[id].map->tiles->tileWidth; + } + + /* draw the next column */ + x= 0; + if(player[plid].q%4) + if(id==0) + mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); + mv[0].video->r=1; +} + + +void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* decrement the pixel position and update the page */ + mv[id].page->dy -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy == 0 ) + { + /* go down one tile */ + mv[id].ty--; + /* Snap the origin downward */ + mv[id].page->data -= mv[id].page->pi; + + mv[id].page->dy = mv[id].map->tiles->tileHeight; + } + + /* draw the next row */ + y= 0; + if(player[plid].q%3) + if(id==0) + mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); + mv[0].video->r=1; +} + +void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* increment the pixel position and update the page */ + mv[id].page->dy += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy >= mv[id].dyThresh ) + { + /* go down one tile */ + mv[id].ty++; + /* Snap the origin downward */ + mv[id].page->data += mv[id].page->pi; + + mv[id].page->dy = mv[id].map->tiles->tileHeight; + } + + /* draw the next row */ + y= mv[0].page->sh + mv[id].map->tiles->tileHeight; + if(player[plid].q%3) + if(id==0) + mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); + mv[0].video->r=1; +} + + +//TODO finish this wwww +void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid) +{ + /* increment the pixel position and update the page */ + mv[id].page->dx += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx >= mv[0].dxThresh ) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin forward */ + mv[id].page->data += 4; + mv[id].page->dx = mv[0].map->tiles->tileWidth; + } +} + +void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid) +{ + /* decrement the pixel position and update the page */ + mv[id].page->dx -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx == 0) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin backward */ + mv[id].page->data -= 4; + mv[id].page->dx = mv[0].map->tiles->tileWidth; + } +} + +void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid) +{ + /* decrement the pixel position and update the page */ + mv[id].page->dy -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy == 0) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin backward */ + mv[id].page->data -= mv[id].page->pi; + mv[id].page->dy = mv[0].map->tiles->tileWidth; + } +} + +void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid) +{ + /* increment the pixel position and update the page */ + mv[id].page->dy += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy >= mv[0].dxThresh ) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin forward */ + mv[id].page->data += mv[id].page->pi; + mv[id].page->dy = mv[0].map->tiles->tileWidth; + } +} + +sword chkmap(map_t *map, word q) +{ +// bitmap_t bp; + static byte x[(MAPW*MAPH)+1] = +{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 }; +/*1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, \ +5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, \ +0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4 };*/ + //check for failed to load map + if((map->width == map->height == 0) && (q>0)) + { + //initiate a null map! + map->width=MAPW;///2; + map->height=MAPH;///2; +// map->data = malloc(((map->width*map->height)+1)*sizeof(byte)); + map->data = &x; + map->tiles = malloc(sizeof(tiles_t)); + //fix this to be far~ +// bp = bitmapLoadPcx("data/ed.pcx"); +// map->tiles->data = &bp; + map->tiles->debug_data = map->data; + map->tiles->tileHeight = 16; + map->tiles->tileWidth = 16; + map->tiles->rows = 1; + map->tiles->cols = 1; + map->tiles->debug_text = true; + } + else map->tiles->debug_text = false; + return 0; +} + +//TODO: player position here +void mapGoTo(map_view_t *mv, int tx, int ty) +{ + int px, py; + unsigned int i; + + /* set up the coordinates */ + mv[0].tx = mv[1].tx = tx; + mv[0].ty = mv[1].ty = ty; + mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth; + mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight; + + /* set up the thresholds */ + mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2; + mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2; + + /* draw the tiles */ + modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0); + py=0; + i=mv[0].ty * mv[0].map->width + mv[0].tx; + for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) { + mapDrawWRow(&mv[0], tx-1, ty, py); + i+=mv->map->width - tx; + } + if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height); +// { +// unsigned int k,j,o; +// /* fill screen with a distinctive pattern */ +// for (k=0;k < vga_state.vga_width;k++) { +// o = k >> 2; +// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); +// for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride) +// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! +// } +// } + modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 16, 32); +} + +void near +mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) +{ + word rx; + word ry; + word textx=0; + word texty=0; + //if(i==0) i=2; + if(i==0) + { + //wwww + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color! + } + else + { + rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth); + ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight); +////0000printf("i=%d\n", i); + switch(t->debug_text) + { + case 0: +#ifndef TILERENDER + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1)); + //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i])); +#else + PBUFBFUN (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); + /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ + //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + //modexDrawBmpRegion (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); +#endif + break; + case 1: + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1); + //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data)); + /*for(texty=0; texty<2; texty++) + { + for(textx=0; textx<2; textx++) + {*/ +// modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data)); +/* } + }*/ + break; + } + } +} + +void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset) +{ + word x; + int i; + poopoffset%=p[0].speed; +//printf("y: %d\n", poopoffset); + /* the position within the map array */ + i=ty * mv->map->width + tx; + for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { + if(i>=0) { + /* we are in the map, so copy! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i++; /* next! */ + } +} + +void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset) +{ + int y; + int i; + poopoffset%=p[0].speed; +//printf("x: %d\n", poopoffset); + /* location in the map array */ + i=ty * mv->map->width + tx; + + /* We'll copy all of the columns in the screen, + i + 1 row above and one below */ + for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { + if(i>=0) { + /* we are in the map, so copy away! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i += mv->map->width; + } +} + +void mapDrawWRow(map_view_t *mv, int tx, int ty, word y) +{ + word x; + int i; + + /* the position within the map array */ + i=ty * mv->map->width + tx; + for(x=0; xpage->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { + if(i>=0) { + /* we are in the map, so copy! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i++; /* next! */ + } +} + +void mapDrawWCol(map_view_t *mv, int tx, int ty, word x) +{ + int y; + int i; + + /* location in the map array */ + i=ty * mv->map->width + tx; + + /* We'll copy all of the columns in the screen, + i + 1 row above and one below */ + for(y=0; ypage->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { + if(i>=0) { + /* we are in the map, so copy away! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i += mv->map->width; + } +} + +/*void qclean() +{ + //setkb(0); +}*/ + +unsigned char shinku_fps_indicator_page = 2; +boolean pageflipflop = 1; +boolean pageploop = 1; + +/* sync */ +void shinku(global_game_variables_t *gv) +{ + word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen + word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen + word w = 64, h = 8, col = 7, bgcol = 0, type = 1; + byte o,o2,i; + //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4); + /* block copy to visible RAM from offscreen */ +// vga_setup_wm1_block_copy(); +// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h); +// o = *(gv->video.page[2].data); // source offscreen +// o2 = *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) +// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ +// vga_restore_rm0wm0(); + if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second)) + { + sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv)); + //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45); + modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee); + gv->kurokku.tiku=0; + /* block copy to visible RAM from offscreen */ +// vga_setup_wm1_block_copy(); +// o = *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen +// o2 = *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) +// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); +// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ +// vga_restore_rm0wm0(); + }else //copy dat sheet + gv->kurokku.tiku++; + + switch(gv->kurokku.fpscap) + { + case 0: + //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!"); + gv->kurokku.frames_per_second=1; + break; + case 1: + //turn this off if XT + //modexWaitBorder(); + vga_wait_for_vsync(); + gv->kurokku.frames_per_second=60; + break; + } + if(pageflipflop){ + if(gv->video.r){ + //vga_setup_wm1_block_copy(); + //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize); + //vga_restore_rm0wm0(); + if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height); + modexShowPage(&(gv->video.page[gv->video.p])); + if(!pageploop) gv->video.p=!gv->video.p; + gv->video.r=!gv->video.r; + //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2; + } + } +} + +void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch) +{ + sword x = player[pn].x; + sword y = player[pn].y; + sword bx = x+16; //buffer's x + sword by = y+16; //buffer's y + word dire=32; //direction + sword qq; //scroll offset + word ls = player[pn].persist_aniframe; + + switch(scrollswitch) + { + case 0: + qq = 0; + break; + default: + qq = ((player[pn].q)*(player[pn].speed)); + break; + } + //x-=4; + y-=pip[0].map->tiles->tileHeight; + switch (player[pn].d) + { + case 0: + //up + dire*=player[pn].d; + y-=qq; + by-=4; + break; + case 3: + // right + dire*=(player[pn].d-2); + x+=qq; + bx+=4; + break; + case 2: + break; + case 4: + //down + dire*=(player[pn].d-2); + y+=qq; + by+=4; + break; + case 1: + //left + dire*=(player[pn].d+2); + x-=qq; + bx-=4; + break; + } + +#ifdef SPRITE +//#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 32, dire, 16, 32, PLAYERBMPDATA); +//#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32, PLAYERBMPDATA); +//#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 16, 32, PLAYERBMPDATA); +//#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 16, dire, 16, 32, PLAYERBMPDATA); +#define FRAME1 animate_spri(player[pn].spri); +#define FRAME2 animate_spri(player[pn].spri); +#define FRAME3 animate_spri(player[pn].spri); +#define FRAME4 animate_spri(player[pn].spri); +#else +#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 2+dire); +#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire); +#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, dire); +#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 16, 32, 1+dire); +#endif + if(!pageflipflop) + modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36); + else{ + //copy old bg to page0 + //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0, 20, 36); + //update buffer + //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 20, 36); + } +//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height); + //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36); + /*modexCopyPageRegion(pip[pip->video->p].page, + pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/ +// else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40); + switch(ls) + { + case 1: + FRAME1 + break; + case 2: + FRAME2 + break; + case 3: + FRAME3 + break; + case 4: + FRAME4 + break; + } +// if(2>ls && ls>=1) { FRAME1 }else +// if(3>ls && ls>=2) { FRAME2 }else +// if(4>ls && ls>=3) { FRAME3 }else +// if(5>ls && ls>=4) { FRAME4 } + //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 16, 32); + //printf("x=%d y=%d bx=%d by=%d\n", x, y, bx, by); + pip->video->r=1; +} diff --git a/src/lib/bakapee.c b/src/lib/bakapee.c index 3f8ab3e5..ee209e36 100755 --- a/src/lib/bakapee.c +++ b/src/lib/bakapee.c @@ -1,278 +1,278 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "src/lib/bakapee.h" - -/* clrstdin() clear any leftover chars tha may be in stdin stream */ -void clrstdin() -{ - int ch = 0; - while( ( ch = getchar() ) != '\n' && ch != EOF ); -} - -//color ‚Ä‚·‚Æ -void colortest(page_t *page, bakapee_t *pee) -{ - //if(pee->coor < 256) - //{ - modexcls(page, pee->coor, VGA); - pee->coor++; - //}else pee->coor = 0; -} - -//color ‚Ä‚·‚Æ -void colorz(page_t *page, bakapee_t *pee) -{ - if(pee->coor <= HGQ) - { - modexcls(page, pee->coor, VGA); - pee->coor++; - }else pee->coor = LGQ; -} - -//slow spectrum down -void ssd(page_t *page, bakapee_t *pee, word svq) -{ - if(pee->sy < page->sh+1) - { - if(pee->sx < page->sw+1) - { - //mxPutPixel(sx, sy, coor); - //printf("%d %d %d %d\n", pee->sx, pee->sy, svq, pee->coor); - dingpp(page, pee); - pee->sx++; - }else pee->sx = 0; - if(pee->sx == page->sw) - { - pee->sy++; - if(svq == 7) pee->coor++; - if(pee->sy == page->sh && svq == 8) pee->coor = rand()%256; - } - }else pee->sy = 0; -} - -//plot pixel or plot tile -void dingpp(page_t *page, bakapee_t *pee) -{ - if(pee->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); -} - -void dingo(page_t *page, bakapee_t *pee) -{ - if(pee->tile) - { - if(pee->xx<0) pee->xx=(page->sw-TILEWH); - if(pee->yy<0) pee->yy=(page->sh-TILEWH); - if(pee->xx>(page->sw-TILEWH)) pee->xx=0; - if(pee->yy>(page->sh-TILEWH)/*+(TILEWH*BUFFMX)*/) pee->yy=0; - } - else - { - if(pee->xx<0) pee->xx=page->sw; - if(pee->yy<0) pee->yy=page->sh; - if(pee->xx>page->sw) pee->xx=0; - if(pee->yy>page->sh) pee->yy=0; - } -} - -//assigning values from randomizer -void dingas(bakapee_t *pee) -{ - if(pee->gq == BONK) dingu(pee); - if(!pee->bakax) - { - if(pee->tile) - pee->xx-=TILEWH; - else pee->xx--; - } - else if(pee->bakax>1) - { - if(pee->tile) - pee->xx+=TILEWH; - else pee->xx++; - } - if(!pee->bakay) - { - if(pee->tile) - pee->yy-=TILEWH; - else pee->yy--; - } - else if(pee->bakay>1) - { - if(pee->tile) - pee->yy+=TILEWH; - else pee->yy++; - } -} - -void dingu(bakapee_t *pee) -{ - if(pee->coor < HGQ && pee->coor < LGQ) pee->coor = LGQ; - if(pee->coor < HGQ) - { - pee->coor++; - }else{ - pee->coor = LGQ; - } -} - -//randomizer -void dingq(bakapee_t *pee) -{ - if(pee->gqgq++; - } - else - { - dingu(pee); - pee->gq = 0; - } - pee->bakax = rand()%3; pee->bakay = rand()%3; -} - -/*-----------ding-------------*/ -void ding(page_t *page, bakapee_t *pee, word q) -{ - word d3y, tx=0,ty=0; - -//++++ if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ; - switch(q) - { - case 1: - dingq(pee); - if(pee->xx==page->sw){pee->bakax=0;} - if(pee->xx==0){pee->bakax=1;} - if(pee->yy==page->sh){pee->bakay=0;} - if(pee->yy==0){pee->bakay=1;} - break; - case 2: - dingq(pee); - dingas(pee); - dingo(page, pee); - dingpp(page, pee); //plot the pixel/tile - if(pee->tile) - modexClearRegion(page, (rand()*TILEWH)%page->width, (rand()*TILEWH)%(page->height), TILEWH, TILEWH, 0); - else - modexputPixel(page, rand()%page->width, rand()%page->height, 0); - break; - case 3: - dingq(pee); - if(pee->xx!=page->sw||pee->yy!=page->sh) - { - if(pee->xx==0){pee->bakax=1;pee->bakay=-1;d3y=1;} - if(pee->yy==0){pee->bakax=1;pee->bakay=0;d3y=1;} - if(pee->xx==page->sw){pee->bakax=-1;pee->bakay=-1;d3y=1;} - if(pee->yy==page->sh){pee->bakax=1;pee->bakay=0;d3y=1;} - }else if(pee->xx==page->sw&&pee->yy==page->sh) pee->xx=pee->yy=0; - if(d3y) - { - if(pee->bakay<0) - { - pee->yy--; - d3y--; - }else - if(pee->bakay>0) - { - pee->yy++; - d3y--; - } - } - if(pee->bakax<0) - { - pee->xx--; - }else - if(pee->bakax>0) - { - pee->xx++; - } - dingpp(page, pee); //plot the pixel/tile - break; - case 4: - dingq(pee); - dingas(pee); - dingo(page, pee); - dingpp(page, pee); //plot the pixel/tile - break; - case 5: - colortest(page, pee); - break; - case 6: - pee->coor = rand()%256; - modexcls(page, pee->coor, VGA); - break; - case 7: - if(pee->coor <= HGQ) - { - ssd(page, pee, q); - pee->coor++; - }else pee->coor = LGQ; - break; - case 8: - colorz(page, pee); - modexprint(page, page->sw/2, page->sh/2, 1, 47, 0, "bakapi"); - break; - case 9: - if(pee->coor <= HGQ) - { - ssd(page, pee, q); - pee->coor++; - }else pee->coor = LGQ; - break; - case 10: - ssd(page, pee, q); /*printf("%d\n", pee->coor);*/ - break; - case 11: - colorz(page, pee); delay(100); - break; - - case 16: //interesting effects - dingq(pee); - if(!pee->bakax){ pee->xx--;} - else if(pee->bakax>0){ pee->xx++; } - if(!pee->bakay){ pee->yy--;} - else if(pee->bakay>0){ pee->yy++; } - dingas(pee); - tx+=pee->xx+TILEWH+4; - ty+=pee->yy+TILEWH+4; - modexClearRegion(page, tx, ty, 4, 4, pee->coor); - if(pee->tile) - modexClearRegion(page, (rand()*4)%page->width, (rand()*4)%(page->height), 4, 4, 0); - else - modexputPixel(page, rand()%page->width, rand()%(page->height), 0); - //printf("%d %d %d %d %d %d\n", pee->xx, pee->yy, tx, ty, TILEWH); - break; - default: - break; - } - //pee->coor++; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/lib/bakapee.h" + +/* clrstdin() clear any leftover chars tha may be in stdin stream */ +void clrstdin() +{ + int ch = 0; + while( ( ch = getchar() ) != '\n' && ch != EOF ); +} + +//color ‚Ä‚·‚Æ +void colortest(page_t *page, bakapee_t *pee) +{ + //if(pee->coor < 256) + //{ + modexcls(page, pee->coor, VGA); + pee->coor++; + //}else pee->coor = 0; +} + +//color ‚Ä‚·‚Æ +void colorz(page_t *page, bakapee_t *pee) +{ + if(pee->coor <= HGQ) + { + modexcls(page, pee->coor, VGA); + pee->coor++; + }else pee->coor = LGQ; +} + +//slow spectrum down +void ssd(page_t *page, bakapee_t *pee, word svq) +{ + if(pee->sy < page->sh+1) + { + if(pee->sx < page->sw+1) + { + //mxPutPixel(sx, sy, coor); + //printf("%d %d %d %d\n", pee->sx, pee->sy, svq, pee->coor); + dingpp(page, pee); + pee->sx++; + }else pee->sx = 0; + if(pee->sx == page->sw) + { + pee->sy++; + if(svq == 7) pee->coor++; + if(pee->sy == page->sh && svq == 8) pee->coor = rand()%256; + } + }else pee->sy = 0; +} + +//plot pixel or plot tile +void dingpp(page_t *page, bakapee_t *pee) +{ + if(pee->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); +} + +void dingo(page_t *page, bakapee_t *pee) +{ + if(pee->tile) + { + if(pee->xx<0) pee->xx=(page->sw-TILEWH); + if(pee->yy<0) pee->yy=(page->sh-TILEWH); + if(pee->xx>(page->sw-TILEWH)) pee->xx=0; + if(pee->yy>(page->sh-TILEWH)/*+(TILEWH*BUFFMX)*/) pee->yy=0; + } + else + { + if(pee->xx<0) pee->xx=page->sw; + if(pee->yy<0) pee->yy=page->sh; + if(pee->xx>page->sw) pee->xx=0; + if(pee->yy>page->sh) pee->yy=0; + } +} + +//assigning values from randomizer +void dingas(bakapee_t *pee) +{ + if(pee->gq == BONK) dingu(pee); + if(!pee->bakax) + { + if(pee->tile) + pee->xx-=TILEWH; + else pee->xx--; + } + else if(pee->bakax>1) + { + if(pee->tile) + pee->xx+=TILEWH; + else pee->xx++; + } + if(!pee->bakay) + { + if(pee->tile) + pee->yy-=TILEWH; + else pee->yy--; + } + else if(pee->bakay>1) + { + if(pee->tile) + pee->yy+=TILEWH; + else pee->yy++; + } +} + +void dingu(bakapee_t *pee) +{ + if(pee->coor < HGQ && pee->coor < LGQ) pee->coor = LGQ; + if(pee->coor < HGQ) + { + pee->coor++; + }else{ + pee->coor = LGQ; + } +} + +//randomizer +void dingq(bakapee_t *pee) +{ + if(pee->gqgq++; + } + else + { + dingu(pee); + pee->gq = 0; + } + pee->bakax = rand()%3; pee->bakay = rand()%3; +} + +/*-----------ding-------------*/ +void ding(page_t *page, bakapee_t *pee, word q) +{ + word d3y, tx=0,ty=0; + +//++++ if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ; + switch(q) + { + case 1: + dingq(pee); + if(pee->xx==page->sw){pee->bakax=0;} + if(pee->xx==0){pee->bakax=1;} + if(pee->yy==page->sh){pee->bakay=0;} + if(pee->yy==0){pee->bakay=1;} + break; + case 2: + dingq(pee); + dingas(pee); + dingo(page, pee); + dingpp(page, pee); //plot the pixel/tile + if(pee->tile) + modexClearRegion(page, (rand()*TILEWH)%page->width, (rand()*TILEWH)%(page->height), TILEWH, TILEWH, 0); + else + modexputPixel(page, rand()%page->width, rand()%page->height, 0); + break; + case 3: + dingq(pee); + if(pee->xx!=page->sw||pee->yy!=page->sh) + { + if(pee->xx==0){pee->bakax=1;pee->bakay=-1;d3y=1;} + if(pee->yy==0){pee->bakax=1;pee->bakay=0;d3y=1;} + if(pee->xx==page->sw){pee->bakax=-1;pee->bakay=-1;d3y=1;} + if(pee->yy==page->sh){pee->bakax=1;pee->bakay=0;d3y=1;} + }else if(pee->xx==page->sw&&pee->yy==page->sh) pee->xx=pee->yy=0; + if(d3y) + { + if(pee->bakay<0) + { + pee->yy--; + d3y--; + }else + if(pee->bakay>0) + { + pee->yy++; + d3y--; + } + } + if(pee->bakax<0) + { + pee->xx--; + }else + if(pee->bakax>0) + { + pee->xx++; + } + dingpp(page, pee); //plot the pixel/tile + break; + case 4: + dingq(pee); + dingas(pee); + dingo(page, pee); + dingpp(page, pee); //plot the pixel/tile + break; + case 5: + colortest(page, pee); + break; + case 6: + pee->coor = rand()%256; + modexcls(page, pee->coor, VGA); + break; + case 7: + if(pee->coor <= HGQ) + { + ssd(page, pee, q); + pee->coor++; + }else pee->coor = LGQ; + break; + case 8: + colorz(page, pee); + modexprint(page, page->sw/2, page->sh/2, 1, 47, 0, "bakapi"); + break; + case 9: + if(pee->coor <= HGQ) + { + ssd(page, pee, q); + pee->coor++; + }else pee->coor = LGQ; + break; + case 10: + ssd(page, pee, q); /*printf("%d\n", pee->coor);*/ + break; + case 11: + colorz(page, pee); delay(100); + break; + + case 16: //interesting effects + dingq(pee); + if(!pee->bakax){ pee->xx--;} + else if(pee->bakax>0){ pee->xx++; } + if(!pee->bakay){ pee->yy--;} + else if(pee->bakay>0){ pee->yy++; } + dingas(pee); + tx+=pee->xx+TILEWH+4; + ty+=pee->yy+TILEWH+4; + modexClearRegion(page, tx, ty, 4, 4, pee->coor); + if(pee->tile) + modexClearRegion(page, (rand()*4)%page->width, (rand()*4)%(page->height), 4, 4, 0); + else + modexputPixel(page, rand()%page->width, rand()%(page->height), 0); + //printf("%d %d %d %d %d %d\n", pee->xx, pee->yy, tx, ty, TILEWH); + break; + default: + break; + } + //pee->coor++; +} diff --git a/src/lib/ems.c b/src/lib/ems.c index 9d371053..4bbfefd6 100755 --- a/src/lib/ems.c +++ b/src/lib/ems.c @@ -1,5 +1,5 @@ -/* - +/* + THE IBM PC PROGRAMMER'S GUIDE TO C @@ -21,8 +21,8 @@ proviso that credit is given to the author. Sections of this work may be used and distributed without payment under the proviso that credit is given to both this work and the author. Source code occuring in this work may be used within commercial and non-commercial applications without -charge and without reference to the author. -*/ +charge and without reference to the author. +*/ /* Various functions for using Expanded memory */ @@ -178,4 +178,4 @@ charge and without reference to the author. regs.x.dx = handle; int86(EMM,®s,®s); return (regs.h.ah == 0); - } + } diff --git a/src/lib/ems.h b/src/lib/ems.h index b288a548..33d24d06 100755 --- a/src/lib/ems.h +++ b/src/lib/ems.h @@ -1,5 +1,5 @@ -/* - +/* + THE IBM PC PROGRAMMER'S GUIDE TO C @@ -21,24 +21,24 @@ proviso that credit is given to the author. Sections of this work may be used and distributed without payment under the proviso that credit is given to both this work and the author. Source code occuring in this work may be used within commercial and non-commercial applications without -charge and without reference to the author. - */ - -#ifndef __EMS_H_ -#define __EMS_H_ - +charge and without reference to the author. + */ + +#ifndef __EMS_H_ +#define __EMS_H_ + #include #define EMM 0x67 -char far *emmbase; - -emmtest(); -emmok(); -long emmavail(); -long emmalloc(int n); -emmmap(long handle, int phys, int page); -void emmmove(int page, char *str, int n); -void emmget(int page, char *str, int n); -emmclose(long handle); - -#endif __EMS_H_ +char far *emmbase; + +emmtest(); +emmok(); +long emmavail(); +long emmalloc(int n); +emmmap(long handle, int phys, int page); +void emmmove(int page, char *str, int n); +void emmget(int page, char *str, int n); +emmclose(long handle); + +#endif __EMS_H_ diff --git a/src/lib/mapread.c b/src/lib/mapread.c index 8a8d5d87..5421d9dd 100755 --- a/src/lib/mapread.c +++ b/src/lib/mapread.c @@ -1,245 +1,245 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "src/lib/mapread.h" - -int jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && - strncmp(json + tok->start, s, tok->end - tok->start) == 0) { - return 0; - } - return -1; -} - -//this function is quite messy ^^; sorry! it is a quick and dirty fix~ -word dump(const char *js, jsmntok_t *t, size_t count, word indent, char *js_sv, map_t *map, dword q) { - dword i; - word j;//, k; - bitmap_t bp; - #ifdef DEBUG_JS - if(indent==0) - { - fprintf(stdout, "%s\n", js); - fprintf(stdout, "\n"); - } - #endif - #ifdef DEBUG_DUMPVARS - fprintf(stdout, "t->size=[%d] ", t->size); - fprintf(stdout, "q=[%d] ", q); - fprintf(stdout, "indent= [%d] ", indent); - fprintf(stdout, "js_sv= [%s]\n", js_sv); - #endif - if (count == 0) { - return 0; - } - /* We may want to do strtol() here to get numeric value */ -//0000fprintf(stderr, "t->type=%d\n", t->type); - if (t->type == JSMN_PRIMITIVE) { - if(strstr(js_sv, "data")) - { - /* - here we should recursivly call dump again here to skip over the array until we get the facking width of the map. - so we can initiate the map which allocates the facking map->tiles->data->data properly and THEN we can return - here to read the data.... That is my design for this... wwww - - FUCK well i am stuck.... wwww - */ - map->data[q] = (byte)atoi(js+t->start); - #ifdef DEBUG_MAPDATA - fprintf(stdout, "%d[%d]", q, map->data[q]); - #endif - } - else - if(strstr(js_sv, "height")) - { - map->height = atoi(js+t->start); - #ifdef DEBUG_MAPVAR - fprintf(stdout, "indent= [%d] ", indent); - fprintf(stdout, "h:[%d]\n", map->height); - #endif - }else if(strstr(js_sv, "width")) - { - map->width = atoi(js+t->start); - #ifdef DEBUG_MAPVAR - fprintf(stdout, "indent= [%d] ", indent); - fprintf(stdout, "w:[%d]\n", map->width); - #endif - } - return 1; - /* We may use strndup() to fetch string value */ - } else if (t->type == JSMN_STRING) { - if(jsoneq(js, t, "data") == 0) - { -// fprintf(stdout, "[[[[%d|%d]]]]\n", &(t+1)->size, (t+1)->size); -// fprintf(stdout, "\n%.*s[xx[%d|%d]xx]\n", (t+1)->end - (t+1)->start, js+(t+1)->start, &(t+1)->size, (t+1)->size); - map->data = malloc(sizeof(byte) * (t+1)->size); - map->tiles = malloc(sizeof(tiles_t)); - map->tiles->btdata = malloc(sizeof(bitmap_t)); - //fix this to be far~ - bp = bitmapLoadPcx("data/ed.pcx"); -// bp = bitmapLoadPcx("data/koishi^^.pcx"); - map->tiles->btdata = &bp; -//---- map->tiles->data = planar_buf_from_bitmap(&bp); - //map->tiles->data->data = malloc((16/**2*/)*16); - //map->tiles->data->width = (16/**2*/); - //map->tiles->data->height= 16; - map->tiles->tileHeight = 16; - map->tiles->tileWidth = 16; - map->tiles->rows = 1; - map->tiles->cols = 1; - map->tiles->debug_text=false; - strcpy(js_sv, "data");//strdup(js+t->start);//, t->end - t->start); - } - else - if (jsoneq(js, t, "height") == 0 && indent<=1) - { - strcpy(js_sv, "height");//strdup(js+t->start);//, t->end - t->start); - }else - if(jsoneq(js, t, "width") == 0 && indent<=1) - { - strcpy(js_sv, "width");//strdup(js+t->start);//, t->end - t->start); - }else strcpy(js_sv, "\0"); - return 1; - } else if (t->type == JSMN_OBJECT) { - //fprintf(stdout, "\n"); - j = 0; - for (i = 0; i < t->size; i++) { - //for (k = 0; k < indent; k++) fprintf(stdout, "\t"); - j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i); - //fprintf(stdout, ": "); - j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i); - //fprintf(stdout, "\n"); - } - return j+1; - } else if (t->type == JSMN_ARRAY) { - j = 0; - //fprintf(stdout, "==\n"); - for (i = 0; i < t->size; i++) { - //for (k = 0; k < indent-1; k++) fprintf(stdout, "\t"); - //fprintf(stdout, "\t-"); - j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i); - //fprintf(stdout, "==\n"); - } - return j+1; - } - return 0; -} - -int loadmap(char *mn, map_t *map) -{ - int r; - static word incr=0; - int eof_expected = 0; - char *js = NULL; - size_t jslen = 0; - char buf[BUFSIZ]; - static char js_ss[16]; - - jsmn_parser p; - jsmntok_t *tok; - size_t tokcount = 2; - - FILE *fh = fopen(mn, "r"); - - /* Prepare parser */ - jsmn_init(&p); - - /* Allocate some tokens as a start */ -//0000fprintf(stderr, "tok malloc\n"); - tok = malloc(sizeof(*tok) * tokcount); - if (tok == NULL) { - fprintf(stderr, "malloc(): errno=%d\n", errno); - return 3; - } - - for (;;) { - /* Read another chunk */ -//0000fprintf(stderr, "read\n"); - r = fread(buf, 1, sizeof(buf), fh); - if (r < 0) { - fprintf(stderr, "fread(): %d, errno=%d\n", r, errno); - return 1; - } - if (r == 0) { - if (eof_expected != 0) { - return 0; - } else { - fprintf(stderr, "fread(): unexpected EOF\n"); - return 2; - } - } -//0000fprintf(stdout, "r= [%d] BUFSIZ=%d\n", r, BUFSIZ); -//0000fprintf(stderr, "js alloc~\n"); - js = realloc(js, jslen + r + 1); - if (js == NULL) { - fprintf(stderr, "*js=%Fp\n", *js); - fprintf(stderr, "realloc(): errno = %d\n", errno); - return 3; - } - strncpy(js + jslen, buf, r); - jslen = jslen + r; - -again: -//0000fprintf(stdout, " parse~ tok=%zu jslen=%zu r=%d _memavl()=%u BUFSIZ=%d~\n", tokcount, jslen, r, _memavl(), BUFSIZ); -//0000fprintf(stdout, "p=[%u] [%u] [%d]\n", p.pos, p.toknext, p.toksuper); -/* - I think it crashes on the line below when it tries to parse the data of huge maps... wwww this is a jsmn problem wwww -*/ - r = jsmn_parse(&p, js, jslen, tok, tokcount); -//0000fprintf(stdout, "r= [%d]\n", r); - if (r < 0) { - if (r == JSMN_ERROR_NOMEM) { - tokcount = tokcount * 2; -//0000fprintf(stderr, "tok realloc~ %zu\n", tokcount); - tok = realloc(tok, sizeof(*tok) * tokcount); - if (tok == NULL) { - fprintf(stderr, "realloc(): errno=%d\n", errno); - return 3; - } - goto again; - } - } else { - //printf("js=%Fp\n", (js)); - //printf("*js=%Fp\n", (*(js))); - //printf("&*js=%s\n", &(*(js))); - //printf("&buf=[%Fp]\n", &buf); - //printf("&buf_seg=[%x]\n", FP_SEG(&buf)); - //printf("&buf_off=[%x]\n", FP_OFF(&buf)); - //printf("&buf_fp=[%Fp]\n", MK_FP(FP_SEG(&buf), FP_OFF(&buf))); - //printf("buf=[\n%s\n]\n", buf); - //printf("buff=[%Fp]\n", buff); - //printf("(*buff)=[%Fp]\n", (*buff)); - //printf("&(*buff)=[\n%s\n]\n", &(*buff)); - #ifdef DEBUG_DUMPVARS - fprintf(stdout, "running dump~\n"); - #endif - dump(js, tok, p.toknext, incr, &js_ss, map, 0); - eof_expected = 1; - } - } - - free(js); - free(tok); - fclose(fh); - - return 0; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/lib/mapread.h" + +int jsoneq(const char *json, jsmntok_t *tok, const char *s) { + if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +//this function is quite messy ^^; sorry! it is a quick and dirty fix~ +word dump(const char *js, jsmntok_t *t, size_t count, word indent, char *js_sv, map_t *map, dword q) { + dword i; + word j;//, k; + bitmap_t bp; + #ifdef DEBUG_JS + if(indent==0) + { + fprintf(stdout, "%s\n", js); + fprintf(stdout, "\n"); + } + #endif + #ifdef DEBUG_DUMPVARS + fprintf(stdout, "t->size=[%d] ", t->size); + fprintf(stdout, "q=[%d] ", q); + fprintf(stdout, "indent= [%d] ", indent); + fprintf(stdout, "js_sv= [%s]\n", js_sv); + #endif + if (count == 0) { + return 0; + } + /* We may want to do strtol() here to get numeric value */ +//0000fprintf(stderr, "t->type=%d\n", t->type); + if (t->type == JSMN_PRIMITIVE) { + if(strstr(js_sv, "data")) + { + /* + here we should recursivly call dump again here to skip over the array until we get the facking width of the map. + so we can initiate the map which allocates the facking map->tiles->data->data properly and THEN we can return + here to read the data.... That is my design for this... wwww + + FUCK well i am stuck.... wwww + */ + map->data[q] = (byte)atoi(js+t->start); + #ifdef DEBUG_MAPDATA + fprintf(stdout, "%d[%d]", q, map->data[q]); + #endif + } + else + if(strstr(js_sv, "height")) + { + map->height = atoi(js+t->start); + #ifdef DEBUG_MAPVAR + fprintf(stdout, "indent= [%d] ", indent); + fprintf(stdout, "h:[%d]\n", map->height); + #endif + }else if(strstr(js_sv, "width")) + { + map->width = atoi(js+t->start); + #ifdef DEBUG_MAPVAR + fprintf(stdout, "indent= [%d] ", indent); + fprintf(stdout, "w:[%d]\n", map->width); + #endif + } + return 1; + /* We may use strndup() to fetch string value */ + } else if (t->type == JSMN_STRING) { + if(jsoneq(js, t, "data") == 0) + { +// fprintf(stdout, "[[[[%d|%d]]]]\n", &(t+1)->size, (t+1)->size); +// fprintf(stdout, "\n%.*s[xx[%d|%d]xx]\n", (t+1)->end - (t+1)->start, js+(t+1)->start, &(t+1)->size, (t+1)->size); + map->data = malloc(sizeof(byte) * (t+1)->size); + map->tiles = malloc(sizeof(tiles_t)); + map->tiles->btdata = malloc(sizeof(bitmap_t)); + //fix this to be far~ + bp = bitmapLoadPcx("data/ed.pcx"); +// bp = bitmapLoadPcx("data/koishi^^.pcx"); + map->tiles->btdata = &bp; +//---- map->tiles->data = planar_buf_from_bitmap(&bp); + //map->tiles->data->data = malloc((16/**2*/)*16); + //map->tiles->data->width = (16/**2*/); + //map->tiles->data->height= 16; + map->tiles->tileHeight = 16; + map->tiles->tileWidth = 16; + map->tiles->rows = 1; + map->tiles->cols = 1; + map->tiles->debug_text=false; + strcpy(js_sv, "data");//strdup(js+t->start);//, t->end - t->start); + } + else + if (jsoneq(js, t, "height") == 0 && indent<=1) + { + strcpy(js_sv, "height");//strdup(js+t->start);//, t->end - t->start); + }else + if(jsoneq(js, t, "width") == 0 && indent<=1) + { + strcpy(js_sv, "width");//strdup(js+t->start);//, t->end - t->start); + }else strcpy(js_sv, "\0"); + return 1; + } else if (t->type == JSMN_OBJECT) { + //fprintf(stdout, "\n"); + j = 0; + for (i = 0; i < t->size; i++) { + //for (k = 0; k < indent; k++) fprintf(stdout, "\t"); + j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i); + //fprintf(stdout, ": "); + j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i); + //fprintf(stdout, "\n"); + } + return j+1; + } else if (t->type == JSMN_ARRAY) { + j = 0; + //fprintf(stdout, "==\n"); + for (i = 0; i < t->size; i++) { + //for (k = 0; k < indent-1; k++) fprintf(stdout, "\t"); + //fprintf(stdout, "\t-"); + j += dump(js, t+1+j, count-j, indent+1, js_sv, map, i); + //fprintf(stdout, "==\n"); + } + return j+1; + } + return 0; +} + +int loadmap(char *mn, map_t *map) +{ + int r; + static word incr=0; + int eof_expected = 0; + char *js = NULL; + size_t jslen = 0; + char buf[BUFSIZ]; + static char js_ss[16]; + + jsmn_parser p; + jsmntok_t *tok; + size_t tokcount = 2; + + FILE *fh = fopen(mn, "r"); + + /* Prepare parser */ + jsmn_init(&p); + + /* Allocate some tokens as a start */ +//0000fprintf(stderr, "tok malloc\n"); + tok = malloc(sizeof(*tok) * tokcount); + if (tok == NULL) { + fprintf(stderr, "malloc(): errno=%d\n", errno); + return 3; + } + + for (;;) { + /* Read another chunk */ +//0000fprintf(stderr, "read\n"); + r = fread(buf, 1, sizeof(buf), fh); + if (r < 0) { + fprintf(stderr, "fread(): %d, errno=%d\n", r, errno); + return 1; + } + if (r == 0) { + if (eof_expected != 0) { + return 0; + } else { + fprintf(stderr, "fread(): unexpected EOF\n"); + return 2; + } + } +//0000fprintf(stdout, "r= [%d] BUFSIZ=%d\n", r, BUFSIZ); +//0000fprintf(stderr, "js alloc~\n"); + js = realloc(js, jslen + r + 1); + if (js == NULL) { + fprintf(stderr, "*js=%Fp\n", *js); + fprintf(stderr, "realloc(): errno = %d\n", errno); + return 3; + } + strncpy(js + jslen, buf, r); + jslen = jslen + r; + +again: +//0000fprintf(stdout, " parse~ tok=%zu jslen=%zu r=%d _memavl()=%u BUFSIZ=%d~\n", tokcount, jslen, r, _memavl(), BUFSIZ); +//0000fprintf(stdout, "p=[%u] [%u] [%d]\n", p.pos, p.toknext, p.toksuper); +/* + I think it crashes on the line below when it tries to parse the data of huge maps... wwww this is a jsmn problem wwww +*/ + r = jsmn_parse(&p, js, jslen, tok, tokcount); +//0000fprintf(stdout, "r= [%d]\n", r); + if (r < 0) { + if (r == JSMN_ERROR_NOMEM) { + tokcount = tokcount * 2; +//0000fprintf(stderr, "tok realloc~ %zu\n", tokcount); + tok = realloc(tok, sizeof(*tok) * tokcount); + if (tok == NULL) { + fprintf(stderr, "realloc(): errno=%d\n", errno); + return 3; + } + goto again; + } + } else { + //printf("js=%Fp\n", (js)); + //printf("*js=%Fp\n", (*(js))); + //printf("&*js=%s\n", &(*(js))); + //printf("&buf=[%Fp]\n", &buf); + //printf("&buf_seg=[%x]\n", FP_SEG(&buf)); + //printf("&buf_off=[%x]\n", FP_OFF(&buf)); + //printf("&buf_fp=[%Fp]\n", MK_FP(FP_SEG(&buf), FP_OFF(&buf))); + //printf("buf=[\n%s\n]\n", buf); + //printf("buff=[%Fp]\n", buff); + //printf("(*buff)=[%Fp]\n", (*buff)); + //printf("&(*buff)=[\n%s\n]\n", &(*buff)); + #ifdef DEBUG_DUMPVARS + fprintf(stdout, "running dump~\n"); + #endif + dump(js, tok, p.toknext, incr, &js_ss, map, 0); + eof_expected = 1; + } + } + + free(js); + free(tok); + fclose(fh); + + return 0; +} diff --git a/src/lib/midi.c b/src/lib/midi.c index 760906c8..7e6ac1c5 100755 --- a/src/lib/midi.c +++ b/src/lib/midi.c @@ -1,730 +1,730 @@ -/* midi.c - * - * Adlib OPL2/OPL3 FM synthesizer chipset test program. - * Play MIDI file using the OPLx synthesizer (well, poorly anyway) - * (C) 2010-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - * - * Compiles for intended target environments: - * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] - */ - -#include "src/lib/midi.h" - -static unsigned int midi_trk_count=0; -struct midi_note midi_notes[ADLIB_FM_VOICES]; -struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; -struct midi_track midi_trk[MIDI_MAX_TRACKS]; - -/* MIDI params. Nobody ever said it was a straightforward standard! - * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */ -static unsigned int ticks_per_quarter_note=0; /* "Ticks per beat" */ - -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) -static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */ - return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p)); -} -#endif - -static inline unsigned char midi_trk_read(struct midi_track *t) { - unsigned char c; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { - t->eof = 1; - return 0xFF; - } - - c = *(t->read); -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */ - t->read = MK_FP(FP_SEG(t->read)+0x1,0); - else - t->read++; -#else - t->read++; -#endif - return c; -} - -void midi_trk_end(struct midi_track *t) { - t->wait = ~0UL; - t->read = t->fence; -} - -void midi_trk_skip(struct midi_track *t,unsigned long len) { - unsigned long rem; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) - return; - - if (len > 0xFFF0UL) { - midi_trk_end(t); - return; - } -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - { - unsigned long tt; - - tt = farptr2phys(t->read); - rem = farptr2phys(t->fence) - tt; - if (rem > len) rem = len; - tt += rem; - t->read = MK_FP(tt>>4,tt&0xF); - } -#else - rem = (unsigned long)(t->fence - t->read); - if (len > rem) len = rem; - t->read += len; -#endif -} - -static const uint32_t midikeys_freqs[0x80] = { - 0x00082d01, /* key 0 = 8.17579891564371Hz */ - 0x0008a976, /* key 1 = 8.66195721802725Hz */ - 0x00092d51, /* key 2 = 9.17702399741899Hz */ - 0x0009b904, /* key 3 = 9.72271824131503Hz */ - 0x000a4d05, /* key 4 = 10.3008611535272Hz */ - 0x000ae9d3, /* key 5 = 10.9133822322814Hz */ - 0x000b8ff4, /* key 6 = 11.5623257097386Hz */ - 0x000c3ff6, /* key 7 = 12.2498573744297Hz */ - 0x000cfa70, /* key 8 = 12.9782717993733Hz */ - 0x000dc000, /* key 9 = 13.75Hz */ - 0x000e914f, /* key 10 = 14.5676175474403Hz */ - 0x000f6f11, /* key 11 = 15.4338531642539Hz */ - 0x00105a02, /* key 12 = 16.3515978312874Hz */ - 0x001152ec, /* key 13 = 17.3239144360545Hz */ - 0x00125aa2, /* key 14 = 18.354047994838Hz */ - 0x00137208, /* key 15 = 19.4454364826301Hz */ - 0x00149a0a, /* key 16 = 20.6017223070544Hz */ - 0x0015d3a6, /* key 17 = 21.8267644645627Hz */ - 0x00171fe9, /* key 18 = 23.1246514194771Hz */ - 0x00187fed, /* key 19 = 24.4997147488593Hz */ - 0x0019f4e0, /* key 20 = 25.9565435987466Hz */ - 0x001b8000, /* key 21 = 27.5Hz */ - 0x001d229e, /* key 22 = 29.1352350948806Hz */ - 0x001ede22, /* key 23 = 30.8677063285078Hz */ - 0x0020b404, /* key 24 = 32.7031956625748Hz */ - 0x0022a5d8, /* key 25 = 34.647828872109Hz */ - 0x0024b545, /* key 26 = 36.7080959896759Hz */ - 0x0026e410, /* key 27 = 38.8908729652601Hz */ - 0x00293414, /* key 28 = 41.2034446141087Hz */ - 0x002ba74d, /* key 29 = 43.6535289291255Hz */ - 0x002e3fd2, /* key 30 = 46.2493028389543Hz */ - 0x0030ffda, /* key 31 = 48.9994294977187Hz */ - 0x0033e9c0, /* key 32 = 51.9130871974931Hz */ - 0x00370000, /* key 33 = 55Hz */ - 0x003a453d, /* key 34 = 58.2704701897612Hz */ - 0x003dbc44, /* key 35 = 61.7354126570155Hz */ - 0x00416809, /* key 36 = 65.4063913251497Hz */ - 0x00454bb0, /* key 37 = 69.295657744218Hz */ - 0x00496a8b, /* key 38 = 73.4161919793519Hz */ - 0x004dc820, /* key 39 = 77.7817459305202Hz */ - 0x00526829, /* key 40 = 82.4068892282175Hz */ - 0x00574e9b, /* key 41 = 87.307057858251Hz */ - 0x005c7fa4, /* key 42 = 92.4986056779086Hz */ - 0x0061ffb5, /* key 43 = 97.9988589954373Hz */ - 0x0067d380, /* key 44 = 103.826174394986Hz */ - 0x006e0000, /* key 45 = 110Hz */ - 0x00748a7b, /* key 46 = 116.540940379522Hz */ - 0x007b7888, /* key 47 = 123.470825314031Hz */ - 0x0082d012, /* key 48 = 130.812782650299Hz */ - 0x008a9760, /* key 49 = 138.591315488436Hz */ - 0x0092d517, /* key 50 = 146.832383958704Hz */ - 0x009b9041, /* key 51 = 155.56349186104Hz */ - 0x00a4d053, /* key 52 = 164.813778456435Hz */ - 0x00ae9d36, /* key 53 = 174.614115716502Hz */ - 0x00b8ff49, /* key 54 = 184.997211355817Hz */ - 0x00c3ff6a, /* key 55 = 195.997717990875Hz */ - 0x00cfa700, /* key 56 = 207.652348789973Hz */ - 0x00dc0000, /* key 57 = 220Hz */ - 0x00e914f6, /* key 58 = 233.081880759045Hz */ - 0x00f6f110, /* key 59 = 246.941650628062Hz */ - 0x0105a025, /* key 60 = 261.625565300599Hz */ - 0x01152ec0, /* key 61 = 277.182630976872Hz */ - 0x0125aa2e, /* key 62 = 293.664767917408Hz */ - 0x01372082, /* key 63 = 311.126983722081Hz */ - 0x0149a0a7, /* key 64 = 329.62755691287Hz */ - 0x015d3a6d, /* key 65 = 349.228231433004Hz */ - 0x0171fe92, /* key 66 = 369.994422711634Hz */ - 0x0187fed4, /* key 67 = 391.995435981749Hz */ - 0x019f4e00, /* key 68 = 415.304697579945Hz */ - 0x01b80000, /* key 69 = 440Hz */ - 0x01d229ec, /* key 70 = 466.16376151809Hz */ - 0x01ede220, /* key 71 = 493.883301256124Hz */ - 0x020b404a, /* key 72 = 523.251130601197Hz */ - 0x022a5d81, /* key 73 = 554.365261953744Hz */ - 0x024b545c, /* key 74 = 587.329535834815Hz */ - 0x026e4104, /* key 75 = 622.253967444162Hz */ - 0x0293414f, /* key 76 = 659.25511382574Hz */ - 0x02ba74da, /* key 77 = 698.456462866008Hz */ - 0x02e3fd24, /* key 78 = 739.988845423269Hz */ - 0x030ffda9, /* key 79 = 783.990871963499Hz */ - 0x033e9c01, /* key 80 = 830.60939515989Hz */ - 0x03700000, /* key 81 = 880Hz */ - 0x03a453d8, /* key 82 = 932.32752303618Hz */ - 0x03dbc440, /* key 83 = 987.766602512248Hz */ - 0x04168094, /* key 84 = 1046.50226120239Hz */ - 0x0454bb03, /* key 85 = 1108.73052390749Hz */ - 0x0496a8b8, /* key 86 = 1174.65907166963Hz */ - 0x04dc8208, /* key 87 = 1244.50793488832Hz */ - 0x0526829e, /* key 88 = 1318.51022765148Hz */ - 0x0574e9b5, /* key 89 = 1396.91292573202Hz */ - 0x05c7fa49, /* key 90 = 1479.97769084654Hz */ - 0x061ffb53, /* key 91 = 1567.981743927Hz */ - 0x067d3802, /* key 92 = 1661.21879031978Hz */ - 0x06e00000, /* key 93 = 1760Hz */ - 0x0748a7b1, /* key 94 = 1864.65504607236Hz */ - 0x07b78880, /* key 95 = 1975.5332050245Hz */ - 0x082d0128, /* key 96 = 2093.00452240479Hz */ - 0x08a97607, /* key 97 = 2217.46104781498Hz */ - 0x092d5171, /* key 98 = 2349.31814333926Hz */ - 0x09b90410, /* key 99 = 2489.01586977665Hz */ - 0x0a4d053c, /* key 100 = 2637.02045530296Hz */ - 0x0ae9d36b, /* key 101 = 2793.82585146403Hz */ - 0x0b8ff493, /* key 102 = 2959.95538169308Hz */ - 0x0c3ff6a7, /* key 103 = 3135.96348785399Hz */ - 0x0cfa7005, /* key 104 = 3322.43758063956Hz */ - 0x0dc00000, /* key 105 = 3520Hz */ - 0x0e914f62, /* key 106 = 3729.31009214472Hz */ - 0x0f6f1100, /* key 107 = 3951.06641004899Hz */ - 0x105a0250, /* key 108 = 4186.00904480958Hz */ - 0x1152ec0e, /* key 109 = 4434.92209562995Hz */ - 0x125aa2e3, /* key 110 = 4698.63628667852Hz */ - 0x13720820, /* key 111 = 4978.03173955329Hz */ - 0x149a0a79, /* key 112 = 5274.04091060592Hz */ - 0x15d3a6d6, /* key 113 = 5587.65170292806Hz */ - 0x171fe927, /* key 114 = 5919.91076338615Hz */ - 0x187fed4e, /* key 115 = 6271.92697570799Hz */ - 0x19f4e00a, /* key 116 = 6644.87516127912Hz */ - 0x1b800000, /* key 117 = 7040Hz */ - 0x1d229ec4, /* key 118 = 7458.62018428944Hz */ - 0x1ede2200, /* key 119 = 7902.13282009799Hz */ - 0x20b404a1, /* key 120 = 8372.01808961916Hz */ - 0x22a5d81c, /* key 121 = 8869.84419125991Hz */ - 0x24b545c7, /* key 122 = 9397.27257335704Hz */ - 0x26e41040, /* key 123 = 9956.06347910659Hz */ - 0x293414f2, /* key 124 = 10548.0818212118Hz */ - 0x2ba74dac, /* key 125 = 11175.3034058561Hz */ - 0x2e3fd24f, /* key 126 = 11839.8215267723Hz */ - 0x30ffda9c /* key 127 = 12543.853951416Hz */ -}; - -static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) { - return midikeys_freqs[key&0x7F]; -} - -static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) { - unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */ - unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ - unsigned int i,freen=~0; - - for (i=0;i < ADLIB_FM_VOICES;i++) { - if (midi_notes[i].busy) { - if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key) - return &midi_notes[i]; - } - else { - if (freen == ~0) freen = i; - } - } - - if (do_alloc && freen != ~0) return &midi_notes[freen]; - return NULL; -} - -static void drop_fm_note(struct midi_channel *ch,unsigned char key) { - unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ - unsigned int i; - - for (i=0;i < ADLIB_FM_VOICES;i++) { - if (midi_notes[i].busy && midi_notes[i].note_channel == ach) { - midi_notes[i].busy = 0; - break; - } - } -} - -static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { - struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); - uint32_t freq = midi_note_freq(ch,key); - unsigned int ach; - - if (note == NULL) return; - - note->busy = 1; - note->note_number = key; - note->note_velocity = vel; - note->note_track = (unsigned int)(t - midi_trk); - note->note_channel = (unsigned int)(ch - midi_ch); - ach = (unsigned int)(note - midi_notes); /* which FM channel? */ - adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); - adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ - adlib_fm[ach].mod.sustain_level = vel >> 3; - adlib_fm[ach].mod.key_on = 1; - adlib_update_groupA0(ach,&adlib_fm[ach]); -} - -static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { - struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1); - uint32_t freq = midi_note_freq(ch,key); - unsigned int ach; - - /* HACK: Ignore percussion */ - if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ || - (ch->program >= 112 && ch->program <= 119)/*Percussive*/ || - ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/) - return; - - if (note == NULL) { - /* then we'll have to knock one off to make room */ - drop_fm_note(ch,key); - note = get_fm_note(t,ch,key,1); - if (note == NULL) return; - } - - note->busy = 1; - note->note_number = key; - note->note_velocity = vel; - note->note_track = (unsigned int)(t - midi_trk); - note->note_channel = (unsigned int)(ch - midi_ch); - ach = (unsigned int)(note - midi_notes); /* which FM channel? */ - adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); - adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ - adlib_fm[ach].mod.sustain_level = vel >> 3; - adlib_fm[ach].mod.key_on = 1; - adlib_update_groupA0(ach,&adlib_fm[ach]); -} - -static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { - struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); - uint32_t freq = midi_note_freq(ch,key); - unsigned int ach; - - if (note == NULL) return; - - note->busy = 0; - ach = (unsigned int)(note - midi_notes); /* which FM channel? */ - adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); - adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ - adlib_fm[ach].mod.sustain_level = vel >> 3; - adlib_fm[ach].mod.key_on = 0; - adlib_update_groupA0(ach,&adlib_fm[ach]); -} - -static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) { -} - -static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) { - ch->program = inst; -} - -static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) { -} - -static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) { -} - -unsigned long midi_trk_read_delta(struct midi_track *t) { - unsigned long tc = 0; - unsigned char c = 0,b; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) - return tc; - - while (c < 4) { - b = midi_trk_read(t); - tc = (tc << 7UL) + (unsigned long)(b&0x7F); - if (!(b&0x80)) break; - c++; - } - - return tc; -} - -void midi_tick_track(unsigned int i) { - struct midi_track *t = midi_trk + i; - struct midi_channel *ch; - unsigned char b,c,d; - int cnt=0; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { - t->eof = 1; - return; - } - - t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note; - while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) { - t->us_tick_cnt_mtpq -= t->us_per_quarter_note; - cnt++; - - while (t->wait == 0) { - if ((unsigned long)t->read >= (unsigned long)t->fence) { - t->eof = 1; - break; - } - - /* read pointer should be pointing at MIDI event bytes, just after the time delay */ - b = midi_trk_read(t); - if (b&0x80) { - if (b < 0xF8) { - if (b >= 0xF0) - t->last_status = 0; - else - t->last_status = b; - } - if (b != 0x00 && ((b&0xF8) != 0xF0)) - c = midi_trk_read(t); - } - else { - /* blegh. last status */ - c = b; - b = t->last_status; - } - switch (b>>4) { - case 0x8: { /* note off */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - on_key_off(t,ch,c,d); - } break; - case 0x9: { /* note on */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */ - else on_key_off(t,ch,c,d); - } break; - case 0xA: { /* polyphonic aftertouch */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - on_key_aftertouch(t,ch,c,d); - } break; - case 0xB: { /* control change */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - on_control_change(t,ch,c,d); - } break; - case 0xC: { /* program change */ - on_program_change(t,ch,c); /* c=instrument d=not used */ - } break; - case 0xD: { /* channel aftertouch */ - on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */ - } break; - case 0xE: { /* pitch bend */ - d = midi_trk_read(t); - on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */ - } break; - case 0xF: { /* event */ - if (b == 0xFF) { - if (c == 0x7F) { /* c=type d=len */ - unsigned long len = midi_trk_read_delta(t); -//==== - fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); -//==== - if (len < 512UL) { - /* unknown */ - midi_trk_skip(t,len); - } - else { - midi_trk_end(t); - } - } - else if (c < 0x7F) { - d = midi_trk_read(t); - - if (c == 0x51 && d >= 3) { - d -= 3; - t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+ - ((unsigned long)midi_trk_read(t)<<8UL)+ - ((unsigned long)midi_trk_read(t)<<0UL); - - if (1/*TODO: If format 0 or format 1*/) { - /* Ugh. Unless format 2, the tempo applies to all tracks */ - int j; - - for (j=0;j < midi_trk_count;j++) { - if (j != i) midi_trk[j].us_per_quarter_note = - t->us_per_quarter_note; - } - } - } - else { -//==== - fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence); -//==== - } - - midi_trk_skip(t,d); - } - else { - fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence); - } - } - else { - unsigned long len = midi_trk_read_delta(t); -//==== - fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); -//==== - midi_trk_skip(t,len); - } - } break; - default: - if (b != 0x00) { - fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence); - midi_trk_end(t); - } - break; - }; - - /* and then read the next event */ - t->wait = midi_trk_read_delta(t); - } - if (t->wait != 0) { - t->wait--; - } - } -} - -//void adlib_shut_up(); -void midi_reset_tracks(); -void midi_reset_channels(); - -void midi_tick() { - if (midi_playing) { - unsigned int i; - int eof=0; - - for (i=0;i < midi_trk_count;i++) { - midi_tick_track(i); - eof += midi_trk[i].eof?1:0; - } - - if (eof >= midi_trk_count) { - adlib_shut_up(); - midi_reset_tracks(); - midi_reset_channels(); - } - } -} - -/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ -void interrupt irq0() { -// midi_tick(); - irq0_ticks++; - if ((irq0_cnt += irq0_add) >= irq0_max) { - irq0_cnt -= irq0_max; - old_irq0(); - } - else { - p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); - } -} - -void adlib_shut_up() { - int i; - - memset(adlib_fm,0,sizeof(adlib_fm)); - memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - f = &adlib_fm[i].mod; - f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; - f = &adlib_fm[i].car; - f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; - } - - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - - midi_notes[i].busy = 0; - midi_notes[i].note_channel = 0; - - f = &adlib_fm[i].mod; - f->mod_multiple = 1; - f->total_level = 63 - 16; - f->attack_rate = 15; - f->decay_rate = 4; - f->sustain_level = 0; - f->release_rate = 8; - f->f_number = 400; - f->sustain = 1; - f->octave = 4; - f->key_on = 0; - - f = &adlib_fm[i].car; - f->mod_multiple = 1; - f->total_level = 63 - 16; - f->attack_rate = 15; - f->decay_rate = 4; - f->sustain_level = 0; - f->release_rate = 8; - f->f_number = 0; - f->sustain = 1; - f->octave = 0; - f->key_on = 0; - } - - adlib_apply_all(); -} - -void midi_reset_track(unsigned int i) { - struct midi_track *t; - - if (i >= MIDI_MAX_TRACKS) return; - t = &midi_trk[i]; - t->eof = 0; - t->last_status = 0; - t->us_tick_cnt_mtpq = 0; - t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */ - t->read = midi_trk[i].raw; - t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */ -} - -void midi_reset_tracks() { - int i; - - for (i=0;i < midi_trk_count;i++) - midi_reset_track(i); -} - -void midi_reset_channels() { - int i; - - for (i=0;i < MIDI_MAX_CHANNELS;i++) { - midi_ch[i].program = 0; - } -} - -int load_midi_file(const char *path) { - unsigned char tmp[256]; - unsigned int tracks=0; - unsigned int tracki=0; - int fd; - - fd = open(path,O_RDONLY|O_BINARY); - if (fd < 0) { - printf("Failed to load file %s\n",path); - return 0; - } - - ticks_per_quarter_note = 0; - while (read(fd,tmp,8) == 8) { - uint32_t sz; - - sz = ((uint32_t)tmp[4] << (uint32_t)24) | - ((uint32_t)tmp[5] << (uint32_t)16) | - ((uint32_t)tmp[6] << (uint32_t)8) | - ((uint32_t)tmp[7] << (uint32_t)0); - if (!memcmp(tmp,"MThd",4)) { - unsigned short t,tdiv; - - if (sz < 6 || sz > 255) { - fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz); - goto err; - } - if (read(fd,tmp,(int)sz) != (int)sz) { - fprintf(stderr,"MThd read error\n"); - goto err; - } - - /* byte 0-1 = format type (0,1 or 2) */ - /* byte 2-3 = number of tracks */ - /* byte 4-5 = time divison */ - t = tmp[1] | (tmp[0] << 8); - if (t > 1) { - fprintf(stderr,"MThd type %u not supported\n",t); - goto err; /* we only take type 0 or 1, don't support 2 */ - } - tracks = tmp[3] | (tmp[2] << 8); - if (tracks > MIDI_MAX_TRACKS) { - fprintf(stderr,"MThd too many (%u) tracks\n",tracks); - goto err; - } - tdiv = tmp[5] | (tmp[4] << 8); - if (tdiv & 0x8000) { - fprintf(stderr,"MThd SMPTE time division not supported\n"); - goto err; /* we do not support the SMPTE form */ - } - if (tdiv == 0) { - fprintf(stderr,"MThd time division == 0\n"); - goto err; - } - ticks_per_quarter_note = tdiv; - } - else if (!memcmp(tmp,"MTrk",4)) { - if (sz == 0UL) continue; -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - if (sz > (640UL << 10UL)) goto err; /* 640KB */ -#elif TARGET_MSDOS == 32 - if (sz > (1UL << 20UL)) goto err; /* 1MB */ -#else - if (sz > (60UL << 10UL)) goto err; /* 60KB */ -#endif - if (tracki >= MIDI_MAX_TRACKS) goto err; -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - { - unsigned segv; - - /* NTS: _fmalloc() is still limited to 64KB sizes */ - if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err; - midi_trk[tracki].raw = MK_FP(segv,0); - } -#else - midi_trk[tracki].raw = malloc(sz); -#endif - if (midi_trk[tracki].raw == NULL) goto err; - midi_trk[tracki].read = midi_trk[tracki].raw; -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - { - unsigned char far *p = midi_trk[tracki].raw; - unsigned long rem = (unsigned long)sz; - unsigned long cando; - unsigned read; - - while (rem != 0UL) { - read = 0; - - cando = 0x10000UL - (unsigned long)FP_OFF(p); - if (cando > rem) cando = rem; - if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */ - - if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err; - if (read != (unsigned)cando) goto err; - - rem -= cando; - if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL) - p = MK_FP(FP_SEG(p)+0x1000,0); - else - p += (unsigned)cando; - } - - cando = farptr2phys(p); - midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF); - } -#else - midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz; - if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err; -#endif - tracki++; - } - else { - fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]); - goto err; - } - } - if (tracki == 0 || ticks_per_quarter_note == 0) goto err; - midi_trk_count = tracki; - - fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note); - - close(fd); - return 1; -err: - close(fd); - return 0; -} +/* midi.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include "src/lib/midi.h" + +static unsigned int midi_trk_count=0; +struct midi_note midi_notes[ADLIB_FM_VOICES]; +struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; +struct midi_track midi_trk[MIDI_MAX_TRACKS]; + +/* MIDI params. Nobody ever said it was a straightforward standard! + * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */ +static unsigned int ticks_per_quarter_note=0; /* "Ticks per beat" */ + +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) +static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */ + return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p)); +} +#endif + +static inline unsigned char midi_trk_read(struct midi_track *t) { + unsigned char c; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return 0xFF; + } + + c = *(t->read); +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */ + t->read = MK_FP(FP_SEG(t->read)+0x1,0); + else + t->read++; +#else + t->read++; +#endif + return c; +} + +void midi_trk_end(struct midi_track *t) { + t->wait = ~0UL; + t->read = t->fence; +} + +void midi_trk_skip(struct midi_track *t,unsigned long len) { + unsigned long rem; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return; + + if (len > 0xFFF0UL) { + midi_trk_end(t); + return; + } +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned long tt; + + tt = farptr2phys(t->read); + rem = farptr2phys(t->fence) - tt; + if (rem > len) rem = len; + tt += rem; + t->read = MK_FP(tt>>4,tt&0xF); + } +#else + rem = (unsigned long)(t->fence - t->read); + if (len > rem) len = rem; + t->read += len; +#endif +} + +static const uint32_t midikeys_freqs[0x80] = { + 0x00082d01, /* key 0 = 8.17579891564371Hz */ + 0x0008a976, /* key 1 = 8.66195721802725Hz */ + 0x00092d51, /* key 2 = 9.17702399741899Hz */ + 0x0009b904, /* key 3 = 9.72271824131503Hz */ + 0x000a4d05, /* key 4 = 10.3008611535272Hz */ + 0x000ae9d3, /* key 5 = 10.9133822322814Hz */ + 0x000b8ff4, /* key 6 = 11.5623257097386Hz */ + 0x000c3ff6, /* key 7 = 12.2498573744297Hz */ + 0x000cfa70, /* key 8 = 12.9782717993733Hz */ + 0x000dc000, /* key 9 = 13.75Hz */ + 0x000e914f, /* key 10 = 14.5676175474403Hz */ + 0x000f6f11, /* key 11 = 15.4338531642539Hz */ + 0x00105a02, /* key 12 = 16.3515978312874Hz */ + 0x001152ec, /* key 13 = 17.3239144360545Hz */ + 0x00125aa2, /* key 14 = 18.354047994838Hz */ + 0x00137208, /* key 15 = 19.4454364826301Hz */ + 0x00149a0a, /* key 16 = 20.6017223070544Hz */ + 0x0015d3a6, /* key 17 = 21.8267644645627Hz */ + 0x00171fe9, /* key 18 = 23.1246514194771Hz */ + 0x00187fed, /* key 19 = 24.4997147488593Hz */ + 0x0019f4e0, /* key 20 = 25.9565435987466Hz */ + 0x001b8000, /* key 21 = 27.5Hz */ + 0x001d229e, /* key 22 = 29.1352350948806Hz */ + 0x001ede22, /* key 23 = 30.8677063285078Hz */ + 0x0020b404, /* key 24 = 32.7031956625748Hz */ + 0x0022a5d8, /* key 25 = 34.647828872109Hz */ + 0x0024b545, /* key 26 = 36.7080959896759Hz */ + 0x0026e410, /* key 27 = 38.8908729652601Hz */ + 0x00293414, /* key 28 = 41.2034446141087Hz */ + 0x002ba74d, /* key 29 = 43.6535289291255Hz */ + 0x002e3fd2, /* key 30 = 46.2493028389543Hz */ + 0x0030ffda, /* key 31 = 48.9994294977187Hz */ + 0x0033e9c0, /* key 32 = 51.9130871974931Hz */ + 0x00370000, /* key 33 = 55Hz */ + 0x003a453d, /* key 34 = 58.2704701897612Hz */ + 0x003dbc44, /* key 35 = 61.7354126570155Hz */ + 0x00416809, /* key 36 = 65.4063913251497Hz */ + 0x00454bb0, /* key 37 = 69.295657744218Hz */ + 0x00496a8b, /* key 38 = 73.4161919793519Hz */ + 0x004dc820, /* key 39 = 77.7817459305202Hz */ + 0x00526829, /* key 40 = 82.4068892282175Hz */ + 0x00574e9b, /* key 41 = 87.307057858251Hz */ + 0x005c7fa4, /* key 42 = 92.4986056779086Hz */ + 0x0061ffb5, /* key 43 = 97.9988589954373Hz */ + 0x0067d380, /* key 44 = 103.826174394986Hz */ + 0x006e0000, /* key 45 = 110Hz */ + 0x00748a7b, /* key 46 = 116.540940379522Hz */ + 0x007b7888, /* key 47 = 123.470825314031Hz */ + 0x0082d012, /* key 48 = 130.812782650299Hz */ + 0x008a9760, /* key 49 = 138.591315488436Hz */ + 0x0092d517, /* key 50 = 146.832383958704Hz */ + 0x009b9041, /* key 51 = 155.56349186104Hz */ + 0x00a4d053, /* key 52 = 164.813778456435Hz */ + 0x00ae9d36, /* key 53 = 174.614115716502Hz */ + 0x00b8ff49, /* key 54 = 184.997211355817Hz */ + 0x00c3ff6a, /* key 55 = 195.997717990875Hz */ + 0x00cfa700, /* key 56 = 207.652348789973Hz */ + 0x00dc0000, /* key 57 = 220Hz */ + 0x00e914f6, /* key 58 = 233.081880759045Hz */ + 0x00f6f110, /* key 59 = 246.941650628062Hz */ + 0x0105a025, /* key 60 = 261.625565300599Hz */ + 0x01152ec0, /* key 61 = 277.182630976872Hz */ + 0x0125aa2e, /* key 62 = 293.664767917408Hz */ + 0x01372082, /* key 63 = 311.126983722081Hz */ + 0x0149a0a7, /* key 64 = 329.62755691287Hz */ + 0x015d3a6d, /* key 65 = 349.228231433004Hz */ + 0x0171fe92, /* key 66 = 369.994422711634Hz */ + 0x0187fed4, /* key 67 = 391.995435981749Hz */ + 0x019f4e00, /* key 68 = 415.304697579945Hz */ + 0x01b80000, /* key 69 = 440Hz */ + 0x01d229ec, /* key 70 = 466.16376151809Hz */ + 0x01ede220, /* key 71 = 493.883301256124Hz */ + 0x020b404a, /* key 72 = 523.251130601197Hz */ + 0x022a5d81, /* key 73 = 554.365261953744Hz */ + 0x024b545c, /* key 74 = 587.329535834815Hz */ + 0x026e4104, /* key 75 = 622.253967444162Hz */ + 0x0293414f, /* key 76 = 659.25511382574Hz */ + 0x02ba74da, /* key 77 = 698.456462866008Hz */ + 0x02e3fd24, /* key 78 = 739.988845423269Hz */ + 0x030ffda9, /* key 79 = 783.990871963499Hz */ + 0x033e9c01, /* key 80 = 830.60939515989Hz */ + 0x03700000, /* key 81 = 880Hz */ + 0x03a453d8, /* key 82 = 932.32752303618Hz */ + 0x03dbc440, /* key 83 = 987.766602512248Hz */ + 0x04168094, /* key 84 = 1046.50226120239Hz */ + 0x0454bb03, /* key 85 = 1108.73052390749Hz */ + 0x0496a8b8, /* key 86 = 1174.65907166963Hz */ + 0x04dc8208, /* key 87 = 1244.50793488832Hz */ + 0x0526829e, /* key 88 = 1318.51022765148Hz */ + 0x0574e9b5, /* key 89 = 1396.91292573202Hz */ + 0x05c7fa49, /* key 90 = 1479.97769084654Hz */ + 0x061ffb53, /* key 91 = 1567.981743927Hz */ + 0x067d3802, /* key 92 = 1661.21879031978Hz */ + 0x06e00000, /* key 93 = 1760Hz */ + 0x0748a7b1, /* key 94 = 1864.65504607236Hz */ + 0x07b78880, /* key 95 = 1975.5332050245Hz */ + 0x082d0128, /* key 96 = 2093.00452240479Hz */ + 0x08a97607, /* key 97 = 2217.46104781498Hz */ + 0x092d5171, /* key 98 = 2349.31814333926Hz */ + 0x09b90410, /* key 99 = 2489.01586977665Hz */ + 0x0a4d053c, /* key 100 = 2637.02045530296Hz */ + 0x0ae9d36b, /* key 101 = 2793.82585146403Hz */ + 0x0b8ff493, /* key 102 = 2959.95538169308Hz */ + 0x0c3ff6a7, /* key 103 = 3135.96348785399Hz */ + 0x0cfa7005, /* key 104 = 3322.43758063956Hz */ + 0x0dc00000, /* key 105 = 3520Hz */ + 0x0e914f62, /* key 106 = 3729.31009214472Hz */ + 0x0f6f1100, /* key 107 = 3951.06641004899Hz */ + 0x105a0250, /* key 108 = 4186.00904480958Hz */ + 0x1152ec0e, /* key 109 = 4434.92209562995Hz */ + 0x125aa2e3, /* key 110 = 4698.63628667852Hz */ + 0x13720820, /* key 111 = 4978.03173955329Hz */ + 0x149a0a79, /* key 112 = 5274.04091060592Hz */ + 0x15d3a6d6, /* key 113 = 5587.65170292806Hz */ + 0x171fe927, /* key 114 = 5919.91076338615Hz */ + 0x187fed4e, /* key 115 = 6271.92697570799Hz */ + 0x19f4e00a, /* key 116 = 6644.87516127912Hz */ + 0x1b800000, /* key 117 = 7040Hz */ + 0x1d229ec4, /* key 118 = 7458.62018428944Hz */ + 0x1ede2200, /* key 119 = 7902.13282009799Hz */ + 0x20b404a1, /* key 120 = 8372.01808961916Hz */ + 0x22a5d81c, /* key 121 = 8869.84419125991Hz */ + 0x24b545c7, /* key 122 = 9397.27257335704Hz */ + 0x26e41040, /* key 123 = 9956.06347910659Hz */ + 0x293414f2, /* key 124 = 10548.0818212118Hz */ + 0x2ba74dac, /* key 125 = 11175.3034058561Hz */ + 0x2e3fd24f, /* key 126 = 11839.8215267723Hz */ + 0x30ffda9c /* key 127 = 12543.853951416Hz */ +}; + +static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) { + return midikeys_freqs[key&0x7F]; +} + +static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) { + unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */ + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i,freen=~0; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy) { + if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key) + return &midi_notes[i]; + } + else { + if (freen == ~0) freen = i; + } + } + + if (do_alloc && freen != ~0) return &midi_notes[freen]; + return NULL; +} + +static void drop_fm_note(struct midi_channel *ch,unsigned char key) { + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy && midi_notes[i].note_channel == ach) { + midi_notes[i].busy = 0; + break; + } + } +} + +static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + /* HACK: Ignore percussion */ + if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ || + (ch->program >= 112 && ch->program <= 119)/*Percussive*/ || + ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/) + return; + + if (note == NULL) { + /* then we'll have to knock one off to make room */ + drop_fm_note(ch,key); + note = get_fm_note(t,ch,key,1); + if (note == NULL) return; + } + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 0; + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 0; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) { +} + +static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) { + ch->program = inst; +} + +static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) { +} + +static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) { +} + +unsigned long midi_trk_read_delta(struct midi_track *t) { + unsigned long tc = 0; + unsigned char c = 0,b; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return tc; + + while (c < 4) { + b = midi_trk_read(t); + tc = (tc << 7UL) + (unsigned long)(b&0x7F); + if (!(b&0x80)) break; + c++; + } + + return tc; +} + +void midi_tick_track(unsigned int i) { + struct midi_track *t = midi_trk + i; + struct midi_channel *ch; + unsigned char b,c,d; + int cnt=0; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return; + } + + t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note; + while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) { + t->us_tick_cnt_mtpq -= t->us_per_quarter_note; + cnt++; + + while (t->wait == 0) { + if ((unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + break; + } + + /* read pointer should be pointing at MIDI event bytes, just after the time delay */ + b = midi_trk_read(t); + if (b&0x80) { + if (b < 0xF8) { + if (b >= 0xF0) + t->last_status = 0; + else + t->last_status = b; + } + if (b != 0x00 && ((b&0xF8) != 0xF0)) + c = midi_trk_read(t); + } + else { + /* blegh. last status */ + c = b; + b = t->last_status; + } + switch (b>>4) { + case 0x8: { /* note off */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_off(t,ch,c,d); + } break; + case 0x9: { /* note on */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */ + else on_key_off(t,ch,c,d); + } break; + case 0xA: { /* polyphonic aftertouch */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_aftertouch(t,ch,c,d); + } break; + case 0xB: { /* control change */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_control_change(t,ch,c,d); + } break; + case 0xC: { /* program change */ + on_program_change(t,ch,c); /* c=instrument d=not used */ + } break; + case 0xD: { /* channel aftertouch */ + on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */ + } break; + case 0xE: { /* pitch bend */ + d = midi_trk_read(t); + on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */ + } break; + case 0xF: { /* event */ + if (b == 0xFF) { + if (c == 0x7F) { /* c=type d=len */ + unsigned long len = midi_trk_read_delta(t); +//==== + fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); +//==== + if (len < 512UL) { + /* unknown */ + midi_trk_skip(t,len); + } + else { + midi_trk_end(t); + } + } + else if (c < 0x7F) { + d = midi_trk_read(t); + + if (c == 0x51 && d >= 3) { + d -= 3; + t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+ + ((unsigned long)midi_trk_read(t)<<8UL)+ + ((unsigned long)midi_trk_read(t)<<0UL); + + if (1/*TODO: If format 0 or format 1*/) { + /* Ugh. Unless format 2, the tempo applies to all tracks */ + int j; + + for (j=0;j < midi_trk_count;j++) { + if (j != i) midi_trk[j].us_per_quarter_note = + t->us_per_quarter_note; + } + } + } + else { +//==== + fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence); +//==== + } + + midi_trk_skip(t,d); + } + else { + fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence); + } + } + else { + unsigned long len = midi_trk_read_delta(t); +//==== + fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); +//==== + midi_trk_skip(t,len); + } + } break; + default: + if (b != 0x00) { + fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence); + midi_trk_end(t); + } + break; + }; + + /* and then read the next event */ + t->wait = midi_trk_read_delta(t); + } + if (t->wait != 0) { + t->wait--; + } + } +} + +//void adlib_shut_up(); +void midi_reset_tracks(); +void midi_reset_channels(); + +void midi_tick() { + if (midi_playing) { + unsigned int i; + int eof=0; + + for (i=0;i < midi_trk_count;i++) { + midi_tick_track(i); + eof += midi_trk[i].eof?1:0; + } + + if (eof >= midi_trk_count) { + adlib_shut_up(); + midi_reset_tracks(); + midi_reset_channels(); + } + } +} + +/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ +void interrupt irq0() { +// midi_tick(); + irq0_ticks++; + if ((irq0_cnt += irq0_add) >= irq0_max) { + irq0_cnt -= irq0_max; + old_irq0(); + } + else { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } +} + +void adlib_shut_up() { + int i; + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + midi_notes[i].busy = 0; + midi_notes[i].note_channel = 0; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 400; + f->sustain = 1; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 0; + f->sustain = 1; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); +} + +void midi_reset_track(unsigned int i) { + struct midi_track *t; + + if (i >= MIDI_MAX_TRACKS) return; + t = &midi_trk[i]; + t->eof = 0; + t->last_status = 0; + t->us_tick_cnt_mtpq = 0; + t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */ + t->read = midi_trk[i].raw; + t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */ +} + +void midi_reset_tracks() { + int i; + + for (i=0;i < midi_trk_count;i++) + midi_reset_track(i); +} + +void midi_reset_channels() { + int i; + + for (i=0;i < MIDI_MAX_CHANNELS;i++) { + midi_ch[i].program = 0; + } +} + +int load_midi_file(const char *path) { + unsigned char tmp[256]; + unsigned int tracks=0; + unsigned int tracki=0; + int fd; + + fd = open(path,O_RDONLY|O_BINARY); + if (fd < 0) { + printf("Failed to load file %s\n",path); + return 0; + } + + ticks_per_quarter_note = 0; + while (read(fd,tmp,8) == 8) { + uint32_t sz; + + sz = ((uint32_t)tmp[4] << (uint32_t)24) | + ((uint32_t)tmp[5] << (uint32_t)16) | + ((uint32_t)tmp[6] << (uint32_t)8) | + ((uint32_t)tmp[7] << (uint32_t)0); + if (!memcmp(tmp,"MThd",4)) { + unsigned short t,tdiv; + + if (sz < 6 || sz > 255) { + fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz); + goto err; + } + if (read(fd,tmp,(int)sz) != (int)sz) { + fprintf(stderr,"MThd read error\n"); + goto err; + } + + /* byte 0-1 = format type (0,1 or 2) */ + /* byte 2-3 = number of tracks */ + /* byte 4-5 = time divison */ + t = tmp[1] | (tmp[0] << 8); + if (t > 1) { + fprintf(stderr,"MThd type %u not supported\n",t); + goto err; /* we only take type 0 or 1, don't support 2 */ + } + tracks = tmp[3] | (tmp[2] << 8); + if (tracks > MIDI_MAX_TRACKS) { + fprintf(stderr,"MThd too many (%u) tracks\n",tracks); + goto err; + } + tdiv = tmp[5] | (tmp[4] << 8); + if (tdiv & 0x8000) { + fprintf(stderr,"MThd SMPTE time division not supported\n"); + goto err; /* we do not support the SMPTE form */ + } + if (tdiv == 0) { + fprintf(stderr,"MThd time division == 0\n"); + goto err; + } + ticks_per_quarter_note = tdiv; + } + else if (!memcmp(tmp,"MTrk",4)) { + if (sz == 0UL) continue; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (sz > (640UL << 10UL)) goto err; /* 640KB */ +#elif TARGET_MSDOS == 32 + if (sz > (1UL << 20UL)) goto err; /* 1MB */ +#else + if (sz > (60UL << 10UL)) goto err; /* 60KB */ +#endif + if (tracki >= MIDI_MAX_TRACKS) goto err; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned segv; + + /* NTS: _fmalloc() is still limited to 64KB sizes */ + if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err; + midi_trk[tracki].raw = MK_FP(segv,0); + } +#else + midi_trk[tracki].raw = malloc(sz); +#endif + if (midi_trk[tracki].raw == NULL) goto err; + midi_trk[tracki].read = midi_trk[tracki].raw; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned char far *p = midi_trk[tracki].raw; + unsigned long rem = (unsigned long)sz; + unsigned long cando; + unsigned read; + + while (rem != 0UL) { + read = 0; + + cando = 0x10000UL - (unsigned long)FP_OFF(p); + if (cando > rem) cando = rem; + if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */ + + if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err; + if (read != (unsigned)cando) goto err; + + rem -= cando; + if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL) + p = MK_FP(FP_SEG(p)+0x1000,0); + else + p += (unsigned)cando; + } + + cando = farptr2phys(p); + midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF); + } +#else + midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz; + if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err; +#endif + tracki++; + } + else { + fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]); + goto err; + } + } + if (tracki == 0 || ticks_per_quarter_note == 0) goto err; + midi_trk_count = tracki; + + fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note); + + close(fd); + return 1; +err: + close(fd); + return 0; +} diff --git a/src/lib/midi.h b/src/lib/midi.h index ac740c80..356255d2 100755 --- a/src/lib/midi.h +++ b/src/lib/midi.h @@ -1,83 +1,83 @@ -/* midi.h - * - * Adlib OPL2/OPL3 FM synthesizer chipset test program. - * Play MIDI file using the OPLx synthesizer (well, poorly anyway) - * (C) 2010-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - * - * Compiles for intended target environments: - * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] - */ - +/* midi.h + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + #ifndef __MIDI__ -#define __MIDI__ - -#include -#include /* this is where Open Watcom hides the outp() etc. functions */ -#include -#include -#include -#include -#include -#include -#include -#include - -//#include "src/lib/doslib/vga.h" -#include "src/lib/doslib/dos.h" -#include "src/lib/16_head.h" -#include "src/lib/doslib/8254.h" /* 8254 timer */ -#include "src/lib/doslib/8259.h" -//#include "src/lib/doslib/vgagui.h" -//#include "src/lib/doslib/vgatty.h" -#include "src/lib/doslib/adlib.h" - -/* one per OPL channel */ -struct midi_note { - unsigned char note_number; - unsigned char note_velocity; - unsigned char note_track; /* from what MIDI track */ - unsigned char note_channel; /* from what MIDI channel */ - unsigned int busy:1; /* if occupied */ -}; - -struct midi_channel { - unsigned char program; -}; - -struct midi_track { - /* track data, raw */ - unsigned char* raw; /* raw data base */ - unsigned char* fence; /* raw data end (last byte + 1) */ - unsigned char* read; /* raw data read ptr */ - /* state */ - unsigned long us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */ - unsigned long us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */ - unsigned long wait; - unsigned char last_status; /* MIDI last status byte */ - unsigned int eof:1; /* we hit the end of the track */ -}; - -#define MIDI_MAX_CHANNELS 16 -#define MIDI_MAX_TRACKS 64 - -extern struct midi_note midi_notes[ADLIB_FM_VOICES]; -extern struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; -extern struct midi_track midi_trk[MIDI_MAX_TRACKS]; - -static void (interrupt *old_irq0)(); -static volatile unsigned long irq0_ticks=0; -static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; -static volatile unsigned char midi_playing=0; - -int load_midi_file(const char *path); -void interrupt irq0(); -void adlib_shut_up(); -void midi_reset_tracks(); -void midi_reset_channels(); -void midi_tick(); - -#endif /* __MIDI__ */ +#define __MIDI__ + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "src/lib/doslib/vga.h" +#include "src/lib/doslib/dos.h" +#include "src/lib/16_head.h" +#include "src/lib/doslib/8254.h" /* 8254 timer */ +#include "src/lib/doslib/8259.h" +//#include "src/lib/doslib/vgagui.h" +//#include "src/lib/doslib/vgatty.h" +#include "src/lib/doslib/adlib.h" + +/* one per OPL channel */ +struct midi_note { + unsigned char note_number; + unsigned char note_velocity; + unsigned char note_track; /* from what MIDI track */ + unsigned char note_channel; /* from what MIDI channel */ + unsigned int busy:1; /* if occupied */ +}; + +struct midi_channel { + unsigned char program; +}; + +struct midi_track { + /* track data, raw */ + unsigned char* raw; /* raw data base */ + unsigned char* fence; /* raw data end (last byte + 1) */ + unsigned char* read; /* raw data read ptr */ + /* state */ + unsigned long us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */ + unsigned long us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */ + unsigned long wait; + unsigned char last_status; /* MIDI last status byte */ + unsigned int eof:1; /* we hit the end of the track */ +}; + +#define MIDI_MAX_CHANNELS 16 +#define MIDI_MAX_TRACKS 64 + +extern struct midi_note midi_notes[ADLIB_FM_VOICES]; +extern struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; +extern struct midi_track midi_trk[MIDI_MAX_TRACKS]; + +static void (interrupt *old_irq0)(); +static volatile unsigned long irq0_ticks=0; +static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; +static volatile unsigned char midi_playing=0; + +int load_midi_file(const char *path); +void interrupt irq0(); +void adlib_shut_up(); +void midi_reset_tracks(); +void midi_reset_channels(); +void midi_tick(); + +#endif /* __MIDI__ */ diff --git a/src/lib/modex16.h b/src/lib/modex16.h index 23202f2d..3467a77d 100755 --- a/src/lib/modex16.h +++ b/src/lib/modex16.h @@ -1,192 +1,192 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* - * Functions for handling modex and doing other basic graphics stuff. - */ -#ifndef MODEX16_H -#define MODEX16_H - -#include "src/lib/16_head.h" -#include "src/lib/bitmap.h" -//#include "src/lib/planar.h" -//#include "src/lib/modex16/16planar.h" -#include "src/lib/16text.h" -#include "src/lib/16render.h" -////#include "src/lib/modex16/320x240.h" -// #include "src/lib/modex16/320x200.h" -// #include "src/lib/modex16/256x192.h" -// #include "src/lib/modex16/192x144_.h" -// #include "src/lib/modex16/160x120.h" - -#ifdef __WATCOMC__ -#include -#include -#include -#include -#include -#endif - -static struct pcxHeader { - byte id; - byte version; - byte encoding; - byte bpp; - word xmin; - word ymin; - word xmax; - word ymax; - word hres; - word vres; - byte pal16[48]; - byte res1; - word bpplane; - word palType; - word hScreenSize; - word vScreenSize; - byte padding[54]; -} head; - -//320x240 = 20x15 -//192x144 = 12x9 - -//temp defines -#define TILEWH 16 -#define TILEWHD TILEWH*2 -#define QUADWH TILEWH/2 - -/* -========================== Types & Macros ==========================- */ -#define PAGE_OFFSET(x,y) (((y)<<6)+((y)<<4)+((x)>>2)) -#define PLANE(x) (1 << ((x) & 3)) -#define SELECT_ALL_PLANES() outpw(0x03c4, 0xff02) -#define PALSIZE 768 - -typedef union -{ - byte red; - byte green; - byte blue; -} rgb_t; - -/* -======================= Constants & Vars ==========================- */ -extern byte far* VGA; /* The VGA Memory */ -#define SCREEN_SEG 0xa000 -#define VIDEO_INT 0x10 -#define SET_MODE 0x00 -#define VGA_256_COLOR_MODE 0x13 -#define TEXT_MODE 0x03 - -#define AC_INDEX 0x03c0 -#define SC_INDEX 0x03c4 -#define SC_DATA 0x03c5 -#define CRTC_INDEX 0x03d4 -#define CRTC_DATA 0x03d5 -#define GC_INDEX 0x03ce -#define MISC_OUTPUT 0x03c2 -#define HIGH_ADDRESS 0x0C -#define LOW_ADDRESS 0x0D -#define VRETRACE 0x08 -//#define INPUT_STATUS_1 0x03da defined in 16_head -#define DISPLAY_ENABLE 0x01 -#define MAP_MASK 0x02 -#define PAL_READ_REG 0x03C7 /* Color register, read address */ -#define PAL_WRITE_REG 0x03C8 /* Color register, write address */ -#define PAL_DATA_REG 0x03C9 /* Color register, data port */ -#define PAL_SIZE (256 * 3) - -/* -============================ Functions =============================- */ -/* mode switching, page, and plane functions */ -void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv); -void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv); -byte vgaGetMode(); -void modexLeave(); -void modexsetBaseXMode(); -page_t modexDefaultPage(page_t *p); -page_t modexNextPage(page_t *p); -page_t modexNextPageFlexibleSize(page_t *p, word x, word y); -void modexCalcVmemRemain(video_t *video); -void modexHiganbanaPageSetup(video_t *video); -void modexShowPage(page_t *page); -void modexPanPage(page_t *page, int dx, int dy); -void modexSelectPlane(byte plane); -void modexClearRegion(page_t *page, int x, int y, int w, int h, byte color); -/* moved to src/lib/modex16/16render.c */ -void modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height); - -/* Palette fade and flash effects */ -void modexFadeOn(word fade, byte *palette); -void modexFadeOff(word fade, byte *palette); -void modexFlashOn(word fade, byte *palette); -void modexFlashOff(word fade, byte *palette); - -/* palette loading and saving */ -void modexPalSave(byte *palette); -byte *modexNewPal(); -void modexLoadPalFile(char *filename, byte **palette); -void modexSavePalFile(char *filename, byte *palette); - -/* fixed palette functions */ -void modexPalBlack(); -void modexPalWhite(); - -/* utility functions */ -void modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset); -void modexPalUpdate1(byte *p); -void modexPalUpdate0(byte *p); -void modexPalOverscan(word col); -void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/); -void modexputPixel(page_t *page, int x, int y, byte color); -byte modexgetPixel(page_t *page, int x, int y); - -#if 0 // not needed anymore. maybe good for reference purposes though. -static inline void modexwritepixel(page_t *page, int x, int y, word addr, byte color) -{ - /* Each address accesses four neighboring pixels, so set - Write Plane Enable according to which pixel we want - to modify. The plane is determined by the two least - significant bits of the x-coordinate: */ - modexSelectPlane(PLANE(x)); - //outp(SC_INDEX, 0x02); - //outp(SC_DATA, 0x01 << (x & 3)); - - /* The offset of the pixel into the video segment is - offset = (width * y + x) / 4, and write the given - color to the plane we selected above. Heed the active - page start selection. */ - vga_state.vga_graphics_ram[addr] = color; -} -static inline byte modexreadPixel(page_t *page, int x, int y, word addr) -{ - /* Select the plane from which we must read the pixel color: */ - outpw(GC_INDEX, 0x04); - outpw(GC_INDEX+1, x & 3); - return vga_state.vga_graphics_ram[addr]; -} -#endif - -void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str); -void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str); -void modexpdump(page_t *pee); -void modexcls(page_t *page, byte color, byte *Where); -void modexWaitBorder(); -void modexprintmeminfo(video_t *v); - -#endif +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + * Functions for handling modex and doing other basic graphics stuff. + */ +#ifndef MODEX16_H +#define MODEX16_H + +#include "src/lib/16_head.h" +#include "src/lib/bitmap.h" +//#include "src/lib/planar.h" +//#include "src/lib/modex16/16planar.h" +#include "src/lib/16text.h" +#include "src/lib/16render.h" +////#include "src/lib/modex16/320x240.h" +// #include "src/lib/modex16/320x200.h" +// #include "src/lib/modex16/256x192.h" +// #include "src/lib/modex16/192x144_.h" +// #include "src/lib/modex16/160x120.h" + +#ifdef __WATCOMC__ +#include +#include +#include +#include +#include +#endif + +static struct pcxHeader { + byte id; + byte version; + byte encoding; + byte bpp; + word xmin; + word ymin; + word xmax; + word ymax; + word hres; + word vres; + byte pal16[48]; + byte res1; + word bpplane; + word palType; + word hScreenSize; + word vScreenSize; + byte padding[54]; +} head; + +//320x240 = 20x15 +//192x144 = 12x9 + +//temp defines +#define TILEWH 16 +#define TILEWHD TILEWH*2 +#define QUADWH TILEWH/2 + +/* -========================== Types & Macros ==========================- */ +#define PAGE_OFFSET(x,y) (((y)<<6)+((y)<<4)+((x)>>2)) +#define PLANE(x) (1 << ((x) & 3)) +#define SELECT_ALL_PLANES() outpw(0x03c4, 0xff02) +#define PALSIZE 768 + +typedef union +{ + byte red; + byte green; + byte blue; +} rgb_t; + +/* -======================= Constants & Vars ==========================- */ +extern byte far* VGA; /* The VGA Memory */ +#define SCREEN_SEG 0xa000 +#define VIDEO_INT 0x10 +#define SET_MODE 0x00 +#define VGA_256_COLOR_MODE 0x13 +#define TEXT_MODE 0x03 + +#define AC_INDEX 0x03c0 +#define SC_INDEX 0x03c4 +#define SC_DATA 0x03c5 +#define CRTC_INDEX 0x03d4 +#define CRTC_DATA 0x03d5 +#define GC_INDEX 0x03ce +#define MISC_OUTPUT 0x03c2 +#define HIGH_ADDRESS 0x0C +#define LOW_ADDRESS 0x0D +#define VRETRACE 0x08 +//#define INPUT_STATUS_1 0x03da defined in 16_head +#define DISPLAY_ENABLE 0x01 +#define MAP_MASK 0x02 +#define PAL_READ_REG 0x03C7 /* Color register, read address */ +#define PAL_WRITE_REG 0x03C8 /* Color register, write address */ +#define PAL_DATA_REG 0x03C9 /* Color register, data port */ +#define PAL_SIZE (256 * 3) + +/* -============================ Functions =============================- */ +/* mode switching, page, and plane functions */ +void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv); +void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv); +byte vgaGetMode(); +void modexLeave(); +void modexsetBaseXMode(); +page_t modexDefaultPage(page_t *p); +page_t modexNextPage(page_t *p); +page_t modexNextPageFlexibleSize(page_t *p, word x, word y); +void modexCalcVmemRemain(video_t *video); +void modexHiganbanaPageSetup(video_t *video); +void modexShowPage(page_t *page); +void modexPanPage(page_t *page, int dx, int dy); +void modexSelectPlane(byte plane); +void modexClearRegion(page_t *page, int x, int y, int w, int h, byte color); +/* moved to src/lib/modex16/16render.c */ +void modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height); + +/* Palette fade and flash effects */ +void modexFadeOn(word fade, byte *palette); +void modexFadeOff(word fade, byte *palette); +void modexFlashOn(word fade, byte *palette); +void modexFlashOff(word fade, byte *palette); + +/* palette loading and saving */ +void modexPalSave(byte *palette); +byte *modexNewPal(); +void modexLoadPalFile(char *filename, byte **palette); +void modexSavePalFile(char *filename, byte *palette); + +/* fixed palette functions */ +void modexPalBlack(); +void modexPalWhite(); + +/* utility functions */ +void modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset); +void modexPalUpdate1(byte *p); +void modexPalUpdate0(byte *p); +void modexPalOverscan(word col); +void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/); +void modexputPixel(page_t *page, int x, int y, byte color); +byte modexgetPixel(page_t *page, int x, int y); + +#if 0 // not needed anymore. maybe good for reference purposes though. +static inline void modexwritepixel(page_t *page, int x, int y, word addr, byte color) +{ + /* Each address accesses four neighboring pixels, so set + Write Plane Enable according to which pixel we want + to modify. The plane is determined by the two least + significant bits of the x-coordinate: */ + modexSelectPlane(PLANE(x)); + //outp(SC_INDEX, 0x02); + //outp(SC_DATA, 0x01 << (x & 3)); + + /* The offset of the pixel into the video segment is + offset = (width * y + x) / 4, and write the given + color to the plane we selected above. Heed the active + page start selection. */ + vga_state.vga_graphics_ram[addr] = color; +} +static inline byte modexreadPixel(page_t *page, int x, int y, word addr) +{ + /* Select the plane from which we must read the pixel color: */ + outpw(GC_INDEX, 0x04); + outpw(GC_INDEX+1, x & 3); + return vga_state.vga_graphics_ram[addr]; +} +#endif + +void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str); +void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str); +void modexpdump(page_t *pee); +void modexcls(page_t *page, byte color, byte *Where); +void modexWaitBorder(); +void modexprintmeminfo(video_t *v); + +#endif diff --git a/src/lib/scroll16.c b/src/lib/scroll16.c index eca613a8..b94e768a 100755 --- a/src/lib/scroll16.c +++ b/src/lib/scroll16.c @@ -1,916 +1,916 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* - scroll16 library~ -*/ -#include "src/lib/scroll16.h" - -void walk(map_view_t *pip, player_t *player, word pn) -{ - #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1; - //printf("player[%d].d=%d\n", pn, player[pn].d); - switch(player[pn].d) - { - //no direction - case 2: - //0000pip[0].video->startclk = (*clockw); - break; - //right movement - case 3: - //printf("pip[0].page->tilesw=%d ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw); - if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && - !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollRight(pip, player, 3, pn); - ScrollRight(pip, player, 2, pn); - mapScrollRight(pip, player, !(pip[0].video->p), pn); - mapScrollRight(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } - } - else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].x+=(player[pn].speed); - animatePlayer(pip, player, pn, 0); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); -#ifdef SPRITE - PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 24, 32, PLAYERBMPDATA); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 14); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx+1; - player[pn].triggery = player[pn].ty; - break; - - //left movement - case 1: - if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && - !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollLeft(pip, player, 3, pn); - ScrollLeft(pip, player, 2, pn); - mapScrollLeft(pip, player, !(pip[0].video->p), pn); - mapScrollLeft(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } - } - else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].x-=(player[pn].speed); - animatePlayer(pip, player, pn, 0); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); -#ifdef SPRITE - PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 96, 24, 32, PLAYERBMPDATA); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 10); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx-1; - player[pn].triggery = player[pn].ty; - break; - - //down movement - case 4: - if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && - !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollDown(pip, player, 3, pn); - ScrollDown(pip, player, 2, pn); - mapScrollDown(pip, player, !(pip[0].video->p), pn); - mapScrollDown(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } - } - else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].y+=(player[pn].speed); - animatePlayer(pip, player, pn, 0); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); -#ifdef SPRITE - PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 64, 24, 32, PLAYERBMPDATA); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 9); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx; - player[pn].triggery = player[pn].ty+1; - break; - - //up movement - case 0: - if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && - !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) //collision detection! - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - animatePlayer(pip, player, pn, 1); - ScrollUp(pip, player, 3, pn); - ScrollUp(pip, player, 2, pn); - mapScrollUp(pip, player, !(pip[0].video->p), pn); - mapScrollUp(pip, player, (pip[0].video->p), pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } - } - else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) - { - if(player[pn].q<=player[pn].spt) - { - INC_PER_FRAME; - player[pn].y-=(player[pn].speed); - animatePlayer(pip, player, 0, pn); - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } - } - else - { - if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); -#ifdef SPRITE - PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 0, 24, 32, PLAYERBMPDATA); -#else - modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 12); -#endif - if(!pageflipflop) modexShowPage(pip[1].page); - player[pn].d = 2; - } - player[pn].triggerx = player[pn].tx; - player[pn].triggery = player[pn].ty-1; - break; - } -} - -//panning page -void panpagemanual(map_view_t *pip, player_t *player, word pn) -{ - switch(player[pn].d) - { - //right movement - case 3: - if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dx+=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; } - } - break; - - //left movement - case 1: - if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dx-=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; } - } - break; - - //down movement - case 4: - if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dy+=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; } - } - break; - - //up movement - case 0: - if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh) - { - if(player[pn].q<=player[pn].spt) - { - pip[pip[0].pan->pn].page->dy-=4; - modexShowPage(pip[pip[0].pan->pn].page); - player[pn].q++; - } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; } - } - break; - } - //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q); -} - -/*map_t -allocMap(int w, int h) { - map_t result; - - result.width =w; - result.height=h; - result.data = malloc(sizeof(byte) * w * h); - //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024); - if(isEMS() || checkEMS()) - { - XMOVE mm; - //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map)) - mm.length=sizeof(result); - mm.sourceH=0; - mm.sourceOff=ptr2long(&result); - mm.destH=emmhandle; - mm.destOff=0; - ist = move_emem(&mm); - if(!ist){ dealloc_emem(emmhandle); exit(5); } - printf("%d\n", coretotalEMS()); - } - - return result; -}*/ - -/*void -initMap(map_t *map) { - // just a place holder to fill out an alternating pattern - int x, y, xx, yy; - int i, q; -// int tile = 1; - //if(!isEMS() || !checkEMS()) -// map->tiles = malloc(sizeof(tiles_t)); - //else - // map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t)); - - //create the tile set - //if(!isEMS() || !checkEMS()) -// map->tiles->data = malloc(sizeof(bitmap_t)); - //else - // map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t)); -// map->tiles->data->width = (TILEWH); -// map->tiles->data->height= TILEWH; - //if(!isEMS() || !checkEMS()) -// map->tiles->data->data = malloc((TILEWH*2)*TILEWH); - //else - // map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH); -// map->tiles->tileHeight = TILEWH; -// map->tiles->tileWidth =TILEWH; -// map->tiles->rows = 1; -// map->tiles->cols = 1;//2; - - q=0; - //for(y=0; yheight; y++) { - //for(x=0; xwidth; x++) { - i=0; - for(yy=0; yytiles->data->data[i+1] = map->data[q];//28;//0x24; -// printf("[%d]", map->tiles->data->data[i]); - //}else{ - //map->tiles->data->data[i] = map->data[q];//0;//0x34; - //printf("]%d[==[%d]", i, map->tiles->data->data[i]); - //} - i++; - } -// printf("\n"); - } -// printf("[%d]", map->data[q]); - q++; -// } - //printf("\n\n"); -// } - - i=0; - for(y=0; yheight; y++) { - for(x=0; xwidth; x++) { -// map->data[i]=255; - printf("[%d]", map->data[i]); - //tile = tile ? 0 : 1; - i++; - } - //tile = tile ? 0 : 1; - } -}*/ - -void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* increment the pixel position and update the page */ - mv[id].page->dx += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx >= mv[id].dxThresh ) - { - /* go forward one tile */ - mv[id].tx++; - /* Snap the origin forward */ - mv[id].page->data += 4; - - mv[id].page->dx = mv[id].map->tiles->tileWidth; - } - - /* draw the next column */ - x= mv[0].page->sw + mv[id].map->tiles->tileWidth; - if(player[plid].q%4) - if(id==0) - mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); - mv[0].video->r=1; -} - - -void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* decrement the pixel position and update the page */ - mv[id].page->dx -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx == 0) - { - /* go backward one tile */ - mv[id].tx--; - /* Snap the origin backward */ - mv[id].page->data -= 4; - - mv[id].page->dx = mv[id].map->tiles->tileWidth; - } - - /* draw the next column */ - x= 0; - if(player[plid].q%4) - if(id==0) - mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); - mv[0].video->r=1; -} - - -void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* decrement the pixel position and update the page */ - mv[id].page->dy -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy == 0 ) - { - /* go down one tile */ - mv[id].ty--; - /* Snap the origin downward */ - mv[id].page->data -= mv[id].page->pi; - - mv[id].page->dy = mv[id].map->tiles->tileHeight; - } - - /* draw the next row */ - y= 0; - if(player[plid].q%3) - if(id==0) - mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); - mv[0].video->r=1; -} - -void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid) -{ - word x, y; /* coordinate for drawing */ - - /* increment the pixel position and update the page */ - mv[id].page->dy += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy >= mv[id].dyThresh ) - { - /* go down one tile */ - mv[id].ty++; - /* Snap the origin downward */ - mv[id].page->data += mv[id].page->pi; - - mv[id].page->dy = mv[id].map->tiles->tileHeight; - } - - /* draw the next row */ - y= mv[0].page->sh + mv[id].map->tiles->tileHeight; - if(player[plid].q%3) - if(id==0) - mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy); - else - if(!pageflipflop && !pageploop) - modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); - mv[0].video->r=1; -} - - -//TODO finish this wwww -void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid) -{ - /* increment the pixel position and update the page */ - mv[id].page->dx += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx >= mv[0].dxThresh ) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin forward */ - mv[id].page->data += 4; - mv[id].page->dx = mv[0].map->tiles->tileWidth; - } -} - -void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid) -{ - /* decrement the pixel position and update the page */ - mv[id].page->dx -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dx == 0) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin backward */ - mv[id].page->data -= 4; - mv[id].page->dx = mv[0].map->tiles->tileWidth; - } -} - -void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid) -{ - /* decrement the pixel position and update the page */ - mv[id].page->dy -= player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy == 0) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin backward */ - mv[id].page->data -= mv[id].page->pi; - mv[id].page->dy = mv[0].map->tiles->tileWidth; - } -} - -void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid) -{ - /* increment the pixel position and update the page */ - mv[id].page->dy += player[plid].speed; - - /* check to see if this changes the tile */ - if(mv[id].page->dy >= mv[0].dxThresh ) - { -// vga_setup_wm1_block_copy(); -// _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); -// vga_restore_rm0wm0(); - /* Snap the origin forward */ - mv[id].page->data += mv[id].page->pi; - mv[id].page->dy = mv[0].map->tiles->tileWidth; - } -} - -sword chkmap(map_t *map, word q) -{ -// bitmap_t bp; - static byte x[(MAPW*MAPH)+1] = -{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 }; -/*1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, \ -5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, \ -0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4 };*/ - //check for failed to load map - if((map->width == map->height == 0) && (q>0)) - { - //initiate a null map! - map->width=MAPW;///2; - map->height=MAPH;///2; -// map->data = malloc(((map->width*map->height)+1)*sizeof(byte)); - map->data = &x; - map->tiles = malloc(sizeof(tiles_t)); - //fix this to be far~ -// bp = bitmapLoadPcx("data/ed.pcx"); -// map->tiles->data = &bp; - map->tiles->debug_data = map->data; - map->tiles->tileHeight = 16; - map->tiles->tileWidth = 16; - map->tiles->rows = 1; - map->tiles->cols = 1; - map->tiles->debug_text = true; - } - else map->tiles->debug_text = false; - return 0; -} - -//TODO: player position here -void mapGoTo(map_view_t *mv, int tx, int ty) -{ - int px, py; - unsigned int i; - - /* set up the coordinates */ - mv[0].tx = mv[1].tx = tx; - mv[0].ty = mv[1].ty = ty; - mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth; - mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight; - - /* set up the thresholds */ - mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2; - mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2; - - /* draw the tiles */ - modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0); - py=0; - i=mv[0].ty * mv[0].map->width + mv[0].tx; - for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) { - mapDrawWRow(&mv[0], tx-1, ty, py); - i+=mv->map->width - tx; - } - if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height); -// { -// unsigned int k,j,o; -// /* fill screen with a distinctive pattern */ -// for (k=0;k < vga_state.vga_width;k++) { -// o = k >> 2; -// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); -// for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride) -// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! -// } -// } - modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 24, 32); -} - -void near -mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) -{ - word rx; - word ry; - word textx=0; - word texty=0; - //if(i==0) i=2; - if(i==0) - { - //wwww - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color! - } - else - { - rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth); - ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight); -////0000printf("i=%d\n", i); - switch(t->debug_text) - { - case 0: -#ifndef TILERENDER - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1)); - //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i])); -#else - PBUFBFUN (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); - /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ - //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - //modexDrawBmpRegion (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); -#endif - break; - case 1: - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1); - //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data)); - /*for(texty=0; texty<2; texty++) - { - for(textx=0; textx<2; textx++) - {*/ -// modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data)); -/* } - }*/ - break; - } - } -} - -void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset) -{ - word x; - int i; - poopoffset%=p[0].speed; -//printf("y: %d\n", poopoffset); - /* the position within the map array */ - i=ty * mv->map->width + tx; - for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { - if(i>=0) { - /* we are in the map, so copy! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i++; /* next! */ - } -} - -void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset) -{ - int y; - int i; - poopoffset%=p[0].speed; -//printf("x: %d\n", poopoffset); - /* location in the map array */ - i=ty * mv->map->width + tx; - - /* We'll copy all of the columns in the screen, - i + 1 row above and one below */ - for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { - if(i>=0) { - /* we are in the map, so copy away! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i += mv->map->width; - } -} - -void mapDrawWRow(map_view_t *mv, int tx, int ty, word y) -{ - word x; - int i; - - /* the position within the map array */ - i=ty * mv->map->width + tx; - for(x=0; xpage->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { - if(i>=0) { - /* we are in the map, so copy! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i++; /* next! */ - } -} - -void mapDrawWCol(map_view_t *mv, int tx, int ty, word x) -{ - int y; - int i; - - /* location in the map array */ - i=ty * mv->map->width + tx; - - /* We'll copy all of the columns in the screen, - i + 1 row above and one below */ - for(y=0; ypage->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { - if(i>=0) { - /* we are in the map, so copy away! */ - mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); - } - i += mv->map->width; - } -} - -/*void qclean() -{ - //setkb(0); -}*/ - -unsigned char shinku_fps_indicator_page = 2; -boolean pageflipflop = 1; -boolean pageploop = 1; - -/* sync */ -void shinku(global_game_variables_t *gv) -{ - word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen - word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen - word w = 64, h = 8, col = 7, bgcol = 0, type = 1; - byte o,o2,i; - //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4); - /* block copy to visible RAM from offscreen */ -// vga_setup_wm1_block_copy(); -// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h); -// o = *(gv->video.page[2].data); // source offscreen -// o2 = *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) -// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ -// vga_restore_rm0wm0(); - if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second)) - { - sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv)); - //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45); - modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee); - gv->kurokku.tiku=0; - /* block copy to visible RAM from offscreen */ -// vga_setup_wm1_block_copy(); -// o = *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen -// o2 = *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) -// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); -// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ -// vga_restore_rm0wm0(); - }else //copy dat sheet - gv->kurokku.tiku++; - - switch(gv->kurokku.fpscap) - { - case 0: - //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!"); - gv->kurokku.frames_per_second=1; - break; - case 1: - //turn this off if XT - //modexWaitBorder(); - vga_wait_for_vsync(); - gv->kurokku.frames_per_second=60; - break; - } - if(pageflipflop){ - if(gv->video.r){ - //vga_setup_wm1_block_copy(); - //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize); - //vga_restore_rm0wm0(); - if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height); - modexShowPage(&(gv->video.page[gv->video.p])); - if(!pageploop) gv->video.p=!gv->video.p; - gv->video.r=!gv->video.r; - //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2; - } - } -} - -void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch) -{ - sword x = player[pn].x; - sword y = player[pn].y; - sword bx = x+16; //buffer's x - sword by = y+16; //buffer's y - word dire=32; //direction - sword qq; //scroll offset - word ls = player[pn].persist_aniframe; - - switch(scrollswitch) - { - case 0: - qq = 0; - break; - default: - qq = ((player[pn].q)*(player[pn].speed)); - break; - } - //x-=4; - y-=pip[0].map->tiles->tileHeight; - switch (player[pn].d) - { - case 0: - //up - dire*=player[pn].d; - y-=qq; - by-=4; - break; - case 3: - // right - dire*=(player[pn].d-2); - x+=qq; - bx+=4; - break; - case 2: - break; - case 4: - //down - dire*=(player[pn].d-2); - y+=qq; - by+=4; - break; - case 1: - //left - dire*=(player[pn].d+2); - x-=qq; - bx-=4; - break; - } - -#ifdef SPRITE -#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32, PLAYERBMPDATA); -#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); -#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA); -#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); -#else -#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire); -#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); -#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire); -#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); -#endif - if(!pageflipflop) - modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36); - else{ - //copy old bg to page0 - //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0, 20, 36); - //update buffer - //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 20, 36); - } -//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height); - //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36); - /*modexCopyPageRegion(pip[pip->video->p].page, - pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/ -// else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40); - switch(ls) - { - case 1: - FRAME1 - break; - case 2: - FRAME2 - break; - case 3: - FRAME3 - break; - case 4: - FRAME4 - break; - } -// if(2>ls && ls>=1) { FRAME1 }else -// if(3>ls && ls>=2) { FRAME2 }else -// if(4>ls && ls>=3) { FRAME3 }else -// if(5>ls && ls>=4) { FRAME4 } - //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 24, 32); - //printf("x=%d y=%d bx=%d by=%d\n", x, y, bx, by); - pip->video->r=1; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + scroll16 library~ +*/ +#include "src/lib/scroll16.h" + +void walk(map_view_t *pip, player_t *player, word pn) +{ + #define INC_PER_FRAME if(player[pn].q&1) player[pn].persist_aniframe++; if(player[pn].persist_aniframe>4) player[pn].persist_aniframe = 1; + //printf("player[%d].d=%d\n", pn, player[pn].d); + switch(player[pn].d) + { + //no direction + case 2: + //0000pip[0].video->startclk = (*clockw); + break; + //right movement + case 3: + //printf("pip[0].page->tilesw=%d ", pip[0].page->tilesw); printf("pip[0].page->tw=%d\n", pip[0].page->tw); + if(pip[0].tx >= 0 && pip[0].tx+pip[0].page->tw < pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && + !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollRight(pip, player, 3, pn); + ScrollRight(pip, player, 2, pn); + mapScrollRight(pip, player, !(pip[0].video->p), pn); + mapScrollRight(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } + } + else if(player[pn].tx < pip[0].map->width && !(pip[0].map->data[(player[pn].tx)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx+1 == TRIGGX && player[pn].ty == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].x+=(player[pn].speed); + animatePlayer(pip, player, pn, 0); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx++; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); +#ifdef SPRITE + PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 24, 32, PLAYERBMPDATA); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 14); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx+1; + player[pn].triggery = player[pn].ty; + break; + + //left movement + case 1: + if(pip[0].tx > 0 && pip[0].tx+pip[0].page->tw <= pip[0].map->width && player[pn].tx == pip[0].tx+pip[0].page->tilemidposscreenx && + !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollLeft(pip, player, 3, pn); + ScrollLeft(pip, player, 2, pn); + mapScrollLeft(pip, player, !(pip[0].video->p), pn); + mapScrollLeft(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } + } + else if(player[pn].tx > 1 && !(pip[0].map->data[(player[pn].tx-2)+(pip[0].map->width*(player[pn].ty-1))] == 0))//!(player[pn].tx-1 == TRIGGX && player[pn].ty == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].x-=(player[pn].speed); + animatePlayer(pip, player, pn, 0); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].tx--; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); +#ifdef SPRITE + PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 96, 24, 32, PLAYERBMPDATA); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 10); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx-1; + player[pn].triggery = player[pn].ty; + break; + + //down movement + case 4: + if(pip[0].ty >= 0 && pip[0].ty+pip[0].page->th < pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && + !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollDown(pip, player, 3, pn); + ScrollDown(pip, player, 2, pn); + mapScrollDown(pip, player, !(pip[0].video->p), pn); + mapScrollDown(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } + } + else if(player[pn].ty < pip[0].map->height && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty+1 == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].y+=(player[pn].speed); + animatePlayer(pip, player, pn, 0); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty++; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); +#ifdef SPRITE + PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 64, 24, 32, PLAYERBMPDATA); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 9); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx; + player[pn].triggery = player[pn].ty+1; + break; + + //up movement + case 0: + if(pip[0].ty > 0 && pip[0].ty+pip[0].page->th <= pip[0].map->height && player[pn].ty == pip[0].ty+pip[0].page->tilemidposscreeny && + !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) //collision detection! + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + animatePlayer(pip, player, pn, 1); + ScrollUp(pip, player, 3, pn); + ScrollUp(pip, player, 2, pn); + mapScrollUp(pip, player, !(pip[0].video->p), pn); + mapScrollUp(pip, player, (pip[0].video->p), pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + //0000pip[0].video->clk = ((*clockw)-pip[0].video->startclk)/18.2; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } + } + else if(player[pn].ty > 1 && !(pip[0].map->data[(player[pn].tx-1)+(pip[0].map->width*(player[pn].ty-2))] == 0))//!(player[pn].tx == TRIGGX && player[pn].ty-1 == TRIGGY)) + { + if(player[pn].q<=player[pn].spt) + { + INC_PER_FRAME; + player[pn].y-=(player[pn].speed); + animatePlayer(pip, player, 0, pn); + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; player[pn].ty--; } + } + else + { + if(!pageflipflop) modexCopyPageRegion(pip[1].page, pip[0].page, player[pn].x, player[pn].y-TILEWH, player[pn].x, player[pn].y-TILEWH, 24, 32); +#ifdef SPRITE + PBUFSFUN(pip[0].page, player[pn].x, player[pn].y-TILEWH, 24, 0, 24, 32, PLAYERBMPDATA); +#else + modexClearRegion(pip[1].page, player[pn].x, player[pn].y-TILEWH, 24, 32, 12); +#endif + if(!pageflipflop) modexShowPage(pip[1].page); + player[pn].d = 2; + } + player[pn].triggerx = player[pn].tx; + player[pn].triggery = player[pn].ty-1; + break; + } +} + +//panning page +void panpagemanual(map_view_t *pip, player_t *player, word pn) +{ + switch(player[pn].d) + { + //right movement + case 3: + if(pip[pip[0].pan->pn].tx >= 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw < pip[pip[0].pan->pn].page->tilesw) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dx+=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx++; } + } + break; + + //left movement + case 1: + if(pip[pip[0].pan->pn].tx > 0 && pip[pip[0].pan->pn].tx+pip[pip[0].pan->pn].page->tw <= pip[pip[0].pan->pn].page->tilesw) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dx-=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].tx--; } + } + break; + + //down movement + case 4: + if(pip[pip[0].pan->pn].ty >= 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th < pip[pip[0].pan->pn].page->tilesh) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dy+=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty++; } + } + break; + + //up movement + case 0: + if(pip[pip[0].pan->pn].ty > 0 && pip[pip[0].pan->pn].ty+pip[pip[0].pan->pn].page->th <= pip[pip[0].pan->pn].page->tilesh) + { + if(player[pn].q<=player[pn].spt) + { + pip[pip[0].pan->pn].page->dy-=4; + modexShowPage(pip[pip[0].pan->pn].page); + player[pn].q++; + } else { player[pn].q = 1; player[pn].d = 2; pip[pip[0].pan->pn].ty--; } + } + break; + } + //if (player[pn].d!=2) printf("player[%u].d=%u player[%u].q=%u\n", pn, player[pn].d, pn, player[pn].q); +} + +/*map_t +allocMap(int w, int h) { + map_t result; + + result.width =w; + result.height=h; + result.data = malloc(sizeof(byte) * w * h); + //result.data = (byte *)alloc_emem(((int)sizeof(byte) * w * h)/1024); + if(isEMS() || checkEMS()) + { + XMOVE mm; + //emmhandle = mallocEMS(coretotalEMS());//alloc_emem((int)sizeof(map)) + mm.length=sizeof(result); + mm.sourceH=0; + mm.sourceOff=ptr2long(&result); + mm.destH=emmhandle; + mm.destOff=0; + ist = move_emem(&mm); + if(!ist){ dealloc_emem(emmhandle); exit(5); } + printf("%d\n", coretotalEMS()); + } + + return result; +}*/ + +/*void +initMap(map_t *map) { + // just a place holder to fill out an alternating pattern + int x, y, xx, yy; + int i, q; +// int tile = 1; + //if(!isEMS() || !checkEMS()) +// map->tiles = malloc(sizeof(tiles_t)); + //else + // map->tiles = (tiles_t *)alloc_emem(sizeof(tiles_t)); + + //create the tile set + //if(!isEMS() || !checkEMS()) +// map->tiles->data = malloc(sizeof(bitmap_t)); + //else + // map->tiles->data = (bitmap_t *)alloc_emem(sizeof(bitmap_t)); +// map->tiles->data->width = (TILEWH); +// map->tiles->data->height= TILEWH; + //if(!isEMS() || !checkEMS()) +// map->tiles->data->data = malloc((TILEWH*2)*TILEWH); + //else + // map->tiles->data->data = (byte *)alloc_emem((TILEWH*2)*TILEWH); +// map->tiles->tileHeight = TILEWH; +// map->tiles->tileWidth =TILEWH; +// map->tiles->rows = 1; +// map->tiles->cols = 1;//2; + + q=0; + //for(y=0; yheight; y++) { + //for(x=0; xwidth; x++) { + i=0; + for(yy=0; yytiles->data->data[i+1] = map->data[q];//28;//0x24; +// printf("[%d]", map->tiles->data->data[i]); + //}else{ + //map->tiles->data->data[i] = map->data[q];//0;//0x34; + //printf("]%d[==[%d]", i, map->tiles->data->data[i]); + //} + i++; + } +// printf("\n"); + } +// printf("[%d]", map->data[q]); + q++; +// } + //printf("\n\n"); +// } + + i=0; + for(y=0; yheight; y++) { + for(x=0; xwidth; x++) { +// map->data[i]=255; + printf("[%d]", map->data[i]); + //tile = tile ? 0 : 1; + i++; + } + //tile = tile ? 0 : 1; + } +}*/ + +void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* increment the pixel position and update the page */ + mv[id].page->dx += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx >= mv[id].dxThresh ) + { + /* go forward one tile */ + mv[id].tx++; + /* Snap the origin forward */ + mv[id].page->data += 4; + + mv[id].page->dx = mv[id].map->tiles->tileWidth; + } + + /* draw the next column */ + x= mv[0].page->sw + mv[id].map->tiles->tileWidth; + if(player[plid].q%4) + if(id==0) + mapDrawCol(&mv[0], mv[0].tx + mv[0].page->tw, mv[0].ty-1, x, player, mv->page->dx); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); + mv[0].video->r=1; +} + + +void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* decrement the pixel position and update the page */ + mv[id].page->dx -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx == 0) + { + /* go backward one tile */ + mv[id].tx--; + /* Snap the origin backward */ + mv[id].page->data -= 4; + + mv[id].page->dx = mv[id].map->tiles->tileWidth; + } + + /* draw the next column */ + x= 0; + if(player[plid].q%4) + if(id==0) + mapDrawCol(&mv[0], mv[0].tx - 1, mv[0].ty-1, x, player, mv->page->dx); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, x, 0, x, 0, mv[id].map->tiles->tileWidth, mv[id].map->tiles->tileHeight*(mv[0].page->th+2)); + mv[0].video->r=1; +} + + +void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* decrement the pixel position and update the page */ + mv[id].page->dy -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy == 0 ) + { + /* go down one tile */ + mv[id].ty--; + /* Snap the origin downward */ + mv[id].page->data -= mv[id].page->pi; + + mv[id].page->dy = mv[id].map->tiles->tileHeight; + } + + /* draw the next row */ + y= 0; + if(player[plid].q%3) + if(id==0) + mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty-1, y, player, mv->page->dy); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); + mv[0].video->r=1; +} + +void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid) +{ + word x, y; /* coordinate for drawing */ + + /* increment the pixel position and update the page */ + mv[id].page->dy += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy >= mv[id].dyThresh ) + { + /* go down one tile */ + mv[id].ty++; + /* Snap the origin downward */ + mv[id].page->data += mv[id].page->pi; + + mv[id].page->dy = mv[id].map->tiles->tileHeight; + } + + /* draw the next row */ + y= mv[0].page->sh + mv[id].map->tiles->tileHeight; + if(player[plid].q%3) + if(id==0) + mapDrawRow(&mv[0], mv[0].tx - 1, mv[0].ty+mv[0].page->th, y, player, mv->page->dy); + else + if(!pageflipflop && !pageploop) + modexCopyPageRegion(mv[id].page, mv[0].page, 0, y, 0, y, mv[id].map->tiles->tileWidth*(mv[0].page->tw+2), mv[id].map->tiles->tileHeight); + mv[0].video->r=1; +} + + +//TODO finish this wwww +void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid) +{ + /* increment the pixel position and update the page */ + mv[id].page->dx += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx >= mv[0].dxThresh ) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data+4, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin forward */ + mv[id].page->data += 4; + mv[id].page->dx = mv[0].map->tiles->tileWidth; + } +} + +void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid) +{ + /* decrement the pixel position and update the page */ + mv[id].page->dx -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dx == 0) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data-4, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin backward */ + mv[id].page->data -= 4; + mv[id].page->dx = mv[0].map->tiles->tileWidth; + } +} + +void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid) +{ + /* decrement the pixel position and update the page */ + mv[id].page->dy -= player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy == 0) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data-mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin backward */ + mv[id].page->data -= mv[id].page->pi; + mv[id].page->dy = mv[0].map->tiles->tileWidth; + } +} + +void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid) +{ + /* increment the pixel position and update the page */ + mv[id].page->dy += player[plid].speed; + + /* check to see if this changes the tile */ + if(mv[id].page->dy >= mv[0].dxThresh ) + { +// vga_setup_wm1_block_copy(); +// _fmemmove(mv[id].page->data+mv[id].page->pi, mv[id].page->data, mv[id].page->pagesize); +// vga_restore_rm0wm0(); + /* Snap the origin forward */ + mv[id].page->data += mv[id].page->pi; + mv[id].page->dy = mv[0].map->tiles->tileWidth; + } +} + +sword chkmap(map_t *map, word q) +{ +// bitmap_t bp; + static byte x[(MAPW*MAPH)+1] = +{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 }; +/*1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, \ +5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, \ +0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4 };*/ + //check for failed to load map + if((map->width == map->height == 0) && (q>0)) + { + //initiate a null map! + map->width=MAPW;///2; + map->height=MAPH;///2; +// map->data = malloc(((map->width*map->height)+1)*sizeof(byte)); + map->data = &x; + map->tiles = malloc(sizeof(tiles_t)); + //fix this to be far~ +// bp = bitmapLoadPcx("data/ed.pcx"); +// map->tiles->data = &bp; + map->tiles->debug_data = map->data; + map->tiles->tileHeight = 16; + map->tiles->tileWidth = 16; + map->tiles->rows = 1; + map->tiles->cols = 1; + map->tiles->debug_text = true; + } + else map->tiles->debug_text = false; + return 0; +} + +//TODO: player position here +void mapGoTo(map_view_t *mv, int tx, int ty) +{ + int px, py; + unsigned int i; + + /* set up the coordinates */ + mv[0].tx = mv[1].tx = tx; + mv[0].ty = mv[1].ty = ty; + mv[0].page->dx = mv[1].page->dx = mv[2].page->dx = mv[3].page->dx = mv->map->tiles->tileWidth; + mv[0].page->dy = mv[1].page->dy = mv[2].page->dy = mv[3].page->dy = mv->map->tiles->tileHeight; + + /* set up the thresholds */ + mv[0].dxThresh = mv[1].dxThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileWidth * 2; + mv[0].dyThresh = mv[1].dyThresh = mv[2].dxThresh = mv[3].dxThresh = mv->map->tiles->tileHeight * 2; + + /* draw the tiles */ + modexClearRegion(mv[0].page, 0, 0, mv[0].page->width, mv[0].page->height, 0); + py=0; + i=mv[0].ty * mv[0].map->width + mv[0].tx; + for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) { + mapDrawWRow(&mv[0], tx-1, ty, py); + i+=mv->map->width - tx; + } + if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height); +// { +// unsigned int k,j,o; +// /* fill screen with a distinctive pattern */ +// for (k=0;k < vga_state.vga_width;k++) { +// o = k >> 2; +// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); +// for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride) +// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! +// } +// } + modexCopyPageRegion(mv[3].page, mv[0].page, 0/**/, 0/**/, 0, 0, 24, 32); +} + +void near +mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) +{ + word rx; + word ry; + word textx=0; + word texty=0; + //if(i==0) i=2; + if(i==0) + { + //wwww + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color! + } + else + { + rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth); + ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight); +////0000printf("i=%d\n", i); + switch(t->debug_text) + { + case 0: +#ifndef TILERENDER + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1)); + //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i])); +#else + PBUFBFUN (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); + /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ + //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + //modexDrawBmpRegion (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); +#endif + break; + case 1: + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1); + //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data)); + /*for(texty=0; texty<2; texty++) + { + for(textx=0; textx<2; textx++) + {*/ +// modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data)); +/* } + }*/ + break; + } + } +} + +void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset) +{ + word x; + int i; + poopoffset%=p[0].speed; +//printf("y: %d\n", poopoffset); + /* the position within the map array */ + i=ty * mv->map->width + tx; + for(x=poopoffset; x<(mv->page->sw+mv->dxThresh)/(poopoffset+1) && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { + if(i>=0) { + /* we are in the map, so copy! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i++; /* next! */ + } +} + +void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset) +{ + int y; + int i; + poopoffset%=p[0].speed; +//printf("x: %d\n", poopoffset); + /* location in the map array */ + i=ty * mv->map->width + tx; + + /* We'll copy all of the columns in the screen, + i + 1 row above and one below */ + for(y=poopoffset; y<(mv->page->sh+mv->dyThresh)/(poopoffset+1) && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { + if(i>=0) { + /* we are in the map, so copy away! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i += mv->map->width; + } +} + +void mapDrawWRow(map_view_t *mv, int tx, int ty, word y) +{ + word x; + int i; + + /* the position within the map array */ + i=ty * mv->map->width + tx; + for(x=0; xpage->sw+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) { + if(i>=0) { + /* we are in the map, so copy! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i++; /* next! */ + } +} + +void mapDrawWCol(map_view_t *mv, int tx, int ty, word x) +{ + int y; + int i; + + /* location in the map array */ + i=ty * mv->map->width + tx; + + /* We'll copy all of the columns in the screen, + i + 1 row above and one below */ + for(y=0; ypage->sh+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) { + if(i>=0) { + /* we are in the map, so copy away! */ + mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y); + } + i += mv->map->width; + } +} + +/*void qclean() +{ + //setkb(0); +}*/ + +unsigned char shinku_fps_indicator_page = 2; +boolean pageflipflop = 1; +boolean pageploop = 1; + +/* sync */ +void shinku(global_game_variables_t *gv) +{ + word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen + word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen + word w = 64, h = 8, col = 7, bgcol = 0, type = 1; + byte o,o2,i; + //modexCopyPageRegion(pip[1].page, pip[2].page, 16, 16, 16, 16, (14*8)+4, 8+4); + /* block copy to visible RAM from offscreen */ +// vga_setup_wm1_block_copy(); +// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x+w, 0, w, h); +// o = *(gv->video.page[2].data); // source offscreen +// o2 = *(gv->video.page[shinku_fps_indicator_page].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) +// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ +// vga_restore_rm0wm0(); + if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second)) + { + sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv)); + //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45); + modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee); + gv->kurokku.tiku=0; + /* block copy to visible RAM from offscreen */ +// vga_setup_wm1_block_copy(); +// o = *(gv->video.page[shinku_fps_indicator_page].data); // source offscreen +// o2 = *(gv->video.page[2].data)+(y * vga_state.vga_stride) + (x >> 2); // dest visible (original stride) +// for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); +// modexCopyPageRegion(&(gv->video.page[shinku_fps_indicator_page]), &(gv->video.page[!shinku_fps_indicator_page]), x, y, x, 0, w, h); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ +// vga_restore_rm0wm0(); + }else //copy dat sheet + gv->kurokku.tiku++; + + switch(gv->kurokku.fpscap) + { + case 0: + //modexprint(&(gv->video.page[shinku_fps_indicator_page]), x, y+8, type, col, bgcol, "sanic!"); + gv->kurokku.frames_per_second=1; + break; + case 1: + //turn this off if XT + //modexWaitBorder(); + vga_wait_for_vsync(); + gv->kurokku.frames_per_second=60; + break; + } + if(pageflipflop){ + if(gv->video.r){ + //vga_setup_wm1_block_copy(); + //_fmemcpy((gv->video.page[(gv->video.p)]).data, (gv->video.page[(!gv->video.p)]).data, gv->video.page[(!gv->video.p)].pagesize); + //vga_restore_rm0wm0(); + if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height); + modexShowPage(&(gv->video.page[gv->video.p])); + if(!pageploop) gv->video.p=!gv->video.p; + gv->video.r=!gv->video.r; + //0000gv->video.tickclk = ((*clockw)-gv->video.startclk)/18.2; + } + } +} + +void near animatePlayer(map_view_t *pip, player_t *player, word pn, sword scrollswitch) +{ + sword x = player[pn].x; + sword y = player[pn].y; + sword bx = x+16; //buffer's x + sword by = y+16; //buffer's y + word dire=32; //direction + sword qq; //scroll offset + word ls = player[pn].persist_aniframe; + + switch(scrollswitch) + { + case 0: + qq = 0; + break; + default: + qq = ((player[pn].q)*(player[pn].speed)); + break; + } + //x-=4; + y-=pip[0].map->tiles->tileHeight; + switch (player[pn].d) + { + case 0: + //up + dire*=player[pn].d; + y-=qq; + by-=4; + break; + case 3: + // right + dire*=(player[pn].d-2); + x+=qq; + bx+=4; + break; + case 2: + break; + case 4: + //down + dire*=(player[pn].d-2); + y+=qq; + by+=4; + break; + case 1: + //left + dire*=(player[pn].d+2); + x-=qq; + bx-=4; + break; + } + +#ifdef SPRITE +#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32, PLAYERBMPDATA); +#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); +#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA); +#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); +#else +#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire); +#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); +#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire); +#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); +#endif + if(!pageflipflop) + modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 36); + else{ + //copy old bg to page0 + //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0, 20, 36); + //update buffer + //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 20, 36); + } +//modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height); + //modexCopyPageRegion(pip[3].page, pip[!(pip->video->p)].page, x-4, y-4, 0, 128, 28, 36); + /*modexCopyPageRegion(pip[pip->video->p].page, + pip[!(pip->video->p)].page, x-4, y-4, x-4, y-4, 28, 36);*/ +// else modexCopyPageRegion(pip[1].page, pip[0].page, x-4, y-4, x-4, y-4, 28, 40); + switch(ls) + { + case 1: + FRAME1 + break; + case 2: + FRAME2 + break; + case 3: + FRAME3 + break; + case 4: + FRAME4 + break; + } +// if(2>ls && ls>=1) { FRAME1 }else +// if(3>ls && ls>=2) { FRAME2 }else +// if(4>ls && ls>=3) { FRAME3 }else +// if(5>ls && ls>=4) { FRAME4 } + //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 24, 32); + //printf("x=%d y=%d bx=%d by=%d\n", x, y, bx, by); + pip->video->r=1; +} diff --git a/src/lib/scroll16.h b/src/lib/scroll16.h index a3402a02..9602732d 100755 --- a/src/lib/scroll16.h +++ b/src/lib/scroll16.h @@ -1,95 +1,95 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __SCROLL16_H_ -#define __SCROLL16_H_ - -#include "src/lib/16_head.h" -#include "src/lib/bakapee.h" -#include "src/lib/modex16.h" -#include "src/lib/16_in.h" -#include "src/lib/bitmap.h" -#include "src/lib/mapread.h" //map is loaded here www -#include "src/lib/16_timer.h" -#include "src/lib/wcpu/wcpu.h" - -#include -#include -#include -#include - -#define SPRITE -//#define TILERENDER - -//modexDrawSpritePBufRegion -//modexDrawBmpPBufRegion -#define PBUFSFUN modexDrawSpriteRegion -#define PBUFBFUN modexDrawBmpRegion -#define PLAYERBMPDATA player[pn].data - -typedef struct { - map_t *map; - page_t *page; - int tx; //appears to be the top left tile position on the viewable screen map - int ty; //appears to be the top left tile position on the viewable screen map - word dxThresh; //???? - word dyThresh; //???? - video_t *video; //pointer to game variables of the video - pan_t *pan; //pointer the the page panning debug system -} map_view_t; - -typedef struct -{ - map_view_t *mv; -} map_view_db_t; - -//for null map! -#define MAPW 40 -#define MAPH 30 - -extern boolean pageflipflop, pageploop; -extern unsigned char shinku_fps_indicator_page; - -//map_t allocMap(int w, int h); -//void initMap(map_t *map); -void walk(map_view_t *pip, player_t *player, word pn); -void panpagemanual(map_view_t *pip, player_t *player, word pn); -void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid); -void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid); -void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid); -void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid); -void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid); -void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid); -void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid); -void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid); -sword chkmap(map_t *map, word q); -void mapGoTo(map_view_t *mv, int tx, int ty); -void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y); -void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset); -void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset); -void mapDrawWRow(map_view_t *mv, int tx, int ty, word y); -void mapDrawWCol(map_view_t *mv, int tx, int ty, word x); -//void qclean(); -void shinku(global_game_variables_t *gv); -void near animatePlayer(map_view_t *pip, player_t *player, word playnum, sword scrollswitch); - -#endif /*__SCROLL16_H_*/ +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __SCROLL16_H_ +#define __SCROLL16_H_ + +#include "src/lib/16_head.h" +#include "src/lib/bakapee.h" +#include "src/lib/modex16.h" +#include "src/lib/16_in.h" +#include "src/lib/bitmap.h" +#include "src/lib/mapread.h" //map is loaded here www +#include "src/lib/16_timer.h" +#include "src/lib/wcpu/wcpu.h" + +#include +#include +#include +#include + +#define SPRITE +//#define TILERENDER + +//modexDrawSpritePBufRegion +//modexDrawBmpPBufRegion +#define PBUFSFUN modexDrawSpriteRegion +#define PBUFBFUN modexDrawBmpRegion +#define PLAYERBMPDATA player[pn].data + +typedef struct { + map_t *map; + page_t *page; + int tx; //appears to be the top left tile position on the viewable screen map + int ty; //appears to be the top left tile position on the viewable screen map + word dxThresh; //???? + word dyThresh; //???? + video_t *video; //pointer to game variables of the video + pan_t *pan; //pointer the the page panning debug system +} map_view_t; + +typedef struct +{ + map_view_t *mv; +} map_view_db_t; + +//for null map! +#define MAPW 40 +#define MAPH 30 + +extern boolean pageflipflop, pageploop; +extern unsigned char shinku_fps_indicator_page; + +//map_t allocMap(int w, int h); +//void initMap(map_t *map); +void walk(map_view_t *pip, player_t *player, word pn); +void panpagemanual(map_view_t *pip, player_t *player, word pn); +void near mapScrollRight(map_view_t *mv, player_t *player, word id, word plid); +void near mapScrollLeft(map_view_t *mv, player_t *player, word id, word plid); +void near mapScrollUp(map_view_t *mv, player_t *player, word id, word plid); +void near mapScrollDown(map_view_t *mv, player_t *player, word id, word plid); +void near ScrollRight(map_view_t *mv, player_t *player, word id, word plid); +void near ScrollLeft(map_view_t *mv, player_t *player, word id, word plid); +void near ScrollUp(map_view_t *mv, player_t *player, word id, word plid); +void near ScrollDown(map_view_t *mv, player_t *player, word id, word plid); +sword chkmap(map_t *map, word q); +void mapGoTo(map_view_t *mv, int tx, int ty); +void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y); +void near mapDrawRow(map_view_t *mv, int tx, int ty, word y, player_t *p, word poopoffset); +void near mapDrawCol(map_view_t *mv, int tx, int ty, word x, player_t *p, word poopoffset); +void mapDrawWRow(map_view_t *mv, int tx, int ty, word y); +void mapDrawWCol(map_view_t *mv, int tx, int ty, word x); +//void qclean(); +void shinku(global_game_variables_t *gv); +void near animatePlayer(map_view_t *pip, player_t *player, word playnum, sword scrollswitch); + +#endif /*__SCROLL16_H_*/ diff --git a/src/lib/xms.c b/src/lib/xms.c index 1781754f..7464a32f 100755 --- a/src/lib/xms.c +++ b/src/lib/xms.c @@ -1,187 +1,187 @@ -/* This file implements rudimentary XMS memory handling. - * Documentation on the XMS API was found on http://www.qzx.com/pc-gpe/xms30.txt - */ - -#include "src\lib\xms.h" - -/* Set up the XMS driver, returns 0 on success and non-zero on failure */ -static int initxms(void) -{ - char XMSStatus = 0; - - if ( XMSControl == 0 ) - { - __asm { - ; Is an XMS driver installed? - mov ax,4300h - int 2Fh - mov [XMSStatus], al - } - - if ( XMSStatus == 0x80 ) - { - __asm { - ; Get the address of the driver control function - mov ax,4310h - int 2Fh - mov word ptr [XMSControl] ,bx - mov word ptr [XMSControl+2],es - } - } - } - - return ( XMSControl == 0 ); -} - -/* Allocate a slab of memory from XMS */ -void huge * xmsmalloc(long unsigned int size) -{ - unsigned int kB; - unsigned int XMSStatus = 0; - unsigned int XMSHandle = 0; - void huge * XMSPointer = NULL; - int n; - - /* If we can not initialize XMS, the allocation fails */ - if ( initxms() ) - return NULL; - - /* It is not possible to allocate more kilobytes than a 16-bit register can hold :-) */ - if ( size / 1024 > UINT_MAX ) - return NULL; - - /* Get the next free entry in the handle <-> pointer mapping */ - for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ ) - { - if ( allocMapXMS[n].XMSPointer == NULL ) - break; - } - - if ( n == MAX_XMS_ALLOCATIONS ) - return NULL; - - kB = size / 1024 + (size % 1024 > 0); - - __asm { - ; Allocate [kB] kilobytes of XMS memory - mov ah, 09h - mov dx, [kB] - call [XMSControl] - mov [XMSStatus], ax - mov [XMSHandle], dx - } - - /* Check if XMS allocation failed */ - if ( XMSStatus == 0) - return NULL; - - __asm { - ; Convert XMS handle to normal pointer - mov ah, 0Ch - mov dx, [XMSHandle] - call [XMSControl] - mov [XMSStatus], ax - - mov word ptr [XMSPointer], bx - mov word ptr [XMSPointer+2],dx - } - - if ( XMSStatus == 0 ) - { - /* Lock failed, deallocate the handle */ - __asm { - ; Free XMS handle - mov ah, 0Ah - mov dx, [XMSHandle] - call [XMSControl] - - ; Return value is not really interesting - ; mov [XMSStatus], ax - } - return NULL; - } - - /* Create an entry in the handle <-> pointer mapping */ - allocMapXMS[n].XMSHandle = XMSHandle; - allocMapXMS[n].XMSPointer = XMSPointer; - - return XMSPointer; -} - -/* Free a pointer allocated with xmsalloc */ -void xmsfree(void huge * XMSPointer) -{ - int n; - - if ( XMSPointer == NULL ) - return; - - if ( initxms() ) - return; - - for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ ) - { - if ( allocMapXMS[n].XMSPointer == XMSPointer ) - { - int XMSHandle = allocMapXMS[n].XMSHandle; - - __asm { - ; Unlock handle so we can free the memory block - mov ah, 0Dh - mov dx, [XMSHandle] - call [XMSControl] - - ; Free XMS memory - mov ah, 0Ah - mov dx, [XMSHandle] - call [XMSControl] - - ; Return value ignored - } - - /* Clear handle <-> pointer map entry so it can be reused */ - allocMapXMS[n].XMSHandle = 0; - allocMapXMS[n].XMSPointer = NULL; - - return; - } - } -} - -/* Write a memory report for debugging purposes */ -void xmsreport(void/*FILE * stream*/) -{ - int XMSVersionNumber = 0; - unsigned int XMSLargestBlock = 0; - unsigned int XMSTotal = 0; - - if ( initxms() ) - { - puts("Could not initialize XMS Driver!"); - return; - } - - __asm { - ; Get the driver version number - mov ah,00h - call [XMSControl] ; Get XMS Version Number - mov [XMSVersionNumber], ax - - ; Get the amount of free XMS memory - mov ah, 08h - call [XMSControl] - mov [XMSLargestBlock], ax - mov [XMSTotal], dx - } - - //fprintf(stream, "XMS Version number: %d\n", XMSVersionNumber); - //fprintf(stream, "Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal); - printf("XMS Version number: %d\n", XMSVersionNumber); - printf("Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal); -} - -/*int main() -{ - xmsreport(fopen("xms.log", "w")); - return 0; -}*/ +/* This file implements rudimentary XMS memory handling. + * Documentation on the XMS API was found on http://www.qzx.com/pc-gpe/xms30.txt + */ + +#include "src\lib\xms.h" + +/* Set up the XMS driver, returns 0 on success and non-zero on failure */ +static int initxms(void) +{ + char XMSStatus = 0; + + if ( XMSControl == 0 ) + { + __asm { + ; Is an XMS driver installed? + mov ax,4300h + int 2Fh + mov [XMSStatus], al + } + + if ( XMSStatus == 0x80 ) + { + __asm { + ; Get the address of the driver control function + mov ax,4310h + int 2Fh + mov word ptr [XMSControl] ,bx + mov word ptr [XMSControl+2],es + } + } + } + + return ( XMSControl == 0 ); +} + +/* Allocate a slab of memory from XMS */ +void huge * xmsmalloc(long unsigned int size) +{ + unsigned int kB; + unsigned int XMSStatus = 0; + unsigned int XMSHandle = 0; + void huge * XMSPointer = NULL; + int n; + + /* If we can not initialize XMS, the allocation fails */ + if ( initxms() ) + return NULL; + + /* It is not possible to allocate more kilobytes than a 16-bit register can hold :-) */ + if ( size / 1024 > UINT_MAX ) + return NULL; + + /* Get the next free entry in the handle <-> pointer mapping */ + for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ ) + { + if ( allocMapXMS[n].XMSPointer == NULL ) + break; + } + + if ( n == MAX_XMS_ALLOCATIONS ) + return NULL; + + kB = size / 1024 + (size % 1024 > 0); + + __asm { + ; Allocate [kB] kilobytes of XMS memory + mov ah, 09h + mov dx, [kB] + call [XMSControl] + mov [XMSStatus], ax + mov [XMSHandle], dx + } + + /* Check if XMS allocation failed */ + if ( XMSStatus == 0) + return NULL; + + __asm { + ; Convert XMS handle to normal pointer + mov ah, 0Ch + mov dx, [XMSHandle] + call [XMSControl] + mov [XMSStatus], ax + + mov word ptr [XMSPointer], bx + mov word ptr [XMSPointer+2],dx + } + + if ( XMSStatus == 0 ) + { + /* Lock failed, deallocate the handle */ + __asm { + ; Free XMS handle + mov ah, 0Ah + mov dx, [XMSHandle] + call [XMSControl] + + ; Return value is not really interesting + ; mov [XMSStatus], ax + } + return NULL; + } + + /* Create an entry in the handle <-> pointer mapping */ + allocMapXMS[n].XMSHandle = XMSHandle; + allocMapXMS[n].XMSPointer = XMSPointer; + + return XMSPointer; +} + +/* Free a pointer allocated with xmsalloc */ +void xmsfree(void huge * XMSPointer) +{ + int n; + + if ( XMSPointer == NULL ) + return; + + if ( initxms() ) + return; + + for ( n = 0; n < MAX_XMS_ALLOCATIONS; n++ ) + { + if ( allocMapXMS[n].XMSPointer == XMSPointer ) + { + int XMSHandle = allocMapXMS[n].XMSHandle; + + __asm { + ; Unlock handle so we can free the memory block + mov ah, 0Dh + mov dx, [XMSHandle] + call [XMSControl] + + ; Free XMS memory + mov ah, 0Ah + mov dx, [XMSHandle] + call [XMSControl] + + ; Return value ignored + } + + /* Clear handle <-> pointer map entry so it can be reused */ + allocMapXMS[n].XMSHandle = 0; + allocMapXMS[n].XMSPointer = NULL; + + return; + } + } +} + +/* Write a memory report for debugging purposes */ +void xmsreport(void/*FILE * stream*/) +{ + int XMSVersionNumber = 0; + unsigned int XMSLargestBlock = 0; + unsigned int XMSTotal = 0; + + if ( initxms() ) + { + puts("Could not initialize XMS Driver!"); + return; + } + + __asm { + ; Get the driver version number + mov ah,00h + call [XMSControl] ; Get XMS Version Number + mov [XMSVersionNumber], ax + + ; Get the amount of free XMS memory + mov ah, 08h + call [XMSControl] + mov [XMSLargestBlock], ax + mov [XMSTotal], dx + } + + //fprintf(stream, "XMS Version number: %d\n", XMSVersionNumber); + //fprintf(stream, "Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal); + printf("XMS Version number: %d\n", XMSVersionNumber); + printf("Largest available block: %d kB (%d kB total)\n", XMSLargestBlock, XMSTotal); +} + +/*int main() +{ + xmsreport(fopen("xms.log", "w")); + return 0; +}*/ diff --git a/src/lib/xms.h b/src/lib/xms.h index b6587494..b1bdb012 100755 --- a/src/lib/xms.h +++ b/src/lib/xms.h @@ -1,28 +1,28 @@ -#ifndef _XMS_H_ -#define _XMS_H_ -#include /* Definition of NULL */ -#include /* Definition of UINT_MAX */ -#include /* fprintf and (FILE *) */ - -/* Allow external configuration of maximum concurrent XMS allocations */ -#ifndef MAX_XMS_ALLOCATIONS -#define MAX_XMS_ALLOCATIONS 4 -#endif - -/* Address of the XMS driver */ -static long XMSControl; - -/* Mapping of XMS handle <-> normal pointer */ -typedef struct { - unsigned int XMSHandle; - void huge * XMSPointer; -} XMSHandleMap; - -static XMSHandleMap allocMapXMS[MAX_XMS_ALLOCATIONS]; - -static int initxms(void); -void huge * xmsmalloc(long unsigned int size); -void xmsfree(void huge * XMSPointer); -void xmsreport(void/*FILE * stream*/); - -#endif/*_XMS_H_*/ +#ifndef _XMS_H_ +#define _XMS_H_ +#include /* Definition of NULL */ +#include /* Definition of UINT_MAX */ +#include /* fprintf and (FILE *) */ + +/* Allow external configuration of maximum concurrent XMS allocations */ +#ifndef MAX_XMS_ALLOCATIONS +#define MAX_XMS_ALLOCATIONS 4 +#endif + +/* Address of the XMS driver */ +static long XMSControl; + +/* Mapping of XMS handle <-> normal pointer */ +typedef struct { + unsigned int XMSHandle; + void huge * XMSPointer; +} XMSHandleMap; + +static XMSHandleMap allocMapXMS[MAX_XMS_ALLOCATIONS]; + +static int initxms(void); +void huge * xmsmalloc(long unsigned int size); +void xmsfree(void huge * XMSPointer); +void xmsreport(void/*FILE * stream*/); + +#endif/*_XMS_H_*/ diff --git a/src/lib/zcroll16.c b/src/lib/zcroll16.c index 02750443..12a5ee1b 100755 --- a/src/lib/zcroll16.c +++ b/src/lib/zcroll16.c @@ -1,360 +1,360 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* - scroll16 library~ -*/ -#include "src/lib/zcroll16.h" - -boolean boundary_check(int x, int y, int dx, int dy, int h, int w){ - return (dx > 0 && (x + dx) < w) || (dx < 0 && (x + dx) >= 0) || (dy > 0 && (y + dy) < h) || (dy < 0 && (y + dy) >= 0) || (dx == dy && dx == 0); -} - -boolean coll_check(int x, int y, int dx, int dy, map_view_t *map_v){ - // Assume everything crosses at most 1 tile at once - return dx && crossable_tile(x + dx, map_v) || dy && crossable_tile(y + dy, map_v); -} - -boolean walk(entity_t *ent, map_view_t *map_v) -{ - int dx = 1; - int dy = 1; - switch(ent->d) - { - case STOP: - return; - case LEFT: - dx = -dx; - case RIGHT: - dy = 0; - break; - case UP: - dy = -dy; - case DOWN: - dx = 0; - break; - } - if(coll_check(ent->x, ent->y, dx, dy, map_v)){ - // Allow movement - // Set speed - // Start animation - // Mark next tile as occupied - // Mark this tile as vacant - return true; - } - return false; -} - -void player_walk(player_t *player, map_view_t *map_v){ - if(walk(player->ent, map_v) && boundary_check(map_v->tx, map_v->ty, dx, dy, map_v->map->width - 2*map_v->page->tilesw, map_v->map->height - 2*map_v->page->tilesh)){ - mapScroll(map_v, player); - // (Un)load stuff? - } -} - - -void near mapScroll(map_view_t *mv, player_t *player){ - word x, y; /* coordinate for drawing */ - int c = 1; - int delta; - mv->delta += player->dx | player->dy; - delta = mv->delta; - mv->d = (player->dx) ? (player->dx > 0) ? RIGHT : LEFT : (player->dy) ? (player->dy > 0) ? DOWN : UP : STOP; - switch(mv->d){ - case DOWN: - c = -1; - delta = -delta; - case UP: - if(!(delta + mv->dxThresh)){ - mv->delta = 0; - mv->ty += c; - } - break; - case RIGHT: - c = -1; - delta = -delta; - case LEFT: - if(!(delta + mv->dyThresh)){ - mv->delta = 0; - mv->tx += c; - } - break; - default: - break; - } - - mv->video->r=1; -} - -sword chkmap(map_t *map, word q) -{ -// bitmap_t bp; - static byte x[(MAPW*MAPH)+1] = -{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 }; -/*1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, \ -5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, \ -0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4 };*/ - //check for failed to load map - if((map->width == map->height == 0) && (q>0)) - { - //initiate a null map! - map->width=MAPW;///2; - map->height=MAPH;///2; -// map->data = malloc(((map->width*map->height)+1)*sizeof(byte)); - map->data = &x; - map->tiles = malloc(sizeof(tiles_t)); - //fix this to be far~ -// bp = bitmapLoadPcx("data/ed.pcx"); -// map->tiles->data = &bp; - map->tiles->debug_data = map->data; - map->tiles->tileHeight = 16; - map->tiles->tileWidth = 16; - map->tiles->rows = 1; - map->tiles->cols = 1; - map->tiles->debug_text = true; - } - else map->tiles->debug_text = false; - return 0; -} - -//TODO: player position here -void mapGoTo(map_view_t *mv, int tx, int ty) -{ - int px, py; - unsigned int i; - - /* set up the coordinates */ - mv->tx = tx; - mv->ty = ty; - mv->page->delta = 0; - - /* set up the thresholds */ - mv->dxThresh = mv->map->tiles[0]->tileWidth * 2; - mv->dyThresh = mv->map->tiles[0]->tileHeight * 2; - - /* draw the tiles */ - modexClearRegion(mv->page, 0, 0, mv->page->width, mv->page->height, 0); - py=0; - i=mv->ty * mv->map->width + mv->tx; -/* for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) { - mapDrawWRow(&mv[0], tx-1, ty, py); - i+=mv->map->width - tx; - } - if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height); -// { -// unsigned int k,j,o; -// // fill screen with a distinctive pattern -// for (k=0;k < vga_state.vga_width;k++) { -// o = k >> 2; -// vga_write_sequencer(0x02/*map mask*//*,1 << (k&3)); -// for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride) -// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! -// } -// } - modexCopyPageRegion(mv[3].page, mv[0].page, 0, 0, 0, 0, 24, 32);*/ -} - -void near -mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) -{ - word rx; - word ry; - word textx=0; - word texty=0; - //if(i==0) i=2; - if(i==0) - { - //wwww - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color! - } - else - { - rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth); - ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight); -////0000printf("i=%d\n", i); - switch(t->debug_text) - { - case 0: -#ifndef TILERENDER - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1)); - //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i])); -#else - PBUFBFUN (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); - /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ - //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - //modexDrawBmpRegion (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); -#endif - break; - case 1: - modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1); - //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data)); - /*for(texty=0; texty<2; texty++) - { - for(textx=0; textx<2; textx++) - {*/ -// modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data)); -/* } - }*/ - break; - } - } -} - -unsigned char shinku_fps_indicator_page = 2; -boolean pageflipflop = 1; -boolean pageploop = 1; - -/* sync */ -void shinku(global_game_variables_t *gv) -{ - word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen - word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen - word w = 64, h = 8, col = 7, bgcol = 0, type = 1; - byte o,o2,i; - if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second)) - { - sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv)); - //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45); - modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee); - gv->kurokku.tiku=0; - }else //copy dat sheet - gv->kurokku.tiku++; - - switch(gv->kurokku.fpscap) - { - case 0: - gv->kurokku.frames_per_second=1; - break; - case 1: - //turn this off if XT - vga_wait_for_vsync(); - gv->kurokku.frames_per_second=60; - break; - } - if(pageflipflop){ - if(gv->video.r){ - if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height); - modexShowPage(&(gv->video.page[gv->video.p])); - if(!pageploop) gv->video.p=!gv->video.p; - gv->video.r=!gv->video.r; - } - } -} - -void near animatePlayer(map_view_t *pip, player_t *player, sword scrollswitch) -{ - sword x = player->x; - sword y = player->y; - sword bx = x+16; //buffer's x - sword by = y+16; //buffer's y - word dire=32; //direction - sword qq; //scroll offset - word ls = player->persist_aniframe; - - switch(scrollswitch) - { - case 0: - qq = 0; - break; - default: - qq = ((player->q)*(player->speed)); - break; - } - //x-=4; - y-=pip->map->tiles->tileHeight; - switch (player->d) - { - case 0: - //up - dire*=player->d; - y-=qq; - by-=4; - break; - case 3: - // right - dire*=(player->d-2); - x+=qq; - bx+=4; - break; - case 2: - break; - case 4: - //down - dire*=(player->d-2); - y+=qq; - by+=4; - break; - case 1: - //left - dire*=(player->d+2); - x-=qq; - bx-=4; - break; - } - -#ifdef SPRITE -#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32, PLAYERBMPDATA); -#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); -#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA); -#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); -#else -#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire); -#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); -#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire); -#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); -#endif - if(!pageflipflop) - modexCopyPageRegion(pip->page, pip->page, x-4, y-4, x-4, y-4, 28, 36); - else{ - //copy old bg to page0 - //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0, 20, 36); - //update buffer - //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 20, 36); - } - switch(ls) - { - case 1: - FRAME1 - break; - case 2: - FRAME2 - break; - case 3: - FRAME3 - break; - case 4: - FRAME4 - break; - } - pip->video->r=1; -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + scroll16 library~ +*/ +#include "src/lib/zcroll16.h" + +boolean boundary_check(int x, int y, int dx, int dy, int h, int w){ + return (dx > 0 && (x + dx) < w) || (dx < 0 && (x + dx) >= 0) || (dy > 0 && (y + dy) < h) || (dy < 0 && (y + dy) >= 0) || (dx == dy && dx == 0); +} + +boolean coll_check(int x, int y, int dx, int dy, map_view_t *map_v){ + // Assume everything crosses at most 1 tile at once + return dx && crossable_tile(x + dx, map_v) || dy && crossable_tile(y + dy, map_v); +} + +boolean walk(entity_t *ent, map_view_t *map_v) +{ + int dx = 1; + int dy = 1; + switch(ent->d) + { + case STOP: + return; + case LEFT: + dx = -dx; + case RIGHT: + dy = 0; + break; + case UP: + dy = -dy; + case DOWN: + dx = 0; + break; + } + if(coll_check(ent->x, ent->y, dx, dy, map_v)){ + // Allow movement + // Set speed + // Start animation + // Mark next tile as occupied + // Mark this tile as vacant + return true; + } + return false; +} + +void player_walk(player_t *player, map_view_t *map_v){ + if(walk(player->ent, map_v) && boundary_check(map_v->tx, map_v->ty, dx, dy, map_v->map->width - 2*map_v->page->tilesw, map_v->map->height - 2*map_v->page->tilesh)){ + mapScroll(map_v, player); + // (Un)load stuff? + } +} + + +void near mapScroll(map_view_t *mv, player_t *player){ + word x, y; /* coordinate for drawing */ + int c = 1; + int delta; + mv->delta += player->dx | player->dy; + delta = mv->delta; + mv->d = (player->dx) ? (player->dx > 0) ? RIGHT : LEFT : (player->dy) ? (player->dy > 0) ? DOWN : UP : STOP; + switch(mv->d){ + case DOWN: + c = -1; + delta = -delta; + case UP: + if(!(delta + mv->dxThresh)){ + mv->delta = 0; + mv->ty += c; + } + break; + case RIGHT: + c = -1; + delta = -delta; + case LEFT: + if(!(delta + mv->dyThresh)){ + mv->delta = 0; + mv->tx += c; + } + break; + default: + break; + } + + mv->video->r=1; +} + +sword chkmap(map_t *map, word q) +{ +// bitmap_t bp; + static byte x[(MAPW*MAPH)+1] = +{ 1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 5, 6, 7, 8, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 9, 10, 11, 12, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10 }; +/*1, 2, 3, 4, 0, 3, 3, 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, 1, 1, 1, \ +5, 6, 7, 8, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +9, 10, 11, 12, 4, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +13, 14, 15, 16, 0, 1, 1, 1, 5, 8, 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, \ +0, 0, 4, 0, 0, 0, 0, 0, 8, 8, 1, 11, 11, 3, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 3, 4 };*/ + //check for failed to load map + if((map->width == map->height == 0) && (q>0)) + { + //initiate a null map! + map->width=MAPW;///2; + map->height=MAPH;///2; +// map->data = malloc(((map->width*map->height)+1)*sizeof(byte)); + map->data = &x; + map->tiles = malloc(sizeof(tiles_t)); + //fix this to be far~ +// bp = bitmapLoadPcx("data/ed.pcx"); +// map->tiles->data = &bp; + map->tiles->debug_data = map->data; + map->tiles->tileHeight = 16; + map->tiles->tileWidth = 16; + map->tiles->rows = 1; + map->tiles->cols = 1; + map->tiles->debug_text = true; + } + else map->tiles->debug_text = false; + return 0; +} + +//TODO: player position here +void mapGoTo(map_view_t *mv, int tx, int ty) +{ + int px, py; + unsigned int i; + + /* set up the coordinates */ + mv->tx = tx; + mv->ty = ty; + mv->page->delta = 0; + + /* set up the thresholds */ + mv->dxThresh = mv->map->tiles[0]->tileWidth * 2; + mv->dyThresh = mv->map->tiles[0]->tileHeight * 2; + + /* draw the tiles */ + modexClearRegion(mv->page, 0, 0, mv->page->width, mv->page->height, 0); + py=0; + i=mv->ty * mv->map->width + mv->tx; +/* for(ty=mv[0].ty-1; py < mv[0].page->sh+mv->dyThresh && ty < mv[0].map->height; ty++, py+=mv[0].map->tiles->tileHeight) { + mapDrawWRow(&mv[0], tx-1, ty, py); + i+=mv->map->width - tx; + } + if(!pageploop) modexCopyPageRegion(mv[1].page, mv[0].page, 0, 0, 0, 0, mv[0].page->width, mv[0].page->height); +// { +// unsigned int k,j,o; +// // fill screen with a distinctive pattern +// for (k=0;k < vga_state.vga_width;k++) { +// o = k >> 2; +// vga_write_sequencer(0x02/*map mask*//*,1 << (k&3)); +// for (j=0;j < (mv[0].page->height)+(mv[1].page->height)+(mv[2].page->height)+(mv[3].page->height);j++,o += vga_state.vga_stride) +// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! +// } +// } + modexCopyPageRegion(mv[3].page, mv[0].page, 0, 0, 0, 0, 24, 32);*/ +} + +void near +mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) +{ + word rx; + word ry; + word textx=0; + word texty=0; + //if(i==0) i=2; + if(i==0) + { + //wwww + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, 0); //currently the over scan color! + } + else + { + rx = (((i-1) % ((t->data->width)/t->tileWidth)) * t->tileWidth); + ry = (((i-1) / ((t->data->height)/t->tileHeight)) * t->tileHeight); +////0000printf("i=%d\n", i); + switch(t->debug_text) + { + case 0: +#ifndef TILERENDER + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, ((t->debug_data[i])+1)); + //modexprint(page, x, y, 1, 15, 0, (char const *)(t->debug_data[i])); +#else + PBUFBFUN (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); + /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ + //draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + //modexDrawBmpRegion (page, x, y, rx, ry, t->tileWidth, t->tileHeight, (t->data)); +#endif + break; + case 1: + modexClearRegion(page, x, y, t->tileWidth, t->tileHeight, (t->debug_data[i])+1); + //modexprintbig(page, x, y, 1, 15, 0, (t->debug_data)); + /*for(texty=0; texty<2; texty++) + { + for(textx=0; textx<2; textx++) + {*/ +// modexprint(page, x+(textx*8), y+(texty*8), 1, (word)(t->debug_data), 0, (t->debug_data)); +/* } + }*/ + break; + } + } +} + +unsigned char shinku_fps_indicator_page = 2; +boolean pageflipflop = 1; +boolean pageploop = 1; + +/* sync */ +void shinku(global_game_variables_t *gv) +{ + word x = (0) + gv->video.page[/*!*/(gv->video.p)].dx; // follow the screen + word y = (0) + gv->video.page[/*!*/(gv->video.p)].dy; // follow the screen + word w = 64, h = 8, col = 7, bgcol = 0, type = 1; + byte o,o2,i; + if(elapsed_timer(gv) >= (1.0 / gv->kurokku.frames_per_second)) + { + sprintf(gv->pee, "%.0f fps", (double)gv->kurokku.tiku/ticktock(gv)); + //modexClearRegion(&(gv->video.page[shinku_fps_indicator_page]), x, y, w, h, 45); + modexprint(&(gv->video.page[/*!*/(gv->video.p)]), x, y, type, col, bgcol, gv->pee); + gv->kurokku.tiku=0; + }else //copy dat sheet + gv->kurokku.tiku++; + + switch(gv->kurokku.fpscap) + { + case 0: + gv->kurokku.frames_per_second=1; + break; + case 1: + //turn this off if XT + vga_wait_for_vsync(); + gv->kurokku.frames_per_second=60; + break; + } + if(pageflipflop){ + if(gv->video.r){ + if(!pageploop) modexCopyPageRegion(&(gv->video.page[(gv->video.p)]), &(gv->video.page[(!gv->video.p)]), 0, 0, 0, 0, gv->video.page[gv->video.p].width, gv->video.page[!gv->video.p].height); + modexShowPage(&(gv->video.page[gv->video.p])); + if(!pageploop) gv->video.p=!gv->video.p; + gv->video.r=!gv->video.r; + } + } +} + +void near animatePlayer(map_view_t *pip, player_t *player, sword scrollswitch) +{ + sword x = player->x; + sword y = player->y; + sword bx = x+16; //buffer's x + sword by = y+16; //buffer's y + word dire=32; //direction + sword qq; //scroll offset + word ls = player->persist_aniframe; + + switch(scrollswitch) + { + case 0: + qq = 0; + break; + default: + qq = ((player->q)*(player->speed)); + break; + } + //x-=4; + y-=pip->map->tiles->tileHeight; + switch (player->d) + { + case 0: + //up + dire*=player->d; + y-=qq; + by-=4; + break; + case 3: + // right + dire*=(player->d-2); + x+=qq; + bx+=4; + break; + case 2: + break; + case 4: + //down + dire*=(player->d-2); + y+=qq; + by+=4; + break; + case 1: + //left + dire*=(player->d+2); + x-=qq; + bx-=4; + break; + } + +#ifdef SPRITE +#define FRAME1 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 48, dire, 24, 32, PLAYERBMPDATA); +#define FRAME2 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); +#define FRAME3 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 0, dire, 24, 32, PLAYERBMPDATA); +#define FRAME4 PBUFSFUN(pip[/*!*/(pip->video->p)].page, x, y, 24, dire, 24, 32, PLAYERBMPDATA); +#else +#define FRAME1 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 2+dire); +#define FRAME2 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); +#define FRAME3 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, dire); +#define FRAME4 modexClearRegion(pip[/*!*/(pip->video->p)].page, x, y, 24, 32, 1+dire); +#endif + if(!pageflipflop) + modexCopyPageRegion(pip->page, pip->page, x-4, y-4, x-4, y-4, 28, 36); + else{ + //copy old bg to page0 + //modexCopyPageRegion(pip[3].page, pip[0].page, bx, by, 0, 0, 20, 36); + //update buffer + //modexCopyPageRegion(pip[0].page, pip[3].page, 0, 0, x, y, 20, 36); + } + switch(ls) + { + case 1: + FRAME1 + break; + case 2: + FRAME2 + break; + case 3: + FRAME3 + break; + case 4: + FRAME4 + break; + } + pip->video->r=1; +} diff --git a/src/lib/zcroll16.h b/src/lib/zcroll16.h index 3c4851c3..6f663429 100755 --- a/src/lib/zcroll16.h +++ b/src/lib/zcroll16.h @@ -1,116 +1,116 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __ZCROLL16_H_ -#define __ZCROLL16_H_ - -#include "src/lib/16_head.h" -//#include "src/lib/bakapee.h" -#include "src/lib/modex16.h" -//#include "src/lib/16_in.h" -#include "src/lib/bitmap.h" -#include "src/lib/16_map.h" //map is loaded here www -#include "src/lib/16_timer.h" -#include "src/lib/wcpu/wcpu.h" - -#include -#include -#include -#include - -#define SPRITE -//#define TILERENDER - -//modexDrawSpritePBufRegion -//modexDrawBmpPBufRegion -#define PBUFSFUN modexDrawSpriteRegion -#define PBUFBFUN modexDrawBmpRegion -#define PLAYERBMPDATA player->data - -typedef struct { - map_t *map; - page_t *page; - int tx; //appears to be the top left tile position on the viewable screen map - int ty; //appears to be the top left tile position on the viewable screen map - word dxThresh; //Threshold for physical tile switch - word dyThresh; //Threshold for physical tile switch - video_t *video; //pointer to game variables of the video - pan_t *pan; //pointer the the page panning debug system -} map_view_t; - -#define MAPW 40 -#define MAPH 30 - -enum direction {STOP, UP, DOWN, LEFT, RIGHT}; -typedef struct { - word id; /* the Identification number of the page~ For layering~ */ - byte far* data; /* the data for the page */ - word sw; /* screen width */ - word sh; /* screen heigth */ - word tw; /* screen width in tiles */ - word th; /* screen height in tiles */ - word width; /* virtual width of the page */ - word height; /* virtual height of the page */ - word tilesw; /* virtual screen width in tiles */ - word tilesh; /* virtual screen height in tiles */ - sword tilemidposscreenx; /* middle tile position */ - sword tilemidposscreeny; /* middle tile position */ - sword tileplayerposscreenx; /* player position on screen */ - sword tileplayerposscreeny; /* player position on screen */ - word stridew; /*width/4*/ - word pagesize; /* page size */ - word pi; /* incremention page by this much to preserve location */ - word delta; // How much should we shift the page for smooth scrolling - direction d; // Direction we should shift the page -} page_t; -extern boolean pageflipflop, pageploop; -extern unsigned char shinku_fps_indicator_page; - -/* Map is presumed to: - * 1. Have all the required layers and tilesets within itself - * 2. Have a 'fence' around accessible blocks to simplify boundary logic - * 3. Have a persistent map and tile size among the layers - * Map view is presumed to: - * 1. Calculate, store and update a panning info, which includes, but not limited to: - * combined layer information, actual map representation (reflecting real state of the game), - * pixel shift for smooth tile scrolling. - * 2. Provide ways to draw a visible part of map. For simplicity with smooth scrolling, - * additional row/column is always drawn at the each side of the map. This implies that 'fence' - * should have a sprite too. Map is drawn left-to-right, top-to-bottom. - */ - -// Move an entity around. Should actually be in 16_entity -boolean walk(entity_t *ent, map_view_t *map_v); - -// Move player around and call map scrolling if required/possible -void walk_player(player_t *player, map_view_t *map_v); - -// Scroll map in one direction (assumed from player's movement) -void near mapScroll(map_view_t *mv, player_t *player); -sword chkmap(map_t *map, word q); -void mapGoTo(map_view_t *mv, int tx, int ty); -void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y); -//void qclean(); -void shinku(global_game_variables_t *gv); -void near animatePlayer(map_view_t *pip, player_t *player, sword scrollswitch); - -#endif /*__ZCROLL16_H_*/ +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __ZCROLL16_H_ +#define __ZCROLL16_H_ + +#include "src/lib/16_head.h" +//#include "src/lib/bakapee.h" +#include "src/lib/modex16.h" +//#include "src/lib/16_in.h" +#include "src/lib/bitmap.h" +#include "src/lib/16_map.h" //map is loaded here www +#include "src/lib/16_timer.h" +#include "src/lib/wcpu/wcpu.h" + +#include +#include +#include +#include + +#define SPRITE +//#define TILERENDER + +//modexDrawSpritePBufRegion +//modexDrawBmpPBufRegion +#define PBUFSFUN modexDrawSpriteRegion +#define PBUFBFUN modexDrawBmpRegion +#define PLAYERBMPDATA player->data + +typedef struct { + map_t *map; + page_t *page; + int tx; //appears to be the top left tile position on the viewable screen map + int ty; //appears to be the top left tile position on the viewable screen map + word dxThresh; //Threshold for physical tile switch + word dyThresh; //Threshold for physical tile switch + video_t *video; //pointer to game variables of the video + pan_t *pan; //pointer the the page panning debug system +} map_view_t; + +#define MAPW 40 +#define MAPH 30 + +enum direction {STOP, UP, DOWN, LEFT, RIGHT}; +typedef struct { + word id; /* the Identification number of the page~ For layering~ */ + byte far* data; /* the data for the page */ + word sw; /* screen width */ + word sh; /* screen heigth */ + word tw; /* screen width in tiles */ + word th; /* screen height in tiles */ + word width; /* virtual width of the page */ + word height; /* virtual height of the page */ + word tilesw; /* virtual screen width in tiles */ + word tilesh; /* virtual screen height in tiles */ + sword tilemidposscreenx; /* middle tile position */ + sword tilemidposscreeny; /* middle tile position */ + sword tileplayerposscreenx; /* player position on screen */ + sword tileplayerposscreeny; /* player position on screen */ + word stridew; /*width/4*/ + word pagesize; /* page size */ + word pi; /* incremention page by this much to preserve location */ + word delta; // How much should we shift the page for smooth scrolling + direction d; // Direction we should shift the page +} page_t; +extern boolean pageflipflop, pageploop; +extern unsigned char shinku_fps_indicator_page; + +/* Map is presumed to: + * 1. Have all the required layers and tilesets within itself + * 2. Have a 'fence' around accessible blocks to simplify boundary logic + * 3. Have a persistent map and tile size among the layers + * Map view is presumed to: + * 1. Calculate, store and update a panning info, which includes, but not limited to: + * combined layer information, actual map representation (reflecting real state of the game), + * pixel shift for smooth tile scrolling. + * 2. Provide ways to draw a visible part of map. For simplicity with smooth scrolling, + * additional row/column is always drawn at the each side of the map. This implies that 'fence' + * should have a sprite too. Map is drawn left-to-right, top-to-bottom. + */ + +// Move an entity around. Should actually be in 16_entity +boolean walk(entity_t *ent, map_view_t *map_v); + +// Move player around and call map scrolling if required/possible +void walk_player(player_t *player, map_view_t *map_v); + +// Scroll map in one direction (assumed from player's movement) +void near mapScroll(map_view_t *mv, player_t *player); +sword chkmap(map_t *map, word q); +void mapGoTo(map_view_t *mv, int tx, int ty); +void near mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y); +//void qclean(); +void shinku(global_game_variables_t *gv); +void near animatePlayer(map_view_t *pip, player_t *player, sword scrollswitch); + +#endif /*__ZCROLL16_H_*/ diff --git a/src/midi.c b/src/midi.c index e36a8532..04126d4e 100755 --- a/src/midi.c +++ b/src/midi.c @@ -1,870 +1,870 @@ -/* midi.c - * - * Adlib OPL2/OPL3 FM synthesizer chipset test program. - * Play MIDI file using the OPLx synthesizer (well, poorly anyway) - * (C) 2010-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - * - * Compiles for intended target environments: - * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] - */ - -#include -#include /* this is where Open Watcom hides the outp() etc. functions */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/lib/doslib/vga.h" -#include "src/lib/doslib/dos.h" -#include "src/lib/doslib/8254.h" /* 8254 timer */ -#include "src/lib/doslib/8259.h" -#include "src/lib/doslib/vgagui.h" -#include "src/lib/doslib/vgatty.h" -#include "src/lib/doslib/adlib.h" - -/* one per OPL channel */ -struct midi_note { - unsigned char note_number; - unsigned char note_velocity; - unsigned char note_track; /* from what MIDI track */ - unsigned char note_channel; /* from what MIDI channel */ - unsigned int busy:1; /* if occupied */ -}; - -struct midi_channel { - unsigned char program; -}; - -struct midi_track { - /* track data, raw */ - unsigned char* raw; /* raw data base */ - unsigned char* fence; /* raw data end (last byte + 1) */ - unsigned char* read; /* raw data read ptr */ - /* state */ - unsigned long us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */ - unsigned long us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */ - unsigned long wait; - unsigned char last_status; /* MIDI last status byte */ - unsigned int eof:1; /* we hit the end of the track */ -}; - -#define MIDI_MAX_CHANNELS 16 -#define MIDI_MAX_TRACKS 64 - -struct midi_note midi_notes[ADLIB_FM_VOICES]; -struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; -struct midi_track midi_trk[MIDI_MAX_TRACKS]; -static unsigned int midi_trk_count=0; -static volatile unsigned char midi_playing=0; - -/* MIDI params. Nobody ever said it was a straightforward standard! - * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */ -static unsigned int ticks_per_quarter_note=0; /* "Ticks per beat" */ - -static void (interrupt *old_irq0)(); -static volatile unsigned long irq0_ticks=0; -static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; - -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) -static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */ - return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p)); -} -#endif - -static inline unsigned char midi_trk_read(struct midi_track *t) { - unsigned char c; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { - t->eof = 1; - return 0xFF; - } - - c = *(t->read); -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */ - t->read = MK_FP(FP_SEG(t->read)+0x1,0); - else - t->read++; -#else - t->read++; -#endif - return c; -} - -void midi_trk_end(struct midi_track *t) { - t->wait = ~0UL; - t->read = t->fence; -} - -void midi_trk_skip(struct midi_track *t,unsigned long len) { - unsigned long rem; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) - return; - - if (len > 0xFFF0UL) { - midi_trk_end(t); - return; - } -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - { - unsigned long tt; - - tt = farptr2phys(t->read); - rem = farptr2phys(t->fence) - tt; - if (rem > len) rem = len; - tt += rem; - t->read = MK_FP(tt>>4,tt&0xF); - } -#else - rem = (unsigned long)(t->fence - t->read); - if (len > rem) len = rem; - t->read += len; -#endif -} - -static const uint32_t midikeys_freqs[0x80] = { - 0x00082d01, /* key 0 = 8.17579891564371Hz */ - 0x0008a976, /* key 1 = 8.66195721802725Hz */ - 0x00092d51, /* key 2 = 9.17702399741899Hz */ - 0x0009b904, /* key 3 = 9.72271824131503Hz */ - 0x000a4d05, /* key 4 = 10.3008611535272Hz */ - 0x000ae9d3, /* key 5 = 10.9133822322814Hz */ - 0x000b8ff4, /* key 6 = 11.5623257097386Hz */ - 0x000c3ff6, /* key 7 = 12.2498573744297Hz */ - 0x000cfa70, /* key 8 = 12.9782717993733Hz */ - 0x000dc000, /* key 9 = 13.75Hz */ - 0x000e914f, /* key 10 = 14.5676175474403Hz */ - 0x000f6f11, /* key 11 = 15.4338531642539Hz */ - 0x00105a02, /* key 12 = 16.3515978312874Hz */ - 0x001152ec, /* key 13 = 17.3239144360545Hz */ - 0x00125aa2, /* key 14 = 18.354047994838Hz */ - 0x00137208, /* key 15 = 19.4454364826301Hz */ - 0x00149a0a, /* key 16 = 20.6017223070544Hz */ - 0x0015d3a6, /* key 17 = 21.8267644645627Hz */ - 0x00171fe9, /* key 18 = 23.1246514194771Hz */ - 0x00187fed, /* key 19 = 24.4997147488593Hz */ - 0x0019f4e0, /* key 20 = 25.9565435987466Hz */ - 0x001b8000, /* key 21 = 27.5Hz */ - 0x001d229e, /* key 22 = 29.1352350948806Hz */ - 0x001ede22, /* key 23 = 30.8677063285078Hz */ - 0x0020b404, /* key 24 = 32.7031956625748Hz */ - 0x0022a5d8, /* key 25 = 34.647828872109Hz */ - 0x0024b545, /* key 26 = 36.7080959896759Hz */ - 0x0026e410, /* key 27 = 38.8908729652601Hz */ - 0x00293414, /* key 28 = 41.2034446141087Hz */ - 0x002ba74d, /* key 29 = 43.6535289291255Hz */ - 0x002e3fd2, /* key 30 = 46.2493028389543Hz */ - 0x0030ffda, /* key 31 = 48.9994294977187Hz */ - 0x0033e9c0, /* key 32 = 51.9130871974931Hz */ - 0x00370000, /* key 33 = 55Hz */ - 0x003a453d, /* key 34 = 58.2704701897612Hz */ - 0x003dbc44, /* key 35 = 61.7354126570155Hz */ - 0x00416809, /* key 36 = 65.4063913251497Hz */ - 0x00454bb0, /* key 37 = 69.295657744218Hz */ - 0x00496a8b, /* key 38 = 73.4161919793519Hz */ - 0x004dc820, /* key 39 = 77.7817459305202Hz */ - 0x00526829, /* key 40 = 82.4068892282175Hz */ - 0x00574e9b, /* key 41 = 87.307057858251Hz */ - 0x005c7fa4, /* key 42 = 92.4986056779086Hz */ - 0x0061ffb5, /* key 43 = 97.9988589954373Hz */ - 0x0067d380, /* key 44 = 103.826174394986Hz */ - 0x006e0000, /* key 45 = 110Hz */ - 0x00748a7b, /* key 46 = 116.540940379522Hz */ - 0x007b7888, /* key 47 = 123.470825314031Hz */ - 0x0082d012, /* key 48 = 130.812782650299Hz */ - 0x008a9760, /* key 49 = 138.591315488436Hz */ - 0x0092d517, /* key 50 = 146.832383958704Hz */ - 0x009b9041, /* key 51 = 155.56349186104Hz */ - 0x00a4d053, /* key 52 = 164.813778456435Hz */ - 0x00ae9d36, /* key 53 = 174.614115716502Hz */ - 0x00b8ff49, /* key 54 = 184.997211355817Hz */ - 0x00c3ff6a, /* key 55 = 195.997717990875Hz */ - 0x00cfa700, /* key 56 = 207.652348789973Hz */ - 0x00dc0000, /* key 57 = 220Hz */ - 0x00e914f6, /* key 58 = 233.081880759045Hz */ - 0x00f6f110, /* key 59 = 246.941650628062Hz */ - 0x0105a025, /* key 60 = 261.625565300599Hz */ - 0x01152ec0, /* key 61 = 277.182630976872Hz */ - 0x0125aa2e, /* key 62 = 293.664767917408Hz */ - 0x01372082, /* key 63 = 311.126983722081Hz */ - 0x0149a0a7, /* key 64 = 329.62755691287Hz */ - 0x015d3a6d, /* key 65 = 349.228231433004Hz */ - 0x0171fe92, /* key 66 = 369.994422711634Hz */ - 0x0187fed4, /* key 67 = 391.995435981749Hz */ - 0x019f4e00, /* key 68 = 415.304697579945Hz */ - 0x01b80000, /* key 69 = 440Hz */ - 0x01d229ec, /* key 70 = 466.16376151809Hz */ - 0x01ede220, /* key 71 = 493.883301256124Hz */ - 0x020b404a, /* key 72 = 523.251130601197Hz */ - 0x022a5d81, /* key 73 = 554.365261953744Hz */ - 0x024b545c, /* key 74 = 587.329535834815Hz */ - 0x026e4104, /* key 75 = 622.253967444162Hz */ - 0x0293414f, /* key 76 = 659.25511382574Hz */ - 0x02ba74da, /* key 77 = 698.456462866008Hz */ - 0x02e3fd24, /* key 78 = 739.988845423269Hz */ - 0x030ffda9, /* key 79 = 783.990871963499Hz */ - 0x033e9c01, /* key 80 = 830.60939515989Hz */ - 0x03700000, /* key 81 = 880Hz */ - 0x03a453d8, /* key 82 = 932.32752303618Hz */ - 0x03dbc440, /* key 83 = 987.766602512248Hz */ - 0x04168094, /* key 84 = 1046.50226120239Hz */ - 0x0454bb03, /* key 85 = 1108.73052390749Hz */ - 0x0496a8b8, /* key 86 = 1174.65907166963Hz */ - 0x04dc8208, /* key 87 = 1244.50793488832Hz */ - 0x0526829e, /* key 88 = 1318.51022765148Hz */ - 0x0574e9b5, /* key 89 = 1396.91292573202Hz */ - 0x05c7fa49, /* key 90 = 1479.97769084654Hz */ - 0x061ffb53, /* key 91 = 1567.981743927Hz */ - 0x067d3802, /* key 92 = 1661.21879031978Hz */ - 0x06e00000, /* key 93 = 1760Hz */ - 0x0748a7b1, /* key 94 = 1864.65504607236Hz */ - 0x07b78880, /* key 95 = 1975.5332050245Hz */ - 0x082d0128, /* key 96 = 2093.00452240479Hz */ - 0x08a97607, /* key 97 = 2217.46104781498Hz */ - 0x092d5171, /* key 98 = 2349.31814333926Hz */ - 0x09b90410, /* key 99 = 2489.01586977665Hz */ - 0x0a4d053c, /* key 100 = 2637.02045530296Hz */ - 0x0ae9d36b, /* key 101 = 2793.82585146403Hz */ - 0x0b8ff493, /* key 102 = 2959.95538169308Hz */ - 0x0c3ff6a7, /* key 103 = 3135.96348785399Hz */ - 0x0cfa7005, /* key 104 = 3322.43758063956Hz */ - 0x0dc00000, /* key 105 = 3520Hz */ - 0x0e914f62, /* key 106 = 3729.31009214472Hz */ - 0x0f6f1100, /* key 107 = 3951.06641004899Hz */ - 0x105a0250, /* key 108 = 4186.00904480958Hz */ - 0x1152ec0e, /* key 109 = 4434.92209562995Hz */ - 0x125aa2e3, /* key 110 = 4698.63628667852Hz */ - 0x13720820, /* key 111 = 4978.03173955329Hz */ - 0x149a0a79, /* key 112 = 5274.04091060592Hz */ - 0x15d3a6d6, /* key 113 = 5587.65170292806Hz */ - 0x171fe927, /* key 114 = 5919.91076338615Hz */ - 0x187fed4e, /* key 115 = 6271.92697570799Hz */ - 0x19f4e00a, /* key 116 = 6644.87516127912Hz */ - 0x1b800000, /* key 117 = 7040Hz */ - 0x1d229ec4, /* key 118 = 7458.62018428944Hz */ - 0x1ede2200, /* key 119 = 7902.13282009799Hz */ - 0x20b404a1, /* key 120 = 8372.01808961916Hz */ - 0x22a5d81c, /* key 121 = 8869.84419125991Hz */ - 0x24b545c7, /* key 122 = 9397.27257335704Hz */ - 0x26e41040, /* key 123 = 9956.06347910659Hz */ - 0x293414f2, /* key 124 = 10548.0818212118Hz */ - 0x2ba74dac, /* key 125 = 11175.3034058561Hz */ - 0x2e3fd24f, /* key 126 = 11839.8215267723Hz */ - 0x30ffda9c /* key 127 = 12543.853951416Hz */ -}; - -static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) { - return midikeys_freqs[key&0x7F]; -} - -static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) { - unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */ - unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ - unsigned int i,freen=~0; - - for (i=0;i < ADLIB_FM_VOICES;i++) { - if (midi_notes[i].busy) { - if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key) - return &midi_notes[i]; - } - else { - if (freen == ~0) freen = i; - } - } - - if (do_alloc && freen != ~0) return &midi_notes[freen]; - return NULL; -} - -static void drop_fm_note(struct midi_channel *ch,unsigned char key) { - unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ - unsigned int i; - - for (i=0;i < ADLIB_FM_VOICES;i++) { - if (midi_notes[i].busy && midi_notes[i].note_channel == ach) { - midi_notes[i].busy = 0; - break; - } - } -} - -static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { - struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); - uint32_t freq = midi_note_freq(ch,key); - unsigned int ach; - - if (note == NULL) return; - - note->busy = 1; - note->note_number = key; - note->note_velocity = vel; - note->note_track = (unsigned int)(t - midi_trk); - note->note_channel = (unsigned int)(ch - midi_ch); - ach = (unsigned int)(note - midi_notes); /* which FM channel? */ - adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); - adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ - adlib_fm[ach].mod.sustain_level = vel >> 3; - adlib_fm[ach].mod.key_on = 1; - adlib_update_groupA0(ach,&adlib_fm[ach]); -} - -static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { - struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1); - uint32_t freq = midi_note_freq(ch,key); - unsigned int ach; - - /* HACK: Ignore percussion */ - if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ || - (ch->program >= 112 && ch->program <= 119)/*Percussive*/ || - ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/) - return; - - if (note == NULL) { - /* then we'll have to knock one off to make room */ - drop_fm_note(ch,key); - note = get_fm_note(t,ch,key,1); - if (note == NULL) return; - } - - note->busy = 1; - note->note_number = key; - note->note_velocity = vel; - note->note_track = (unsigned int)(t - midi_trk); - note->note_channel = (unsigned int)(ch - midi_ch); - ach = (unsigned int)(note - midi_notes); /* which FM channel? */ - adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); - adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ - adlib_fm[ach].mod.sustain_level = vel >> 3; - adlib_fm[ach].mod.key_on = 1; - adlib_update_groupA0(ach,&adlib_fm[ach]); -} - -static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { - struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); - uint32_t freq = midi_note_freq(ch,key); - unsigned int ach; - - if (note == NULL) return; - - note->busy = 0; - ach = (unsigned int)(note - midi_notes); /* which FM channel? */ - adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); - adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ - adlib_fm[ach].mod.sustain_level = vel >> 3; - adlib_fm[ach].mod.key_on = 0; - adlib_update_groupA0(ach,&adlib_fm[ach]); -} - -static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) { -} - -static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) { - ch->program = inst; -} - -static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) { -} - -static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) { -} - -unsigned long midi_trk_read_delta(struct midi_track *t) { - unsigned long tc = 0; - unsigned char c = 0,b; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) - return tc; - - while (c < 4) { - b = midi_trk_read(t); - tc = (tc << 7UL) + (unsigned long)(b&0x7F); - if (!(b&0x80)) break; - c++; - } - - return tc; -} - -void midi_tick_track(unsigned int i) { - struct midi_track *t = midi_trk + i; - struct midi_channel *ch; - unsigned char b,c,d; - int cnt=0; - - /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ - if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { - t->eof = 1; - return; - } - - t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note; - while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) { - t->us_tick_cnt_mtpq -= t->us_per_quarter_note; - cnt++; - - while (t->wait == 0) { - if ((unsigned long)t->read >= (unsigned long)t->fence) { - t->eof = 1; - break; - } - - /* read pointer should be pointing at MIDI event bytes, just after the time delay */ - b = midi_trk_read(t); - if (b&0x80) { - if (b < 0xF8) { - if (b >= 0xF0) - t->last_status = 0; - else - t->last_status = b; - } - if (b != 0x00 && ((b&0xF8) != 0xF0)) - c = midi_trk_read(t); - } - else { - /* blegh. last status */ - c = b; - b = t->last_status; - } - switch (b>>4) { - case 0x8: { /* note off */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - on_key_off(t,ch,c,d); - } break; - case 0x9: { /* note on */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */ - else on_key_off(t,ch,c,d); - } break; - case 0xA: { /* polyphonic aftertouch */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - on_key_aftertouch(t,ch,c,d); - } break; - case 0xB: { /* control change */ - d = midi_trk_read(t); - ch = midi_ch + (b&0xF); /* c=key d=velocity */ - on_control_change(t,ch,c,d); - } break; - case 0xC: { /* program change */ - on_program_change(t,ch,c); /* c=instrument d=not used */ - } break; - case 0xD: { /* channel aftertouch */ - on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */ - } break; - case 0xE: { /* pitch bend */ - d = midi_trk_read(t); - on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */ - } break; - case 0xF: { /* event */ - if (b == 0xFF) { - if (c == 0x7F) { /* c=type d=len */ - unsigned long len = midi_trk_read_delta(t); -// fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); - if (len < 512UL) { - /* unknown */ - midi_trk_skip(t,len); - } - else { - midi_trk_end(t); - } - } - else if (c < 0x7F) { - d = midi_trk_read(t); - - if (c == 0x51 && d >= 3) { - d -= 3; - t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+ - ((unsigned long)midi_trk_read(t)<<8UL)+ - ((unsigned long)midi_trk_read(t)<<0UL); - - if (1/*TODO: If format 0 or format 1*/) { - /* Ugh. Unless format 2, the tempo applies to all tracks */ - int j; - - for (j=0;j < midi_trk_count;j++) { - if (j != i) midi_trk[j].us_per_quarter_note = - t->us_per_quarter_note; - } - } - } - else { -// fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence); - } - - midi_trk_skip(t,d); - } - else { - fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence); - } - } - else { - unsigned long len = midi_trk_read_delta(t); -// fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); - midi_trk_skip(t,len); - } - } break; - default: - if (b != 0x00) { - fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence); - midi_trk_end(t); - } - break; - }; - - /* and then read the next event */ - t->wait = midi_trk_read_delta(t); - } - if (t->wait != 0) { - t->wait--; - } - } -} - -void adlib_shut_up(); -void midi_reset_tracks(); -void midi_reset_channels(); - -void midi_tick() { - if (midi_playing) { - unsigned int i; - int eof=0; - - for (i=0;i < midi_trk_count;i++) { - midi_tick_track(i); - eof += midi_trk[i].eof?1:0; - } - - if (eof >= midi_trk_count) { - adlib_shut_up(); - midi_reset_tracks(); - midi_reset_channels(); - } - } -} - -/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ -void interrupt irq0() { -// midi_tick(); - irq0_ticks++; - if ((irq0_cnt += irq0_add) >= irq0_max) { - irq0_cnt -= irq0_max; - old_irq0(); - } - else { - p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); - } -} - -void adlib_shut_up() { - int i; - - memset(adlib_fm,0,sizeof(adlib_fm)); - memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - f = &adlib_fm[i].mod; - f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; - f = &adlib_fm[i].car; - f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; - } - - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - - midi_notes[i].busy = 0; - midi_notes[i].note_channel = 0; - - f = &adlib_fm[i].mod; - f->mod_multiple = 1; - f->total_level = 63 - 16; - f->attack_rate = 15; - f->decay_rate = 4; - f->sustain_level = 0; - f->release_rate = 8; - f->f_number = 400; - f->sustain = 1; - f->octave = 4; - f->key_on = 0; - - f = &adlib_fm[i].car; - f->mod_multiple = 1; - f->total_level = 63 - 16; - f->attack_rate = 15; - f->decay_rate = 4; - f->sustain_level = 0; - f->release_rate = 8; - f->f_number = 0; - f->sustain = 1; - f->octave = 0; - f->key_on = 0; - } - - adlib_apply_all(); -} - -void midi_reset_track(unsigned int i) { - struct midi_track *t; - - if (i >= MIDI_MAX_TRACKS) return; - t = &midi_trk[i]; - t->eof = 0; - t->last_status = 0; - t->us_tick_cnt_mtpq = 0; - t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */ - t->read = midi_trk[i].raw; - t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */ -} - -void midi_reset_tracks() { - int i; - - for (i=0;i < midi_trk_count;i++) - midi_reset_track(i); -} - -void midi_reset_channels() { - int i; - - for (i=0;i < MIDI_MAX_CHANNELS;i++) { - midi_ch[i].program = 0; - } -} - -int load_midi_file(const char *path) { - unsigned char tmp[256]; - unsigned int tracks=0; - unsigned int tracki=0; - int fd; - - fd = open(path,O_RDONLY|O_BINARY); - if (fd < 0) { - printf("Failed to load file %s\n",path); - return 0; - } - - ticks_per_quarter_note = 0; - while (read(fd,tmp,8) == 8) { - uint32_t sz; - - sz = ((uint32_t)tmp[4] << (uint32_t)24) | - ((uint32_t)tmp[5] << (uint32_t)16) | - ((uint32_t)tmp[6] << (uint32_t)8) | - ((uint32_t)tmp[7] << (uint32_t)0); - if (!memcmp(tmp,"MThd",4)) { - unsigned short t,tdiv; - - if (sz < 6 || sz > 255) { - fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz); - goto err; - } - if (read(fd,tmp,(int)sz) != (int)sz) { - fprintf(stderr,"MThd read error\n"); - goto err; - } - - /* byte 0-1 = format type (0,1 or 2) */ - /* byte 2-3 = number of tracks */ - /* byte 4-5 = time divison */ - t = tmp[1] | (tmp[0] << 8); - if (t > 1) { - fprintf(stderr,"MThd type %u not supported\n",t); - goto err; /* we only take type 0 or 1, don't support 2 */ - } - tracks = tmp[3] | (tmp[2] << 8); - if (tracks > MIDI_MAX_TRACKS) { - fprintf(stderr,"MThd too many (%u) tracks\n",tracks); - goto err; - } - tdiv = tmp[5] | (tmp[4] << 8); - if (tdiv & 0x8000) { - fprintf(stderr,"MThd SMPTE time division not supported\n"); - goto err; /* we do not support the SMPTE form */ - } - if (tdiv == 0) { - fprintf(stderr,"MThd time division == 0\n"); - goto err; - } - ticks_per_quarter_note = tdiv; - } - else if (!memcmp(tmp,"MTrk",4)) { - if (sz == 0UL) continue; -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - if (sz > (640UL << 10UL)) goto err; /* 640KB */ -#elif TARGET_MSDOS == 32 - if (sz > (1UL << 20UL)) goto err; /* 1MB */ -#else - if (sz > (60UL << 10UL)) goto err; /* 60KB */ -#endif - if (tracki >= MIDI_MAX_TRACKS) goto err; -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - { - unsigned segv; - - /* NTS: _fmalloc() is still limited to 64KB sizes */ - if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err; - midi_trk[tracki].raw = MK_FP(segv,0); - } -#else - midi_trk[tracki].raw = malloc(sz); -#endif - if (midi_trk[tracki].raw == NULL) goto err; - midi_trk[tracki].read = midi_trk[tracki].raw; -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - { - unsigned char far *p = midi_trk[tracki].raw; - unsigned long rem = (unsigned long)sz; - unsigned long cando; - unsigned read; - - while (rem != 0UL) { - read = 0; - - cando = 0x10000UL - (unsigned long)FP_OFF(p); - if (cando > rem) cando = rem; - if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */ - - if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err; - if (read != (unsigned)cando) goto err; - - rem -= cando; - if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL) - p = MK_FP(FP_SEG(p)+0x1000,0); - else - p += (unsigned)cando; - } - - cando = farptr2phys(p); - midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF); - } -#else - midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz; - if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err; -#endif - tracki++; - } - else { - fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]); - goto err; - } - } - if (tracki == 0 || ticks_per_quarter_note == 0) goto err; - midi_trk_count = tracki; - - fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note); - - close(fd); - return 1; -err: - close(fd); - return 0; -} - -int main(int argc,char **argv) { - unsigned long ptick; - int i,c; - - printf("ADLIB FM test program\n"); - if (argc < 2) { - printf("You must specify a MIDI file to play\n"); - return 1; - } - - if (!probe_vga()) { - printf("Cannot init VGA\n"); - return 1; - } - if (!init_adlib()) { - printf("Cannot init library\n"); - return 1; - } - if (!probe_8254()) { /* we need the timer to keep time with the music */ - printf("8254 timer not found\n"); - return 1; - } - - for (i=0;i < MIDI_MAX_TRACKS;i++) { - midi_trk[i].raw = NULL; - midi_trk[i].read = NULL; - midi_trk[i].fence = NULL; - } - - if (load_midi_file(argv[1]) == 0) { - printf("Failed to load MIDI\n"); - return 1; - } - - write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */ - irq0_cnt = 0; - irq0_add = 182; - irq0_max = 1000; /* about 18.2Hz */ - old_irq0 = _dos_getvect(8);/*IRQ0*/ - _dos_setvect(8,irq0); - - adlib_shut_up(); - midi_reset_channels(); - midi_reset_tracks(); - _cli(); - irq0_ticks = ptick = 0; - _sti(); - midi_playing = 1; - - while (1) { - unsigned long adv; - - _cli(); - adv = irq0_ticks - ptick; - if (adv >= 100UL) adv = 100UL; - ptick = irq0_ticks; - _sti(); - - while (adv != 0) { - midi_tick(); - adv--; - } - - if (kbhit()) { - c = getch(); - if (c == 0) c = getch() << 8; - - if (c == 27) { - break; - } - } - } - - midi_playing = 0; - adlib_shut_up(); - shutdown_adlib(); - _dos_setvect(8,old_irq0); - write_8254_system_timer(0); /* back to normal 18.2Hz */ - - for (i=0;i < MIDI_MAX_TRACKS;i++) { - if (midi_trk[i].raw) { -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */ -#else - free(midi_trk[i].raw); -#endif - midi_trk[i].raw = NULL; - } - midi_trk[i].fence = NULL; - midi_trk[i].read = NULL; - } - - return 0; -} +/* midi.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/lib/doslib/vga.h" +#include "src/lib/doslib/dos.h" +#include "src/lib/doslib/8254.h" /* 8254 timer */ +#include "src/lib/doslib/8259.h" +#include "src/lib/doslib/vgagui.h" +#include "src/lib/doslib/vgatty.h" +#include "src/lib/doslib/adlib.h" + +/* one per OPL channel */ +struct midi_note { + unsigned char note_number; + unsigned char note_velocity; + unsigned char note_track; /* from what MIDI track */ + unsigned char note_channel; /* from what MIDI channel */ + unsigned int busy:1; /* if occupied */ +}; + +struct midi_channel { + unsigned char program; +}; + +struct midi_track { + /* track data, raw */ + unsigned char* raw; /* raw data base */ + unsigned char* fence; /* raw data end (last byte + 1) */ + unsigned char* read; /* raw data read ptr */ + /* state */ + unsigned long us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */ + unsigned long us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */ + unsigned long wait; + unsigned char last_status; /* MIDI last status byte */ + unsigned int eof:1; /* we hit the end of the track */ +}; + +#define MIDI_MAX_CHANNELS 16 +#define MIDI_MAX_TRACKS 64 + +struct midi_note midi_notes[ADLIB_FM_VOICES]; +struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; +struct midi_track midi_trk[MIDI_MAX_TRACKS]; +static unsigned int midi_trk_count=0; +static volatile unsigned char midi_playing=0; + +/* MIDI params. Nobody ever said it was a straightforward standard! + * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */ +static unsigned int ticks_per_quarter_note=0; /* "Ticks per beat" */ + +static void (interrupt *old_irq0)(); +static volatile unsigned long irq0_ticks=0; +static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; + +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) +static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */ + return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p)); +} +#endif + +static inline unsigned char midi_trk_read(struct midi_track *t) { + unsigned char c; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return 0xFF; + } + + c = *(t->read); +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */ + t->read = MK_FP(FP_SEG(t->read)+0x1,0); + else + t->read++; +#else + t->read++; +#endif + return c; +} + +void midi_trk_end(struct midi_track *t) { + t->wait = ~0UL; + t->read = t->fence; +} + +void midi_trk_skip(struct midi_track *t,unsigned long len) { + unsigned long rem; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return; + + if (len > 0xFFF0UL) { + midi_trk_end(t); + return; + } +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned long tt; + + tt = farptr2phys(t->read); + rem = farptr2phys(t->fence) - tt; + if (rem > len) rem = len; + tt += rem; + t->read = MK_FP(tt>>4,tt&0xF); + } +#else + rem = (unsigned long)(t->fence - t->read); + if (len > rem) len = rem; + t->read += len; +#endif +} + +static const uint32_t midikeys_freqs[0x80] = { + 0x00082d01, /* key 0 = 8.17579891564371Hz */ + 0x0008a976, /* key 1 = 8.66195721802725Hz */ + 0x00092d51, /* key 2 = 9.17702399741899Hz */ + 0x0009b904, /* key 3 = 9.72271824131503Hz */ + 0x000a4d05, /* key 4 = 10.3008611535272Hz */ + 0x000ae9d3, /* key 5 = 10.9133822322814Hz */ + 0x000b8ff4, /* key 6 = 11.5623257097386Hz */ + 0x000c3ff6, /* key 7 = 12.2498573744297Hz */ + 0x000cfa70, /* key 8 = 12.9782717993733Hz */ + 0x000dc000, /* key 9 = 13.75Hz */ + 0x000e914f, /* key 10 = 14.5676175474403Hz */ + 0x000f6f11, /* key 11 = 15.4338531642539Hz */ + 0x00105a02, /* key 12 = 16.3515978312874Hz */ + 0x001152ec, /* key 13 = 17.3239144360545Hz */ + 0x00125aa2, /* key 14 = 18.354047994838Hz */ + 0x00137208, /* key 15 = 19.4454364826301Hz */ + 0x00149a0a, /* key 16 = 20.6017223070544Hz */ + 0x0015d3a6, /* key 17 = 21.8267644645627Hz */ + 0x00171fe9, /* key 18 = 23.1246514194771Hz */ + 0x00187fed, /* key 19 = 24.4997147488593Hz */ + 0x0019f4e0, /* key 20 = 25.9565435987466Hz */ + 0x001b8000, /* key 21 = 27.5Hz */ + 0x001d229e, /* key 22 = 29.1352350948806Hz */ + 0x001ede22, /* key 23 = 30.8677063285078Hz */ + 0x0020b404, /* key 24 = 32.7031956625748Hz */ + 0x0022a5d8, /* key 25 = 34.647828872109Hz */ + 0x0024b545, /* key 26 = 36.7080959896759Hz */ + 0x0026e410, /* key 27 = 38.8908729652601Hz */ + 0x00293414, /* key 28 = 41.2034446141087Hz */ + 0x002ba74d, /* key 29 = 43.6535289291255Hz */ + 0x002e3fd2, /* key 30 = 46.2493028389543Hz */ + 0x0030ffda, /* key 31 = 48.9994294977187Hz */ + 0x0033e9c0, /* key 32 = 51.9130871974931Hz */ + 0x00370000, /* key 33 = 55Hz */ + 0x003a453d, /* key 34 = 58.2704701897612Hz */ + 0x003dbc44, /* key 35 = 61.7354126570155Hz */ + 0x00416809, /* key 36 = 65.4063913251497Hz */ + 0x00454bb0, /* key 37 = 69.295657744218Hz */ + 0x00496a8b, /* key 38 = 73.4161919793519Hz */ + 0x004dc820, /* key 39 = 77.7817459305202Hz */ + 0x00526829, /* key 40 = 82.4068892282175Hz */ + 0x00574e9b, /* key 41 = 87.307057858251Hz */ + 0x005c7fa4, /* key 42 = 92.4986056779086Hz */ + 0x0061ffb5, /* key 43 = 97.9988589954373Hz */ + 0x0067d380, /* key 44 = 103.826174394986Hz */ + 0x006e0000, /* key 45 = 110Hz */ + 0x00748a7b, /* key 46 = 116.540940379522Hz */ + 0x007b7888, /* key 47 = 123.470825314031Hz */ + 0x0082d012, /* key 48 = 130.812782650299Hz */ + 0x008a9760, /* key 49 = 138.591315488436Hz */ + 0x0092d517, /* key 50 = 146.832383958704Hz */ + 0x009b9041, /* key 51 = 155.56349186104Hz */ + 0x00a4d053, /* key 52 = 164.813778456435Hz */ + 0x00ae9d36, /* key 53 = 174.614115716502Hz */ + 0x00b8ff49, /* key 54 = 184.997211355817Hz */ + 0x00c3ff6a, /* key 55 = 195.997717990875Hz */ + 0x00cfa700, /* key 56 = 207.652348789973Hz */ + 0x00dc0000, /* key 57 = 220Hz */ + 0x00e914f6, /* key 58 = 233.081880759045Hz */ + 0x00f6f110, /* key 59 = 246.941650628062Hz */ + 0x0105a025, /* key 60 = 261.625565300599Hz */ + 0x01152ec0, /* key 61 = 277.182630976872Hz */ + 0x0125aa2e, /* key 62 = 293.664767917408Hz */ + 0x01372082, /* key 63 = 311.126983722081Hz */ + 0x0149a0a7, /* key 64 = 329.62755691287Hz */ + 0x015d3a6d, /* key 65 = 349.228231433004Hz */ + 0x0171fe92, /* key 66 = 369.994422711634Hz */ + 0x0187fed4, /* key 67 = 391.995435981749Hz */ + 0x019f4e00, /* key 68 = 415.304697579945Hz */ + 0x01b80000, /* key 69 = 440Hz */ + 0x01d229ec, /* key 70 = 466.16376151809Hz */ + 0x01ede220, /* key 71 = 493.883301256124Hz */ + 0x020b404a, /* key 72 = 523.251130601197Hz */ + 0x022a5d81, /* key 73 = 554.365261953744Hz */ + 0x024b545c, /* key 74 = 587.329535834815Hz */ + 0x026e4104, /* key 75 = 622.253967444162Hz */ + 0x0293414f, /* key 76 = 659.25511382574Hz */ + 0x02ba74da, /* key 77 = 698.456462866008Hz */ + 0x02e3fd24, /* key 78 = 739.988845423269Hz */ + 0x030ffda9, /* key 79 = 783.990871963499Hz */ + 0x033e9c01, /* key 80 = 830.60939515989Hz */ + 0x03700000, /* key 81 = 880Hz */ + 0x03a453d8, /* key 82 = 932.32752303618Hz */ + 0x03dbc440, /* key 83 = 987.766602512248Hz */ + 0x04168094, /* key 84 = 1046.50226120239Hz */ + 0x0454bb03, /* key 85 = 1108.73052390749Hz */ + 0x0496a8b8, /* key 86 = 1174.65907166963Hz */ + 0x04dc8208, /* key 87 = 1244.50793488832Hz */ + 0x0526829e, /* key 88 = 1318.51022765148Hz */ + 0x0574e9b5, /* key 89 = 1396.91292573202Hz */ + 0x05c7fa49, /* key 90 = 1479.97769084654Hz */ + 0x061ffb53, /* key 91 = 1567.981743927Hz */ + 0x067d3802, /* key 92 = 1661.21879031978Hz */ + 0x06e00000, /* key 93 = 1760Hz */ + 0x0748a7b1, /* key 94 = 1864.65504607236Hz */ + 0x07b78880, /* key 95 = 1975.5332050245Hz */ + 0x082d0128, /* key 96 = 2093.00452240479Hz */ + 0x08a97607, /* key 97 = 2217.46104781498Hz */ + 0x092d5171, /* key 98 = 2349.31814333926Hz */ + 0x09b90410, /* key 99 = 2489.01586977665Hz */ + 0x0a4d053c, /* key 100 = 2637.02045530296Hz */ + 0x0ae9d36b, /* key 101 = 2793.82585146403Hz */ + 0x0b8ff493, /* key 102 = 2959.95538169308Hz */ + 0x0c3ff6a7, /* key 103 = 3135.96348785399Hz */ + 0x0cfa7005, /* key 104 = 3322.43758063956Hz */ + 0x0dc00000, /* key 105 = 3520Hz */ + 0x0e914f62, /* key 106 = 3729.31009214472Hz */ + 0x0f6f1100, /* key 107 = 3951.06641004899Hz */ + 0x105a0250, /* key 108 = 4186.00904480958Hz */ + 0x1152ec0e, /* key 109 = 4434.92209562995Hz */ + 0x125aa2e3, /* key 110 = 4698.63628667852Hz */ + 0x13720820, /* key 111 = 4978.03173955329Hz */ + 0x149a0a79, /* key 112 = 5274.04091060592Hz */ + 0x15d3a6d6, /* key 113 = 5587.65170292806Hz */ + 0x171fe927, /* key 114 = 5919.91076338615Hz */ + 0x187fed4e, /* key 115 = 6271.92697570799Hz */ + 0x19f4e00a, /* key 116 = 6644.87516127912Hz */ + 0x1b800000, /* key 117 = 7040Hz */ + 0x1d229ec4, /* key 118 = 7458.62018428944Hz */ + 0x1ede2200, /* key 119 = 7902.13282009799Hz */ + 0x20b404a1, /* key 120 = 8372.01808961916Hz */ + 0x22a5d81c, /* key 121 = 8869.84419125991Hz */ + 0x24b545c7, /* key 122 = 9397.27257335704Hz */ + 0x26e41040, /* key 123 = 9956.06347910659Hz */ + 0x293414f2, /* key 124 = 10548.0818212118Hz */ + 0x2ba74dac, /* key 125 = 11175.3034058561Hz */ + 0x2e3fd24f, /* key 126 = 11839.8215267723Hz */ + 0x30ffda9c /* key 127 = 12543.853951416Hz */ +}; + +static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) { + return midikeys_freqs[key&0x7F]; +} + +static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) { + unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */ + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i,freen=~0; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy) { + if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key) + return &midi_notes[i]; + } + else { + if (freen == ~0) freen = i; + } + } + + if (do_alloc && freen != ~0) return &midi_notes[freen]; + return NULL; +} + +static void drop_fm_note(struct midi_channel *ch,unsigned char key) { + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy && midi_notes[i].note_channel == ach) { + midi_notes[i].busy = 0; + break; + } + } +} + +static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + /* HACK: Ignore percussion */ + if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ || + (ch->program >= 112 && ch->program <= 119)/*Percussive*/ || + ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/) + return; + + if (note == NULL) { + /* then we'll have to knock one off to make room */ + drop_fm_note(ch,key); + note = get_fm_note(t,ch,key,1); + if (note == NULL) return; + } + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 0; + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 0; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) { +} + +static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) { + ch->program = inst; +} + +static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) { +} + +static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) { +} + +unsigned long midi_trk_read_delta(struct midi_track *t) { + unsigned long tc = 0; + unsigned char c = 0,b; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return tc; + + while (c < 4) { + b = midi_trk_read(t); + tc = (tc << 7UL) + (unsigned long)(b&0x7F); + if (!(b&0x80)) break; + c++; + } + + return tc; +} + +void midi_tick_track(unsigned int i) { + struct midi_track *t = midi_trk + i; + struct midi_channel *ch; + unsigned char b,c,d; + int cnt=0; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return; + } + + t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note; + while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) { + t->us_tick_cnt_mtpq -= t->us_per_quarter_note; + cnt++; + + while (t->wait == 0) { + if ((unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + break; + } + + /* read pointer should be pointing at MIDI event bytes, just after the time delay */ + b = midi_trk_read(t); + if (b&0x80) { + if (b < 0xF8) { + if (b >= 0xF0) + t->last_status = 0; + else + t->last_status = b; + } + if (b != 0x00 && ((b&0xF8) != 0xF0)) + c = midi_trk_read(t); + } + else { + /* blegh. last status */ + c = b; + b = t->last_status; + } + switch (b>>4) { + case 0x8: { /* note off */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_off(t,ch,c,d); + } break; + case 0x9: { /* note on */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */ + else on_key_off(t,ch,c,d); + } break; + case 0xA: { /* polyphonic aftertouch */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_aftertouch(t,ch,c,d); + } break; + case 0xB: { /* control change */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_control_change(t,ch,c,d); + } break; + case 0xC: { /* program change */ + on_program_change(t,ch,c); /* c=instrument d=not used */ + } break; + case 0xD: { /* channel aftertouch */ + on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */ + } break; + case 0xE: { /* pitch bend */ + d = midi_trk_read(t); + on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */ + } break; + case 0xF: { /* event */ + if (b == 0xFF) { + if (c == 0x7F) { /* c=type d=len */ + unsigned long len = midi_trk_read_delta(t); +// fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); + if (len < 512UL) { + /* unknown */ + midi_trk_skip(t,len); + } + else { + midi_trk_end(t); + } + } + else if (c < 0x7F) { + d = midi_trk_read(t); + + if (c == 0x51 && d >= 3) { + d -= 3; + t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+ + ((unsigned long)midi_trk_read(t)<<8UL)+ + ((unsigned long)midi_trk_read(t)<<0UL); + + if (1/*TODO: If format 0 or format 1*/) { + /* Ugh. Unless format 2, the tempo applies to all tracks */ + int j; + + for (j=0;j < midi_trk_count;j++) { + if (j != i) midi_trk[j].us_per_quarter_note = + t->us_per_quarter_note; + } + } + } + else { +// fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence); + } + + midi_trk_skip(t,d); + } + else { + fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence); + } + } + else { + unsigned long len = midi_trk_read_delta(t); +// fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); + midi_trk_skip(t,len); + } + } break; + default: + if (b != 0x00) { + fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence); + midi_trk_end(t); + } + break; + }; + + /* and then read the next event */ + t->wait = midi_trk_read_delta(t); + } + if (t->wait != 0) { + t->wait--; + } + } +} + +void adlib_shut_up(); +void midi_reset_tracks(); +void midi_reset_channels(); + +void midi_tick() { + if (midi_playing) { + unsigned int i; + int eof=0; + + for (i=0;i < midi_trk_count;i++) { + midi_tick_track(i); + eof += midi_trk[i].eof?1:0; + } + + if (eof >= midi_trk_count) { + adlib_shut_up(); + midi_reset_tracks(); + midi_reset_channels(); + } + } +} + +/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ +void interrupt irq0() { +// midi_tick(); + irq0_ticks++; + if ((irq0_cnt += irq0_add) >= irq0_max) { + irq0_cnt -= irq0_max; + old_irq0(); + } + else { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } +} + +void adlib_shut_up() { + int i; + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + midi_notes[i].busy = 0; + midi_notes[i].note_channel = 0; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 400; + f->sustain = 1; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 0; + f->sustain = 1; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); +} + +void midi_reset_track(unsigned int i) { + struct midi_track *t; + + if (i >= MIDI_MAX_TRACKS) return; + t = &midi_trk[i]; + t->eof = 0; + t->last_status = 0; + t->us_tick_cnt_mtpq = 0; + t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */ + t->read = midi_trk[i].raw; + t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */ +} + +void midi_reset_tracks() { + int i; + + for (i=0;i < midi_trk_count;i++) + midi_reset_track(i); +} + +void midi_reset_channels() { + int i; + + for (i=0;i < MIDI_MAX_CHANNELS;i++) { + midi_ch[i].program = 0; + } +} + +int load_midi_file(const char *path) { + unsigned char tmp[256]; + unsigned int tracks=0; + unsigned int tracki=0; + int fd; + + fd = open(path,O_RDONLY|O_BINARY); + if (fd < 0) { + printf("Failed to load file %s\n",path); + return 0; + } + + ticks_per_quarter_note = 0; + while (read(fd,tmp,8) == 8) { + uint32_t sz; + + sz = ((uint32_t)tmp[4] << (uint32_t)24) | + ((uint32_t)tmp[5] << (uint32_t)16) | + ((uint32_t)tmp[6] << (uint32_t)8) | + ((uint32_t)tmp[7] << (uint32_t)0); + if (!memcmp(tmp,"MThd",4)) { + unsigned short t,tdiv; + + if (sz < 6 || sz > 255) { + fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz); + goto err; + } + if (read(fd,tmp,(int)sz) != (int)sz) { + fprintf(stderr,"MThd read error\n"); + goto err; + } + + /* byte 0-1 = format type (0,1 or 2) */ + /* byte 2-3 = number of tracks */ + /* byte 4-5 = time divison */ + t = tmp[1] | (tmp[0] << 8); + if (t > 1) { + fprintf(stderr,"MThd type %u not supported\n",t); + goto err; /* we only take type 0 or 1, don't support 2 */ + } + tracks = tmp[3] | (tmp[2] << 8); + if (tracks > MIDI_MAX_TRACKS) { + fprintf(stderr,"MThd too many (%u) tracks\n",tracks); + goto err; + } + tdiv = tmp[5] | (tmp[4] << 8); + if (tdiv & 0x8000) { + fprintf(stderr,"MThd SMPTE time division not supported\n"); + goto err; /* we do not support the SMPTE form */ + } + if (tdiv == 0) { + fprintf(stderr,"MThd time division == 0\n"); + goto err; + } + ticks_per_quarter_note = tdiv; + } + else if (!memcmp(tmp,"MTrk",4)) { + if (sz == 0UL) continue; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (sz > (640UL << 10UL)) goto err; /* 640KB */ +#elif TARGET_MSDOS == 32 + if (sz > (1UL << 20UL)) goto err; /* 1MB */ +#else + if (sz > (60UL << 10UL)) goto err; /* 60KB */ +#endif + if (tracki >= MIDI_MAX_TRACKS) goto err; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned segv; + + /* NTS: _fmalloc() is still limited to 64KB sizes */ + if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err; + midi_trk[tracki].raw = MK_FP(segv,0); + } +#else + midi_trk[tracki].raw = malloc(sz); +#endif + if (midi_trk[tracki].raw == NULL) goto err; + midi_trk[tracki].read = midi_trk[tracki].raw; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned char far *p = midi_trk[tracki].raw; + unsigned long rem = (unsigned long)sz; + unsigned long cando; + unsigned read; + + while (rem != 0UL) { + read = 0; + + cando = 0x10000UL - (unsigned long)FP_OFF(p); + if (cando > rem) cando = rem; + if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */ + + if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err; + if (read != (unsigned)cando) goto err; + + rem -= cando; + if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL) + p = MK_FP(FP_SEG(p)+0x1000,0); + else + p += (unsigned)cando; + } + + cando = farptr2phys(p); + midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF); + } +#else + midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz; + if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err; +#endif + tracki++; + } + else { + fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]); + goto err; + } + } + if (tracki == 0 || ticks_per_quarter_note == 0) goto err; + midi_trk_count = tracki; + + fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note); + + close(fd); + return 1; +err: + close(fd); + return 0; +} + +int main(int argc,char **argv) { + unsigned long ptick; + int i,c; + + printf("ADLIB FM test program\n"); + if (argc < 2) { + printf("You must specify a MIDI file to play\n"); + return 1; + } + + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + if (!probe_8254()) { /* we need the timer to keep time with the music */ + printf("8254 timer not found\n"); + return 1; + } + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + midi_trk[i].raw = NULL; + midi_trk[i].read = NULL; + midi_trk[i].fence = NULL; + } + + if (load_midi_file(argv[1]) == 0) { + printf("Failed to load MIDI\n"); + return 1; + } + + write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */ + irq0_cnt = 0; + irq0_add = 182; + irq0_max = 1000; /* about 18.2Hz */ + old_irq0 = _dos_getvect(8);/*IRQ0*/ + _dos_setvect(8,irq0); + + adlib_shut_up(); + midi_reset_channels(); + midi_reset_tracks(); + _cli(); + irq0_ticks = ptick = 0; + _sti(); + midi_playing = 1; + + while (1) { + unsigned long adv; + + _cli(); + adv = irq0_ticks - ptick; + if (adv >= 100UL) adv = 100UL; + ptick = irq0_ticks; + _sti(); + + while (adv != 0) { + midi_tick(); + adv--; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + } + } + + midi_playing = 0; + adlib_shut_up(); + shutdown_adlib(); + _dos_setvect(8,old_irq0); + write_8254_system_timer(0); /* back to normal 18.2Hz */ + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + if (midi_trk[i].raw) { +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */ +#else + free(midi_trk[i].raw); +#endif + midi_trk[i].raw = NULL; + } + midi_trk[i].fence = NULL; + midi_trk[i].read = NULL; + } + + return 0; +} diff --git a/src/miditest.c b/src/miditest.c index 73b47057..ade69519 100755 --- a/src/miditest.c +++ b/src/miditest.c @@ -1,112 +1,112 @@ -/* miditest.c - * - * Adlib OPL2/OPL3 FM synthesizer chipset test program. - * Play MIDI file using the OPLx synthesizer (well, poorly anyway) - * (C) 2010-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - * - * Compiles for intended target environments: - * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] - */ - -#include "src/lib/midi.h" - -int main(int argc,char **argv) { - unsigned long ptick; - int i,c; - - printf("ADLIB FM test program\n"); - if (argc < 2) { - printf("You must specify a MIDI file to play\n"); - return 1; - } - - /*if (!probe_vga()) { - printf("Cannot init VGA\n"); - return 1; - }*/ - if (!init_adlib()) { - printf("Cannot init library\n"); - return 1; - } - if (!probe_8254()) { /* we need the timer to keep time with the music */ - printf("8254 timer not found\n"); - return 1; - } - - for (i=0;i < MIDI_MAX_TRACKS;i++) { - midi_trk[i].raw = NULL; - midi_trk[i].read = NULL; - midi_trk[i].fence = NULL; - } - - if (load_midi_file(argv[1]) == 0) { - printf("Failed to load MIDI\n"); - return 1; - } - - write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */ - irq0_cnt = 0; - irq0_add = 182; - irq0_max = 1000; /* about 18.2Hz */ - old_irq0 = _dos_getvect(8);/*IRQ0*/ - _dos_setvect(8,irq0); - - //adlib_shut_up(); - midi_reset_channels(); - midi_reset_tracks(); - _cli(); - irq0_ticks = ptick = 0; - _sti(); - midi_playing = 1; - - while (1) { - unsigned long adv; - - _cli(); - adv = irq0_ticks - ptick; - //adv = ptick; - if (adv >= 100UL) adv = 100UL; - ptick = irq0_ticks; - //ptick++; - _sti(); - - while (adv != 0) { - midi_tick(); - adv--; - } - - if (kbhit()) { - c = getch(); - if (c == 0) c = getch() << 8; - - if (c == 27) { - break; - } - } - } - - midi_playing = 0; - //adlib_shut_up(); - shutdown_adlib(); - _dos_setvect(8,old_irq0); - write_8254_system_timer(0); /* back to normal 18.2Hz */ - - for (i=0;i < MIDI_MAX_TRACKS;i++) { - if (midi_trk[i].raw) { -#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) - _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */ -#else - free(midi_trk[i].raw); -#endif - midi_trk[i].raw = NULL; - } - midi_trk[i].fence = NULL; - midi_trk[i].read = NULL; - } - - return 0; -} +/* miditest.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include "src/lib/midi.h" + +int main(int argc,char **argv) { + unsigned long ptick; + int i,c; + + printf("ADLIB FM test program\n"); + if (argc < 2) { + printf("You must specify a MIDI file to play\n"); + return 1; + } + + /*if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + }*/ + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + if (!probe_8254()) { /* we need the timer to keep time with the music */ + printf("8254 timer not found\n"); + return 1; + } + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + midi_trk[i].raw = NULL; + midi_trk[i].read = NULL; + midi_trk[i].fence = NULL; + } + + if (load_midi_file(argv[1]) == 0) { + printf("Failed to load MIDI\n"); + return 1; + } + + write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */ + irq0_cnt = 0; + irq0_add = 182; + irq0_max = 1000; /* about 18.2Hz */ + old_irq0 = _dos_getvect(8);/*IRQ0*/ + _dos_setvect(8,irq0); + + //adlib_shut_up(); + midi_reset_channels(); + midi_reset_tracks(); + _cli(); + irq0_ticks = ptick = 0; + _sti(); + midi_playing = 1; + + while (1) { + unsigned long adv; + + _cli(); + adv = irq0_ticks - ptick; + //adv = ptick; + if (adv >= 100UL) adv = 100UL; + ptick = irq0_ticks; + //ptick++; + _sti(); + + while (adv != 0) { + midi_tick(); + adv--; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + } + } + + midi_playing = 0; + //adlib_shut_up(); + shutdown_adlib(); + _dos_setvect(8,old_irq0); + write_8254_system_timer(0); /* back to normal 18.2Hz */ + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + if (midi_trk[i].raw) { +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */ +#else + free(midi_trk[i].raw); +#endif + midi_trk[i].raw = NULL; + } + midi_trk[i].fence = NULL; + midi_trk[i].read = NULL; + } + + return 0; +} diff --git a/src/scroll.c b/src/scroll.c index 2746ca4f..e638df1b 100755 --- a/src/scroll.c +++ b/src/scroll.c @@ -1,368 +1,368 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "src/lib/scroll16.h" -#include "src/lib/16_timer.h" -#include "src/lib/wcpu/wcpu.h" - -//#define FADE -#define MODEX //this is for mode x initiating - -//word far *clock= (word far*) 0x046C; /* 18.2hz clock */ -//bitmap_t *p; -global_game_variables_t gvar; -static map_t map; -player_t player[MaxPlayers]; -map_view_t mv[4]; -//word pn=0; //i forgot ww -float t; -sword bakapee; -pan_t pan; -//debugswitches -boolean panswitch=0; -//extern boolean pageflipflop=1; - unsigned int i; - const char *cpus; - //static int persist_aniframe = 0; /* gonna be increased to 1 before being used, so 0 is ok for default */ - - //map_view_db_t pgid[4]; - word pg; -//#ifdef FADE - static word paloffset=0; - byte *dpal; -//#endif - byte *gpal; - byte *ptr; - byte *mappalptr; - -void main(int argc, char *argv[]) -{ - byte *mesg=malloc(sizeof(dword)); - - if(argv[1]) bakapee = atoi(argv[1]); - else bakapee = 1; - - // DOSLIB: check our environment - probe_dos(); - - // DOSLIB: what CPU are we using? - // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. - // So this code by itself shouldn't care too much what CPU it's running on. Except that other - // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for - // the CPU to carry out tasks. --J.C. - cpu_probe(); - - // DOSLIB: check for VGA - if (!probe_vga()) { - printf("VGA probe failed\n"); - return; - } - // hardware must be VGA or higher! - if (!(vga_state.vga_flags & VGA_IS_VGA)) { - printf("This program requires VGA or higher graphics hardware\n"); - return; - } - - if (_DEBUG_INIT() == 0) { -#ifdef DEBUGSERIAL - printf("WARNING: Failed to initialize DEBUG output\n"); -#endif - } - _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log - _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U); - - pan.pn=1; - - start_timer(&gvar); - - /* create the map */ - fprintf(stderr, "testing map load~ "); - loadmap("data/test.map", &map); - chkmap(&map, 0); - printf("chkmap ok "); - fprintf(stderr, "yay map loaded~~\n"); - - /* draw the tiles */ -#ifdef MODEX - ptr = map.data; - //mappalptr = map.tiles->btdata->palette; - - /* data */ - player[0].data = malloc(48*128); //TODO use exmm - *player[0].data = bitmapLoadPcx("data/chikyuu.pcx"); // load sprite - - /* create the planar buffer */ -////++++ (player[0].data) = *planar_buf_from_bitmap(&p); - /*++++printf("load pee!! "); - pp = planar_buf_from_bitmap(&p); - printf("done!\n");*/ - -#endif - /* input! */ - IN_Startup(); - IN_Default(0,&player,ctrl_Joystick); - //IN_Default(1,&player,ctrl_Joystick); - - /* save the palette */ -#ifdef MODEX -#ifdef FADE - dpal = modexNewPal(); - modexPalSave(dpal); - modexFadeOff(4, dpal); -#endif - - textInit(); - VGAmodeX(bakapee, 1, &gvar); -// printf("%dx%d\n", gvar.video.page[0].sw, gvar.video.page[0].sh); -#ifdef FADE - modexPalBlack(); //reset the palette~ -#endif -#endif -// printf("Total used @ before palette initiation: %zu\n", oldfreemem-GetFreeSize()); -//++++ player[0].data.offset=(paloffset/3); -//++++ modexPalUpdate1(&player[0].data, &paloffset, 0, 0); - modexPalUpdate1(player[0].data->palette); -//++++0000 modexPalUpdate1(map.tiles->btdata->palette); - //printf(" %d\n", sizeof(ptmp->data)); - //printf("1: %d\n", paloffset); -//++++ map.tiles->data->offset=(paloffset/3); - //XTmodexPalUpdate(map.tiles->data, &paloffset, 0, 0); -// printf("\n====\n"); -// printf("0 paloffset= %d\n", paloffset/3); -// printf("====\n\n"); -#ifdef MODEX -#ifdef FADE - gpal = modexNewPal(); - modexPalSave(gpal); - modexSavePalFile("data/g.pal", gpal); - modexPalBlack(); //so player will not see loadings~ -#endif -#endif - - /* setup camera and screen~ */ - modexHiganbanaPageSetup(&gvar.video); - for(i=0;idata, mv[0].page->data, mv[0].page->pagesize); - - //TODO: put player in starting position of spot - //default player position on the viewable map - player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx; - player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny; - IN_initplayer(&player, 0); - //IN_initplayer(&player, 1); - -#ifndef SPRITE - modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); - //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); -#else - //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA); - PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32, player[0].data); -#endif - - if(!pageflipflop) modexShowPage(mv[1].page); - else modexShowPage(mv[0].page);//!(gvar.video.p) - shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible. - - /* buffer pages */ -// modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47); -// modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45); -// { -// unsigned int k,j,o; -// /* fill screen with a distinctive pattern */ -// for (k=0;k < vga_state.vga_width;k++) { -// o = k >> 2; -// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); -// for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) -// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! -// } -// } - modexClearRegion(mv[3].page, 0, 128, 24, 36, 15); - -#ifdef MODEX -#ifdef FADE - modexFadeOn(4, gpal); -#endif -#endif - while(!IN_KeyDown(sc_Escape) && player[0].hp>0) - { - shinku(&gvar); - //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square - //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction - //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map - - //player movement - IN_ReadControl(0,&player); - if(!panswitch){ - walk(mv, player, 0); - }else{ - panpagemanual(mv, player, 0); - //printf(" player[0].q: %d", player[0].q); printf(" player[0].d: %d\n", player[0].d); - } - - //the scripting stuff.... - //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) - if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) - { - short i; - for(i=800; i>=400; i--) - { - sound(i); - } - nosound(); - } - if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; } - //debugging binds! - if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; } - if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; } - if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; } - if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; } - if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page); - IN_UserInput(1,1); - } //p -#ifdef MODEX -#ifdef FADE - if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page); IN_UserInput(1,1); } - if(IN_KeyDown(22)){ - paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0); - printf("1paloffset = %d\n", paloffset/3); - modexPalUpdate(map.tiles->data, &paloffset, 0, 0); - printf("2paloffset = %d\n", paloffset/3); - modexpdump(mv[0].page); modexpdump(mv[1].page); - IN_UserInput(1,1); - } -#endif -#endif - //pan switch - if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);} //f12 - if(IN_KeyDown(87)) //f11 - { - pageflipflop=!pageflipflop; - IN_UserInput(1,1); -// VGAmodeX(0, 0, &gvar); -// IN_Shutdown(); -// __asm -// { -// mov ah,31h -// int 21h -// } - } - if(IN_KeyDown(68)) //f10 - { - gvar.kurokku.fpscap=!gvar.kurokku.fpscap; - IN_UserInput(1,1); - } - if(IN_KeyDown(67)) //f9 - { - modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2); - modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3); - modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4); - modexClearRegion(mv[3].page, 0, 0, 20, 36, 15); - //IN_UserInput(1,1); - } - if(IN_KeyDown(66)) //f8 - { -// modexDrawSprite(mv[0].page, 16, 16, p); - modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data)); - } - //TODO fmemtest into page - /*if(IN_KeyDown(4+1)) //4 - { - pg=1; - SELECT_ALL_PLANES(); - _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4); - }*/ - - //9 - if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); } - //if(IN_KeyDown(11)){ modexPalOverscan(15); } - if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break; //incase things go out of sync! - } - - /* fade back to text mode */ - /* but 1st lets save the game palette~ */ -#ifdef MODEX -#ifdef FADE - modexPalSave(gpal); - modexSavePalFile("data/g.pal", gpal); - modexFadeOff(4, gpal); -#endif - VGAmodeX(0, 1, &gvar); -#endif - IN_Shutdown(); - printf("\nProject 16 scroll.exe. This is just a test file!\n"); - printf("version %s\n", VERSION); - printf("tx: %d ", mv[0].tx); - printf("ty: %d\n", mv[0].ty); - printf("\n"); - printf("player vars:\n"); - printf(" x: %d", player[0].x); printf(" y: %d\n", player[0].y); - //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8); - //else printf("\nplayer[0].y: %d\n", player[0].y); - printf(" tx: %d", player[0].tx); printf(" ty: %d\n", player[0].ty); - printf(" triggx: %d", player[0].triggerx); printf(" triggy: %d\n", player[0].triggery); - printf(" hp: %d", (player[0].hp)); printf(" q: %d", player[0].q); printf(" player.info.dir: %d", player[0].info.dir); printf(" player.d: %d ", player[0].d); - printf(" pdir=%d\n", player[0].pdir); - printf(" tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]); -// printf("palette offset: %d\n", paloffset/3); -//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize()); -//++++ printf("Total free: %zu\n", GetFreeSize()); -//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n"); -//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n"); - printf("Virtual Screen: %dx", gvar.video.page[0].width); printf("%d ", gvar.video.page[0].height); - printf("Screen: %dx", gvar.video.page[0].sw); printf("%d\n", gvar.video.page[0].sh); - printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw); printf("%d ", gvar.video.page[0].tilesh); - printf("tile resolution: %dx", gvar.video.page[0].tw); printf("%d\n", gvar.video.page[0].th); - printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx); printf("%d\n", gvar.video.page[0].tilemidposscreeny); - modexprintmeminfo(&gvar.video); - //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf(" mv[%u].ty: %d ", pan.pn, mv[pan.pn].ty); - printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r); - printf("pageflipflop=%u\n", pageflipflop); - //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk); - //0000printf("gvar.video.clk=%f", gvar.video.clk); - printf("\n"); - //printf("map.width=%d map.height=%d map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]); - - printf("\n"); - switch(detectcpu()) - { - case 0: cpus = "8086/8088 or 186/88"; break; - case 1: cpus = "286"; break; - case 2: cpus = "386 or newer"; break; - default: cpus = "internal error"; break; - } - printf("detected CPU type: %s\n", cpus); -#ifdef MODEX -#ifdef FADE - modexFadeOn(4, dpal); -#endif -#endif -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/lib/scroll16.h" +#include "src/lib/16_timer.h" +#include "src/lib/wcpu/wcpu.h" + +//#define FADE +#define MODEX //this is for mode x initiating + +//word far *clock= (word far*) 0x046C; /* 18.2hz clock */ +//bitmap_t *p; +global_game_variables_t gvar; +static map_t map; +player_t player[MaxPlayers]; +map_view_t mv[4]; +//word pn=0; //i forgot ww +float t; +sword bakapee; +pan_t pan; +//debugswitches +boolean panswitch=0; +//extern boolean pageflipflop=1; + unsigned int i; + const char *cpus; + //static int persist_aniframe = 0; /* gonna be increased to 1 before being used, so 0 is ok for default */ + + //map_view_db_t pgid[4]; + word pg; +//#ifdef FADE + static word paloffset=0; + byte *dpal; +//#endif + byte *gpal; + byte *ptr; + byte *mappalptr; + +void main(int argc, char *argv[]) +{ + byte *mesg=malloc(sizeof(dword)); + + if(argv[1]) bakapee = atoi(argv[1]); + else bakapee = 1; + + // DOSLIB: check our environment + probe_dos(); + + // DOSLIB: what CPU are we using? + // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. + // So this code by itself shouldn't care too much what CPU it's running on. Except that other + // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for + // the CPU to carry out tasks. --J.C. + cpu_probe(); + + // DOSLIB: check for VGA + if (!probe_vga()) { + printf("VGA probe failed\n"); + return; + } + // hardware must be VGA or higher! + if (!(vga_state.vga_flags & VGA_IS_VGA)) { + printf("This program requires VGA or higher graphics hardware\n"); + return; + } + + if (_DEBUG_INIT() == 0) { +#ifdef DEBUGSERIAL + printf("WARNING: Failed to initialize DEBUG output\n"); +#endif + } + _DEBUG("Serial debug output started\n"); // NTS: All serial output must end messages with newline, or DOSBox-X will not emit text to log + _DEBUGF("Serial debug output printf test %u %u %u\n",1U,2U,3U); + + pan.pn=1; + + start_timer(&gvar); + + /* create the map */ + fprintf(stderr, "testing map load~ "); + loadmap("data/test.map", &map); + chkmap(&map, 0); + printf("chkmap ok "); + fprintf(stderr, "yay map loaded~~\n"); + + /* draw the tiles */ +#ifdef MODEX + ptr = map.data; + //mappalptr = map.tiles->btdata->palette; + + /* data */ + player[0].data = malloc(48*128); //TODO use exmm + *player[0].data = bitmapLoadPcx("data/chikyuu.pcx"); // load sprite + + /* create the planar buffer */ +////++++ (player[0].data) = *planar_buf_from_bitmap(&p); + /*++++printf("load pee!! "); + pp = planar_buf_from_bitmap(&p); + printf("done!\n");*/ + +#endif + /* input! */ + IN_Startup(); + IN_Default(0,&player,ctrl_Joystick); + //IN_Default(1,&player,ctrl_Joystick); + + /* save the palette */ +#ifdef MODEX +#ifdef FADE + dpal = modexNewPal(); + modexPalSave(dpal); + modexFadeOff(4, dpal); +#endif + + textInit(); + VGAmodeX(bakapee, 1, &gvar); +// printf("%dx%d\n", gvar.video.page[0].sw, gvar.video.page[0].sh); +#ifdef FADE + modexPalBlack(); //reset the palette~ +#endif +#endif +// printf("Total used @ before palette initiation: %zu\n", oldfreemem-GetFreeSize()); +//++++ player[0].data.offset=(paloffset/3); +//++++ modexPalUpdate1(&player[0].data, &paloffset, 0, 0); + modexPalUpdate1(player[0].data->palette); +//++++0000 modexPalUpdate1(map.tiles->btdata->palette); + //printf(" %d\n", sizeof(ptmp->data)); + //printf("1: %d\n", paloffset); +//++++ map.tiles->data->offset=(paloffset/3); + //XTmodexPalUpdate(map.tiles->data, &paloffset, 0, 0); +// printf("\n====\n"); +// printf("0 paloffset= %d\n", paloffset/3); +// printf("====\n\n"); +#ifdef MODEX +#ifdef FADE + gpal = modexNewPal(); + modexPalSave(gpal); + modexSavePalFile("data/g.pal", gpal); + modexPalBlack(); //so player will not see loadings~ +#endif +#endif + + /* setup camera and screen~ */ + modexHiganbanaPageSetup(&gvar.video); + for(i=0;idata, mv[0].page->data, mv[0].page->pagesize); + + //TODO: put player in starting position of spot + //default player position on the viewable map + player[0].tx = mv[0].tx + mv[0].page->tilemidposscreenx; + player[0].ty = mv[0].ty + mv[0].page->tilemidposscreeny; + IN_initplayer(&player, 0); + //IN_initplayer(&player, 1); + +#ifndef SPRITE + modexClearRegion(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); + //modexClearRegion(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 32, 15); +#else + //PBUFSFUN(mv[1].page, player[0].x, player[0].y-TILEWH, 16, 64, 24, 32, PLAYERBMPDATA); + PBUFSFUN(mv[0].page, player[0].x, player[0].y-TILEWH, 16, 64, 16, 32, player[0].data); +#endif + + if(!pageflipflop) modexShowPage(mv[1].page); + else modexShowPage(mv[0].page);//!(gvar.video.p) + shinku_fps_indicator_page = 0; // we're on page 1 now, shinku(). follow along please or it will not be visible. + + /* buffer pages */ +// modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 47); +// modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 45); +// { +// unsigned int k,j,o; +// /* fill screen with a distinctive pattern */ +// for (k=0;k < vga_state.vga_width;k++) { +// o = k >> 2; +// vga_write_sequencer(0x02/*map mask*/,1 << (k&3)); +// for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) +// vga_state.vga_graphics_ram[o] = (k^j)&15; // VRL samples put all colors in first 15! +// } +// } + modexClearRegion(mv[3].page, 0, 128, 24, 36, 15); + +#ifdef MODEX +#ifdef FADE + modexFadeOn(4, gpal); +#endif +#endif + while(!IN_KeyDown(sc_Escape) && player[0].hp>0) + { + shinku(&gvar); + //top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square + //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction + //when player[0].tx or player[0].ty == 0 or player[0].tx == 20 or player[0].ty == 15 then stop because that is edge of map and you do not want to walk of the map + + //player movement + IN_ReadControl(0,&player); + if(!panswitch){ + walk(mv, player, 0); + }else{ + panpagemanual(mv, player, 0); + //printf(" player[0].q: %d", player[0].q); printf(" player[0].d: %d\n", player[0].d); + } + + //the scripting stuff.... + //if(((player[0].triggerx == TRIGGX && player[0].triggery == TRIGGY) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) + if(((mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))] == 0) && IN_KeyDown(0x1C))||(player[0].tx == 5 && player[0].ty == 5)) + { + short i; + for(i=800; i>=400; i--) + { + sound(i); + } + nosound(); + } + if(player[0].q == (TILEWH/(player[0].speed))+1 && player[0].info.dir != 2 && (player[0].triggerx == 5 && player[0].triggery == 5)){ player[0].hp--; } + //debugging binds! + if(IN_KeyDown(2)){ modexShowPage(mv[0].page); pan.pn=0; } + if(IN_KeyDown(3)){ modexShowPage(mv[1].page); pan.pn=1; } + if(IN_KeyDown(4)){ modexShowPage(mv[2].page); pan.pn=2; } + if(IN_KeyDown(4+1)){ modexShowPage(mv[3].page); pan.pn=3; } + if(IN_KeyDown(25)){ modexpdump(mv[0].page); modexpdump(mv[1].page); + IN_UserInput(1,1); + } //p +#ifdef MODEX +#ifdef FADE + if(IN_KeyDown(24)){ modexPalUpdate0(gpal); paloffset=0; modexpdump(mv[0].page); modexpdump(mv[1].page); IN_UserInput(1,1); } + if(IN_KeyDown(22)){ + paloffset=0; modexPalBlack(); modexPalUpdate(player[0].data, &paloffset, 0, 0); + printf("1paloffset = %d\n", paloffset/3); + modexPalUpdate(map.tiles->data, &paloffset, 0, 0); + printf("2paloffset = %d\n", paloffset/3); + modexpdump(mv[0].page); modexpdump(mv[1].page); + IN_UserInput(1,1); + } +#endif +#endif + //pan switch + if(IN_KeyDown(88)){panswitch=!panswitch; IN_UserInput(1,1);} //f12 + if(IN_KeyDown(87)) //f11 + { + pageflipflop=!pageflipflop; + IN_UserInput(1,1); +// VGAmodeX(0, 0, &gvar); +// IN_Shutdown(); +// __asm +// { +// mov ah,31h +// int 21h +// } + } + if(IN_KeyDown(68)) //f10 + { + gvar.kurokku.fpscap=!gvar.kurokku.fpscap; + IN_UserInput(1,1); + } + if(IN_KeyDown(67)) //f9 + { + modexClearRegion(mv[1].page, 0, 0, mv[1].page->width, mv[1].page->height, 2); + modexClearRegion(mv[2].page, 0, 0, mv[2].page->width, mv[2].page->height, 3); + modexClearRegion(mv[3].page, 0, 0, mv[3].page->width, mv[3].page->height, 4); + modexClearRegion(mv[3].page, 0, 0, 20, 36, 15); + //IN_UserInput(1,1); + } + if(IN_KeyDown(66)) //f8 + { +// modexDrawSprite(mv[0].page, 16, 16, p); + modexDrawSprite(mv[0].page, 32+48, 16, (player[0].data)); + } + //TODO fmemtest into page + /*if(IN_KeyDown(4+1)) //4 + { + pg=1; + SELECT_ALL_PLANES(); + _fmemset(((mv[pg].page->data+4)+(16*(mv[pg].page->width/4))), 15, 4); + }*/ + + //9 + if(IN_KeyDown(10)){ modexPalOverscan(rand()%56); modexPalUpdate1(dpal); IN_UserInput(1,1); } + //if(IN_KeyDown(11)){ modexPalOverscan(15); } + if((player[0].q==1) && !(player[0].x%TILEWH==0 && player[0].y%TILEWH==0)) break; //incase things go out of sync! + } + + /* fade back to text mode */ + /* but 1st lets save the game palette~ */ +#ifdef MODEX +#ifdef FADE + modexPalSave(gpal); + modexSavePalFile("data/g.pal", gpal); + modexFadeOff(4, gpal); +#endif + VGAmodeX(0, 1, &gvar); +#endif + IN_Shutdown(); + printf("\nProject 16 scroll.exe. This is just a test file!\n"); + printf("version %s\n", VERSION); + printf("tx: %d ", mv[0].tx); + printf("ty: %d\n", mv[0].ty); + printf("\n"); + printf("player vars:\n"); + printf(" x: %d", player[0].x); printf(" y: %d\n", player[0].y); + //if(player[0].hp==0) printf("%d wwww\n", player[0].y+8); + //else printf("\nplayer[0].y: %d\n", player[0].y); + printf(" tx: %d", player[0].tx); printf(" ty: %d\n", player[0].ty); + printf(" triggx: %d", player[0].triggerx); printf(" triggy: %d\n", player[0].triggery); + printf(" hp: %d", (player[0].hp)); printf(" q: %d", player[0].q); printf(" player.info.dir: %d", player[0].info.dir); printf(" player.d: %d ", player[0].d); + printf(" pdir=%d\n", player[0].pdir); + printf(" tile data value at player trigger position: %d\n\n", mv[0].map->data[(player[0].triggerx-1)+(map.width*(player[0].triggery-1))]); +// printf("palette offset: %d\n", paloffset/3); +//++++ printf("Total used: %zu\n", oldfreemem-GetFreeSize()); +//++++ printf("Total free: %zu\n", GetFreeSize()); +//not used now printf("temporary player sprite 0: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=45556867\n"); +//not used now printf("temporary player sprite 1: http://www.pixiv.net/member_illust.php?mode=medium&illust_id=44606385\n"); + printf("Virtual Screen: %dx", gvar.video.page[0].width); printf("%d ", gvar.video.page[0].height); + printf("Screen: %dx", gvar.video.page[0].sw); printf("%d\n", gvar.video.page[0].sh); + printf("virtual tile resolution: %dx", gvar.video.page[0].tilesw); printf("%d ", gvar.video.page[0].tilesh); + printf("tile resolution: %dx", gvar.video.page[0].tw); printf("%d\n", gvar.video.page[0].th); + printf("middle tile position: %dx", gvar.video.page[0].tilemidposscreenx); printf("%d\n", gvar.video.page[0].tilemidposscreeny); + modexprintmeminfo(&gvar.video); + //printf("mv[%u].tx: %d", pan.pn, mv[pan.pn].tx); printf(" mv[%u].ty: %d ", pan.pn, mv[pan.pn].ty); + printf("gvar.video.p=%u ", gvar.video.p); printf("gvar.video.r=%u ", gvar.video.r); + printf("pageflipflop=%u\n", pageflipflop); + //0000printf("\ngvar.video.tickclk=%f\n", gvar.video.tickclk); + //0000printf("gvar.video.clk=%f", gvar.video.clk); + printf("\n"); + //printf("map.width=%d map.height=%d map.data[0]=%d\n", mv[0].map->width, mv[0].map->height, mv[0].map->data[0]); + + printf("\n"); + switch(detectcpu()) + { + case 0: cpus = "8086/8088 or 186/88"; break; + case 1: cpus = "286"; break; + case 2: cpus = "386 or newer"; break; + default: cpus = "internal error"; break; + } + printf("detected CPU type: %s\n", cpus); +#ifdef MODEX +#ifdef FADE + modexFadeOn(4, dpal); +#endif +#endif +} diff --git a/src/testemm.c b/src/testemm.c index b78f449e..40a2ac41 100755 --- a/src/testemm.c +++ b/src/testemm.c @@ -1,275 +1,275 @@ -/* testemm.c - * - * Test program: Expanded Memory Manager functions - * (C) 2011-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -//#include "src/lib/doslib/cpu.h" -#include "src/lib/doslib/dos.h" -#include "src/lib/doslib/emm.h" -//#include - -static const char *message = "Hello world. How are you?"; -static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; -static char tmp[128],tmp2[128]; -extern int probe_emm0(); - -#if 1 -# define x_memcpy(a,b,c) memcpy(a,b,c) -#else -/* what have we come to when friggin' memcpy() causes a GPF?!? */ -static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { - fprintf(stderr,"memcpy %p -> %p (%lu)\n", - dst,src,(unsigned long)c); - - while (c != 0) { - *dst++ = *src++; - c--; - } -} -#endif - -int main() { - size_t message_l = strlen(message),message2_l = strlen(message2); - - probe_dos(); - printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); - /*if (detect_windows()) { - printf("I am running under Windows.\n"); - printf(" Mode: %s\n",windows_mode_str(windows_mode)); - printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); - } - else { - printf("Not running under Windows or OS/2\n"); - }*/ - - sanity(); - if (probe_emm()) { - int h1,h2,h3; - - sanity(); - printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); - emm_update_page_count(); - sanity(); - printf(" Unallocated pages: %u (%luKB)\n", - emm_unallocated_pages, - (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ - printf(" Total pages: %u (%luKB)\n", - emm_total_pages, - (unsigned long)emm_total_pages << 4UL); - printf(" Physical pages: %u (%luKB)\n", - emm_phys_pages, - (unsigned long)emm_phys_pages << 4UL); - - while (getch() != 13); - sanity(); - - /* print out the mapping table, if available */ - if (emm_phys_map != NULL) { - struct emm_phys_page_map *me; - unsigned int i; - - printf("Physical page to segment table\n"); - for (i=0;i < emm_phys_pages;i++) { - me = emm_phys_map + i; - printf(" %02x: 0x%04x",me->number,me->segment); - if ((i%5) == 4) printf("\n"); - } - printf("\n"); - sanity(); - } - - printf("Allocating EMM pages (1): "); - h1 = emm_alloc_pages(1); - sanity(); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (!emm_free_pages(h1)) printf("cannot free\n"); - } - else printf("FAILED\n"); - - printf("Allocating EMM pages (16KB): "); - h1 = emm_alloc_pages(1); - sanity(); - if (h1 >= 0) printf("OK, handle=%u\n",h1); - else printf("FAILED\n"); - - printf("Allocating EMM pages (1.6MB): "); - h2 = emm_alloc_pages(0x19999AUL >> 14UL); - sanity(); - if (h2 >= 0) printf("OK, handle=%u\n",h2); - else printf("FAILED\n"); - - printf("Allocating EMM pages (12MB): "); - h3 = emm_alloc_pages(0xC00000UL >> 14UL); - sanity(); - if (h3 >= 0) printf("OK, handle=%u\n",h3); - else printf("FAILED\n"); - - while (getch() != 13); - - if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); - sanity(); - if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); - sanity(); - if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); - sanity(); - - printf("Allocating EMM pages (32KB): "); - h1 = emm_alloc_pages(2); - sanity(); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { - unsigned int segm = emm_last_phys_page_segment(0); - printf("Seg %04x\n",segm); - sanity(); - if (segm > 0) { -#if TARGET_MSDOS == 16 - char far *ptr = MK_FP(segm,0); -#else - char *ptr = (char*)(segm << 4UL); -#endif - -#if TARGET_MSDOS == 16 - _fmemcpy(ptr,(char far*)message,message_l+1); - _fmemcpy((char far*)tmp,ptr,message_l+1); -#else - x_memcpy(ptr,message,message_l+1); - x_memcpy(tmp,ptr,message_l+1); -#endif - printf("After writing message there, I read back: '%s'\n",tmp); - - if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); - -#if TARGET_MSDOS == 16 - _fmemcpy(ptr,(char far*)message2,message2_l+1); - _fmemcpy((char far*)tmp,ptr,message2_l+1); -#else - x_memcpy(ptr,message2,message2_l+1); - x_memcpy(tmp,ptr,message2_l+1); -#endif - printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); - - if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); - -#if TARGET_MSDOS == 16 - _fmemcpy((char far*)tmp,ptr,message_l+1); -#else - x_memcpy(tmp,ptr,message_l+1); -#endif - printf("After mapping back to 1, I read back: '%s'\n",tmp); - - if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); - } - else { - printf("Cannot get segment\n"); - } - if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); - } - else { - printf("Cannot map\n"); - } - if (!emm_free_pages(h1)) printf("Cannot free\n"); - } - else printf("FAILED\n"); - - printf("Allocating EMM pages (32KB): "); - h1 = emm_alloc_pages(2); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && - emm_map_page(h1,/*physical*/1,/*logical*/1)) { - unsigned int seg1 = emm_last_phys_page_segment(0); - unsigned int seg2 = emm_last_phys_page_segment(1); - printf("Seg %04x,%04x\n",seg1,seg2); - if (seg1 > 0 && seg2 > 0) { -#if TARGET_MSDOS == 16 - char far *ptr1 = MK_FP(seg1,0); - char far *ptr2 = MK_FP(seg2,0); -#else - char *ptr1 = (char*)(seg1 << 4UL); - char *ptr2 = (char*)(seg2 << 4UL); -#endif - -#if TARGET_MSDOS == 16 - _fmemcpy(ptr1,(char far*)message,message_l+1); - _fmemcpy(ptr2,(char far*)message2,message2_l+1); -#else - memcpy(ptr1,message,message_l+1); - memcpy(ptr2,message2,message2_l+1); -#endif - -#if TARGET_MSDOS == 16 - _fmemcpy((char far*)tmp,ptr1,message_l+1); - _fmemcpy((char far*)tmp2,ptr2,message2_l+1); -#else - memcpy(tmp,ptr1,message_l+1); - memcpy(tmp2,ptr2,message2_l+1); -#endif - - printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); - - /* now swap the pages */ - if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); - if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); - -#if TARGET_MSDOS == 16 - _fmemcpy((char far*)tmp,ptr1,message2_l+1); - _fmemcpy((char far*)tmp2,ptr2,message_l+1); -#else - memcpy(tmp,ptr1,message2_l+1); - memcpy(tmp2,ptr2,message_l+1); -#endif - - printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); - } - else { - printf("Cannot get segment\n"); - } - if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); - } - else { - printf("Cannot map\n"); - } - if (!emm_free_pages(h1)) printf("Cannot free\n"); - } - else printf("FAILED\n"); - - getch(); - - /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. - * the host could have 256MB of total memory and it would still report 32MB in EMS */ - printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS"); - printf("Allocating EMM pages (48MB): "); - h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (!emm_free_pages(h1)) printf("cannot free\n"); - } - else printf("FAILED\n"); - - printf("Allocating EMM pages (96MB): "); - h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (!emm_free_pages(h1)) printf("cannot free\n"); - } - else printf("FAILED\n"); - } - - return 0; -} - +/* testemm.c + * + * Test program: Expanded Memory Manager functions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +//#include "src/lib/doslib/cpu.h" +#include "src/lib/doslib/dos.h" +#include "src/lib/doslib/emm.h" +//#include + +static const char *message = "Hello world. How are you?"; +static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; +static char tmp[128],tmp2[128]; +extern int probe_emm0(); + +#if 1 +# define x_memcpy(a,b,c) memcpy(a,b,c) +#else +/* what have we come to when friggin' memcpy() causes a GPF?!? */ +static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { + fprintf(stderr,"memcpy %p -> %p (%lu)\n", + dst,src,(unsigned long)c); + + while (c != 0) { + *dst++ = *src++; + c--; + } +} +#endif + +int main() { + size_t message_l = strlen(message),message2_l = strlen(message2); + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + /*if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + }*/ + + sanity(); + if (probe_emm()) { + int h1,h2,h3; + + sanity(); + printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); + emm_update_page_count(); + sanity(); + printf(" Unallocated pages: %u (%luKB)\n", + emm_unallocated_pages, + (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ + printf(" Total pages: %u (%luKB)\n", + emm_total_pages, + (unsigned long)emm_total_pages << 4UL); + printf(" Physical pages: %u (%luKB)\n", + emm_phys_pages, + (unsigned long)emm_phys_pages << 4UL); + + while (getch() != 13); + sanity(); + + /* print out the mapping table, if available */ + if (emm_phys_map != NULL) { + struct emm_phys_page_map *me; + unsigned int i; + + printf("Physical page to segment table\n"); + for (i=0;i < emm_phys_pages;i++) { + me = emm_phys_map + i; + printf(" %02x: 0x%04x",me->number,me->segment); + if ((i%5) == 4) printf("\n"); + } + printf("\n"); + sanity(); + } + + printf("Allocating EMM pages (1): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (16KB): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) printf("OK, handle=%u\n",h1); + else printf("FAILED\n"); + + printf("Allocating EMM pages (1.6MB): "); + h2 = emm_alloc_pages(0x19999AUL >> 14UL); + sanity(); + if (h2 >= 0) printf("OK, handle=%u\n",h2); + else printf("FAILED\n"); + + printf("Allocating EMM pages (12MB): "); + h3 = emm_alloc_pages(0xC00000UL >> 14UL); + sanity(); + if (h3 >= 0) printf("OK, handle=%u\n",h3); + else printf("FAILED\n"); + + while (getch() != 13); + + if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); + sanity(); + if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); + sanity(); + if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); + sanity(); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { + unsigned int segm = emm_last_phys_page_segment(0); + printf("Seg %04x\n",segm); + sanity(); + if (segm > 0) { +#if TARGET_MSDOS == 16 + char far *ptr = MK_FP(segm,0); +#else + char *ptr = (char*)(segm << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message,message_l+1); + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(ptr,message,message_l+1); + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After writing message there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message2,message2_l+1); + _fmemcpy((char far*)tmp,ptr,message2_l+1); +#else + x_memcpy(ptr,message2,message2_l+1); + x_memcpy(tmp,ptr,message2_l+1); +#endif + printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After mapping back to 1, I read back: '%s'\n",tmp); + + if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && + emm_map_page(h1,/*physical*/1,/*logical*/1)) { + unsigned int seg1 = emm_last_phys_page_segment(0); + unsigned int seg2 = emm_last_phys_page_segment(1); + printf("Seg %04x,%04x\n",seg1,seg2); + if (seg1 > 0 && seg2 > 0) { +#if TARGET_MSDOS == 16 + char far *ptr1 = MK_FP(seg1,0); + char far *ptr2 = MK_FP(seg2,0); +#else + char *ptr1 = (char*)(seg1 << 4UL); + char *ptr2 = (char*)(seg2 << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr1,(char far*)message,message_l+1); + _fmemcpy(ptr2,(char far*)message2,message2_l+1); +#else + memcpy(ptr1,message,message_l+1); + memcpy(ptr2,message2,message2_l+1); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message_l+1); + _fmemcpy((char far*)tmp2,ptr2,message2_l+1); +#else + memcpy(tmp,ptr1,message_l+1); + memcpy(tmp2,ptr2,message2_l+1); +#endif + + printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + + /* now swap the pages */ + if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); + if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message2_l+1); + _fmemcpy((char far*)tmp2,ptr2,message_l+1); +#else + memcpy(tmp,ptr1,message2_l+1); + memcpy(tmp2,ptr2,message_l+1); +#endif + + printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + getch(); + + /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. + * the host could have 256MB of total memory and it would still report 32MB in EMS */ + printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS"); + printf("Allocating EMM pages (48MB): "); + h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (96MB): "); + h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + } + + return 0; +} + diff --git a/src/testemm0.c b/src/testemm0.c index 16f5654b..a83564e7 100755 --- a/src/testemm0.c +++ b/src/testemm0.c @@ -1,276 +1,276 @@ -/* testemm.c - * - * Test program: Expanded Memory Manager functions - * (C) 2011-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -//#include "src/lib/doslib/cpu.h" -#include "src/lib/doslib/dos.h" -#include "src/lib/doslib/emm.h" -//#include - -static const char *message = "Hello world. How are you?"; -static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; -static char tmp[128],tmp2[128]; -extern int probe_emm0(); - -#if 1 -# define x_memcpy(a,b,c) memcpy(a,b,c) -#else -/* what have we come to when friggin' memcpy() causes a GPF?!? */ -static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { - fprintf(stderr,"memcpy %p -> %p (%lu)\n", - dst,src,(unsigned long)c); - - while (c != 0) { - *dst++ = *src++; - c--; - } -} -#endif - -int main() { - size_t message_l = strlen(message),message2_l = strlen(message2); - - probe_dos(); - printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); - /*if (detect_windows()) { - printf("I am running under Windows.\n"); - printf(" Mode: %s\n",windows_mode_str(windows_mode)); - printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); - } - else { - printf("Not running under Windows or OS/2\n"); - }*/ - - sanity(); - if (probe_emm()) { - int h1,h2,h3; - - sanity(); - printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); - emm_update_page_count(); - sanity(); - printf(" Unallocated pages: %u (%luKB)\n", - emm_unallocated_pages, - (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ - printf(" Total pages: %u (%luKB)\n", - emm_total_pages, - (unsigned long)emm_total_pages << 4UL); - printf(" Physical pages: %u (%luKB)\n", - emm_phys_pages, - (unsigned long)emm_phys_pages << 4UL); - - while (getch() != 13); - sanity(); - - /* print out the mapping table, if available */ - if (emm_phys_map != NULL) { - struct emm_phys_page_map *me; - unsigned int i; - - printf("Physical page to segment table\n"); - for (i=0;i < emm_phys_pages;i++) { - me = emm_phys_map + i; - printf(" %02x: 0x%04x",me->number,me->segment); - if ((i%5) == 4) printf("\n"); - } - printf("\n"); - sanity(); - } - - printf("Allocating EMM pages (1): "); - h1 = emm_alloc_pages(1); - sanity(); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (!emm_free_pages(h1)) printf("cannot free\n"); - } - else printf("FAILED\n"); - - printf("Allocating EMM pages (%luKB): ", (dword)emm_unallocated_pages << 4UL); - h1 = emm_alloc_pages(emm_unallocated_pages); - sanity(); - if (h1 >= 0) printf("OK, handle=%u\n",h1); - else printf("FAILED\n"); - -// printf("Allocating EMM pages (1.6MB): "); - //h2 = emm_alloc_pages(0x19999AUL >> 14UL); - /*h2 = emm_alloc_pages(1); - sanity(); - if (h2 >= 0) printf("OK, handle=%u\n",h2); - else printf("FAILED\n"); - - //printf("Allocating EMM pages (12MB): "); - //h3 = emm_alloc_pages(0xC00000UL >> 14UL); - h3 = emm_alloc_pages(1); - sanity(); - if (h3 >= 0) printf("OK, handle=%u\n",h3); - else printf("FAILED\n");*/ - - while (getch() != 13); - - if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); - sanity(); - /*if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); - sanity(); - if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); - sanity();*/ - - printf("Allocating EMM pages (32KB): "); - h1 = emm_alloc_pages(2); - sanity(); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { - unsigned int segm = emm_last_phys_page_segment(0); - printf("Seg %04x\n",segm); - sanity(); - if (segm > 0) { -#if TARGET_MSDOS == 16 - char far *ptr = MK_FP(segm,0); -#else - char *ptr = (char*)(segm << 4UL); -#endif - -#if TARGET_MSDOS == 16 - _fmemcpy(ptr,(char far*)message,message_l+1); - _fmemcpy((char far*)tmp,ptr,message_l+1); -#else - x_memcpy(ptr,message,message_l+1); - x_memcpy(tmp,ptr,message_l+1); -#endif - printf("After writing message there, I read back: '%s'\n",tmp); - - if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); - -#if TARGET_MSDOS == 16 - _fmemcpy(ptr,(char far*)message2,message2_l+1); - _fmemcpy((char far*)tmp,ptr,message2_l+1); -#else - x_memcpy(ptr,message2,message2_l+1); - x_memcpy(tmp,ptr,message2_l+1); -#endif - printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); - - if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); - -#if TARGET_MSDOS == 16 - _fmemcpy((char far*)tmp,ptr,message_l+1); -#else - x_memcpy(tmp,ptr,message_l+1); -#endif - printf("After mapping back to 1, I read back: '%s'\n",tmp); - - if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); - } - else { - printf("Cannot get segment\n"); - } - if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); - } - else { - printf("Cannot map\n"); - } - if (!emm_free_pages(h1)) printf("Cannot free\n"); - } - else printf("FAILED\n"); - - printf("Allocating EMM pages (32KB): "); - h1 = emm_alloc_pages(2); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && - emm_map_page(h1,/*physical*/1,/*logical*/1)) { - unsigned int seg1 = emm_last_phys_page_segment(0); - unsigned int seg2 = emm_last_phys_page_segment(1); - printf("Seg %04x,%04x\n",seg1,seg2); - if (seg1 > 0 && seg2 > 0) { -#if TARGET_MSDOS == 16 - char far *ptr1 = MK_FP(seg1,0); - char far *ptr2 = MK_FP(seg2,0); -#else - char *ptr1 = (char*)(seg1 << 4UL); - char *ptr2 = (char*)(seg2 << 4UL); -#endif - -#if TARGET_MSDOS == 16 - _fmemcpy(ptr1,(char far*)message,message_l+1); - _fmemcpy(ptr2,(char far*)message2,message2_l+1); -#else - memcpy(ptr1,message,message_l+1); - memcpy(ptr2,message2,message2_l+1); -#endif - -#if TARGET_MSDOS == 16 - _fmemcpy((char far*)tmp,ptr1,message_l+1); - _fmemcpy((char far*)tmp2,ptr2,message2_l+1); -#else - memcpy(tmp,ptr1,message_l+1); - memcpy(tmp2,ptr2,message2_l+1); -#endif - - printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); - - /* now swap the pages */ - if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); - if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); - -#if TARGET_MSDOS == 16 - _fmemcpy((char far*)tmp,ptr1,message2_l+1); - _fmemcpy((char far*)tmp2,ptr2,message_l+1); -#else - memcpy(tmp,ptr1,message2_l+1); - memcpy(tmp2,ptr2,message_l+1); -#endif - - printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); - } - else { - printf("Cannot get segment\n"); - } - if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); - } - else { - printf("Cannot map\n"); - } - if (!emm_free_pages(h1)) printf("Cannot free\n"); - } - else printf("FAILED\n"); - - getch(); - - /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. - * the host could have 256MB of total memory and it would still report 32MB in EMS */ - printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS"); - printf("Allocating EMM pages (48MB): "); - h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (!emm_free_pages(h1)) printf("cannot free\n"); - } - else printf("FAILED\n"); - - printf("Allocating EMM pages (96MB): "); - h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); - if (h1 >= 0) { - printf("OK, handle=%u\n",h1); - if (!emm_free_pages(h1)) printf("cannot free\n"); - } - else printf("FAILED\n"); - } - - return 0; -} +/* testemm.c + * + * Test program: Expanded Memory Manager functions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +//#include "src/lib/doslib/cpu.h" +#include "src/lib/doslib/dos.h" +#include "src/lib/doslib/emm.h" +//#include + +static const char *message = "Hello world. How are you?"; +static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; +static char tmp[128],tmp2[128]; +extern int probe_emm0(); + +#if 1 +# define x_memcpy(a,b,c) memcpy(a,b,c) +#else +/* what have we come to when friggin' memcpy() causes a GPF?!? */ +static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { + fprintf(stderr,"memcpy %p -> %p (%lu)\n", + dst,src,(unsigned long)c); + + while (c != 0) { + *dst++ = *src++; + c--; + } +} +#endif + +int main() { + size_t message_l = strlen(message),message2_l = strlen(message2); + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + /*if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + }*/ + + sanity(); + if (probe_emm()) { + int h1,h2,h3; + + sanity(); + printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); + emm_update_page_count(); + sanity(); + printf(" Unallocated pages: %u (%luKB)\n", + emm_unallocated_pages, + (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ + printf(" Total pages: %u (%luKB)\n", + emm_total_pages, + (unsigned long)emm_total_pages << 4UL); + printf(" Physical pages: %u (%luKB)\n", + emm_phys_pages, + (unsigned long)emm_phys_pages << 4UL); + + while (getch() != 13); + sanity(); + + /* print out the mapping table, if available */ + if (emm_phys_map != NULL) { + struct emm_phys_page_map *me; + unsigned int i; + + printf("Physical page to segment table\n"); + for (i=0;i < emm_phys_pages;i++) { + me = emm_phys_map + i; + printf(" %02x: 0x%04x",me->number,me->segment); + if ((i%5) == 4) printf("\n"); + } + printf("\n"); + sanity(); + } + + printf("Allocating EMM pages (1): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (%luKB): ", (dword)emm_unallocated_pages << 4UL); + h1 = emm_alloc_pages(emm_unallocated_pages); + sanity(); + if (h1 >= 0) printf("OK, handle=%u\n",h1); + else printf("FAILED\n"); + +// printf("Allocating EMM pages (1.6MB): "); + //h2 = emm_alloc_pages(0x19999AUL >> 14UL); + /*h2 = emm_alloc_pages(1); + sanity(); + if (h2 >= 0) printf("OK, handle=%u\n",h2); + else printf("FAILED\n"); + + //printf("Allocating EMM pages (12MB): "); + //h3 = emm_alloc_pages(0xC00000UL >> 14UL); + h3 = emm_alloc_pages(1); + sanity(); + if (h3 >= 0) printf("OK, handle=%u\n",h3); + else printf("FAILED\n");*/ + + while (getch() != 13); + + if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); + sanity(); + /*if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); + sanity(); + if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); + sanity();*/ + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { + unsigned int segm = emm_last_phys_page_segment(0); + printf("Seg %04x\n",segm); + sanity(); + if (segm > 0) { +#if TARGET_MSDOS == 16 + char far *ptr = MK_FP(segm,0); +#else + char *ptr = (char*)(segm << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message,message_l+1); + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(ptr,message,message_l+1); + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After writing message there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message2,message2_l+1); + _fmemcpy((char far*)tmp,ptr,message2_l+1); +#else + x_memcpy(ptr,message2,message2_l+1); + x_memcpy(tmp,ptr,message2_l+1); +#endif + printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After mapping back to 1, I read back: '%s'\n",tmp); + + if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && + emm_map_page(h1,/*physical*/1,/*logical*/1)) { + unsigned int seg1 = emm_last_phys_page_segment(0); + unsigned int seg2 = emm_last_phys_page_segment(1); + printf("Seg %04x,%04x\n",seg1,seg2); + if (seg1 > 0 && seg2 > 0) { +#if TARGET_MSDOS == 16 + char far *ptr1 = MK_FP(seg1,0); + char far *ptr2 = MK_FP(seg2,0); +#else + char *ptr1 = (char*)(seg1 << 4UL); + char *ptr2 = (char*)(seg2 << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr1,(char far*)message,message_l+1); + _fmemcpy(ptr2,(char far*)message2,message2_l+1); +#else + memcpy(ptr1,message,message_l+1); + memcpy(ptr2,message2,message2_l+1); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message_l+1); + _fmemcpy((char far*)tmp2,ptr2,message2_l+1); +#else + memcpy(tmp,ptr1,message_l+1); + memcpy(tmp2,ptr2,message2_l+1); +#endif + + printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + + /* now swap the pages */ + if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); + if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message2_l+1); + _fmemcpy((char far*)tmp2,ptr2,message_l+1); +#else + memcpy(tmp,ptr1,message2_l+1); + memcpy(tmp2,ptr2,message_l+1); +#endif + + printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + getch(); + + /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. + * the host could have 256MB of total memory and it would still report 32MB in EMS */ + printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS"); + printf("Allocating EMM pages (48MB): "); + h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (96MB): "); + h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + } + + return 0; +} diff --git a/src/testsnd.c b/src/testsnd.c index 4c5f6534..43dae78e 100755 --- a/src/testsnd.c +++ b/src/testsnd.c @@ -1,450 +1,450 @@ -/* test.c - * - * Adlib OPL2/OPL3 FM synthesizer chipset test program. - * (C) 2010-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - * - * Compiles for intended target environments: - * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] - * - * This test program uses a "text user interface" to allow you to play - * with the OPL2/OPL3 chipset and it's parameters. Some "instruments" - * are preset for you if you want to make noise faster. - */ - -#include -#include /* this is where Open Watcom hides the outp() etc. functions */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include /* 8254 timer */ -#include -#include -#include - -static unsigned int musical_scale[18] = { - 0x1B0, /* E */ - 0x1CA, /* F */ - 0x1E5, /* f# */ - 0x202, /* G */ - 0x220, /* G# */ - 0x241, /* A */ - 0x263, /* A# */ - 0x287, /* B */ - 0x2AE, /* C */ - - 0x2B0, /* E */ - 0x2CA, /* F */ - 0x2E5, /* f# */ - 0x302, /* G */ - 0x320, /* G# */ - 0x341, /* A */ - 0x363, /* A# */ - 0x387, /* B */ - 0x3AE, /* C */ -}; - -int main(int argc,char **argv) { - int i,loop,redraw,c,cc,selector=0,redrawln=0,hselect=0,selectsub=0; - VGA_ALPHA_PTR vga; - char tmp[128]; - - printf("ADLIB FM test program\n"); - - if (!probe_vga()) { - printf("Cannot init VGA\n"); - return 1; - } - if (!init_adlib()) { - printf("Cannot init library\n"); - return 1; - } - - int10_setmode(3); - - /* for VGA: free up space if needed by going to 80x50 */ - if (adlib_fm_voices > 9) - vga_bios_set_80x50_text(); - - memset(adlib_fm,0,sizeof(adlib_fm)); - memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - f = &adlib_fm[i].mod; - f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; - f = &adlib_fm[i].car; - f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; - } - - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - - f = &adlib_fm[i].mod; - f->mod_multiple = 1; - f->total_level = 63 - 16; - f->attack_rate = 15; - f->decay_rate = 0; - f->sustain_level = 7; - f->release_rate = 7; - f->f_number = musical_scale[i%18]; - f->octave = 4; - f->key_on = 0; - - f = &adlib_fm[i].car; - f->mod_multiple = 1; - f->total_level = 63 - 16; - f->attack_rate = 15; - f->decay_rate = 0; - f->sustain_level = 7; - f->release_rate = 7; - f->f_number = 0; - f->octave = 0; - f->key_on = 0; - } - - adlib_apply_all(); - - vga_write_color(0x07); - vga_clear(); - - loop=1; - redraw=1; - while (loop) { - if (redraw || redrawln) { - if (redraw) { - for (vga=vga_alpha_ram,cc=0;cc < (80*vga_height);cc++) *vga++ = 0x1E00 | 177; - vga_moveto(0,0); - vga_write_color(0x1F); - sprintf(tmp,"Adlib FM, %u-voice %s. Use Z & X to adj F10=PRESET F1=QUIET ",adlib_fm_voices, - (adlib_flags & ADLIB_FM_OPL3) ? "OPL3" : - (adlib_flags & ADLIB_FM_DUAL_OPL2) ? "Dual OPL2" : "OPL2"); - vga_write(tmp); - if (adlib_flags & ADLIB_FM_OPL3) vga_write("F2=OPL3 off "); - } - - if (redrawln || redraw) { - struct adlib_reg_bd *bd = &adlib_reg_bd; - static const char *hsel_str[18] = { - "Amplitude modulatation", - "Vibrato", - "Sustain", - "Key scaling rate", - "Modulator frequency multiple", - "Level key scaling", - "Total level", - "Attack rate", - "Decay rate", - "Sustain level", - "Release rate", - "KEY ON", - "Octave", - "F-Number", - "Feedback", - "Connection (operator 1 -> operator 2)", - "Waveform", - "Channel mapping (OPL3)" - }; - - vga_write_color(0x1A); - - vga_moveto(0,2); - sprintf(tmp,"AM=%u VB=%u RYTHM=%u BAS=%u SNA=%u TOM=%u CYM=%u HI=%u\n", - bd->am_depth, - bd->vibrato_depth, - bd->rythm_enable, - bd->bass_drum_on, - bd->snare_drum_on, - bd->tom_tom_on, - bd->cymbal_on, - bd->hi_hat_on); - vga_write(tmp); - - vga_moveto(0,3); - vga_write(" "); - vga_moveto(0,3); - vga_write(hsel_str[hselect]); - - vga_moveto(0,4); - vga_write_color(hselect == 0 ? 0x70 : 0x1E); vga_write("AM "); - vga_write_color(hselect == 1 ? 0x70 : 0x1E); vga_write("VB "); - vga_write_color(hselect == 2 ? 0x70 : 0x1E); vga_write("SUST "); - vga_write_color(hselect == 3 ? 0x70 : 0x1E); vga_write("KSR "); - vga_write_color(hselect == 4 ? 0x70 : 0x1E); vga_write("MMUL "); - vga_write_color(hselect == 5 ? 0x70 : 0x1E); vga_write("LKS "); - vga_write_color(hselect == 6 ? 0x70 : 0x1E); vga_write("TL "); - vga_write_color(hselect == 7 ? 0x70 : 0x1E); vga_write("AR "); - vga_write_color(hselect == 8 ? 0x70 : 0x1E); vga_write("DR "); - vga_write_color(hselect == 9 ? 0x70 : 0x1E); vga_write("SL "); - vga_write_color(hselect == 10 ? 0x70 : 0x1E); vga_write("RR "); - vga_write_color(hselect == 11 ? 0x70 : 0x1E); vga_write("KEY "); - vga_write_color(hselect == 12 ? 0x70 : 0x1E); vga_write("OCT "); - vga_write_color(hselect == 13 ? 0x70 : 0x1E); vga_write("FNUM "); - vga_write_color(hselect == 14 ? 0x70 : 0x1E); vga_write("FEED "); - vga_write_color(hselect == 15 ? 0x70 : 0x1E); vga_write("CON "); - vga_write_color(hselect == 16 ? 0x70 : 0x1E); vga_write("WV "); - vga_write_color(hselect == 17 ? 0x70 : 0x1E); vga_write("ABCD "); - - for (i=0;i < adlib_fm_voices;i++) { - struct adlib_fm_operator *f; - double freq; - - f = &adlib_fm[i].mod; - vga_moveto(0,5+i*2); - freq = adlib_fm_op_to_freq(f); - vga_write_color(i == selector && selectsub == 0 ? 0x70 : 0x1E); - cc = sprintf(tmp,"%u %u %u %u %-2u %u %-2u %-2u %-2u %-2u %-2u %u %u %-4u %u %u %u %c%c%c%c %u %.1fHz ", - f->am, f->vibrato, f->sustain, f->key_scaling_rate, - f->mod_multiple, f->level_key_scale, f->total_level, f->attack_rate, - f->decay_rate, f->sustain_level, f->release_rate, f->key_on, - f->octave, f->f_number, f->feedback, f->connection, - f->waveform, f->ch_a?'*':'-', f->ch_b?'*':'-', f->ch_c?'*':'-', - f->ch_d?'*':'-', i+1, freq); - vga_write(tmp); - - f = &adlib_fm[i].car; - vga_moveto(0,5+i*2+1); - vga_write_color(i == selector && selectsub == 1 ? 0x70 : 0x1E); - cc = sprintf(tmp,"%u %u %u %u %-2u %u %-2u %-2u %-2u %-2u %-2u %u CAR ", - f->am, f->vibrato, f->sustain, f->key_scaling_rate, - f->mod_multiple, f->level_key_scale, f->total_level, f->attack_rate, - f->decay_rate, f->sustain_level, f->release_rate, f->waveform); - vga_write(tmp); - } - } - - redrawln = 0; - redraw = 0; - } - - if (kbhit()) { - c = getch(); - if (c == 0) c = getch() << 8; - - if (c == 27) { - loop = 0; - } - else if (c == 0x3B00) { /* F1 */ - for (i=0;i < adlib_fm_voices;i++) { - adlib_fm[i].mod.key_on = 0; - adlib_fm[i].car.key_on = 0; - adlib_update_groupA0(i,&adlib_fm[i]); - } - redrawln = 1; - } - else if (c == 0x3C00) { /* F2 */ - if (adlib_flags & ADLIB_FM_OPL3) { - shutdown_adlib_opl3(); - int10_setmode(3); - redraw = 1; - } - } - else if (c == 0x4400) { /* F10 */ - unsigned short op = adlib_voice_to_op[selector]; - - vga_write_color(0x07); - vga_clear(); - vga_moveto(0,0); - - vga_write("Choose an instrument to load into the channel:\n"); - vga_write(" 1. Violin 2. Piano 3. Harpsichord 4. Horn 5. Deep bass drum\n"); - vga_write(" 6. Small drum \n"); - vga_write_sync(); - - c = getch(); - - if (c == '1') - adlib_fm[selector] = - (adlib_flags & ADLIB_FM_OPL3 ? - adlib_fm_preset_violin_opl3 : adlib_fm_preset_violin_opl2); - else if (c == '2') - adlib_fm[selector] = adlib_fm_preset_piano; - else if (c == '3') - adlib_fm[selector] = adlib_fm_preset_harpsichord; - else if (c == '4') - adlib_fm[selector] = adlib_fm_preset_horn; - else if (c == '5') - adlib_fm[selector] = adlib_fm_preset_deep_bass_drum; - else if (c == '6') - adlib_fm[selector] = adlib_fm_preset_small_drum; - - adlib_update_groupA0(selector,&adlib_fm[selector]); - adlib_update_groupC0(selector,&adlib_fm[selector]); - adlib_update_operator(op,&adlib_fm[selector].mod); - adlib_update_operator(op+3,&adlib_fm[selector].car); - - redraw = 1; - } - else if (c == ' ') { - adlib_fm[selector].mod.key_on ^= 1; - adlib_update_groupA0(selector,&adlib_fm[selector]); - redrawln=1; - } - else if (c == 'a') { - if (hselect == 17) { - struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_a ^= 1; - adlib_update_groupC0(selector,&adlib_fm[selector]); - } - else { - adlib_reg_bd.am_depth ^= 1; - adlib_update_bd(&adlib_reg_bd); - } - redrawln = 1; - } - else if (c == 'v') { - adlib_reg_bd.vibrato_depth ^= 1; - adlib_update_bd(&adlib_reg_bd); - redrawln = 1; - } - else if (c == 'r') { - adlib_reg_bd.rythm_enable ^= 1; - adlib_update_bd(&adlib_reg_bd); - redrawln = 1; - } - else if (c == 'b') { - if (hselect == 17) { - struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_b ^= 1; - adlib_update_groupC0(selector,&adlib_fm[selector]); - } - else { - adlib_reg_bd.bass_drum_on ^= 1; - adlib_update_bd(&adlib_reg_bd); - } - redrawln = 1; - } - else if (c == 's') { - adlib_reg_bd.snare_drum_on ^= 1; - adlib_update_bd(&adlib_reg_bd); - redrawln = 1; - } - else if (c == 't') { - adlib_reg_bd.tom_tom_on ^= 1; - adlib_update_bd(&adlib_reg_bd); - redrawln = 1; - } - else if (c == 'c') { - if (hselect == 17) { - struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_c ^= 1; - adlib_update_groupC0(selector,&adlib_fm[selector]); - } - else { - adlib_reg_bd.cymbal_on ^= 1; - adlib_update_bd(&adlib_reg_bd); - } - redrawln = 1; - } - else if (c == 'd') { - if (hselect == 17) { - struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_d ^= 1; - adlib_update_groupC0(selector,&adlib_fm[selector]); - } - else { - } - redrawln = 1; - } - else if (c == 'h') { - adlib_reg_bd.hi_hat_on ^= 1; - adlib_update_bd(&adlib_reg_bd); - redrawln = 1; - } - else if (c == 'z' || c == 'Z' || c == 'x' || c == 'X') { - struct adlib_fm_operator *f; - int dec = tolower(c) == 'z'; - unsigned short operator; - - switch (hselect) { - case 11:selectsub = 0; - break; - } - - if (selectsub) f = &adlib_fm[selector].car; - else f = &adlib_fm[selector].mod; - operator = adlib_voice_to_op[selector] + (selectsub*3); - - switch (hselect) { - case 0: f->am ^= 1; adlib_update_group20(operator,f); break; - case 11: f->key_on ^= 1; adlib_update_groupA0(selector,&adlib_fm[selector]); break; - case 1: f->vibrato ^= 1; adlib_update_group20(operator,f); break; - case 2: f->sustain ^= 1; adlib_update_group20(operator,f); break; - case 15: f->connection ^= 1; adlib_update_group20(operator,f); break; - case 3: f->key_scaling_rate ^= 1; adlib_update_group20(operator,f); break; - - case 4: if (dec) f->mod_multiple--; else f->mod_multiple++; - adlib_update_group20(operator,f); break; - case 5: if (dec) f->level_key_scale--; else f->level_key_scale++; - adlib_update_group40(operator,f); break; - case 6: if (dec) f->total_level--; else f->total_level++; - adlib_update_group40(operator,f); break; - case 7: if (dec) f->attack_rate--; else f->attack_rate++; - adlib_update_group60(operator,f); break; - case 8: if (dec) f->decay_rate--; else f->decay_rate++; - adlib_update_group60(operator,f); break; - case 9: if (dec) f->sustain_level--; else f->sustain_level++; - adlib_update_group80(operator,f); break; - case 10: if (dec) f->release_rate--; else f->release_rate++; - adlib_update_group80(operator,f); break; - case 12: if (dec) f->octave--; else f->octave++; - adlib_update_groupA0(selector,&adlib_fm[selector]); break; - case 13: if (dec) f->f_number--; else f->f_number++; - adlib_update_groupA0(selector,&adlib_fm[selector]); break; - case 14: if (dec) f->feedback--; else f->feedback++; - adlib_update_groupC0(selector,&adlib_fm[selector]); break; - case 16: if (dec) f->waveform--; else f->waveform++; - adlib_update_groupE0(operator,f); break; - }; - - redrawln=1; - } - else if (c == 0x4800) { - if (selectsub && !(hselect >= 11 && hselect <= 15)) { - selectsub = 0; - redrawln = 1; - } - else if (selector > 0) { - selectsub = !(hselect >= 11 && hselect <= 15); - selector--; - redrawln = 1; - } - } - else if (c == 0x4B00) { - if (hselect > 0) { - hselect--; - redrawln=1; - } - } - else if (c == 0x4D00) { - if (hselect < 17) { - hselect++; - redrawln=1; - } - } - else if (c == 0x5000) { - if (selectsub == 0 && !(hselect >= 11 && hselect <= 15)) { - selectsub = 1; - redrawln = 1; - } - else if ((selector+1) < adlib_fm_voices) { - selectsub = 0; - selector++; - redrawln=1; - } - } - - } - } - - shutdown_adlib(); - int10_setmode(3); - - return 0; -} - +/* test.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * This test program uses a "text user interface" to allow you to play + * with the OPL2/OPL3 chipset and it's parameters. Some "instruments" + * are preset for you if you want to make noise faster. + */ + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* 8254 timer */ +#include +#include +#include + +static unsigned int musical_scale[18] = { + 0x1B0, /* E */ + 0x1CA, /* F */ + 0x1E5, /* f# */ + 0x202, /* G */ + 0x220, /* G# */ + 0x241, /* A */ + 0x263, /* A# */ + 0x287, /* B */ + 0x2AE, /* C */ + + 0x2B0, /* E */ + 0x2CA, /* F */ + 0x2E5, /* f# */ + 0x302, /* G */ + 0x320, /* G# */ + 0x341, /* A */ + 0x363, /* A# */ + 0x387, /* B */ + 0x3AE, /* C */ +}; + +int main(int argc,char **argv) { + int i,loop,redraw,c,cc,selector=0,redrawln=0,hselect=0,selectsub=0; + VGA_ALPHA_PTR vga; + char tmp[128]; + + printf("ADLIB FM test program\n"); + + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + + int10_setmode(3); + + /* for VGA: free up space if needed by going to 80x50 */ + if (adlib_fm_voices > 9) + vga_bios_set_80x50_text(); + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 0; + f->sustain_level = 7; + f->release_rate = 7; + f->f_number = musical_scale[i%18]; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 0; + f->sustain_level = 7; + f->release_rate = 7; + f->f_number = 0; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); + + vga_write_color(0x07); + vga_clear(); + + loop=1; + redraw=1; + while (loop) { + if (redraw || redrawln) { + if (redraw) { + for (vga=vga_alpha_ram,cc=0;cc < (80*vga_height);cc++) *vga++ = 0x1E00 | 177; + vga_moveto(0,0); + vga_write_color(0x1F); + sprintf(tmp,"Adlib FM, %u-voice %s. Use Z & X to adj F10=PRESET F1=QUIET ",adlib_fm_voices, + (adlib_flags & ADLIB_FM_OPL3) ? "OPL3" : + (adlib_flags & ADLIB_FM_DUAL_OPL2) ? "Dual OPL2" : "OPL2"); + vga_write(tmp); + if (adlib_flags & ADLIB_FM_OPL3) vga_write("F2=OPL3 off "); + } + + if (redrawln || redraw) { + struct adlib_reg_bd *bd = &adlib_reg_bd; + static const char *hsel_str[18] = { + "Amplitude modulatation", + "Vibrato", + "Sustain", + "Key scaling rate", + "Modulator frequency multiple", + "Level key scaling", + "Total level", + "Attack rate", + "Decay rate", + "Sustain level", + "Release rate", + "KEY ON", + "Octave", + "F-Number", + "Feedback", + "Connection (operator 1 -> operator 2)", + "Waveform", + "Channel mapping (OPL3)" + }; + + vga_write_color(0x1A); + + vga_moveto(0,2); + sprintf(tmp,"AM=%u VB=%u RYTHM=%u BAS=%u SNA=%u TOM=%u CYM=%u HI=%u\n", + bd->am_depth, + bd->vibrato_depth, + bd->rythm_enable, + bd->bass_drum_on, + bd->snare_drum_on, + bd->tom_tom_on, + bd->cymbal_on, + bd->hi_hat_on); + vga_write(tmp); + + vga_moveto(0,3); + vga_write(" "); + vga_moveto(0,3); + vga_write(hsel_str[hselect]); + + vga_moveto(0,4); + vga_write_color(hselect == 0 ? 0x70 : 0x1E); vga_write("AM "); + vga_write_color(hselect == 1 ? 0x70 : 0x1E); vga_write("VB "); + vga_write_color(hselect == 2 ? 0x70 : 0x1E); vga_write("SUST "); + vga_write_color(hselect == 3 ? 0x70 : 0x1E); vga_write("KSR "); + vga_write_color(hselect == 4 ? 0x70 : 0x1E); vga_write("MMUL "); + vga_write_color(hselect == 5 ? 0x70 : 0x1E); vga_write("LKS "); + vga_write_color(hselect == 6 ? 0x70 : 0x1E); vga_write("TL "); + vga_write_color(hselect == 7 ? 0x70 : 0x1E); vga_write("AR "); + vga_write_color(hselect == 8 ? 0x70 : 0x1E); vga_write("DR "); + vga_write_color(hselect == 9 ? 0x70 : 0x1E); vga_write("SL "); + vga_write_color(hselect == 10 ? 0x70 : 0x1E); vga_write("RR "); + vga_write_color(hselect == 11 ? 0x70 : 0x1E); vga_write("KEY "); + vga_write_color(hselect == 12 ? 0x70 : 0x1E); vga_write("OCT "); + vga_write_color(hselect == 13 ? 0x70 : 0x1E); vga_write("FNUM "); + vga_write_color(hselect == 14 ? 0x70 : 0x1E); vga_write("FEED "); + vga_write_color(hselect == 15 ? 0x70 : 0x1E); vga_write("CON "); + vga_write_color(hselect == 16 ? 0x70 : 0x1E); vga_write("WV "); + vga_write_color(hselect == 17 ? 0x70 : 0x1E); vga_write("ABCD "); + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + double freq; + + f = &adlib_fm[i].mod; + vga_moveto(0,5+i*2); + freq = adlib_fm_op_to_freq(f); + vga_write_color(i == selector && selectsub == 0 ? 0x70 : 0x1E); + cc = sprintf(tmp,"%u %u %u %u %-2u %u %-2u %-2u %-2u %-2u %-2u %u %u %-4u %u %u %u %c%c%c%c %u %.1fHz ", + f->am, f->vibrato, f->sustain, f->key_scaling_rate, + f->mod_multiple, f->level_key_scale, f->total_level, f->attack_rate, + f->decay_rate, f->sustain_level, f->release_rate, f->key_on, + f->octave, f->f_number, f->feedback, f->connection, + f->waveform, f->ch_a?'*':'-', f->ch_b?'*':'-', f->ch_c?'*':'-', + f->ch_d?'*':'-', i+1, freq); + vga_write(tmp); + + f = &adlib_fm[i].car; + vga_moveto(0,5+i*2+1); + vga_write_color(i == selector && selectsub == 1 ? 0x70 : 0x1E); + cc = sprintf(tmp,"%u %u %u %u %-2u %u %-2u %-2u %-2u %-2u %-2u %u CAR ", + f->am, f->vibrato, f->sustain, f->key_scaling_rate, + f->mod_multiple, f->level_key_scale, f->total_level, f->attack_rate, + f->decay_rate, f->sustain_level, f->release_rate, f->waveform); + vga_write(tmp); + } + } + + redrawln = 0; + redraw = 0; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + loop = 0; + } + else if (c == 0x3B00) { /* F1 */ + for (i=0;i < adlib_fm_voices;i++) { + adlib_fm[i].mod.key_on = 0; + adlib_fm[i].car.key_on = 0; + adlib_update_groupA0(i,&adlib_fm[i]); + } + redrawln = 1; + } + else if (c == 0x3C00) { /* F2 */ + if (adlib_flags & ADLIB_FM_OPL3) { + shutdown_adlib_opl3(); + int10_setmode(3); + redraw = 1; + } + } + else if (c == 0x4400) { /* F10 */ + unsigned short op = adlib_voice_to_op[selector]; + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write("Choose an instrument to load into the channel:\n"); + vga_write(" 1. Violin 2. Piano 3. Harpsichord 4. Horn 5. Deep bass drum\n"); + vga_write(" 6. Small drum \n"); + vga_write_sync(); + + c = getch(); + + if (c == '1') + adlib_fm[selector] = + (adlib_flags & ADLIB_FM_OPL3 ? + adlib_fm_preset_violin_opl3 : adlib_fm_preset_violin_opl2); + else if (c == '2') + adlib_fm[selector] = adlib_fm_preset_piano; + else if (c == '3') + adlib_fm[selector] = adlib_fm_preset_harpsichord; + else if (c == '4') + adlib_fm[selector] = adlib_fm_preset_horn; + else if (c == '5') + adlib_fm[selector] = adlib_fm_preset_deep_bass_drum; + else if (c == '6') + adlib_fm[selector] = adlib_fm_preset_small_drum; + + adlib_update_groupA0(selector,&adlib_fm[selector]); + adlib_update_groupC0(selector,&adlib_fm[selector]); + adlib_update_operator(op,&adlib_fm[selector].mod); + adlib_update_operator(op+3,&adlib_fm[selector].car); + + redraw = 1; + } + else if (c == ' ') { + adlib_fm[selector].mod.key_on ^= 1; + adlib_update_groupA0(selector,&adlib_fm[selector]); + redrawln=1; + } + else if (c == 'a') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_a ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + adlib_reg_bd.am_depth ^= 1; + adlib_update_bd(&adlib_reg_bd); + } + redrawln = 1; + } + else if (c == 'v') { + adlib_reg_bd.vibrato_depth ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'r') { + adlib_reg_bd.rythm_enable ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'b') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_b ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + adlib_reg_bd.bass_drum_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + } + redrawln = 1; + } + else if (c == 's') { + adlib_reg_bd.snare_drum_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 't') { + adlib_reg_bd.tom_tom_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'c') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_c ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + adlib_reg_bd.cymbal_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + } + redrawln = 1; + } + else if (c == 'd') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_d ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + } + redrawln = 1; + } + else if (c == 'h') { + adlib_reg_bd.hi_hat_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'z' || c == 'Z' || c == 'x' || c == 'X') { + struct adlib_fm_operator *f; + int dec = tolower(c) == 'z'; + unsigned short operator; + + switch (hselect) { + case 11:selectsub = 0; + break; + } + + if (selectsub) f = &adlib_fm[selector].car; + else f = &adlib_fm[selector].mod; + operator = adlib_voice_to_op[selector] + (selectsub*3); + + switch (hselect) { + case 0: f->am ^= 1; adlib_update_group20(operator,f); break; + case 11: f->key_on ^= 1; adlib_update_groupA0(selector,&adlib_fm[selector]); break; + case 1: f->vibrato ^= 1; adlib_update_group20(operator,f); break; + case 2: f->sustain ^= 1; adlib_update_group20(operator,f); break; + case 15: f->connection ^= 1; adlib_update_group20(operator,f); break; + case 3: f->key_scaling_rate ^= 1; adlib_update_group20(operator,f); break; + + case 4: if (dec) f->mod_multiple--; else f->mod_multiple++; + adlib_update_group20(operator,f); break; + case 5: if (dec) f->level_key_scale--; else f->level_key_scale++; + adlib_update_group40(operator,f); break; + case 6: if (dec) f->total_level--; else f->total_level++; + adlib_update_group40(operator,f); break; + case 7: if (dec) f->attack_rate--; else f->attack_rate++; + adlib_update_group60(operator,f); break; + case 8: if (dec) f->decay_rate--; else f->decay_rate++; + adlib_update_group60(operator,f); break; + case 9: if (dec) f->sustain_level--; else f->sustain_level++; + adlib_update_group80(operator,f); break; + case 10: if (dec) f->release_rate--; else f->release_rate++; + adlib_update_group80(operator,f); break; + case 12: if (dec) f->octave--; else f->octave++; + adlib_update_groupA0(selector,&adlib_fm[selector]); break; + case 13: if (dec) f->f_number--; else f->f_number++; + adlib_update_groupA0(selector,&adlib_fm[selector]); break; + case 14: if (dec) f->feedback--; else f->feedback++; + adlib_update_groupC0(selector,&adlib_fm[selector]); break; + case 16: if (dec) f->waveform--; else f->waveform++; + adlib_update_groupE0(operator,f); break; + }; + + redrawln=1; + } + else if (c == 0x4800) { + if (selectsub && !(hselect >= 11 && hselect <= 15)) { + selectsub = 0; + redrawln = 1; + } + else if (selector > 0) { + selectsub = !(hselect >= 11 && hselect <= 15); + selector--; + redrawln = 1; + } + } + else if (c == 0x4B00) { + if (hselect > 0) { + hselect--; + redrawln=1; + } + } + else if (c == 0x4D00) { + if (hselect < 17) { + hselect++; + redrawln=1; + } + } + else if (c == 0x5000) { + if (selectsub == 0 && !(hselect >= 11 && hselect <= 15)) { + selectsub = 1; + redrawln = 1; + } + else if ((selector+1) < adlib_fm_voices) { + selectsub = 0; + selector++; + redrawln=1; + } + } + + } + } + + shutdown_adlib(); + int10_setmode(3); + + return 0; +} + diff --git a/src/tesuto.c b/src/tesuto.c index 83f3712e..ab7e2db6 100755 --- a/src/tesuto.c +++ b/src/tesuto.c @@ -1,344 +1,344 @@ -#include -#include -#include -#include - -#include "src/tesuto.h" - -static unsigned char palette[768]; - -int main(int argc,char **argv) { - struct vrl1_vgax_header *vrl_header; - vrl1_vgax_offset_t *vrl_lineoffs; - unsigned char *buffer; - unsigned int bufsz; - int fd; - - if (argc < 3) { - fprintf(stderr,"drawvrl \n"); - return 1; - } - - fd = open(argv[1],O_RDONLY|O_BINARY); - if (fd < 0) { - fprintf(stderr,"Unable to open '%s'\n",argv[1]); - return 1; - } - { - unsigned long sz = lseek(fd,0,SEEK_END); - if (sz < sizeof(*vrl_header)) return 1; - if (sz >= 65535UL) return 1; - - bufsz = (unsigned int)sz; - buffer = malloc(bufsz); - if (buffer == NULL) return 1; - - lseek(fd,0,SEEK_SET); - if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1; - - vrl_header = (struct vrl1_vgax_header*)buffer; - if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1; - if (vrl_header->width == 0 || vrl_header->height == 0) return 1; - } - close(fd); - - probe_dos(); - if (!probe_vga()) { - printf("VGA probe failed\n"); - return 1; - } - int10_setmode(19); - update_state_from_vga(); - vga_enable_256color_modex(); // VGA mode X - vga_state.vga_width = 320; // VGA lib currently does not update this - vga_state.vga_height = 240; // VGA lib currently does not update this - -#if 1 // 320x240 test mode: this is how Project 16 is using our code, enable for test case - { - struct vga_mode_params cm; - - vga_read_crtc_mode(&cm); - - // 320x240 mode 60Hz - cm.vertical_total = 525; - cm.vertical_start_retrace = 0x1EA; - cm.vertical_end_retrace = 0x1EC; - cm.vertical_display_end = 480; - cm.vertical_blank_start = 489; - cm.vertical_blank_end = 517; - - vga_write_crtc_mode(&cm,0); - } - vga_state.vga_height = 240; // VGA lib currently does not update this -#endif - - /* load color palette */ - fd = open(argv[2],O_RDONLY|O_BINARY); - if (fd >= 0) { - unsigned int i; - - read(fd,palette,768); - close(fd); - - vga_palette_lseek(0); - for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2); - } - - /* preprocess the sprite to generate line offsets */ - vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - if (vrl_lineoffs == NULL) return 1; - - { - unsigned int i,j,o; - - /* fill screen with a distinctive pattern */ - for (i=0;i < vga_state.vga_width;i++) { - o = i >> 2; - vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); - for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) - vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! - } - } - //while (getch() != 13); - - /* make distinctive pattern offscreen, render sprite, copy onscreen */ - { - const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height); - unsigned int i,j,o,o2,x,y,rx,ry,w,h; - unsigned int overdraw = 1; // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks. - // if the sprite's edge pixels are clear anyway, you can set this to 0. - VGA_RAM_PTR omemptr; - int xdir=1,ydir=1; - - /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */ - x = 0; - y = 0; - - /* do it */ - omemptr = vga_state.vga_graphics_ram; // save original mem ptr - while (1) { - /* stop animating if the user hits ENTER */ - if (kbhit()) { - if (getch() == 13) break; - } - - /* render box bounds. y does not need modification, but x and width must be multiple of 4 */ - if (x >= overdraw) rx = (x - overdraw) & (~3); - else rx = 0; - if (y >= overdraw) ry = (y - overdraw); - else ry = 0; - h = vrl_header->height + overdraw + y - ry; - w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3); - if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx; - if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry; - - /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */ - vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2; - vga_state.vga_draw_stride = w >> 2; - vga_state.vga_graphics_ram = omemptr + offscreen_ofs; - - /* first draw pattern corresponding to that part of the screen. this COULD be optimized, obviously, but it's designed for study. - * also note we don't have to use the same stride as the display! */ - for (i=rx;i < (rx+w);i++) { - o = (i-rx) >> 2; - vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); - for (j=ry;j < (ry+h);j++,o += vga_state.vga_draw_stride) - vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! - } - - /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ - draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - - /* restore ptr */ - vga_state.vga_graphics_ram = omemptr; - - /* block copy to visible RAM from offscreen */ - vga_setup_wm1_block_copy(); - o = offscreen_ofs; // source offscreen - o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride) - for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ - vga_restore_rm0wm0(); - - /* restore stride */ - vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride; - - /* step */ - x += xdir; - y += ydir; - if (x >= (vga_state.vga_width - 1) || x == 0) - xdir = -xdir; - if (y >= (vga_state.vga_height - 1) || y == 0) - ydir = -ydir; - } - } - - /* make distinctive pattern offscreen, render sprite, copy onscreen. - * this time, we render the distinctive pattern to another offscreen location and just copy. - * note this version is much faster too! */ - { - const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height); - const unsigned int pattern_ofs = 0x10000UL - (vga_state.vga_stride * vga_state.vga_height); - unsigned int i,j,o,o2,x,y,rx,ry,w,h; - unsigned int overdraw = 1; // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks. - // if the sprite's edge pixels are clear anyway, you can set this to 0. - VGA_RAM_PTR omemptr; - int xdir=1,ydir=1; - - /* fill pattern offset with a distinctive pattern */ - for (i=0;i < vga_state.vga_width;i++) { - o = (i >> 2) + pattern_ofs; - vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); - for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) - vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! - } - - /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */ - x = 0; - y = 0; - - /* do it */ - omemptr = vga_state.vga_graphics_ram; // save original mem ptr - while (1) { - /* stop animating if the user hits ENTER */ - if (kbhit()) { - if (getch() == 13) break; - } - - /* render box bounds. y does not need modification, but x and width must be multiple of 4 */ - if (x >= overdraw) rx = (x - overdraw) & (~3); - else rx = 0; - if (y >= overdraw) ry = (y - overdraw); - else ry = 0; - h = vrl_header->height + overdraw + y - ry; - w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3); - if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx; - if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry; - - /* block copy pattern to where we will draw the sprite */ - vga_setup_wm1_block_copy(); - o2 = offscreen_ofs; - o = pattern_ofs + (ry * vga_state.vga_stride) + (rx >> 2); // source offscreen - for (i=0;i < h;i++,o += vga_state.vga_stride,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ - vga_restore_rm0wm0(); - - /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */ - vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2; - vga_state.vga_draw_stride = w >> 2; - vga_state.vga_graphics_ram = omemptr + offscreen_ofs; - - /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ - draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); - - /* restore ptr */ - vga_state.vga_graphics_ram = omemptr; - - /* block copy to visible RAM from offscreen */ - vga_setup_wm1_block_copy(); - o = offscreen_ofs; // source offscreen - o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride) - for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); - /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ - vga_restore_rm0wm0(); - - /* restore stride */ - vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride; - - /* step */ - x += xdir; - y += ydir; - if (x >= (vga_state.vga_width - 1) || x == 0) - xdir = -xdir; - if (y >= (vga_state.vga_height - 1) || y == 0) - ydir = -ydir; - } - } - - /* another handy "demo" effect using VGA write mode 1. - * we can take what's on screen and vertically squash it like an old analog TV set turning off. */ - { - unsigned int blank_line_ofs = (vga_state.vga_stride * vga_state.vga_height * 2); - unsigned int copy_ofs = (vga_state.vga_stride * vga_state.vga_height); - unsigned int display_ofs = 0x0000; - unsigned int i,y,soh,doh,dstart; - unsigned int dh_blankfill = 8; - unsigned int dh_step = 8; - uint32_t sh,dh,yf,ystep; - - /* copy active display (0) to offscreen buffer (0x4000) */ - vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride; - vga_setup_wm1_block_copy(); - vga_wm1_mem_block_copy(copy_ofs,display_ofs,vga_state.vga_stride * vga_state.vga_height); - vga_restore_rm0wm0(); - - /* need a blank line as well */ - for (i=0;i < vga_state.vga_stride;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0; - - sh = dh = vga_state.vga_height; - while (dh >= dh_step) { - /* stop animating if the user hits ENTER */ - if (kbhit()) { - if (getch() == 13) break; - } - - /* wait for vsync end */ - vga_wait_for_vsync_end(); - - /* what scalefactor to use for stretching? */ - ystep = (0x10000UL * sh) / dh; - dstart = (vga_state.vga_height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen - doh = display_ofs; - soh = copy_ofs; - yf = 0; - y = 0; - - /* for performance, keep VGA in write mode 1 the entire render */ - vga_setup_wm1_block_copy(); - - /* blank lines */ - if (dstart >= dh_blankfill) y = dstart - dh_blankfill; - else y = 0; - doh = vga_state.vga_stride * y; - - while (y < dstart) { - vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride); - doh += vga_state.vga_stride; - y++; - } - - /* draw */ - while (y < (dh+dstart)) { - soh = copy_ofs + ((yf >> 16UL) * vga_state.vga_stride); - vga_wm1_mem_block_copy(doh,soh,vga_state.vga_stride); - doh += vga_state.vga_stride; - yf += ystep; - y++; - } - - /* blank lines */ - while (y < vga_state.vga_height && y < (dh+dstart+dh_blankfill)) { - vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride); - doh += vga_state.vga_stride; - y++; - } - - /* done */ - vga_restore_rm0wm0(); - - /* wait for vsync */ - vga_wait_for_vsync(); - - /* make it shrink */ - dh -= dh_step; - if (dh < 40) dh_step = 1; - } - } - - int10_setmode(3); - free(vrl_lineoffs); - buffer = NULL; - free(buffer); - bufsz = 0; - return 0; -} +#include +#include +#include +#include + +#include "src/tesuto.h" + +static unsigned char palette[768]; + +int main(int argc,char **argv) { + struct vrl1_vgax_header *vrl_header; + vrl1_vgax_offset_t *vrl_lineoffs; + unsigned char *buffer; + unsigned int bufsz; + int fd; + + if (argc < 3) { + fprintf(stderr,"drawvrl \n"); + return 1; + } + + fd = open(argv[1],O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Unable to open '%s'\n",argv[1]); + return 1; + } + { + unsigned long sz = lseek(fd,0,SEEK_END); + if (sz < sizeof(*vrl_header)) return 1; + if (sz >= 65535UL) return 1; + + bufsz = (unsigned int)sz; + buffer = malloc(bufsz); + if (buffer == NULL) return 1; + + lseek(fd,0,SEEK_SET); + if ((unsigned int)read(fd,buffer,bufsz) < bufsz) return 1; + + vrl_header = (struct vrl1_vgax_header*)buffer; + if (memcmp(vrl_header->vrl_sig,"VRL1",4) || memcmp(vrl_header->fmt_sig,"VGAX",4)) return 1; + if (vrl_header->width == 0 || vrl_header->height == 0) return 1; + } + close(fd); + + probe_dos(); + if (!probe_vga()) { + printf("VGA probe failed\n"); + return 1; + } + int10_setmode(19); + update_state_from_vga(); + vga_enable_256color_modex(); // VGA mode X + vga_state.vga_width = 320; // VGA lib currently does not update this + vga_state.vga_height = 240; // VGA lib currently does not update this + +#if 1 // 320x240 test mode: this is how Project 16 is using our code, enable for test case + { + struct vga_mode_params cm; + + vga_read_crtc_mode(&cm); + + // 320x240 mode 60Hz + cm.vertical_total = 525; + cm.vertical_start_retrace = 0x1EA; + cm.vertical_end_retrace = 0x1EC; + cm.vertical_display_end = 480; + cm.vertical_blank_start = 489; + cm.vertical_blank_end = 517; + + vga_write_crtc_mode(&cm,0); + } + vga_state.vga_height = 240; // VGA lib currently does not update this +#endif + + /* load color palette */ + fd = open(argv[2],O_RDONLY|O_BINARY); + if (fd >= 0) { + unsigned int i; + + read(fd,palette,768); + close(fd); + + vga_palette_lseek(0); + for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2); + } + + /* preprocess the sprite to generate line offsets */ + vrl_lineoffs = vrl1_vgax_genlineoffsets(vrl_header,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + if (vrl_lineoffs == NULL) return 1; + + { + unsigned int i,j,o; + + /* fill screen with a distinctive pattern */ + for (i=0;i < vga_state.vga_width;i++) { + o = i >> 2; + vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); + for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) + vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! + } + } + //while (getch() != 13); + + /* make distinctive pattern offscreen, render sprite, copy onscreen */ + { + const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height); + unsigned int i,j,o,o2,x,y,rx,ry,w,h; + unsigned int overdraw = 1; // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks. + // if the sprite's edge pixels are clear anyway, you can set this to 0. + VGA_RAM_PTR omemptr; + int xdir=1,ydir=1; + + /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */ + x = 0; + y = 0; + + /* do it */ + omemptr = vga_state.vga_graphics_ram; // save original mem ptr + while (1) { + /* stop animating if the user hits ENTER */ + if (kbhit()) { + if (getch() == 13) break; + } + + /* render box bounds. y does not need modification, but x and width must be multiple of 4 */ + if (x >= overdraw) rx = (x - overdraw) & (~3); + else rx = 0; + if (y >= overdraw) ry = (y - overdraw); + else ry = 0; + h = vrl_header->height + overdraw + y - ry; + w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3); + if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx; + if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry; + + /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */ + vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2; + vga_state.vga_draw_stride = w >> 2; + vga_state.vga_graphics_ram = omemptr + offscreen_ofs; + + /* first draw pattern corresponding to that part of the screen. this COULD be optimized, obviously, but it's designed for study. + * also note we don't have to use the same stride as the display! */ + for (i=rx;i < (rx+w);i++) { + o = (i-rx) >> 2; + vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); + for (j=ry;j < (ry+h);j++,o += vga_state.vga_draw_stride) + vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! + } + + /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ + draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + + /* restore ptr */ + vga_state.vga_graphics_ram = omemptr; + + /* block copy to visible RAM from offscreen */ + vga_setup_wm1_block_copy(); + o = offscreen_ofs; // source offscreen + o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride) + for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ + vga_restore_rm0wm0(); + + /* restore stride */ + vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride; + + /* step */ + x += xdir; + y += ydir; + if (x >= (vga_state.vga_width - 1) || x == 0) + xdir = -xdir; + if (y >= (vga_state.vga_height - 1) || y == 0) + ydir = -ydir; + } + } + + /* make distinctive pattern offscreen, render sprite, copy onscreen. + * this time, we render the distinctive pattern to another offscreen location and just copy. + * note this version is much faster too! */ + { + const unsigned int offscreen_ofs = (vga_state.vga_stride * vga_state.vga_height); + const unsigned int pattern_ofs = 0x10000UL - (vga_state.vga_stride * vga_state.vga_height); + unsigned int i,j,o,o2,x,y,rx,ry,w,h; + unsigned int overdraw = 1; // how many pixels to "overdraw" so that moving sprites with edge pixels don't leave streaks. + // if the sprite's edge pixels are clear anyway, you can set this to 0. + VGA_RAM_PTR omemptr; + int xdir=1,ydir=1; + + /* fill pattern offset with a distinctive pattern */ + for (i=0;i < vga_state.vga_width;i++) { + o = (i >> 2) + pattern_ofs; + vga_write_sequencer(0x02/*map mask*/,1 << (i&3)); + for (j=0;j < vga_state.vga_height;j++,o += vga_state.vga_stride) + vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15! + } + + /* starting coords. note: this technique is limited to x coordinates of multiple of 4 */ + x = 0; + y = 0; + + /* do it */ + omemptr = vga_state.vga_graphics_ram; // save original mem ptr + while (1) { + /* stop animating if the user hits ENTER */ + if (kbhit()) { + if (getch() == 13) break; + } + + /* render box bounds. y does not need modification, but x and width must be multiple of 4 */ + if (x >= overdraw) rx = (x - overdraw) & (~3); + else rx = 0; + if (y >= overdraw) ry = (y - overdraw); + else ry = 0; + h = vrl_header->height + overdraw + y - ry; + w = (x + vrl_header->width + (overdraw*2) + 3/*round up*/ - rx) & (~3); + if ((rx+w) > vga_state.vga_width) w = vga_state.vga_width-rx; + if ((ry+h) > vga_state.vga_height) h = vga_state.vga_height-ry; + + /* block copy pattern to where we will draw the sprite */ + vga_setup_wm1_block_copy(); + o2 = offscreen_ofs; + o = pattern_ofs + (ry * vga_state.vga_stride) + (rx >> 2); // source offscreen + for (i=0;i < h;i++,o += vga_state.vga_stride,o2 += (w >> 2)) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ + vga_restore_rm0wm0(); + + /* replace VGA stride with our own and mem ptr. then sprite rendering at this stage is just (0,0) */ + vga_state.vga_draw_stride_limit = (vga_state.vga_width + 3/*round up*/ - x) >> 2; + vga_state.vga_draw_stride = w >> 2; + vga_state.vga_graphics_ram = omemptr + offscreen_ofs; + + /* then the sprite. note modding ram ptr means we just draw to (x&3,0) */ + draw_vrl1_vgax_modex(x-rx,y-ry,vrl_header,vrl_lineoffs,buffer+sizeof(*vrl_header),bufsz-sizeof(*vrl_header)); + + /* restore ptr */ + vga_state.vga_graphics_ram = omemptr; + + /* block copy to visible RAM from offscreen */ + vga_setup_wm1_block_copy(); + o = offscreen_ofs; // source offscreen + o2 = (ry * vga_state.vga_stride) + (rx >> 2); // dest visible (original stride) + for (i=0;i < h;i++,o += vga_state.vga_draw_stride,o2 += vga_state.vga_stride) vga_wm1_mem_block_copy(o2,o,w >> 2); + /* must restore Write Mode 0/Read Mode 0 for this code to continue drawing normally */ + vga_restore_rm0wm0(); + + /* restore stride */ + vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride; + + /* step */ + x += xdir; + y += ydir; + if (x >= (vga_state.vga_width - 1) || x == 0) + xdir = -xdir; + if (y >= (vga_state.vga_height - 1) || y == 0) + ydir = -ydir; + } + } + + /* another handy "demo" effect using VGA write mode 1. + * we can take what's on screen and vertically squash it like an old analog TV set turning off. */ + { + unsigned int blank_line_ofs = (vga_state.vga_stride * vga_state.vga_height * 2); + unsigned int copy_ofs = (vga_state.vga_stride * vga_state.vga_height); + unsigned int display_ofs = 0x0000; + unsigned int i,y,soh,doh,dstart; + unsigned int dh_blankfill = 8; + unsigned int dh_step = 8; + uint32_t sh,dh,yf,ystep; + + /* copy active display (0) to offscreen buffer (0x4000) */ + vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride; + vga_setup_wm1_block_copy(); + vga_wm1_mem_block_copy(copy_ofs,display_ofs,vga_state.vga_stride * vga_state.vga_height); + vga_restore_rm0wm0(); + + /* need a blank line as well */ + for (i=0;i < vga_state.vga_stride;i++) vga_state.vga_graphics_ram[i+blank_line_ofs] = 0; + + sh = dh = vga_state.vga_height; + while (dh >= dh_step) { + /* stop animating if the user hits ENTER */ + if (kbhit()) { + if (getch() == 13) break; + } + + /* wait for vsync end */ + vga_wait_for_vsync_end(); + + /* what scalefactor to use for stretching? */ + ystep = (0x10000UL * sh) / dh; + dstart = (vga_state.vga_height - dh) / 2; // center the squash effect on screen, otherwise it would squash to top of screen + doh = display_ofs; + soh = copy_ofs; + yf = 0; + y = 0; + + /* for performance, keep VGA in write mode 1 the entire render */ + vga_setup_wm1_block_copy(); + + /* blank lines */ + if (dstart >= dh_blankfill) y = dstart - dh_blankfill; + else y = 0; + doh = vga_state.vga_stride * y; + + while (y < dstart) { + vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride); + doh += vga_state.vga_stride; + y++; + } + + /* draw */ + while (y < (dh+dstart)) { + soh = copy_ofs + ((yf >> 16UL) * vga_state.vga_stride); + vga_wm1_mem_block_copy(doh,soh,vga_state.vga_stride); + doh += vga_state.vga_stride; + yf += ystep; + y++; + } + + /* blank lines */ + while (y < vga_state.vga_height && y < (dh+dstart+dh_blankfill)) { + vga_wm1_mem_block_copy(doh,blank_line_ofs,vga_state.vga_stride); + doh += vga_state.vga_stride; + y++; + } + + /* done */ + vga_restore_rm0wm0(); + + /* wait for vsync */ + vga_wait_for_vsync(); + + /* make it shrink */ + dh -= dh_step; + if (dh < 40) dh_step = 1; + } + } + + int10_setmode(3); + free(vrl_lineoffs); + buffer = NULL; + free(buffer); + bufsz = 0; + return 0; +} diff --git a/src/tesuto.h b/src/tesuto.h index dbe0bfc7..d1f8bbbe 100755 --- a/src/tesuto.h +++ b/src/tesuto.h @@ -1,20 +1,20 @@ -#ifndef __TESUTO_H__ -#define __TESUTO_H__ - -#include "src/lib/16_head.h" -#include "src/lib/modex16.h" -#include "src/lib/16_in.h" -#include -#include -#include -#include - -typedef unsigned char far *VGA_RAM_PTR; -//VGA_RAM_PTR vga_graphics_ram = (VGA_RAM_PTR)MK_FP(0xA000,0x0000); -//unsigned char vga_stride = 80; // 80 x 4 = 320 for 320-pixel wide modes - -/*static inline void vga_write_sequencer(unsigned char i,unsigned char c) { - outp(0x3C4,i); - outp(0x3C5,c); -}*/ -#endif +#ifndef __TESUTO_H__ +#define __TESUTO_H__ + +#include "src/lib/16_head.h" +#include "src/lib/modex16.h" +#include "src/lib/16_in.h" +#include +#include +#include +#include + +typedef unsigned char far *VGA_RAM_PTR; +//VGA_RAM_PTR vga_graphics_ram = (VGA_RAM_PTR)MK_FP(0xA000,0x0000); +//unsigned char vga_stride = 80; // 80 x 4 = 320 for 320-pixel wide modes + +/*static inline void vga_write_sequencer(unsigned char i,unsigned char c) { + outp(0x3C4,i); + outp(0x3C5,c); +}*/ +#endif diff --git a/src/tsthimem.c b/src/tsthimem.c index 7476b7ea..245a5335 100755 --- a/src/tsthimem.c +++ b/src/tsthimem.c @@ -1,295 +1,295 @@ -/* tsthimem.c - * - * Test program: HIMEM.SYS functions - * (C) 2010-2012 Jonathan Campbell. - * Hackipedia DOS library. - * - * This code is licensed under the LGPL. - * - */ - -#include -#include -#include -#include -#include -#include - -//#include "src/lib/doslib/cpu.h" -#include "src/lib/doslib/dos.h" -//#include doswin.h> -#include "src/lib/doslib/himemsys.h" - -int main() { - probe_dos(); - printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); - /*if (detect_windows()) { - printf("I am running under Windows.\n"); - printf(" Mode: %s\n",windows_mode_str(windows_mode)); - printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); - } - else { - printf("Not running under Windows or OS/2\n"); - }*/ - - if (probe_himem_sys()) { - int h1,h2,h3; - - printf("HIMEM.SYS detected. Entry point %04x:%04x. v%x.%02x\n", - (unsigned int)((himem_sys_entry >> 16) & 0xFFFFUL), - (unsigned int)(himem_sys_entry & 0xFFFFUL), - (unsigned int)(himem_sys_version >> 8), - (unsigned int)(himem_sys_version & 0xFF)); - - if (himem_sys_flags & HIMEM_F_HMA) - printf(" - HMA is present\n"); - if (himem_sys_flags & HIMEM_F_4GB) - printf(" - Extensions are present to address up to 4GB of memory\n"); - - printf("A20 status: %u\n",himem_sys_query_a20()); - printf("Global A20 line: "); fflush(stdout); - printf("en=%d ",himem_sys_global_a20(1)); fflush(stdout); - printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); - printf("dis=%d ",himem_sys_global_a20(0)); fflush(stdout); - printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); - printf("\n"); - - printf("Local A20 line: "); fflush(stdout); - printf("en=%d ",himem_sys_local_a20(1)); fflush(stdout); - printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); - printf("dis=%d ",himem_sys_local_a20(0)); fflush(stdout); - printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); - printf("\n"); - - himem_sys_update_free_memory_status(); - printf("Free memory: %luKB (largest block %luKB)\n", - (unsigned long)himem_sys_total_free, - (unsigned long)himem_sys_largest_free); - - printf("Attempting to alloc 4KB: "); - h1 = himem_sys_alloc(4); /* NTS: This is in KB, not bytes */ - if (h1 != -1) printf("ok, handle %u\n",h1); - else printf("failed\n"); - - printf("Attempting to alloc 64KB: "); - h2 = himem_sys_alloc(46); /* NTS: This is in KB, not bytes */ - if (h2 != -1) printf("ok, handle %u\n",h2); - else printf("failed\n"); - - printf("Attempting to alloc 1MB: "); - h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ - if (h3 != -1) printf("ok, handle %u\n",h3); - else printf("failed\n"); - - if (h1 != -1) { - if (!himem_sys_free(h1)) printf(" - Free failed\n"); - } - if (h2 != -1) { - if (!himem_sys_free(h2)) printf(" - Free failed\n"); - } - if (h3 != -1) { - if (!himem_sys_free(h3)) printf(" - Free failed\n"); - } - - printf("Attempting to alloc 1MB (for writing to): "); - h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ - if (h3 != -1) { - uint32_t ofs; - unsigned int i; - struct himem_block_info binf; -#if TARGET_MSDOS == 32 - char *msg; - unsigned char *tmp; - uint16_t tmpsel=0,msgsel=0; - const char *msgref = "Testing 123 hello"; -#else - unsigned char tmp[16]; - const char *msg = "Testing 123 hello"; -#endif - -#if TARGET_MSDOS == 32 - tmp = dpmi_alloc_dos(16,&tmpsel); - if (tmp == NULL) abort(); - msg = dpmi_alloc_dos(strlen(msgref)+16,&msgsel); - if (msg == NULL) abort(); - memcpy(msg,msgref,strlen(msgref)+1); -#endif - - printf("ok, handle %u\n",h3); - - if (himem_sys_get_handle_info(h3,&binf)) { - printf("Handle info:\n"); - printf(" Lock count=%u Free handles=%u Size=%luKB\n", - (unsigned int)binf.lock_count, - (unsigned int)binf.free_handles, - (unsigned long)binf.block_length_kb); - } - else { - printf("Cannot get handle info\n"); - } - -#if TARGET_MSDOS == 32 - if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) -#else - if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) -#endif - printf("Copy didn't work\n"); - - for (i=0;i < 16;i += 2) { - tmp[i+0] = 0x55; - tmp[i+1] = 0xAA; - } - -#if TARGET_MSDOS == 32 - if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) -#else - if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) -#endif - printf("Copy didn't work\n"); - - for (i=0;i < 16;i++) printf("%02x ",tmp[i]); - printf("\n"); - - ofs = himem_sys_lock(h3); - if (ofs != 0UL) { - printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); - if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); - } - else { - printf(" - Cannot lock\n"); - } - - printf("now resizing to 2MB\n"); - if (himem_sys_realloc(h3,2048)) { -#if TARGET_MSDOS == 32 - if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) -#else - if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) -#endif - printf("Copy didn't work\n"); - - for (i=0;i < 16;i++) printf("%02x ",tmp[i]); - printf("\n"); - - ofs = himem_sys_lock(h3); - if (ofs != 0UL) { - printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); - if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); - } - else { - printf(" - Cannot lock\n"); - } - } - else { - printf(" - Cannot realloc\n"); - } - - if (!himem_sys_free(h3)) printf(" - Free failed\n"); - -#if TARGET_MSDOS == 32 - dpmi_free_dos(tmpsel); tmp=NULL; - dpmi_free_dos(msgsel); msg=NULL; -#endif - } - else printf("failed\n"); - - printf("Attempting to alloc 129MB (for writing to): "); - h3 = himem_sys_alloc(129UL * 1024UL); /* NTS: This is in KB, not bytes */ - if (h3 != -1) { - uint32_t ofs; - unsigned int i; - unsigned char tmp[16]; - struct himem_block_info binf; - const char *msg = "Testing 123 hello"; - - printf("ok, handle %u\n",h3); - - if (himem_sys_get_handle_info(h3,&binf)) { - printf("Handle info:\n"); - printf(" Lock count=%u Free handles=%u Size=%luKB\n", - (unsigned int)binf.lock_count, - (unsigned int)binf.free_handles, - (unsigned long)binf.block_length_kb); - } - else { - printf("Cannot get handle info\n"); - } - -#if TARGET_MSDOS == 32 - if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) -#else - if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) -#endif - printf("Copy didn't work\n"); - - for (i=0;i < 16;i += 2) { - tmp[i+0] = 0x55; - tmp[i+1] = 0xAA; - } - -#if TARGET_MSDOS == 32 - if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) -#else - if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) -#endif - printf("Copy didn't work\n"); - - for (i=0;i < 16;i++) printf("%02x ",tmp[i]); - printf("\n"); - - ofs = himem_sys_lock(h3); - if (ofs != 0UL) { - printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); - if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); - } - else { - printf(" - Cannot lock\n"); - } - - printf("now resizing to 144MB\n"); - if (himem_sys_realloc(h3,144UL*1024UL)) { - if (himem_sys_get_handle_info(h3,&binf)) { - printf("Handle info:\n"); - printf(" Lock count=%u Free handles=%u Size=%luKB\n", - (unsigned int)binf.lock_count, - (unsigned int)binf.free_handles, - (unsigned long)binf.block_length_kb); - } - else { - printf("Cannot get handle info\n"); - } - -#if TARGET_MSDOS == 32 - if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) -#else - if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) -#endif - printf("Copy didn't work\n"); - - for (i=0;i < 16;i++) printf("%02x ",tmp[i]); - printf("\n"); - - ofs = himem_sys_lock(h3); - if (ofs != 0UL) { - printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); - if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); - } - else { - printf(" - Cannot lock\n"); - } - } - else { - printf(" - Cannot realloc\n"); - } - - if (!himem_sys_free(h3)) printf(" - Free failed\n"); - } - else printf("failed\n"); - } - else { - printf("HIMEM.SYS not found\n"); - } - - return 0; -} - +/* tsthimem.c + * + * Test program: HIMEM.SYS functions + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include + +//#include "src/lib/doslib/cpu.h" +#include "src/lib/doslib/dos.h" +//#include doswin.h> +#include "src/lib/doslib/himemsys.h" + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + /*if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + }*/ + + if (probe_himem_sys()) { + int h1,h2,h3; + + printf("HIMEM.SYS detected. Entry point %04x:%04x. v%x.%02x\n", + (unsigned int)((himem_sys_entry >> 16) & 0xFFFFUL), + (unsigned int)(himem_sys_entry & 0xFFFFUL), + (unsigned int)(himem_sys_version >> 8), + (unsigned int)(himem_sys_version & 0xFF)); + + if (himem_sys_flags & HIMEM_F_HMA) + printf(" - HMA is present\n"); + if (himem_sys_flags & HIMEM_F_4GB) + printf(" - Extensions are present to address up to 4GB of memory\n"); + + printf("A20 status: %u\n",himem_sys_query_a20()); + printf("Global A20 line: "); fflush(stdout); + printf("en=%d ",himem_sys_global_a20(1)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("dis=%d ",himem_sys_global_a20(0)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("\n"); + + printf("Local A20 line: "); fflush(stdout); + printf("en=%d ",himem_sys_local_a20(1)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("dis=%d ",himem_sys_local_a20(0)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("\n"); + + himem_sys_update_free_memory_status(); + printf("Free memory: %luKB (largest block %luKB)\n", + (unsigned long)himem_sys_total_free, + (unsigned long)himem_sys_largest_free); + + printf("Attempting to alloc 4KB: "); + h1 = himem_sys_alloc(4); /* NTS: This is in KB, not bytes */ + if (h1 != -1) printf("ok, handle %u\n",h1); + else printf("failed\n"); + + printf("Attempting to alloc 64KB: "); + h2 = himem_sys_alloc(46); /* NTS: This is in KB, not bytes */ + if (h2 != -1) printf("ok, handle %u\n",h2); + else printf("failed\n"); + + printf("Attempting to alloc 1MB: "); + h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ + if (h3 != -1) printf("ok, handle %u\n",h3); + else printf("failed\n"); + + if (h1 != -1) { + if (!himem_sys_free(h1)) printf(" - Free failed\n"); + } + if (h2 != -1) { + if (!himem_sys_free(h2)) printf(" - Free failed\n"); + } + if (h3 != -1) { + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + } + + printf("Attempting to alloc 1MB (for writing to): "); + h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ + if (h3 != -1) { + uint32_t ofs; + unsigned int i; + struct himem_block_info binf; +#if TARGET_MSDOS == 32 + char *msg; + unsigned char *tmp; + uint16_t tmpsel=0,msgsel=0; + const char *msgref = "Testing 123 hello"; +#else + unsigned char tmp[16]; + const char *msg = "Testing 123 hello"; +#endif + +#if TARGET_MSDOS == 32 + tmp = dpmi_alloc_dos(16,&tmpsel); + if (tmp == NULL) abort(); + msg = dpmi_alloc_dos(strlen(msgref)+16,&msgsel); + if (msg == NULL) abort(); + memcpy(msg,msgref,strlen(msgref)+1); +#endif + + printf("ok, handle %u\n",h3); + + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) +#else + if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i += 2) { + tmp[i+0] = 0x55; + tmp[i+1] = 0xAA; + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + + printf("now resizing to 2MB\n"); + if (himem_sys_realloc(h3,2048)) { +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + } + else { + printf(" - Cannot realloc\n"); + } + + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + +#if TARGET_MSDOS == 32 + dpmi_free_dos(tmpsel); tmp=NULL; + dpmi_free_dos(msgsel); msg=NULL; +#endif + } + else printf("failed\n"); + + printf("Attempting to alloc 129MB (for writing to): "); + h3 = himem_sys_alloc(129UL * 1024UL); /* NTS: This is in KB, not bytes */ + if (h3 != -1) { + uint32_t ofs; + unsigned int i; + unsigned char tmp[16]; + struct himem_block_info binf; + const char *msg = "Testing 123 hello"; + + printf("ok, handle %u\n",h3); + + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) +#else + if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i += 2) { + tmp[i+0] = 0x55; + tmp[i+1] = 0xAA; + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + + printf("now resizing to 144MB\n"); + if (himem_sys_realloc(h3,144UL*1024UL)) { + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + } + else { + printf(" - Cannot realloc\n"); + } + + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + } + else printf("failed\n"); + } + else { + printf("HIMEM.SYS not found\n"); + } + + return 0; +} + diff --git a/src/vrstest.c b/src/vrstest.c index 8ed43620..05db59e1 100755 --- a/src/vrstest.c +++ b/src/vrstest.c @@ -1,174 +1,174 @@ -/* Project 16 Source Code~ - * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover - * - * This file is part of Project 16. - * - * Project 16 is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Project 16 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see , or - * write to the Free Software Foundation, Inc., 51 Franklin Street, - * Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "src/lib/modex16.h" -#include "src/lib/16_sprit.h" -#include "src/lib/16_ca.h" -#include "src/lib/16_mm.h" - -void main() { - global_game_variables_t gvar; - __segment sega; - memptr bigbuffer; - int i; - word start; - int plane; - float t1, t2; - boolean baka; - byte *pal; - int size, size1; - struct sprite spri; - vrl1_vgax_offset_t * off, *off1; - struct vrs_container vrs; - vrl1_vgax_offset_t **vrl_line_offsets; - uint32_t huge *vrl_headers_offsets; - uint16_t huge *vrl_id_iter; - uint32_t vrl_size; - int num_of_vrl; - struct vrl1_vgax_header huge *curr_vrl; - struct vrl_container *vrl; - word w=0; - - // DOSLIB: check our environment - probe_dos(); - - // DOSLIB: what CPU are we using? - // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. - // So this code by itself shouldn't care too much what CPU it's running on. Except that other - // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for - // the CPU to carry out tasks. --J.C. - cpu_probe(); - - // DOSLIB: check for VGA - if (!probe_vga()) { - printf("VGA probe failed\n"); - return; - } - // hardware must be VGA or higher! - if (!(vga_state.vga_flags & VGA_IS_VGA)) { - printf("This program requires VGA or higher graphics hardware\n"); - return; - } - - //gvar.video.page[0]=modexDefaultPage(&gvar.video.page[0]); - - gvar.mm.mmstarted=0; - MM_Startup(&gvar); - CA_Startup(&gvar); - // What should be done by read_vrs: - //sega = (mm.bufferseg); - if(CA_LoadFile("data/spri/chikyuu.vrs", &bigbuffer, &gvar)) baka=1; else baka=0; - - // Insert sanity cheks later - vrs.buffer = bigbuffer; - vrs.data_size = size - sizeof(struct vrl1_vgax_header); - num_of_vrl = 0; - vrl_id_iter = (uint16_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]); - while(vrl_id_iter[num_of_vrl]){ - num_of_vrl++; - } - - // Allocate memory for vrl line offsets table - vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl); - - vrl_headers_offsets = (uint32_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]); - // Calculate line offsets for each vrl - for(i = 0; i < num_of_vrl; i++){ - curr_vrl = (struct vrl1_vgax_header huge *)(vrs.buffer + vrl_headers_offsets[i]); - - // Calc. vrl size as (next_offset - curr_offset) - if (i != num_of_vrl - 1){ - vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); - } - // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset) - else{ - vrl_size = vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); - } - vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size); - } - vrs.vrl_line_offsets = vrl_line_offsets; - - - //read_vrs(&gvar, "data/spri/chikyuu.vrs", &vrs); - spri.spritesheet = &vrs; - spri.sprite_vrl_cont = malloc(sizeof(struct vrl_container)); - i = set_anim_by_id(&spri, 11); - if (i == -1) - { - return; - } - spri.x = 5; - spri.y = 100; - -// Uncomment to see broken sprites -/* sega = mm.bufferseg; - if(CA_LoadFile("data/spri/CHUBACW1.vrl", &bigbuffer, &mm, &mmi)) baka=1; else baka=0;*/ - - /* clear and draw one sprite and one bitmap */ - VGAmodeX(1, 1, &gvar); - modexHiganbanaPageSetup(&gvar.video); - - /* non sprite comparison */ - start = *clockw; - modexCopyPageRegion(&gvar.video.page[0], &gvar.video.page[0], 0, 0, 0, 0, 320, 240); - t1 = (*clockw-start) /18.2; - - start = *clockw; - - t2 = (*clockw-start)/18.2; - - for (i = 0; i < 5; i++){ - spri.delay = 1; animate_spri(&spri); spri.x += 20; sleep(1); } - - while(!kbhit()) - { - switch(w) - { - case 1024: - modexPalUpdate0(pal); - w=0; - default: - w++; - break; - } - } - VGAmodeX(0, 1, &gvar); - MM_ShowMemory(&gvar); - MM_DumpData(&gvar); - free(spri.sprite_vrl_cont); - MM_FreePtr(&bigbuffer, &gvar); - //MM_FreePtr(&((void __based(sega)*)spri.spritesheet->buffer), &mm); - CA_Shutdown(&gvar); - MM_Shutdown(&gvar); - //printf("CPU to VGA: %f\n", t1); - //printf("VGA to VGA: %f\n", t2); - heapdump(&gvar); - printf("Project 16 vrstest.exe. This is just a test file!\n"); - printf("version %s\n", VERSION); - printf("t1: %f\n", t1); - printf("t2: %f\n", t2); - printf("gvar.video.page[0].width: %u\n", gvar.video.page[0].width); - printf("gvar.video.page[0].height: %u\n", gvar.video.page[0].height); - printf("Num %d", num_of_vrl); - if(baka) printf("\nyay!\n"); - else printf("\npoo!\n"); -} +/* Project 16 Source Code~ + * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/lib/modex16.h" +#include "src/lib/16_sprit.h" +#include "src/lib/16_ca.h" +#include "src/lib/16_mm.h" + +void main() { + global_game_variables_t gvar; + __segment sega; + memptr bigbuffer; + int i; + word start; + int plane; + float t1, t2; + boolean baka; + byte *pal; + int size, size1; + struct sprite spri; + vrl1_vgax_offset_t * off, *off1; + struct vrs_container vrs; + vrl1_vgax_offset_t **vrl_line_offsets; + uint32_t huge *vrl_headers_offsets; + uint16_t huge *vrl_id_iter; + uint32_t vrl_size; + int num_of_vrl; + struct vrl1_vgax_header huge *curr_vrl; + struct vrl_container *vrl; + word w=0; + + // DOSLIB: check our environment + probe_dos(); + + // DOSLIB: what CPU are we using? + // NTS: I can see from the makefile Sparky4 intends this to run on 8088 by the -0 switch in CFLAGS. + // So this code by itself shouldn't care too much what CPU it's running on. Except that other + // parts of this project (DOSLIB itself) rely on CPU detection to know what is appropriate for + // the CPU to carry out tasks. --J.C. + cpu_probe(); + + // DOSLIB: check for VGA + if (!probe_vga()) { + printf("VGA probe failed\n"); + return; + } + // hardware must be VGA or higher! + if (!(vga_state.vga_flags & VGA_IS_VGA)) { + printf("This program requires VGA or higher graphics hardware\n"); + return; + } + + //gvar.video.page[0]=modexDefaultPage(&gvar.video.page[0]); + + gvar.mm.mmstarted=0; + MM_Startup(&gvar); + CA_Startup(&gvar); + // What should be done by read_vrs: + //sega = (mm.bufferseg); + if(CA_LoadFile("data/spri/chikyuu.vrs", &bigbuffer, &gvar)) baka=1; else baka=0; + + // Insert sanity cheks later + vrs.buffer = bigbuffer; + vrs.data_size = size - sizeof(struct vrl1_vgax_header); + num_of_vrl = 0; + vrl_id_iter = (uint16_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST]); + while(vrl_id_iter[num_of_vrl]){ + num_of_vrl++; + } + + // Allocate memory for vrl line offsets table + vrl_line_offsets = malloc(sizeof(vrl1_vgax_offset_t *)*num_of_vrl); + + vrl_headers_offsets = (uint32_t huge *)(vrs.buffer + vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_VRS_LIST]); + // Calculate line offsets for each vrl + for(i = 0; i < num_of_vrl; i++){ + curr_vrl = (struct vrl1_vgax_header huge *)(vrs.buffer + vrl_headers_offsets[i]); + + // Calc. vrl size as (next_offset - curr_offset) + if (i != num_of_vrl - 1){ + vrl_size = vrl_headers_offsets[i+1] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); + } + // If it's the last vrl, size is (next_vrs_struct_offset - curr_offset) + else{ + vrl_size = vrs.vrs_hdr->offset_table[VRS_HEADER_OFFSET_SPRITE_ID_LIST] - vrl_headers_offsets[i] - sizeof(struct vrl1_vgax_header); + } + vrl_line_offsets[i] = vrl1_vgax_genlineoffsets(curr_vrl, (byte *)curr_vrl + sizeof(struct vrl1_vgax_header), vrl_size); + } + vrs.vrl_line_offsets = vrl_line_offsets; + + + //read_vrs(&gvar, "data/spri/chikyuu.vrs", &vrs); + spri.spritesheet = &vrs; + spri.sprite_vrl_cont = malloc(sizeof(struct vrl_container)); + i = set_anim_by_id(&spri, 11); + if (i == -1) + { + return; + } + spri.x = 5; + spri.y = 100; + +// Uncomment to see broken sprites +/* sega = mm.bufferseg; + if(CA_LoadFile("data/spri/CHUBACW1.vrl", &bigbuffer, &mm, &mmi)) baka=1; else baka=0;*/ + + /* clear and draw one sprite and one bitmap */ + VGAmodeX(1, 1, &gvar); + modexHiganbanaPageSetup(&gvar.video); + + /* non sprite comparison */ + start = *clockw; + modexCopyPageRegion(&gvar.video.page[0], &gvar.video.page[0], 0, 0, 0, 0, 320, 240); + t1 = (*clockw-start) /18.2; + + start = *clockw; + + t2 = (*clockw-start)/18.2; + + for (i = 0; i < 5; i++){ + spri.delay = 1; animate_spri(&spri); spri.x += 20; sleep(1); } + + while(!kbhit()) + { + switch(w) + { + case 1024: + modexPalUpdate0(pal); + w=0; + default: + w++; + break; + } + } + VGAmodeX(0, 1, &gvar); + MM_ShowMemory(&gvar); + MM_DumpData(&gvar); + free(spri.sprite_vrl_cont); + MM_FreePtr(&bigbuffer, &gvar); + //MM_FreePtr(&((void __based(sega)*)spri.spritesheet->buffer), &mm); + CA_Shutdown(&gvar); + MM_Shutdown(&gvar); + //printf("CPU to VGA: %f\n", t1); + //printf("VGA to VGA: %f\n", t2); + heapdump(&gvar); + printf("Project 16 vrstest.exe. This is just a test file!\n"); + printf("version %s\n", VERSION); + printf("t1: %f\n", t1); + printf("t2: %f\n", t2); + printf("gvar.video.page[0].width: %u\n", gvar.video.page[0].width); + printf("gvar.video.page[0].height: %u\n", gvar.video.page[0].height); + printf("Num %d", num_of_vrl); + if(baka) printf("\nyay!\n"); + else printf("\npoo!\n"); +} -- 2.39.5