levels now has their own scripts; no more hardcoded lights
[dd2d.git] / xmain_d2d.d
blob91b99c8bfb5e16043e12516b2c168bce53d26e16
1 /* DooM2D: Midnight on the Firing Line
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module xmain_d2d is aliced;
20 private:
21 import core.atomic;
22 import core.thread;
23 import core.time;
25 import std.concurrency;
27 import iv.glbinds;
28 import glutils;
29 import console;
30 import wadarc;
32 import iv.stream;
34 import d2dmap;
35 import d2dadefs;
36 //import d2dactors;
37 import d2dgfx;
38 import d2dfont;
39 import dacs;
41 import d2dunigrid;
43 // `map` is there
44 import dengapi;
46 import d2dparts;
48 import render;
51 // ////////////////////////////////////////////////////////////////////////// //
52 import arsd.color;
53 import arsd.png;
56 // ////////////////////////////////////////////////////////////////////////// //
57 void main (string[] args) {
58 FuncPool.dumpCode = false;
59 FuncPool.dumpCodeSize = false;
60 dacsDumpSemantic = false;
61 dacsOptimize = 9;
62 //version(rdmd) { dacsOptimize = 0; }
63 bool compileOnly = false;
64 bool doVBL = true;
66 for (usize idx = 1; idx < args.length; ++idx) {
67 bool remove = true;
68 if (args[idx] == "--dump-code") FuncPool.dumpCode = true;
69 else if (args[idx] == "--dump-code-size") FuncPool.dumpCodeSize = true;
70 else if (args[idx] == "--dump-semantic") dacsDumpSemantic = true;
71 else if (args[idx] == "--dump-all") { FuncPool.dumpCode = true; FuncPool.dumpCodeSize = true; dacsDumpSemantic = true; }
72 else if (args[idx] == "--compile") compileOnly = true;
73 else if (args[idx] == "--compile-only") compileOnly = true;
74 else if (args[idx] == "--messages") ++dacsMessages;
75 else if (args[idx] == "--no-copro") dacsOptimizeNoCoPro = true;
76 else if (args[idx] == "--no-deadass") dacsOptimizeNoDeadAss = true;
77 else if (args[idx] == "--no-purekill") dacsOptimizeNoPureKill = true;
78 else if (args[idx] == "--no-vsync") doVBL = false;
79 else if (args[idx] == "--vsync") doVBL = true;
80 else if (args[idx].length > 2 && args[idx][0..2] == "-O") {
81 import std.conv : to;
82 ubyte olevel = to!ubyte(args[idx][2..$]);
83 dacsOptimize = olevel;
85 else remove = false;
86 if (remove) {
87 foreach (immutable c; idx+1..args.length) args.ptr[c-1] = args.ptr[c];
88 args.length -= 1;
89 --idx; //hack
93 addInternalActorFields();
95 static void setDP () {
96 version(rdmd) {
97 setDataPath("data");
98 } else {
99 import std.file : thisExePath;
100 import std.path : dirName;
101 setDataPath(thisExePath.dirName);
103 addPak(getDataPath~"base.pk3"); registerWadScripts();
104 //addWad("/home/ketmar/k8prj/doom2d-tl/data/doom2d.wad"); registerWadScripts();
105 //addWad("/home/ketmar/k8prj/doom2d-tl/data/meat.wad"); registerWadScripts();
106 //addWad("/home/ketmar/k8prj/doom2d-tl/data/megadm.wad"); registerWadScripts();
107 //addWad("/home/ketmar/k8prj/doom2d-tl/data/megadm1.wad"); registerWadScripts();
108 //addWad("/home/ketmar/k8prj/doom2d-tl/data/superdm.wad"); registerWadScripts();
109 //addWad("/home/ketmar/k8prj/doom2d-tl/data/zadoomka.wad"); registerWadScripts();
110 loadWadScripts();
113 setDP();
115 if (compileOnly) return;
117 try {
118 registerAPI();
119 loadPalette();
121 setOpenGLContextVersion(3, 2); // up to GLSL 150
122 //openGLContextCompatible = false;
124 curmapname = "maps/map01.d2m";
125 //conwriteln(genNextMapName());
127 //map = new LevelMap("maps/map01.d2m");
128 //ugInit(map.width*8, map.height*8);
130 //scale = 2;
133 //mapOfsX = 8*26;
134 //mapOfsY = 8*56;
135 map.getThingPos(1/*ThingId.Player1*/, &mapOfsX, &mapOfsY);
136 // fix viewport
138 mapOfsX = (mapOfsX*2)-vlWidth/2;
139 if (mapOfsX+vlWidth > map.width*16) mapOfsX = map.width*16-vlWidth;
140 if (mapOfsX < 0) mapOfsX = 0;
141 mapOfsY = (mapOfsY*2)-vlHeight/2;
142 if (mapOfsY+vlHeight > map.height*16) mapOfsY = map.height*16-vlHeight;
143 if (mapOfsY < 0) mapOfsY = 0;
145 setMapViewPos(mapOfsX, mapOfsY);
146 mapOfsX = mapViewPosX[1];
147 mapOfsY = mapViewPosY[1];
150 sdwindow = new SimpleWindow(vlWidth, vlHeight, "D2D", OpenGlOptions.yes, Resizablity.fixedSize);
152 sdwindow.visibleForTheFirstTime = delegate () {
153 sdwindow.setAsCurrentOpenGlContext(); // make this window active
154 glbindLoadFunctions();
157 import core.stdc.stdio;
158 printf("GL version: %s\n", glGetString(GL_VERSION));
159 GLint l, h;
160 glGetIntegerv(GL_MAJOR_VERSION, &h);
161 glGetIntegerv(GL_MINOR_VERSION, &l);
162 printf("version: %d.%d\n", h, l);
163 printf("shader version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
164 GLint svcount;
165 glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, &svcount);
166 if (svcount > 0) {
167 printf("%d shader versions supported:\n", svcount);
168 foreach (GLuint n; 0..svcount) printf(" %d: %s\n", n, glGetStringi(GL_SHADING_LANGUAGE_VERSION, n));
171 GLint ecount;
172 glGetIntegerv(GL_NUM_EXTENSIONS, &ecount);
173 if (ecount > 0) {
174 printf("%d extensions supported:\n", ecount);
175 foreach (GLuint n; 0..ecount) printf(" %d: %s\n", n, glGetStringi(GL_EXTENSIONS, n));
180 // check if we have sufficient shader version here
182 bool found = false;
183 GLint svcount;
184 glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, &svcount);
185 if (svcount > 0) {
186 foreach (GLuint n; 0..svcount) {
187 import core.stdc.string : strncmp;
188 auto v = glGetStringi(GL_SHADING_LANGUAGE_VERSION, n);
189 if (v is null) continue;
190 if (strncmp(v, "120", 3) != 0) continue;
191 if (v[3] > ' ') continue;
192 found = true;
193 break;
196 if (!found) assert(0, "can't find OpenGL GLSL 120");
198 auto adr = glGetProcAddress("glTexParameterf");
199 if (adr is null) assert(0);
202 version(dont_use_vsync) {
203 sdwindow.vsync = false;
204 } else {
205 sdwindow.vsync = true;
207 //sdwindow.useGLFinish = false;
208 initOpenGL();
209 //sdwindow.redrawOpenGlScene();
210 if (!sdwindow.releaseCurrentOpenGlContext()) { import core.stdc.stdio; printf("can't release OpenGL context(1)\n"); }
212 if (!renderTid) {
213 renderTid = new Thread(&renderThread);
214 renderTid.start();
217 startRenderThread();
218 postLoadLevel(curmapname);
219 //postAddMessage("WRYYYYYYYYYY");
220 //postAddMessage("wryyyyyyyyyy");
223 //sdwindow.redrawOpenGlScene = delegate () { renderScene(); };
225 enum MSecsPerFrame = 1000/30; /* 30 is FPS */
227 enum { Left, Right, Up, Down }
228 bool[4] pressed = false;
229 bool testLightLocked = false;
231 sdwindow.eventLoop(MSecsPerFrame,
232 delegate () {
233 if (sdwindow.closed) return;
235 if (pressed[Left]) mapOfsX -= 8;
236 if (pressed[Right]) mapOfsX += 8;
237 if (pressed[Up]) mapOfsY -= 8;
238 if (pressed[Down]) mapOfsY += 8;
239 import std.math : cos, sin;
240 __gshared float itime = 0.0;
241 itime += 0.02;
242 if (movement) {
243 mapOfsX = cast(int)(800.0/2.0+cos(itime)*220.0);
244 mapOfsY = cast(int)(800.0/2.0+120.0+sin(itime)*160.0);
246 if (scale == 1) mapOfsX = mapOfsY = 0;
248 //sdwindow.redrawOpenGlSceneNow();
250 delegate (KeyEvent event) {
251 if (sdwindow.closed) return;
252 if (event.pressed && event.key == Key.Escape) { closeWindow(); return; }
254 switch (event.key) {
255 case Key.X: if (event.pressed) altMove = !altMove; break;
256 case Key.Left: if (altMove) pressed[Left] = event.pressed; break;
257 case Key.Right: if (altMove) pressed[Right] = event.pressed; break;
258 case Key.Up: if (altMove) pressed[Up] = event.pressed; break;
259 case Key.Down: if (altMove) pressed[Down] = event.pressed; break;
260 default:
263 if (true/*!altMove*/) {
264 switch (event.key) {
265 case Key.Left: case Key.Pad4: plrKeyUpDown(0, PLK_LEFT, event.pressed); break;
266 case Key.Right: case Key.Pad6: plrKeyUpDown(0, PLK_RIGHT, event.pressed); break;
267 case Key.Up: case Key.Pad8: plrKeyUpDown(0, PLK_UP, event.pressed); break;
268 case Key.Down: case Key.Pad2: plrKeyUpDown(0, PLK_DOWN, event.pressed); break;
269 case Key.Alt: plrKeyUpDown(0, PLK_JUMP, event.pressed); break;
270 case Key.Ctrl: plrKeyUpDown(0, PLK_FIRE, event.pressed); break;
271 case Key.Shift: plrKeyUpDown(0, PLK_USE, event.pressed); break;
272 default:
276 delegate (MouseEvent event) {
278 testLightX = event.x/*/scale*/;
279 testLightY = event.y/*/scale*/;
280 //testLightX += mapOfsX/scale;
281 //testLightY += mapOfsY/scale;
283 if (!testLightLocked) postTestLightMove(event.x, event.y);
285 delegate (dchar ch) {
286 if (ch == 'q') { closeWindow(); return; }
287 //if (ch == 's') scanlines = !scanlines;
288 if (ch == '1') postSetOption("scale", 1);
289 if (ch == '2') postSetOption("scale", 2);
290 if (ch == 'D') postToggleOption("cheatNoDoors", showMessage:true);
291 if (ch == 'i') postToggleOption("interpolation", showMessage:true);
292 if (ch == 'l') postToggleOption("lighting", showMessage:true);
293 if (ch == 'W') postToggleOption("CheatNoWallClip", showMessage:true);
294 if (ch == 'L') testLightLocked = !testLightLocked;
295 if (ch == 'p') postToggleOption("pause", showMessage:false);
296 if (ch == '!') postSkipLevel();
297 //if (ch == ' ') movement = !movement;
300 } catch (Exception e) {
301 import std.stdio : stderr;
302 stderr.writeln("FUUUUUUUUUUUU\n", e.toString);
304 closeWindow();
305 flushGui();