Subversion Repositories eduke32

Rev

Rev 8478 | Rev 8490 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2
// Ken Silverman's official web site: "http://www.advsys.net/ken"
3
// See the included license file "BUILDLIC.TXT" for license info.
4
//
5
// This file has been modified from Ken Silverman's original release
2456 hendricks2 6
// by Jonathon Fowler (jf@jonof.id.au)
7139 hendricks2 7
// by the EDuke32 team (development@voidpoint.com)
5 Plagman 8
 
9
#include "build.h"
7818 terminx 10
 
11
#include "baselayer.h"
12
#include "cache1d.h"
13
#include "colmatch.h"
14
#include "common.h"
5 Plagman 15
#include "compat.h"
7818 terminx 16
#include "editor.h"
17
#include "m32script.h"
5 Plagman 18
#include "osd.h"
5789 terminx 19
#include "palette.h"
7818 terminx 20
#include "pragmas.h"
21
#include "renderlayer.h"
6860 terminx 22
#include "scancodes.h"
7359 hendricks2 23
#include "vfs.h"
24
 
3221 hendricks2 25
#ifdef _WIN32
7818 terminx 26
#include "winbits.h"
5 Plagman 27
#endif
28
 
4557 hendricks2 29
char levelname[BMAX_PATH] = {0};
30
 
1205 terminx 31
#define updatecrc16(crc,dat) (crc = (((crc<<8)&65535)^crctable[((((uint16_t)crc)>>8)&65535)^dat]))
32
static int32_t crctable[256];
1101 terminx 33
static char kensig[64];
5 Plagman 34
 
4555 hendricks2 35
static const char *CallExtGetVer(void);
36
static int32_t CallExtInit(void);
5552 hendricks2 37
static int32_t CallExtPreInit(int32_t argc,char const * const * argv);
4557 hendricks2 38
static int32_t CallExtPostStartupWindow(void);
5345 hendricks2 39
static void CallExtPostInit(void);
4555 hendricks2 40
static void CallExtUnInit(void);
41
static void CallExtPreCheckKeys(void);
8428 hendricks2 42
static void CallExtAnalyzeSprites(int32_t, int32_t, int32_t, int32_t, int32_t);
4555 hendricks2 43
static void CallExtCheckKeys(void);
44
static void CallExtPreLoadMap(void);
45
static void CallExtSetupMapFilename(const char *mapname);
46
static void CallExtLoadMap(const char *mapname);
47
static int32_t CallExtPreSaveMap(void);
48
static void CallExtSaveMap(const char *mapname);
5290 terminx 49
static inline const char *CallExtGetSectorCaption(int16_t sectnum) { return ExtGetSectorCaption(sectnum); }
50
static inline const char *CallExtGetWallCaption(int16_t wallnum) { return ExtGetWallCaption(wallnum); }
51
static inline const char *CallExtGetSpriteCaption(int16_t spritenum) { return ExtGetSpriteCaption(spritenum); }
4555 hendricks2 52
static void CallExtShowSectorData(int16_t sectnum);
53
static void CallExtShowWallData(int16_t wallnum);
54
static void CallExtShowSpriteData(int16_t spritenum);
55
static void CallExtEditSectorData(int16_t sectnum);
56
static void CallExtEditWallData(int16_t wallnum);
57
static void CallExtEditSpriteData(int16_t spritenum);
58
// static const char *CallExtGetSectorType(int32_t lotag);
5 Plagman 59
 
2028 helixhorne 60
int8_t m32_clipping=2;
2942 helixhorne 61
static int32_t m32_rotateang = 0;
5 Plagman 62
 
726 terminx 63
// 0   1     2     3      4       5      6      7
64
// up, down, left, right, lshift, rctrl, lctrl, space
65
// 8  9  10    11    12   13
66
// a, z, pgdn, pgup, [,], [.]
67
// 14       15     16 17 18   19
68
// kpenter, enter, =, -, tab, `
1205 terminx 69
uint8_t buildkeys[NUMBUILDKEYS] =
584 terminx 70
{
71
    0xc8,0xd0,0xcb,0xcd,0x2a,0x9d,0x1d,0x39,
72
    0x1e,0x2c,0xd1,0xc9,0x33,0x34,
73
    0x9c,0x1c,0xd,0xc,0xf,0x29
74
};
5 Plagman 75
 
3697 helixhorne 76
// Start position
77
vec3_t startpos;
78
int16_t startang, startsectnum;
79
 
80
// Current position
1208 terminx 81
vec3_t pos;
82
int32_t horiz = 100;
1205 terminx 83
int16_t ang, cursectnum;
3509 helixhorne 84
static int32_t hvel, vel, svel, angvel;
3532 helixhorne 85
int32_t g_doHardcodedMovement = 1;
5 Plagman 86
 
1886 helixhorne 87
static int32_t mousexsurp = 0, mouseysurp = 0;
4890 terminx 88
double msens = 1.0;
1886 helixhorne 89
 
1205 terminx 90
int32_t grponlymode = 0;
91
int32_t graphicsmode = 0;
5 Plagman 92
 
1205 terminx 93
int32_t synctics = 0, lockclock = 0;
5 Plagman 94
 
1679 helixhorne 95
// those ones save the respective 3d video vars while in 2d mode
96
// so that exiting from mapster32 in 2d mode saves the correct ones
4606 terminx 97
float vid_gamma_3d=-1, vid_contrast_3d=-1, vid_brightness_3d=-1;
1679 helixhorne 98
 
1205 terminx 99
int32_t xdim2d = 640, ydim2d = 480, xdimgame = 640, ydimgame = 480, bppgame = 8;
100
int32_t forcesetup = 1;
5 Plagman 101
 
3582 hendricks2 102
#ifndef GEKKO
8205 terminx 103
int32_t g_maxCacheSize = 128<<20;
3582 hendricks2 104
#else
105
int32_t g_maxCacheSize = 8<<20;
106
#endif
5 Plagman 107
 
1205 terminx 108
static int16_t oldmousebstatus = 0;
4558 hendricks2 109
 
110
char game_executable[BMAX_PATH] = {0};
111
 
2260 helixhorne 112
int32_t zlock = 0x7fffffff, zmode = 0, kensplayerheight = 32;
8440 hendricks2 113
int16_t defaultspritecstat = 0;
5 Plagman 114
 
1205 terminx 115
int16_t localartfreq[MAXTILES];
116
int16_t localartlookup[MAXTILES], localartlookupnum;
5 Plagman 117
 
118
char tempbuf[4096];
119
 
120
char names[MAXTILES][25];
1832 helixhorne 121
const char *g_namesFileName = "NAMES.H";
5 Plagman 122
 
1205 terminx 123
int16_t asksave = 0;
124
int32_t osearchx, osearchy;                               //old search input
5 Plagman 125
 
5281 terminx 126
int32_t grid = 0, autogrid = 1, gridlock = 1, showtags = 2;
127
int32_t zoom = 768, gettilezoom = 1, ztarget = 768;
1359 terminx 128
int32_t lastpm16time = 0;
5 Plagman 129
 
1205 terminx 130
extern int32_t mapversion;
5 Plagman 131
 
1733 helixhorne 132
int16_t highlight[MAXWALLS+MAXSPRITES];
1205 terminx 133
int16_t highlightsector[MAXSECTORS], highlightsectorcnt = -1;
5 Plagman 134
extern char textfont[128][8];
135
 
2715 helixhorne 136
int32_t tempsectornum = -1;  // for auto ceiling/floor alignment
137
int32_t temppicnum, tempcstat, templotag, temphitag, tempextra;
138
uint32_t temppal, tempvis, tempxrepeat, tempyrepeat, tempxpanning=0, tempypanning=0;
139
int32_t tempshade, tempxvel, tempyvel, tempzvel;
5925 terminx 140
int32_t tempstatnum=0, tempblend=0;
2715 helixhorne 141
char somethingintab = 255;
142
 
143
// Only valid when highlightsectorcnt>0 and no structural
1886 helixhorne 144
// modifications (deleting/inserting sectors or points, setting new firstwall)
2715 helixhorne 145
// have been made:
2119 helixhorne 146
static int16_t onextwall[MAXWALLS];  // onextwall[i]>=0 implies wall[i].nextwall < 0
1886 helixhorne 147
static void mkonwvalid(void) { chsecptr_onextwall = onextwall; }
2715 helixhorne 148
static void mkonwinvalid(void) { chsecptr_onextwall = NULL; tempsectornum=-1; }
2716 helixhorne 149
static void mkonwinvalid_keeptempsect(void) { chsecptr_onextwall = NULL; }
1886 helixhorne 150
static int32_t onwisvalid(void) { return chsecptr_onextwall != NULL; }
151
 
1843 helixhorne 152
int32_t mlook = 0, mskip=0;
1205 terminx 153
int32_t revertCTRL=0,scrollamount=3;
154
int32_t unrealedlook=1, quickmapcycling=1; //PK
5 Plagman 155
 
1361 terminx 156
char program_origcwd[BMAX_PATH];
1904 helixhorne 157
const char *mapster32_fullpath;
1361 terminx 158
char *testplay_addparam = 0;
159
 
5 Plagman 160
static char boardfilename[BMAX_PATH], selectedboardfilename[BMAX_PATH];
2096 helixhorne 161
//extern char levelname[BMAX_PATH];  // in astub.c   XXX: clean up this mess!!!
5 Plagman 162
 
4121 helixhorne 163
void B_SetBoardFileName(const char *fn)
164
{
165
    Bstrncpyz(boardfilename, fn, BMAX_PATH);
166
}
167
 
2556 helixhorne 168
static fnlist_t fnlist;
8199 terminx 169
static BUILDVFS_FIND_REC *finddirshigh=NULL, *findfileshigh=NULL;
1205 terminx 170
static int32_t currentlist=0;
5 Plagman 171
 
1205 terminx 172
//static int32_t repeatcountx, repeatcounty;
5 Plagman 173
 
1205 terminx 174
static int32_t fillist[640];
2132 helixhorne 175
// used for fillsector, batch point insertion, backup_highlighted_map
1930 helixhorne 176
static int32_t tempxyar[MAXWALLS][2];
5 Plagman 177
 
1644 helixhorne 178
static int32_t mousx, mousy;
1892 helixhorne 179
int16_t prefixtiles[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
7594 terminx 180
uint8_t hlsectorbitmap[(MAXSECTORS+7)>>3];  // show2dsector is already taken...
2144 helixhorne 181
static int32_t minhlsectorfloorz, numhlsecwalls;
5289 terminx 182
int32_t searchlock = 0;
1644 helixhorne 183
 
2787 helixhorne 184
// used for:
185
//  - hl_all_bunch_sectors_p
186
//  - AlignWalls
187
//  - trace_loop
7594 terminx 188
static uint8_t visited[(MAXWALLS+7)>>3];
1830 helixhorne 189
 
5281 terminx 190
int32_t m32_2d3dmode = 0;
191
int32_t m32_2d3dsize = 4;
6061 hendricks2 192
vec2_t m32_2d3d = { 0xffff, 4 };
5281 terminx 193
 
7435 terminx 194
int32_t m32_3dundo = 1;
195
 
1730 helixhorne 196
typedef struct
197
{
198
    int16_t numsectors, numwalls, numsprites;
2136 helixhorne 199
#ifdef YAX_ENABLE
200
    int16_t numyaxbunches;
201
    int16_t *bunchnum;  // [numsectors][2]
202
    int16_t *ynextwall;  // [numwalls][2]
203
#endif
5796 terminx 204
    usectortype *sector;
205
    uwalltype *wall;
206
    uspritetype *sprite;
1730 helixhorne 207
} mapinfofull_t;
208
 
2818 helixhorne 209
int32_t g_doScreenShot;
210
 
6860 terminx 211
#define eitherALT   (keystatus[sc_LeftAlt]|keystatus[sc_RightAlt])
212
#define eitherCTRL  (keystatus[sc_LeftControl]|keystatus[sc_RightControl])
213
#define eitherSHIFT (keystatus[sc_LeftShift]|keystatus[sc_RightShift])
1644 helixhorne 214
 
215
#define DOWN_BK(BuildKey) (keystatus[buildkeys[BK_##BuildKey]])
216
 
1205 terminx 217
int32_t pk_turnaccel=16;
218
int32_t pk_turndecel=12;
219
int32_t pk_uedaccel=3;
5 Plagman 220
 
3398 helixhorne 221
int8_t keeptexturestretch = 1;
1730 helixhorne 222
int8_t sideview_reversehrot = 0;
223
 
6318 hendricks2 224
int16_t pointhighlightdist = 256;
5568 terminx 225
int16_t linehighlightdist = 1024;
226
 
1372 helixhorne 227
char lastpm16buf[156];
1359 terminx 228
 
1760 helixhorne 229
//static int32_t checksectorpointer_warn = 0;
2110 helixhorne 230
static int32_t saveboard_savedtags, saveboard_fixedsprites;
3911 helixhorne 231
static int32_t saveboard_canceled;
1730 helixhorne 232
 
3697 helixhorne 233
static int32_t backup_highlighted_map(mapinfofull_t *mapinfo);
234
static int32_t restore_highlighted_map(mapinfofull_t *mapinfo, int32_t forreal);
235
static void SaveBoardAndPrintMessage(const char *fn);
236
 
1644 helixhorne 237
static int32_t adjustmark(int32_t *xplc, int32_t *yplc, int16_t danumwalls);
238
static void locktogrid(int32_t *dax, int32_t *day);
239
static int32_t checkautoinsert(int32_t dax, int32_t day, int16_t danumwalls);
3061 helixhorne 240
static void keytimerstuff(void);
1644 helixhorne 241
static void flipwalls(int16_t numwalls, int16_t newnumwalls);
2125 helixhorne 242
static int32_t insertpoint(int16_t linehighlight, int32_t dax, int32_t day, int32_t *mapwallnum);
2599 helixhorne 243
static void deletepoint(int16_t point, int32_t runi);
1644 helixhorne 244
static int32_t deletesector(int16_t sucksect);
1843 helixhorne 245
static int16_t whitelinescan(int16_t sucksect, int16_t dalinehighlight);
3061 helixhorne 246
static void printcoords16(int32_t posxe, int32_t posye, int16_t ange);
247
static void overheadeditor(void);
4026 helixhorne 248
static int32_t getlinehighlight(int32_t xplc, int32_t yplc, int32_t line, int8_t ignore_pointhighlight);
1644 helixhorne 249
static int32_t movewalls(int32_t start, int32_t offs);
5414 hendricks2 250
static void loadnames(const char *namesfile);
1865 helixhorne 251
static void getclosestpointonwall(int32_t x, int32_t y, int32_t dawall, int32_t *nx, int32_t *ny,
252
                                  int32_t maybe_screen_coord_p);
1644 helixhorne 253
static void initcrc(void);
5 Plagman 254
 
1644 helixhorne 255
static int32_t menuselect(void);
5282 terminx 256
static int32_t menuselect_auto(int, int); //PK
726 terminx 257
 
7072 terminx 258
static int32_t insert_sprite_common(int32_t sectnum, int32_t dax, int32_t day);
1801 helixhorne 259
static void correct_ornamented_sprite(int32_t i, int32_t hitw);
260
 
1644 helixhorne 261
static int32_t getfilenames(const char *path, const char *kind);
5 Plagman 262
 
3750 helixhorne 263
// Get basename of BUILD file name (forward slashes as directory separators).
264
static const char *getbasefn(const char *fn)
265
{
266
    const char *slash = Bstrrchr(fn, '/');
267
    return slash ? slash+1 : fn;
268
}
3697 helixhorne 269
 
3061 helixhorne 270
void clearkeys(void)
271
{
272
    Bmemset(keystatus,0,sizeof(keystatus));
273
}
5 Plagman 274
 
1740 helixhorne 275
#ifdef USE_OPENGL
7154 terminx 276
int osdcmd_restartvid(osdcmdptr_t UNUSED(parm))
5 Plagman 277
{
6297 terminx 278
    UNREFERENCED_CONST_PARAMETER(parm);
655 terminx 279
 
3823 helixhorne 280
    if (!in3dmode()) return OSDCMD_OK;
5 Plagman 281
 
6828 terminx 282
    videoResetMode();
6939 pogokeen 283
    if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor))
109 terminx 284
        OSD_Printf("restartvid: Reset failed...\n");
285
 
286
    return OSDCMD_OK;
5 Plagman 287
}
2289 helixhorne 288
#endif
5 Plagman 289
 
7154 terminx 290
static int osdcmd_vidmode(osdcmdptr_t parm)
5 Plagman 291
{
6939 pogokeen 292
    int32_t newx = xres, newy = yres, newbpp = bpp, newfullscreen = fullscreen;
2685 hendricks2 293
#ifdef USE_OPENGL
294
    int32_t tmp;
295
#endif
5 Plagman 296
 
584 terminx 297
    switch (parm->numparms)
298
    {
2289 helixhorne 299
#ifdef USE_OPENGL
109 terminx 300
    case 1:     // bpp switch
1456 helixhorne 301
        tmp = Batol(parm->parms[0]);
2311 helixhorne 302
        if (!(tmp==8 || tmp==16 || tmp==32))
303
            return OSDCMD_SHOWHELP;
304
        newbpp = tmp;
2315 helixhorne 305
        break;
109 terminx 306
    case 4:     // fs, res, bpp switch
307
        newfullscreen = (Batol(parm->parms[3]) != 0);
6370 terminx 308
        fallthrough__;
109 terminx 309
    case 3:     // res & bpp switch
1456 helixhorne 310
        tmp = Batol(parm->parms[2]);
2311 helixhorne 311
        if (!(tmp==8 || tmp==16 || tmp==32))
312
            return OSDCMD_SHOWHELP;
313
        newbpp = tmp;
6370 terminx 314
        fallthrough__;
2289 helixhorne 315
#endif
109 terminx 316
    case 2: // res switch
317
        newx = Batol(parm->parms[0]);
318
        newy = Batol(parm->parms[1]);
319
        break;
331 terminx 320
    default:
321
        return OSDCMD_SHOWHELP;
109 terminx 322
    }
5 Plagman 323
 
3823 helixhorne 324
    if (!in3dmode())
626 terminx 325
    {
6828 terminx 326
        videoSet2dMode(newx,newy);
626 terminx 327
        xdim2d = xdim;
328
        ydim2d = ydim;
329
 
6828 terminx 330
        videoBeginDrawing();    //{{{
1665 terminx 331
        CLEARLINES2D(0, ydim16, 0);
6828 terminx 332
        videoEndDrawing();      //}}}
1648 helixhorne 333
 
1359 terminx 334
        ydim16 = ydim-STATUS2DSIZ2;
1843 helixhorne 335
 
626 terminx 336
        return OSDCMD_OK;
337
    }
338
 
6939 pogokeen 339
    if (videoSetGameMode(newfullscreen,newx,newy,newbpp,upscalefactor))
109 terminx 340
        OSD_Printf("vidmode: Mode change failed!\n");
1644 helixhorne 341
 
342
    xdimgame = newx;
343
    ydimgame = newy;
344
    bppgame = newbpp;
345
    fullscreen = newfullscreen;
346
 
109 terminx 347
    return OSDCMD_OK;
5 Plagman 348
}
349
 
350
 
1456 helixhorne 351
#ifdef M32_SHOWDEBUG
1706 helixhorne 352
char m32_debugstr[64][128];
353
int32_t m32_numdebuglines=0;
1456 helixhorne 354
 
1644 helixhorne 355
static void M32_drawdebug(void)
1456 helixhorne 356
{
2265 helixhorne 357
    int32_t i;
358
    int32_t x=4, y=8;
1456 helixhorne 359
 
1797 helixhorne 360
#if 0
361
    {
362
        static char tstr[128];
1848 helixhorne 363
        Bsprintf(tstr, "search... stat=%d, sector=%d, wall=%d (%d), isbottom=%d, asksave=%d",
364
                 searchstat, searchsector, searchwall, searchbottomwall, searchisbottom, asksave);
1797 helixhorne 365
        printext256(x,y,whitecol,0,tstr,xdimgame>640?0:1);
366
    }
367
#endif
1836 helixhorne 368
    if (m32_numdebuglines>0)
1456 helixhorne 369
    {
6828 terminx 370
        videoBeginDrawing();
1877 helixhorne 371
        for (i=0; i<m32_numdebuglines && y<ydim-8; i++, y+=8)
1836 helixhorne 372
            printext256(x,y,whitecol,0,m32_debugstr[i],xdimgame>640?0:1);
6828 terminx 373
        videoEndDrawing();
1456 helixhorne 374
    }
375
    m32_numdebuglines=0;
376
}
377
#endif
378
 
1843 helixhorne 379
#ifdef YAX_ENABLE
1882 helixhorne 380
// Check whether bunchnum has exactly one corresponding floor and ceiling
381
// and return it in this case. If not 1-to-1, return -1.
382
int32_t yax_is121(int16_t bunchnum, int16_t getfloor)
383
{
384
    int32_t i;
385
    i = headsectbunch[0][bunchnum];
386
    if (i<0 || nextsectbunch[0][i]>=0)
387
        return -1;
388
    i = headsectbunch[1][bunchnum];
389
    if (i<0 || nextsectbunch[1][i]>=0)
390
        return -1;
391
 
392
    return headsectbunch[getfloor][bunchnum];
393
}
394
 
1900 helixhorne 395
static int32_t yax_numsectsinbunch(int16_t bunchnum, int16_t cf)
396
{
397
    int32_t i, n=0;
398
 
399
    if (bunchnum<0 || bunchnum>=numyaxbunches)
400
        return -1;
401
 
402
    for (SECTORS_OF_BUNCH(bunchnum, cf, i))
403
        n++;
404
 
405
    return n;
406
}
407
 
1875 helixhorne 408
static void yax_fixreverselinks(int16_t oldwall, int16_t newwall)
1865 helixhorne 409
{
1875 helixhorne 410
    int32_t cf, ynw;
411
    for (cf=0; cf<2; cf++)
1865 helixhorne 412
    {
1875 helixhorne 413
        ynw = yax_getnextwall(oldwall, cf);
414
        if (ynw >= 0)
415
            yax_setnextwall(ynw, !cf, newwall);
1865 helixhorne 416
    }
417
}
418
 
1875 helixhorne 419
static void yax_tweakwalls(int16_t start, int16_t offs)
420
{
421
    int32_t i, nw, cf;
422
    for (i=0; i<numwalls; i++)
423
        for (cf=0; cf<2; cf++)
424
        {
425
            nw = yax_getnextwall(i, cf);
426
            if (nw >= start)
427
                yax_setnextwall(i, cf, nw+offs);
428
        }
429
}
430
 
1843 helixhorne 431
static void yax_resetbunchnums(void)
432
{
433
    int32_t i;
434
 
435
    for (i=0; i<MAXSECTORS; i++)
436
        yax_setbunches(i, -1, -1);
1856 helixhorne 437
    yax_update(1);
1869 helixhorne 438
    yax_updategrays(pos.z);
1843 helixhorne 439
}
1854 helixhorne 440
 
1856 helixhorne 441
// Whether a wall is constrained by sector extensions.
442
// If false, it's a wall that you can freely move around,
443
// attach points to, etc...
2091 helixhorne 444
static int32_t yax_islockedwall(int16_t line)
1854 helixhorne 445
{
3658 helixhorne 446
#ifdef NEW_MAP_FORMAT
447
    return (wall[line].upwall>=0 || wall[line].dnwall>=0);
448
#else
1865 helixhorne 449
    return !!(wall[line].cstat&YAX_NEXTWALLBITS);
3658 helixhorne 450
#endif
1865 helixhorne 451
}
1854 helixhorne 452
 
1900 helixhorne 453
# define DEFAULT_YAX_HEIGHT (2048<<4)
1843 helixhorne 454
#endif
455
 
456
static void reset_default_mapstate(void)
457
{
458
    pos.x = 32768;          //new board!
459
    pos.y = 32768;
460
    pos.z = 0;
461
    ang = 1536;
1854 helixhorne 462
    cursectnum = -1;
463
 
1843 helixhorne 464
    numsectors = 0;
465
    numwalls = 0;
1854 helixhorne 466
 
1886 helixhorne 467
    editorzrange[0] = INT32_MIN;
468
    editorzrange[1] = INT32_MAX;
1877 helixhorne 469
 
1843 helixhorne 470
    initspritelists();
1867 helixhorne 471
    taglab_init();
6830 terminx 472
    artClearMapArt();
1843 helixhorne 473
#ifdef YAX_ENABLE
474
    yax_resetbunchnums();
475
#endif
3911 helixhorne 476
    g_loadedMapVersion = -1;
1843 helixhorne 477
}
478
 
2122 helixhorne 479
static void m32_keypresscallback(int32_t code, int32_t downp)
480
{
2123 helixhorne 481
    UNREFERENCED_PARAMETER(downp);
482
 
2122 helixhorne 483
    g_iReturnVar = code;
484
    VM_OnEvent(EVENT_KEYPRESS, -1);
485
}
486
 
2350 helixhorne 487
void M32_ResetFakeRORTiles(void)
488
{
489
#ifdef POLYMER
490
# ifdef YAX_ENABLE
491
        // END_TWEAK ceiling/floor fake 'TROR' pics, see BEGIN_TWEAK in engine.c
6829 terminx 492
        if (videoGetRenderMode() == REND_POLYMER && showinvisibility)
2350 helixhorne 493
        {
494
            int32_t i;
495
 
496
            for (i=0; i<numyaxbunches; i++)
497
            {
498
                yax_tweakpicnums(i, YAX_CEILING, 1);
499
                yax_tweakpicnums(i, YAX_FLOOR, 1);
500
            }
501
        }
502
# endif
503
#endif
504
}
505
 
2314 helixhorne 506
void M32_DrawRoomsAndMasks(void)
507
{
4880 helixhorne 508
    static int srchwall = -1;
5182 helixhorne 509
    const int32_t tmpyx=yxaspect, tmpvr=viewingrange;
4880 helixhorne 510
 
5182 helixhorne 511
    if (r_usenewaspect)
512
    {
513
        newaspect_enable = 1;
6828 terminx 514
        videoSetCorrectedAspect();
5182 helixhorne 515
    }
516
 
3648 helixhorne 517
    VM_OnEvent(EVENT_PREDRAW3DSCREEN, -1);
518
 
2314 helixhorne 519
    yax_preparedrawrooms();
520
    drawrooms(pos.x,pos.y,pos.z,ang,horiz,cursectnum);
4555 hendricks2 521
    yax_drawrooms(CallExtAnalyzeSprites, cursectnum, 0, 0);
2314 helixhorne 522
 
4880 helixhorne 523
    const int osearchwall=searchwall, osearchstat=searchstat;
524
    if (srchwall >= 0)
525
    {
526
        // a.m32 states 'tduprot' and 'tduplin' need searchstat to check for
527
        // whether we've hit a sprite, but these would be only set after the
528
        // drawmasks(). Hence this hackish workaround.
529
        searchstat = 3;
530
        searchwall = srchwall;
531
    }
8428 hendricks2 532
    CallExtAnalyzeSprites(0,0,0,0,0);
4880 helixhorne 533
    searchwall = osearchwall, searchstat=osearchstat;
534
 
6831 terminx 535
    renderDrawMasks();
4880 helixhorne 536
    srchwall = (searchstat == 3) ? searchwall : -1;
2350 helixhorne 537
    M32_ResetFakeRORTiles();
2314 helixhorne 538
 
539
#ifdef POLYMER
6829 terminx 540
    if (videoGetRenderMode() == REND_POLYMER && searchit == 2)
2314 helixhorne 541
    {
542
        polymer_editorpick();
543
        drawrooms(pos.x,pos.y,pos.z,ang,horiz,cursectnum);
8428 hendricks2 544
        CallExtAnalyzeSprites(0,0,0,0,0);
6831 terminx 545
        renderDrawMasks();
2350 helixhorne 546
        M32_ResetFakeRORTiles();
2314 helixhorne 547
    }
548
#endif
2818 helixhorne 549
 
550
    VM_OnEvent(EVENT_DRAW3DSCREEN, -1);
551
 
552
    if (g_doScreenShot)
553
    {
6831 terminx 554
        videoCaptureScreen("mcapxxxx.tga", 0);
2818 helixhorne 555
        g_doScreenShot = 0;
556
    }
5182 helixhorne 557
 
558
    if (r_usenewaspect)
559
    {
560
        newaspect_enable = 0;
6831 terminx 561
        renderSetAspect(tmpvr, tmpyx);
5182 helixhorne 562
    }
2314 helixhorne 563
}
564
 
7156 terminx 565
void M32_OnShowOSD(int shown)
5321 helixhorne 566
{
6827 terminx 567
    mouseLockToWindow((!shown) + 2);
5321 helixhorne 568
}
569
 
5345 hendricks2 570
static void M32_FatalEngineError(void)
571
{
8191 terminx 572
#ifdef DEBUGGINGAIDS
573
    debug_break();
574
#endif
575
    Bsprintf(tempbuf, "There was a problem initializing the engine: %s\n", engineerrstr);
576
    ERRprintf("%s", tempbuf);
577
    fatal_exit(tempbuf);
5345 hendricks2 578
}
579
 
8478 hendricks2 580
static void InitCustomColors()
581
{
582
    /* blue */
583
    vgapal16[9*4+0] = 252;
584
    vgapal16[9*4+1] = 124;
585
    vgapal16[9*4+2] = 28;
586
 
587
    /* orange */
588
    vgapal16[31*4+0] = 80; // blue
589
    vgapal16[31*4+1] = 180; // green
590
    vgapal16[31*4+2] = 240; // red
591
 
592
    // UNUSED?
593
    vgapal16[39*4+0] = 144;
594
    vgapal16[39*4+1] = 212;
595
    vgapal16[39*4+2] = 252;
596
 
597
 
598
    /* light yellow */
599
    vgapal16[22*4+0] = 204;
600
    vgapal16[22*4+1] = 252;
601
    vgapal16[22*4+2] = 252;
602
 
603
    /* grey */
604
    vgapal16[23*4+0] = 180;
605
    vgapal16[23*4+1] = 180;
606
    vgapal16[23*4+2] = 180;
607
 
608
    /* blue */
609
    vgapal16[24*4+0] = 204;
610
    vgapal16[24*4+1] = 164;
611
    vgapal16[24*4+2] = 48;
612
 
613
    vgapal16[32*4+0] = 240;
614
    vgapal16[32*4+1] = 200;
615
    vgapal16[32*4+2] = 84;
616
 
617
    // grid color
618
    vgapal16[25*4+0] = 64;
619
    vgapal16[25*4+1] = 56;
620
    vgapal16[25*4+2] = 56;
621
 
622
    vgapal16[26*4+0] = 96;
623
    vgapal16[26*4+1] = 96;
624
    vgapal16[26*4+2] = 96;
625
 
626
    // UNUSED?
627
    vgapal16[33*4+0] = 0; //60; // blue
628
    vgapal16[33*4+1] = 0; //120; // green
629
    vgapal16[33*4+2] = 192; //180; // red
630
 
631
    // UNUSED?
632
    vgapal16[41*4+0] = 0; //96;
633
    vgapal16[41*4+1] = 0; //160;
634
    vgapal16[41*4+2] = 252; //192;
635
 
636
    for (int i = 0; i<256; i++)
637
    {
638
        if (editorcolors[i] == 0)
639
        {
640
            palette_t *edcol = (palette_t *)&vgapal16[4*i];
8488 hendricks2 641
            editorcolors[i] = paletteGetClosestColorUpToIndex(edcol->b,edcol->g,edcol->r, 239);
8478 hendricks2 642
        }
643
    }
644
}
645
 
5828 terminx 646
int app_main(int argc, char const * const * argv)
5 Plagman 647
{
2079 helixhorne 648
#ifdef STARTUP_SETUP_WINDOW
649
    char cmdsetup = 0;
650
#endif
651
    char quitflag;
4973 helixhorne 652
    int32_t i;
5 Plagman 653
 
109 terminx 654
    pathsearchmode = 1;         // unrestrict findfrompath so that full access to the filesystem can be had
655
 
5 Plagman 656
#ifdef USE_OPENGL
627 terminx 657
    OSD_RegisterFunction("restartvid","restartvid: reinitialize the video mode",osdcmd_restartvid);
1112 hnt_ts 658
    OSD_RegisterFunction("vidmode","vidmode <xdim> <ydim> <bpp> <fullscreen>: immediately change the video mode",osdcmd_vidmode);
4015 helixhorne 659
    baselayer_osdcmd_vidmode_func = osdcmd_vidmode;
2289 helixhorne 660
#else
661
    OSD_RegisterFunction("vidmode","vidmode <xdim> <ydim>: immediately change the video mode",osdcmd_vidmode);
5 Plagman 662
#endif
4015 helixhorne 663
 
4558 hendricks2 664
    wm_setapptitle(AppProperName);
5 Plagman 665
 
1706 helixhorne 666
    editstatus = 1;
1717 helixhorne 667
 
4555 hendricks2 668
    if ((i = CallExtPreInit(argc,argv)) < 0) return -1;
5 Plagman 669
 
3221 hendricks2 670
#ifdef _WIN32
8174 terminx 671
    win_priorityclass = 1;
5 Plagman 672
#endif
673
 
584 terminx 674
    for (i=1; i<argc; i++)
675
    {
676
        if (argv[i][0] == '-')
677
        {
2079 helixhorne 678
#ifdef STARTUP_SETUP_WINDOW
1644 helixhorne 679
            if (!Bstrcmp(argv[i], "-setup")) cmdsetup = 1;
2079 helixhorne 680
            else
681
#endif
682
            if (!Bstrcmp(argv[i], "-help") || !Bstrcmp(argv[i], "--help") || !Bstrcmp(argv[i], "-?"))
584 terminx 683
            {
4558 hendricks2 684
#ifdef WM_MSGBOX_WINDOW
685
                wm_msgbox(AppProperName,
686
#else
687
                Bprintf(
688
#endif
689
                    "%s\n"
690
                    "Syntax: %s [options] mapname\n"
109 terminx 691
                    "Options:\n"
692
                    "\t-grp\tUse an extra GRP or ZIP file.\n"
693
                    "\t-g\tSame as above.\n"
2079 helixhorne 694
#ifdef STARTUP_SETUP_WINDOW
109 terminx 695
                    "\t-setup\tDisplays the configuration dialogue box before entering the editor.\n"
5 Plagman 696
#endif
4558 hendricks2 697
                    , AppProperName, AppTechnicalName);
109 terminx 698
                return 0;
699
            }
700
            continue;
701
        }
702
    }
3749 helixhorne 703
 
584 terminx 704
    if (boardfilename[0] == 0)
109 terminx 705
        Bstrcpy(boardfilename,"newboard.map");
584 terminx 706
    else if (Bstrchr(boardfilename,'.') == 0)
109 terminx 707
        Bstrcat(boardfilename, ".map");
708
    //Bcanonicalisefilename(boardfilename,0);
5 Plagman 709
 
4558 hendricks2 710
    OSD_SetFunctions(
711
        NULL, NULL, NULL, NULL, NULL,
712
        COMMON_clearbackground,
713
        BGetTime,
5321 helixhorne 714
        M32_OnShowOSD
4558 hendricks2 715
    );
716
 
7359 hendricks2 717
    if (!buildvfs_getcwd(program_origcwd,BMAX_PATH))
4557 hendricks2 718
        program_origcwd[0] = '\0';
719
 
4558 hendricks2 720
    Bstrncpy(game_executable, DefaultGameLocalExec, sizeof(game_executable));
721
 
6831 terminx 722
    if (enginePreInit())
5345 hendricks2 723
        M32_FatalEngineError();
4740 terminx 724
 
4555 hendricks2 725
    if ((i = CallExtInit()) < 0) return -1;
4557 hendricks2 726
 
2079 helixhorne 727
#ifdef STARTUP_SETUP_WINDOW
584 terminx 728
    if (i || forcesetup || cmdsetup)
729
    {
1762 terminx 730
        if (quitevent || !startwin_run())
1665 terminx 731
        {
6831 terminx 732
            engineUnInit();
8274 hendricks2 733
            exit(EXIT_SUCCESS);
1665 terminx 734
        }
194 terminx 735
    }
5 Plagman 736
#endif
737
 
4557 hendricks2 738
    if (CallExtPostStartupWindow() < 0) return -1;
739
 
5414 hendricks2 740
    loadnames(g_namesFileName);
1711 helixhorne 741
 
342 terminx 742
    if (initinput()) return -1;
1836 helixhorne 743
 
6827 terminx 744
    mouseInit();
342 terminx 745
 
8171 terminx 746
    timerInit(CLOCKTICKSPERSECOND);
6828 terminx 747
    timerSetCallback(keytimerstuff);
5 Plagman 748
 
6830 terminx 749
    artLoadFiles("tiles000.art", g_maxCacheSize);
109 terminx 750
 
5384 hendricks2 751
    Bstrcpy(kensig,"Uses BUILD technology by Ken Silverman");
752
    initcrc();
753
 
754
    const char *defsfile = G_DefFile();
755
 
7431 terminx 756
    if (testkopen("editor.def", 0))
757
        G_AddDefModule("editor.def");
758
 
5384 hendricks2 759
    if (!loaddefinitionsfile(defsfile))
760
        initprintf("Definitions file \"%s\" loaded.\n",defsfile);
761
 
6673 hendricks2 762
    for (char * m : g_defModules)
763
        free(m);
764
    g_defModules.clear();
5384 hendricks2 765
 
6831 terminx 766
    if (enginePostInit())
5384 hendricks2 767
        M32_FatalEngineError();
768
 
8478 hendricks2 769
    InitCustomColors();
770
 
5384 hendricks2 771
    CallExtPostInit();
772
 
1869 helixhorne 773
#ifdef YAX_ENABLE
774
    // init dummy texture for YAX
775
    // must be after loadpics(), which inits BUILD's cache
776
 
1895 helixhorne 777
    i = MAXTILES-1;
5842 hendricks2 778
    if (tilesiz[i].x==0 && tilesiz[i].y==0)
1895 helixhorne 779
    {
780
        static char R[8*16] = { //
781
            0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
782
            0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
783
            0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
784
            0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0,
785
            0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
786
            0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
787
            0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0,
788
        };
1869 helixhorne 789
 
1895 helixhorne 790
        char *newtile;
791
        int32_t sx=32, sy=32, col, j;
1869 helixhorne 792
 
8204 terminx 793
        walock[i] = CACHE1D_PERMANENT;
1895 helixhorne 794
        picsiz[i] = 5 + (5<<4);
4623 terminx 795
        tilesiz[i].x = sx; tilesiz[i].y = sy;
8204 terminx 796
        g_cache.allocateBlock(&waloff[i], sx*sy, &walock[i]);
1895 helixhorne 797
        newtile = (char *)waloff[i];
1869 helixhorne 798
 
6831 terminx 799
        col = paletteGetClosestColor(128, 128, 0);
1895 helixhorne 800
        for (j=0; j<(signed)sizeof(R); j++)
801
            R[j] *= col;
1869 helixhorne 802
 
1895 helixhorne 803
        Bmemset(newtile, 0, sx*sy);
804
        for (j=0; j<8; j++)
805
            Bmemcpy(&newtile[32*j], &R[16*j], 16);
806
    }
1869 helixhorne 807
#endif
808
 
2495 hendricks2 809
#ifdef HAVE_CLIPSHAPE_FEATURE
6831 terminx 810
    int k = engineLoadClipMaps();
1728 helixhorne 811
    if (k>0)
1722 helixhorne 812
        initprintf("There was an error loading the sprite clipping map (status %d).\n", k);
2495 hendricks2 813
 
6673 hendricks2 814
    for (char * f : g_clipMapFiles)
815
        free(f);
816
    g_clipMapFiles.clear();
2270 helixhorne 817
#endif
1719 helixhorne 818
 
1867 helixhorne 819
    taglab_init();
820
 
1886 helixhorne 821
    mkonwinvalid();
822
 
6223 terminx 823
    // executed once per init
824
    OSD_Exec("m32_autoexec.cfg");
825
 
1760 helixhorne 826
    if (LoadBoard(boardfilename, 1))
1843 helixhorne 827
        reset_default_mapstate();
5 Plagman 828
 
109 terminx 829
    totalclock = 0;
584 terminx 830
 
1208 terminx 831
    updatesector(pos.x,pos.y,&cursectnum);
584 terminx 832
 
6827 terminx 833
    keySetCallback(&m32_keypresscallback);
5321 helixhorne 834
    M32_OnShowOSD(0);  // make sure the desktop's mouse cursor is hidden
2122 helixhorne 835
 
456 terminx 836
    if (cursectnum == -1)
837
    {
6828 terminx 838
        vid_gamma_3d = g_videoGamma;
839
        vid_brightness_3d = g_videoBrightness;
840
        vid_contrast_3d = g_videoContrast;
1679 helixhorne 841
 
6828 terminx 842
        g_videoGamma = g_videoContrast = 1.0;
843
        g_videoBrightness = 0.0;
1665 terminx 844
 
6829 terminx 845
        videoSetPalette(0,0,0);
6939 pogokeen 846
        if (videoSetGameMode(fullscreen, xdim2d, ydim2d, 8, upscalefactor) < 0)
1364 terminx 847
        {
4555 hendricks2 848
            CallExtUnInit();
6831 terminx 849
            engineUnInit();
1364 terminx 850
            Bprintf("%d * %d not supported in this graphics mode\n",xdim2d,ydim2d);
8190 terminx 851
            Bexit(EXIT_SUCCESS);
1364 terminx 852
        }
1691 helixhorne 853
 
4090 hendricks2 854
        system_getcvars();
855
 
456 terminx 856
        overheadeditor();
727 terminx 857
        keystatus[buildkeys[BK_MODE2D_3D]] = 0;
1665 terminx 858
 
6828 terminx 859
        g_videoGamma = vid_gamma_3d;
860
        g_videoContrast = vid_contrast_3d;
861
        g_videoBrightness = vid_brightness_3d;
1679 helixhorne 862
 
863
        vid_gamma_3d = vid_contrast_3d = vid_brightness_3d = -1;
864
 
6829 terminx 865
        videoSetPalette(GAMMA_CALC,0,0);
456 terminx 866
    }
1360 terminx 867
    else
868
    {
6939 pogokeen 869
        if (videoSetGameMode(fullscreen, xdimgame, ydimgame, bppgame, upscalefactor) < 0)
1360 terminx 870
        {
4555 hendricks2 871
            CallExtUnInit();
6831 terminx 872
            engineUnInit();
1360 terminx 873
            Bprintf("%d * %d not supported in this graphics mode\n",xdim,ydim);
8190 terminx 874
            Bexit(EXIT_SUCCESS);
1360 terminx 875
        }
1691 helixhorne 876
 
4090 hendricks2 877
        system_getcvars();
878
 
6829 terminx 879
        videoSetPalette(GAMMA_CALC,0,0);
1360 terminx 880
    }
1760 helixhorne 881
 
5 Plagman 882
CANCEL:
109 terminx 883
    quitflag = 0;
884
    while (quitflag == 0)
885
    {
584 terminx 886
        if (handleevents())
887
        {
888
            if (quitevent)
889
            {
6860 terminx 890
                keystatus[sc_Escape] = 1;
109 terminx 891
                quitevent = 0;
892
            }
407 terminx 893
        }
584 terminx 894
 
109 terminx 895
        OSD_DispatchQueued();
5 Plagman 896
 
6828 terminx 897
        videoNextPage();
8050 pogokeen 898
        synctics = (int32_t) totalclock-lockclock;
1656 terminx 899
        lockclock += synctics;
900
 
4555 hendricks2 901
        CallExtPreCheckKeys();
1854 helixhorne 902
 
2314 helixhorne 903
        M32_DrawRoomsAndMasks();
1877 helixhorne 904
 
4200 hendricks2 905
        inputchecked = 1;
906
 
1456 helixhorne 907
#ifdef M32_SHOWDEBUG
1706 helixhorne 908
        if (searchstat>=0 && (searchwall<0 || searchsector<0))
909
        {
1866 helixhorne 910
            if (m32_numdebuglines<64)
911
                Bsprintf(m32_debugstr[m32_numdebuglines++], "inconsistent search variables!");
1706 helixhorne 912
            searchstat = -1;
913
        }
914
 
1456 helixhorne 915
        M32_drawdebug();
916
#endif
4555 hendricks2 917
        CallExtCheckKeys();
5 Plagman 918
 
919
 
6860 terminx 920
        if (keystatus[sc_Escape])
109 terminx 921
        {
6860 terminx 922
            keystatus[sc_Escape] = 0;
1776 helixhorne 923
 
5 Plagman 924
            printext256(0,0,whitecol,0,"Are you sure you want to quit?",0);
925
 
6828 terminx 926
            videoShowFrame(1);
8050 pogokeen 927
            synctics = (int32_t) totalclock-lockclock;
109 terminx 928
            lockclock += synctics;
5 Plagman 929
 
6860 terminx 930
            while ((keystatus[sc_Escape]|keystatus[sc_Enter]|keystatus[sc_Space]|keystatus[sc_N]) == 0)
109 terminx 931
            {
1486 helixhorne 932
                idle_waitevent();
584 terminx 933
                if (handleevents())
934
                {
935
                    if (quitevent)
936
                    {
109 terminx 937
                        quitflag = 1;
938
                        break;
939
                    }
451 terminx 940
                }
5 Plagman 941
 
6860 terminx 942
                if (keystatus[sc_Y]||keystatus[sc_Enter]) // Y or ENTER
584 terminx 943
                {
6860 terminx 944
                    keystatus[sc_Y] = 0;
945
                    keystatus[sc_Enter] = 0;
109 terminx 946
                    quitflag = 1; break;
947
                }
948
            }
6860 terminx 949
            while (keystatus[sc_Escape])
5 Plagman 950
            {
6860 terminx 951
                keystatus[sc_Escape] = 0;
5 Plagman 952
                quitevent = 0;
953
                goto CANCEL;
954
            }
109 terminx 955
        }
956
    }
5 Plagman 957
 
109 terminx 958
    if (asksave)
959
    {
1790 helixhorne 960
        i = CheckMapCorruption(4, 0);
1760 helixhorne 961
 
962
        printext256(0,8,whitecol,0,i<4?"Save changes?":"Map is heavily corrupt. Save changes?",0);
6828 terminx 963
        videoShowFrame(1);
5 Plagman 964
 
6860 terminx 965
        while ((keystatus[sc_Escape]|keystatus[sc_Enter]|keystatus[sc_Space]|keystatus[sc_N]|keystatus[sc_C]) == 0)
109 terminx 966
        {
1486 helixhorne 967
            idle_waitevent();
406 terminx 968
            if (handleevents()) { if (quitevent) break; } // like saying no
584 terminx 969
 
6860 terminx 970
            if (keystatus[sc_Y] || keystatus[sc_Enter]) // Y or ENTER
584 terminx 971
            {
6860 terminx 972
                keystatus[sc_Y] = keystatus[sc_Enter] = 0;
1760 helixhorne 973
 
3911 helixhorne 974
                SaveBoard(NULL, M32_SB_ASKOV);
1760 helixhorne 975
 
109 terminx 976
                break;
977
            }
978
        }
6860 terminx 979
        while (keystatus[sc_Escape]||keystatus[sc_C])
5 Plagman 980
        {
6860 terminx 981
            keystatus[sc_Escape] = keystatus[sc_C] = 0;
5 Plagman 982
            quitevent = 0;
983
            goto CANCEL;
109 terminx 984
        }
5 Plagman 985
    }
986
 
987
 
4555 hendricks2 988
    CallExtUnInit();
1843 helixhorne 989
//    clearfilenames();
6831 terminx 990
    engineUnInit();
5 Plagman 991
 
5803 terminx 992
    return 0;
5 Plagman 993
}
1644 helixhorne 994
 
995
static int32_t mhk=0;
2236 helixhorne 996
static void loadmhk(int32_t domessage)
606 terminx 997
{
3735 helixhorne 998
    char levname[BMAX_PATH];
606 terminx 999
 
1644 helixhorne 1000
    if (!mhk)
1001
        return;
1760 helixhorne 1002
 
1644 helixhorne 1003
    Bstrcpy(levname, boardfilename);
3735 helixhorne 1004
    append_ext_UNSAFE(levname, ".mhk");
1760 helixhorne 1005
 
6831 terminx 1006
    if (!engineLoadMHK(levname))
1760 helixhorne 1007
    {
1008
        if (domessage)
2538 hendricks2 1009
            message("Loaded map hack file \"%s\"",levname);
1760 helixhorne 1010
        else
2538 hendricks2 1011
            initprintf("Loaded map hack file \"%s\"\n",levname);
1760 helixhorne 1012
    }
1013
    else
1014
    {
1015
        mhk=2;
1016
        if (domessage)
2538 hendricks2 1017
            message("No maphack found for map \"%s\"",boardfilename);
1760 helixhorne 1018
    }
606 terminx 1019
}
1020
 
1854 helixhorne 1021
// this is spriteon{ceiling,ground}z from astub.c packed into
1022
// one convenient function
1023
void spriteoncfz(int32_t i, int32_t *czptr, int32_t *fzptr)
1024
{
3205 helixhorne 1025
    int32_t height, zofs;
1836 helixhorne 1026
 
3205 helixhorne 1027
    getzsofslope(sprite[i].sectnum, sprite[i].x,sprite[i].y, czptr, fzptr);
1028
    if ((sprite[i].cstat&48)==32)
1029
        return;
1854 helixhorne 1030
 
3205 helixhorne 1031
    zofs = spriteheightofs(i, &height, 0);
1032
 
1033
    *czptr += height - zofs;
1034
    *fzptr -= zofs;
1854 helixhorne 1035
}
1036
 
1836 helixhorne 1037
static void move_and_update(int32_t xvect, int32_t yvect, int32_t addshr)
1038
{
2028 helixhorne 1039
    if (m32_clipping==0)
1836 helixhorne 1040
    {
1041
        pos.x += xvect>>(14+addshr);
1042
        pos.y += yvect>>(14+addshr);
1043
        updatesector(pos.x,pos.y, &cursectnum);
1044
    }
1045
    else
2028 helixhorne 1046
    {
1836 helixhorne 1047
        clipmove(&pos,&cursectnum, xvect>>addshr,yvect>>addshr,
2028 helixhorne 1048
                 128,4<<8,4<<8, (m32_clipping==1) ? 0 : CLIPMASK0);
1049
    }
5277 terminx 1050
 
1051
    if (in3dmode())
1052
    {
1053
        silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1054
        getmessagetimeoff = (int32_t) totalclock+30;
5277 terminx 1055
    }
1836 helixhorne 1056
}
1057
 
1854 helixhorne 1058
static void mainloop_move(void)
1836 helixhorne 1059
{
1060
    int32_t xvect, yvect, doubvel;
1061
 
1062
    if (angvel != 0)  //ang += angvel * constant
1063
    {
5281 terminx 1064
        if (eitherCTRL && m32_2d3dmode)
1065
        {
1066
            int x = m32_2d3d.x + (angvel / 32);
1067
            int xx = m32_2d3d.x + XSIZE_2D3D + (angvel / 32);
1836 helixhorne 1068
 
5281 terminx 1069
            if (x > 4 && xx < xdim2d - 4)
1070
            {
1071
                silentmessage("2d3d x:%d y:%d", m32_2d3d.x, m32_2d3d.y);
1072
                m32_2d3d.x += (angvel / 32);
1073
            }
1074
        }
1075
        else
1076
        {
1077
            //ENGINE calculates angvel for you
1836 helixhorne 1078
 
5281 terminx 1079
            //Lt. shift makes turn velocity 50% faster
1080
            doubvel = (synctics + DOWN_BK(RUN)*(synctics>>1));
5277 terminx 1081
 
5281 terminx 1082
            ang += ((angvel*doubvel)>>4);
1083
            ang &= 2047;
1084
 
1085
            if (in3dmode())
1086
            {
1087
                silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1088
                getmessagetimeoff = (int32_t) totalclock+30;
5281 terminx 1089
            }
5277 terminx 1090
        }
1836 helixhorne 1091
    }
1092
    if ((vel|svel) != 0)
1093
    {
5281 terminx 1094
        if (eitherCTRL && m32_2d3dmode)
1095
        {
1096
            int y = m32_2d3d.y - (vel / 64);
1097
            int yy = m32_2d3d.y + YSIZE_2D3D - (vel / 64);
1836 helixhorne 1098
 
5281 terminx 1099
            if (y > 4 && yy < ydim2d - STATUS2DSIZ2 - 4)
1100
            {
1101
                silentmessage("2d3d x:%d y:%d", m32_2d3d.x, m32_2d3d.y);
1102
                m32_2d3d.y -= (vel / 64);
1103
            }
1104
        }
1105
        else
1836 helixhorne 1106
 
1107
        {
5281 terminx 1108
            //Lt. shift doubles forward velocity
1109
            doubvel = (1+(DOWN_BK(RUN)))*synctics;
1110
 
1111
            xvect = 0;
1112
            yvect = 0;
1113
 
1114
            if (vel != 0)
1115
            {
5282 terminx 1116
                xvect += ((vel*doubvel)>>3)*(int32_t) sintable[(ang+2560)&2047];
1117
                yvect += ((vel*doubvel)>>3)*(int32_t) sintable[(ang+2048)&2047];
5281 terminx 1118
            }
1119
            if (svel != 0)
1120
            {
5282 terminx 1121
                xvect += ((svel*doubvel)>>3)*(int32_t) sintable[(ang+2048)&2047];
1122
                yvect += ((svel*doubvel)>>3)*(int32_t) sintable[(ang+1536)&2047];
5281 terminx 1123
            }
1124
 
1125
            move_and_update(xvect, yvect, 0);
1836 helixhorne 1126
        }
1127
    }
1128
}
1129
 
2699 helixhorne 1130
static void handle_sprite_in_clipboard(int32_t i)
1131
{
1132
    if (somethingintab == 3)
1133
    {
1134
        int32_t j, k;
1135
 
1136
        sprite[i].picnum = temppicnum;
4623 terminx 1137
        if (tilesiz[temppicnum].x <= 0 || tilesiz[temppicnum].y <= 0)
2699 helixhorne 1138
        {
1139
            j = 0;
1140
            for (k=0; k<MAXTILES; k++)
4623 terminx 1141
                if (tilesiz[k].x > 0 && tilesiz[k].y > 0)
2699 helixhorne 1142
                {
1143
                    j = k;
1144
                    break;
1145
                }
1146
            sprite[i].picnum = j;
1147
        }
1148
        sprite[i].shade = tempshade;
6175 terminx 1149
        sprite[i].blend = tempblend;
2699 helixhorne 1150
        sprite[i].pal = temppal;
7078 terminx 1151
        sprite[i].xrepeat = max(tempxrepeat, 1u);
1152
        sprite[i].yrepeat = max(tempyrepeat, 1u);
2699 helixhorne 1153
        sprite[i].cstat = tempcstat;
1154
    }
1155
}
1156
 
1157
 
5 Plagman 1158
void editinput(void)
1159
{
1205 terminx 1160
    int32_t mousz, bstatus;
2699 helixhorne 1161
    int32_t i, tempint=0;
1843 helixhorne 1162
    int32_t goalz, xvect, yvect, hiz, loz, oposz;
5239 terminx 1163
    int32_t hihit, lohit, omlook=mlook;
5 Plagman 1164
 
726 terminx 1165
// 3B  3C  3D  3E   3F  40  41  42   43  44  57  58          46
1166
// F1  F2  F3  F4   F5  F6  F7  F8   F9 F10 F11 F12        SCROLL
1167
 
109 terminx 1168
    mousz = 0;
6831 terminx 1169
    mouseGetValues(&mousx,&mousy,&bstatus);
1836 helixhorne 1170
    mousx = (mousx<<16) + mousexsurp;
1171
    mousy = (mousy<<16) + mouseysurp;
1055 terminx 1172
 
1836 helixhorne 1173
    if (unrealedlook && !mskip)
1174
    {
1175
        if (mlook==0 && (bstatus&(1|2|4))==2)
1176
            mlook = 3;
1177
        else if ((bstatus&(1|2|4))==1)
1178
            mlook = 3;
1179
    }
1055 terminx 1180
 
109 terminx 1181
    {
1182
        ldiv_t ld;
1055 terminx 1183
        if (mlook)
1184
        {
1836 helixhorne 1185
            ld = ldiv(mousx, (int32_t)((1<<16)/(msens*0.5f))); mousx = ld.quot; mousexsurp = ld.rem;
1186
            ld = ldiv(mousy, (int32_t)((1<<16)/(msens*0.25f))); mousy = ld.quot; mouseysurp = ld.rem;
1055 terminx 1187
        }
1188
        else
1189
        {
1836 helixhorne 1190
            ld = ldiv(mousx, (int32_t)((1<<16)/msens)); mousx = ld.quot; mousexsurp = ld.rem;
1191
            ld = ldiv(mousy, (int32_t)((1<<16)/msens)); mousy = ld.quot; mouseysurp = ld.rem;
1055 terminx 1192
        }
109 terminx 1193
    }
5 Plagman 1194
 
1055 terminx 1195
    if (mlook == 3)
1836 helixhorne 1196
        mlook = omlook;
1055 terminx 1197
 
726 terminx 1198
    // UnrealEd:
1199
    // rmb: mouselook
1200
    // lbm: x:turn y:fwd/back local x
1201
    // lmb&rmb: x:strafe y:up/dn (move in local yz plane)
1202
    // mmb: fwd/back in viewing vector
1203
 
728 terminx 1204
    if (unrealedlook && !mskip)    //PK
5 Plagman 1205
    {
1836 helixhorne 1206
        if ((bstatus&(1|2|4))==1)
726 terminx 1207
        {
1055 terminx 1208
            ang += mousx;
1205 terminx 1209
            xvect = -((mousy*(int32_t)sintable[(ang+2560)&2047])<<(3+pk_uedaccel));
1210
            yvect = -((mousy*(int32_t)sintable[(ang+2048)&2047])<<(3+pk_uedaccel));
726 terminx 1211
 
1836 helixhorne 1212
            move_and_update(xvect, yvect, 0);
726 terminx 1213
        }
1836 helixhorne 1214
        else if (!mlook && (bstatus&(1|2|4))==2)
726 terminx 1215
        {
1216
            mlook=2;
1217
        }
1836 helixhorne 1218
        else if ((bstatus&(1|2|4))==(1|2))
726 terminx 1219
        {
1220
            zmode = 2;
1205 terminx 1221
            xvect = -((mousx*(int32_t)sintable[(ang+2048)&2047])<<pk_uedaccel);
1222
            yvect = -((mousx*(int32_t)sintable[(ang+1536)&2047])<<pk_uedaccel);
1208 terminx 1223
            pos.z += mousy<<(4+pk_uedaccel);
1836 helixhorne 1224
 
1225
            move_and_update(xvect, yvect, 0);
726 terminx 1226
        }
1836 helixhorne 1227
        else if ((bstatus&(1|2|4))==4)
726 terminx 1228
        {
1229
            zmode = 2;
1230
 
1231
            // horiz-100 of 200 is viewing at 326.4 build angle units (=atan(200/128)) upward
1232
            tempint = getangle(128, horiz-100);
1233
 
1234
            xvect = -((mousy*
1205 terminx 1235
                       ((int32_t)sintable[(ang+2560)&2047]>>6)*
1236
                       ((int32_t)sintable[(tempint+512)&2047])>>6)
726 terminx 1237
                      <<pk_uedaccel);
1238
            yvect = -((mousy*
1205 terminx 1239
                       ((int32_t)sintable[(ang+2048)&2047]>>6)*
1240
                       ((int32_t)sintable[(tempint+512)&2047])>>6)
726 terminx 1241
                      <<pk_uedaccel);
1242
 
1836 helixhorne 1243
            pos.z += mousy*(((int32_t)sintable[(tempint+2048)&2047])>>(10-pk_uedaccel));
726 terminx 1244
 
1836 helixhorne 1245
            move_and_update(xvect, yvect, 2);
726 terminx 1246
        }
1247
    }
1248
 
1052 terminx 1249
    if (mskip)
1836 helixhorne 1250
    {
1251
        // mskip was set in astub.c to not trigger UEd mouse movements.
1252
        // Reset now.
1253
        mskip = 0;
1254
    }
1052 terminx 1255
    else
726 terminx 1256
    {
1836 helixhorne 1257
        if (mlook && (unrealedlook==0 || (bstatus&(1|4))==0))
1052 terminx 1258
        {
1055 terminx 1259
            ang += mousx;
1260
            horiz -= mousy;
164 terminx 1261
 
1836 helixhorne 1262
            /*
1263
            if (mousy && !(mousy/4))
1264
                horiz--;
1265
            if (mousx && !(mousx/2))
1266
                ang++;
1267
            */
1762 terminx 1268
 
1854 helixhorne 1269
            inpclamp(&horiz, -99, 299);
1644 helixhorne 1270
 
1052 terminx 1271
            if (mlook == 1)
1272
            {
1273
                searchx = xdim>>1;
1274
                searchy = ydim>>1;
1275
            }
1276
            osearchx = searchx-mousx;
1277
            osearchy = searchy-mousy;
5277 terminx 1278
 
5305 terminx 1279
            if (mousx || mousy)
1280
            {
1281
                silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1282
                getmessagetimeoff = (int32_t) totalclock+30;
5305 terminx 1283
            }
1052 terminx 1284
        }
1836 helixhorne 1285
        else if (unrealedlook==0 || (bstatus&(1|2|4))==0)
500 terminx 1286
        {
1052 terminx 1287
            osearchx = searchx;
1288
            osearchy = searchy;
1289
            searchx += mousx;
1290
            searchy += mousy;
1644 helixhorne 1291
 
1854 helixhorne 1292
            inpclamp(&searchx, 12, xdim-13);
1293
            inpclamp(&searchy, 12, ydim-13);
584 terminx 1294
        }
5 Plagman 1295
    }
1296
 
728 terminx 1297
//    showmouse();
5 Plagman 1298
 
6860 terminx 1299
    if (keystatus[sc_F9])  // F9
606 terminx 1300
    {
1656 terminx 1301
        if (mhk)
1302
        {
1303
            Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES);
1830 helixhorne 1304
            Bmemset(spritesmooth, 0, sizeof(spritesmooth_t) * (MAXSPRITES+MAXUNIQHUDID));
6831 terminx 1305
            engineClearLightsFromMHK();
1656 terminx 1306
            mhk = 0;
1760 helixhorne 1307
            message("Maphacks disabled");
1656 terminx 1308
        }
1309
        else
1310
        {
1311
            mhk = 1;
1760 helixhorne 1312
            loadmhk(1);
1656 terminx 1313
        }
1314
 
6860 terminx 1315
        keystatus[sc_F9] = 0;
606 terminx 1316
    }
1644 helixhorne 1317
 
1836 helixhorne 1318
    mainloop_move();
1644 helixhorne 1319
 
2028 helixhorne 1320
    getzrange(&pos,cursectnum, &hiz,&hihit, &loz,&lohit, 128, (m32_clipping==1)?0:CLIPMASK0);
1866 helixhorne 1321
/*
1322
{
1323
    int32_t his = !(hihit&32768), los = !(lohit&32768);
1324
    if (m32_numdebuglines<64)
1325
        Bsprintf(m32_debugstr[m32_numdebuglines++], "s%d: cf[%s%d, %s%d] z(%d, %d)", cursectnum,
1326
                 his?"s":"w",hihit&16383, los?"s":"w",lohit&16383, hiz,loz);
1327
}
1328
*/
1843 helixhorne 1329
    oposz = pos.z;
109 terminx 1330
    if (zmode == 0)
1331
    {
1644 helixhorne 1332
        goalz = loz-(kensplayerheight<<8);  //playerheight pixels above floor
1333
        if (goalz < hiz+(16<<8))  //ceiling&floor too close
1334
            goalz = (loz+hiz)>>1;
109 terminx 1335
        goalz += mousz;
1644 helixhorne 1336
 
1337
        if (DOWN_BK(MOVEUP))  //A (stand high)
109 terminx 1338
        {
1836 helixhorne 1339
            goalz -= (16<<8);
1340
            if (DOWN_BK(RUN))
2092 helixhorne 1341
                goalz -= (24<<8);
109 terminx 1342
        }
1644 helixhorne 1343
        if (DOWN_BK(MOVEDOWN))  //Z (stand low)
109 terminx 1344
        {
1836 helixhorne 1345
            goalz += (12<<8);
1346
            if (DOWN_BK(RUN))
109 terminx 1347
                goalz += (12<<8);
1348
        }
5 Plagman 1349
 
1208 terminx 1350
        if (goalz != pos.z)
109 terminx 1351
        {
1208 terminx 1352
            if (pos.z < goalz) hvel += 64;
1353
            if (pos.z > goalz) hvel = ((goalz-pos.z)>>3);
5 Plagman 1354
 
1208 terminx 1355
            pos.z += hvel;
1356
            if (pos.z > loz-(4<<8)) pos.z = loz-(4<<8), hvel = 0;
1357
            if (pos.z < hiz+(4<<8)) pos.z = hiz+(4<<8), hvel = 0;
109 terminx 1358
        }
1359
    }
1360
    else
1361
    {
1208 terminx 1362
        goalz = pos.z;
1644 helixhorne 1363
        if (DOWN_BK(MOVEUP))  //A
109 terminx 1364
        {
7303 terminx 1365
            if (eitherALT)
584 terminx 1366
            {
1644 helixhorne 1367
                horiz = max(-100,horiz-((DOWN_BK(RUN)+1)*synctics*2));
584 terminx 1368
            }
1369
            else
1370
            {
109 terminx 1371
                if (zmode != 1)
1372
                    goalz -= (8<<8);
1373
                else
1374
                {
1375
                    zlock += (4<<8);
1644 helixhorne 1376
                    DOWN_BK(MOVEUP) = 0;
109 terminx 1377
                }
1378
            }
1379
        }
1644 helixhorne 1380
        if (DOWN_BK(MOVEDOWN))  //Z (stand low)
109 terminx 1381
        {
7303 terminx 1382
            if (eitherALT)
584 terminx 1383
            {
1644 helixhorne 1384
                horiz = min(300,horiz+((DOWN_BK(RUN)+1)*synctics*2));
584 terminx 1385
            }
1386
            else
1387
            {
109 terminx 1388
                if (zmode != 1)
1389
                    goalz += (8<<8);
1390
                else if (zlock > 0)
1391
                {
1392
                    zlock -= (4<<8);
1644 helixhorne 1393
                    DOWN_BK(MOVEDOWN) = 0;
109 terminx 1394
                }
1395
            }
1396
        }
5 Plagman 1397
 
2028 helixhorne 1398
        if (m32_clipping)
1854 helixhorne 1399
            inpclamp(&goalz, hiz+(4<<8), loz-(4<<8));
1644 helixhorne 1400
 
109 terminx 1401
        if (zmode == 1) goalz = loz-zlock;
2028 helixhorne 1402
        if (m32_clipping && (goalz < hiz+(4<<8)))
1644 helixhorne 1403
            goalz = ((loz+hiz)>>1);  //ceiling&floor too close
1208 terminx 1404
        if (zmode == 1) pos.z = goalz;
5 Plagman 1405
 
1208 terminx 1406
        if (goalz != pos.z)
109 terminx 1407
        {
1644 helixhorne 1408
            //if (pos.z < goalz) hvel += (32<<DOWN_BK(RUN));
1409
            //if (pos.z > goalz) hvel -= (32<<DOWN_BK(RUN));
1836 helixhorne 1410
            if (pos.z < goalz)
1411
                hvel = ((192*synctics)<<DOWN_BK(RUN));
1412
            else
1413
                hvel = -((192*synctics)<<DOWN_BK(RUN));
5 Plagman 1414
 
1208 terminx 1415
            pos.z += hvel;
5 Plagman 1416
 
2028 helixhorne 1417
            if (m32_clipping)
717 plagman 1418
            {
1208 terminx 1419
                if (pos.z > loz-(4<<8)) pos.z = loz-(4<<8), hvel = 0;
1420
                if (pos.z < hiz+(4<<8)) pos.z = hiz+(4<<8), hvel = 0;
717 plagman 1421
            }
109 terminx 1422
        }
1423
        else
1424
            hvel = 0;
1425
    }
5 Plagman 1426
 
1843 helixhorne 1427
    {
1428
        int16_t ocursectnum = cursectnum;
1429
        updatesectorz(pos.x,pos.y,pos.z, &cursectnum);
1430
        if (cursectnum<0)
1431
        {
1432
            if (zmode != 2)
1433
                pos.z = oposz;  // don't allow to fall into infinity when in void space
1434
            cursectnum = ocursectnum;
1435
        }
1436
    }
1830 helixhorne 1437
 
5277 terminx 1438
    if (pos.z != oposz && in3dmode())
1439
    {
1440
        silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1441
        getmessagetimeoff = (int32_t) totalclock+30;
5277 terminx 1442
    }
1443
 
109 terminx 1444
    searchit = 2;
1445
    if (searchstat >= 0)
1446
    {
6860 terminx 1447
        if ((bstatus&(1|2|4)) || keystatus[sc_Space])  // SPACE
109 terminx 1448
            searchit = 0;
5 Plagman 1449
 
6860 terminx 1450
        if (keystatus[sc_S])  //S (insert sprite) (3D)
109 terminx 1451
        {
2877 helixhorne 1452
            hitdata_t hit;
7495 hendricks2 1453
            vec2_t osearch = {searchx, searchy};
1454
            vec2_t bdim = {xdim, ydim};
1455
            if (m32_is2d3dmode())
1456
            {
1457
                xdim = XSIZE_2D3D;
1458
                ydim = YSIZE_2D3D;
1459
                searchx -= m32_2d3d.x;
1460
                searchy -= m32_2d3d.y;
1461
            }
1801 helixhorne 1462
 
5239 terminx 1463
            vec2_t da = { 16384, divscale14(searchx-(xdim>>1), xdim>>1) };
5 Plagman 1464
 
5239 terminx 1465
            rotatepoint(zerovec, da, ang, &da);
1466
 
5277 terminx 1467
#ifdef USE_OPENGL
6829 terminx 1468
            if (videoGetRenderMode() == REND_POLYMOST)
5277 terminx 1469
                hit = polymost_hitdata;
1470
            else
1471
#endif
1472
                hitscan((const vec3_t *)&pos,cursectnum,              //Start position
5239 terminx 1473
                    da.x,da.y,(scale(searchy,200,ydim)-horiz)*2000, //vector of 3D ang
2877 helixhorne 1474
                    &hit,CLIPMASK1);
5 Plagman 1475
 
2877 helixhorne 1476
            if (hit.sect >= 0)
109 terminx 1477
            {
5239 terminx 1478
                da.x = hit.pos.x;
1479
                da.y = hit.pos.y;
1644 helixhorne 1480
                if (gridlock && grid > 0)
109 terminx 1481
                {
1854 helixhorne 1482
                    if (AIMING_AT_WALL || AIMING_AT_MASKWALL)
2877 helixhorne 1483
                        hit.pos.z &= 0xfffffc00;
109 terminx 1484
                    else
5239 terminx 1485
                        locktogrid(&da.x, &da.y);
109 terminx 1486
                }
5 Plagman 1487
 
5239 terminx 1488
                i = insert_sprite_common(hit.sect, da.x, da.y);
5 Plagman 1489
 
1801 helixhorne 1490
                if (i < 0)
1491
                    message("Couldn't insert sprite.");
109 terminx 1492
                else
1801 helixhorne 1493
                {
1494
                    int32_t cz, fz;
5 Plagman 1495
 
2699 helixhorne 1496
                    handle_sprite_in_clipboard(i);
1801 helixhorne 1497
 
1854 helixhorne 1498
                    spriteoncfz(i, &cz, &fz);
3780 helixhorne 1499
                    sprite[i].z = clamp2(hit.pos.z, cz, fz);
5 Plagman 1500
 
1854 helixhorne 1501
                    if (AIMING_AT_WALL || AIMING_AT_MASKWALL)
109 terminx 1502
                    {
1801 helixhorne 1503
                        sprite[i].cstat &= ~48;
1504
                        sprite[i].cstat |= (16+64);
1505
 
2877 helixhorne 1506
                        correct_ornamented_sprite(i, hit.wall);
109 terminx 1507
                    }
1801 helixhorne 1508
                    else
4623 terminx 1509
                        sprite[i].cstat |= (tilesiz[sprite[i].picnum].y>=32);
5 Plagman 1510
 
1832 helixhorne 1511
                    correct_sprite_yoffset(i);
1512
 
1801 helixhorne 1513
                    asksave = 1;
1493 helixhorne 1514
 
1801 helixhorne 1515
                    VM_OnEvent(EVENT_INSERTSPRITE3D, i);
1516
                }
109 terminx 1517
            }
5 Plagman 1518
 
7495 hendricks2 1519
            xdim = bdim.x;
1520
            ydim = bdim.y;
1521
            searchx = osearch.x;
1522
            searchy = osearch.y;
6860 terminx 1523
            keystatus[sc_S] = 0;
109 terminx 1524
        }
5 Plagman 1525
 
6860 terminx 1526
        if (keystatus[sc_F5]||keystatus[sc_F6])  //F5,F6
109 terminx 1527
        {
331 terminx 1528
            switch (searchstat)
109 terminx 1529
            {
1854 helixhorne 1530
            case SEARCH_CEILING:
1531
            case SEARCH_FLOOR:
4555 hendricks2 1532
                CallExtShowSectorData(searchsector); break;
1854 helixhorne 1533
            case SEARCH_WALL:
1534
            case SEARCH_MASKWALL:
4555 hendricks2 1535
                CallExtShowWallData(searchwall); break;
1854 helixhorne 1536
            case SEARCH_SPRITE:
4555 hendricks2 1537
                CallExtShowSpriteData(searchwall); break;
109 terminx 1538
            }
1836 helixhorne 1539
 
6860 terminx 1540
            keystatus[sc_F5] = keystatus[sc_F6] = 0;
109 terminx 1541
        }
6860 terminx 1542
        if (keystatus[sc_F7]||keystatus[sc_F8])  //F7,F8
109 terminx 1543
        {
331 terminx 1544
            switch (searchstat)
109 terminx 1545
            {
1854 helixhorne 1546
            case SEARCH_CEILING:
1547
            case SEARCH_FLOOR:
4555 hendricks2 1548
                CallExtEditSectorData(searchsector); break;
1854 helixhorne 1549
            case SEARCH_WALL:
1550
            case SEARCH_MASKWALL:
4555 hendricks2 1551
                CallExtEditWallData(searchwall); break;
1854 helixhorne 1552
            case SEARCH_SPRITE:
4555 hendricks2 1553
                CallExtEditSpriteData(searchwall); break;
109 terminx 1554
            }
1836 helixhorne 1555
 
6860 terminx 1556
            keystatus[sc_F7] = keystatus[sc_F8] = 0;
109 terminx 1557
        }
5 Plagman 1558
 
109 terminx 1559
    }
1665 terminx 1560
 
5281 terminx 1561
    if (keystatus[buildkeys[BK_MODE2D_3D]] && !m32_is2d3dmode())  // Enter
109 terminx 1562
    {
1665 terminx 1563
 
6828 terminx 1564
        vid_gamma_3d = g_videoGamma;
1565
        vid_contrast_3d = g_videoContrast;
1566
        vid_brightness_3d = g_videoBrightness;
1679 helixhorne 1567
 
6828 terminx 1568
        g_videoGamma = g_videoContrast = 1.0;
1569
        g_videoBrightness = 0.0;
1665 terminx 1570
 
6829 terminx 1571
        videoSetPalette(0,0,0);
1679 helixhorne 1572
 
1648 helixhorne 1573
        keystatus[buildkeys[BK_MODE2D_3D]] = 0;
109 terminx 1574
        overheadeditor();
1648 helixhorne 1575
        keystatus[buildkeys[BK_MODE2D_3D]] = 0;
1665 terminx 1576
 
6828 terminx 1577
        g_videoGamma = vid_gamma_3d;
1578
        g_videoContrast = vid_contrast_3d;
1579
        g_videoBrightness = vid_brightness_3d;
1679 helixhorne 1580
 
1581
        vid_gamma_3d = vid_contrast_3d = vid_brightness_3d = -1;
1582
 
6829 terminx 1583
        videoSetPalette(GAMMA_CALC,0,0);
109 terminx 1584
    }
5 Plagman 1585
}
1586
 
1205 terminx 1587
char changechar(char dachar, int32_t dadir, char smooshyalign, char boundcheck)
5 Plagman 1588
{
109 terminx 1589
    if (dadir < 0)
1590
    {
1591
        if ((dachar > 0) || (boundcheck == 0))
1592
        {
1593
            dachar--;
1594
            if (smooshyalign > 0)
1595
                dachar = (dachar&0xf8);
1596
        }
1597
    }
1598
    else if (dadir > 0)
1599
    {
1600
        if ((dachar < 255) || (boundcheck == 0))
1601
        {
1602
            dachar++;
1603
            if (smooshyalign > 0)
1604
            {
1605
                if (dachar >= 256-8) dachar = 255;
1606
                else dachar = ((dachar+7)&0xf8);
1607
            }
1608
        }
1609
    }
5803 terminx 1610
    return dachar;
5 Plagman 1611
}
1612
 
1644 helixhorne 1613
 
1614
////////////////////// OVERHEADEDITOR //////////////////////
1615
 
2089 helixhorne 1616
// some 2d mode state
1617
static struct overheadstate
1618
{
2090 helixhorne 1619
    // number of backed up drawn walls
1620
    int32_t bak_wallsdrawn;
1621
 
2089 helixhorne 1622
    // state related to line drawing
1623
    int16_t suckwall, split;
1624
    int16_t splitsect;
1625
    int16_t splitstartwall;
1626
} ovh;
1627
 
1869 helixhorne 1628
 
3038 helixhorne 1629
static int32_t inside_editor(const vec3_t *pos, int32_t searchx, int32_t searchy, int32_t zoom,
1630
                             int32_t x, int32_t y, int16_t sectnum)
1830 helixhorne 1631
{
1632
    if (!m32_sideview)
1633
        return inside(x, y, sectnum);
1634
 
1635
    // if in side-view mode, use the screen coords instead
1636
    {
1637
        int32_t dst = MAXSECTORS+M32_FIXME_SECTORS-1, i, oi;
1638
        int32_t srcw=sector[sectnum].wallptr, dstw=MAXWALLS;
1639
        int32_t ret;
1640
 
1641
        if (sector[sectnum].wallnum > M32_FIXME_WALLS)
1642
            return -1;
1643
 
1644
        Bmemcpy(&sector[dst], &sector[sectnum], sizeof(sectortype));
1645
        sector[dst].wallptr = dstw;
1646
 
1647
        Bmemcpy(&wall[dstw], &wall[srcw], sector[dst].wallnum*sizeof(walltype));
1648
        for (i=dstw, oi=srcw; i<dstw+sector[dst].wallnum; i++, oi++)
1649
        {
1650
            wall[i].point2 += dstw-srcw;
1651
 
6831 terminx 1652
            editorGet2dScreenCoordinates(&wall[i].x, &wall[i].y, wall[i].x-pos->x, wall[i].y-pos->y, zoom);
1830 helixhorne 1653
            wall[i].y += getscreenvdisp(getflorzofslope(sectnum,wall[oi].x,wall[oi].y)-pos->z, zoom);
1654
            wall[i].x += halfxdim16;
1655
            wall[i].y += midydim16;
1656
        }
1657
 
1658
        i = numsectors;
1659
        numsectors = dst+1;
1660
        ret = inside(searchx, searchy, dst);
1661
        numsectors = i;
1662
        return ret;
1663
    }
1664
}
1665
 
3038 helixhorne 1666
int32_t inside_editor_curpos(int16_t sectnum)
1667
{
1668
    // TODO: take care: mous[xy]plc global vs overheadeditor auto
1669
    return inside_editor(&pos, searchx,searchy, zoom, mousxplc,mousyplc, sectnum);
1670
}
1671
 
1672
 
1730 helixhorne 1673
static inline void drawline16base(int32_t bx, int32_t by, int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col)
1674
{
6831 terminx 1675
    editorDraw2dLine(bx+x1, by+y1, bx+x2, by+y2, col);
1730 helixhorne 1676
}
1677
 
5289 terminx 1678
void drawsmallabel(const char *text, char col, char backcol, char border, int32_t dax, int32_t day, int32_t daz)
1790 helixhorne 1679
{
6831 terminx 1680
    editorGet2dScreenCoordinates(&dax,&day, dax-pos.x,day-pos.y, zoom);
1790 helixhorne 1681
 
1832 helixhorne 1682
    if (m32_sideview)
1683
        day += getscreenvdisp(daz-pos.z, zoom);
1684
 
5293 terminx 1685
    int32_t const x1 = halfxdim16+dax-(Bstrlen(text)<<1);
1686
    int32_t const y1 = midydim16+day-4;
1687
    int32_t const x2 = x1 + (Bstrlen(text)<<2)+2;
1688
    int32_t const y2 = y1 + 7;
1792 helixhorne 1689
 
5289 terminx 1690
    int f = mulscale8(x2-x1, zoom);
1691
 
5293 terminx 1692
    if ((x1 <= -f) || (x2 >= xdim + f) || (y1 <= -f) || (y2 >= ydim16 + f))
1693
        return;
5289 terminx 1694
 
5293 terminx 1695
    printext16(x1,y1, col,backcol, text,1);
5289 terminx 1696
 
6831 terminx 1697
    editorDraw2dLine(x1-2, y1-2, x2-2, y1-2, border);
1698
    editorDraw2dLine(x1-2, y2+1, x2-2, y2+1, border);
5289 terminx 1699
 
6831 terminx 1700
    editorDraw2dLine(x1-3, y1-1, x1-3, y2+0, border);
1701
    editorDraw2dLine(x2-1, y1-1, x2-1, y2+0, border);
5289 terminx 1702
 
6831 terminx 1703
    editorDraw2dLine(x1-1,y1-1, x2-3,y1-1, backcol);
1704
    editorDraw2dLine(x1-1,y2+0, x2-3,y2+0, backcol);
1792 helixhorne 1705
 
6831 terminx 1706
    editorDraw2dLine(x1-2,y1+0, x1-2,y2-1, backcol);
1707
    editorDraw2dLine(x2-2,y1+0, x2-2,y2-1, backcol);
1708
    editorDraw2dLine(x2-3,y1+0, x2-3,y2+0, backcol);
5293 terminx 1709
 
6828 terminx 1710
    videoBeginDrawing(); //{{{
5293 terminx 1711
 
1712
    if ((unsigned)y1-1 < ydim16+0u && (unsigned) (x1-2) < xdim2d+0u && (unsigned) (x2-2) < xdim2d+0u)
1713
    {
1714
        drawpixel((char *) (frameplace + ((y1-1) * bytesperline) + (x1-2)), border);
1715
        drawpixel((char *) (frameplace + ((y1-1) * bytesperline) + (x2-2)), border);
1792 helixhorne 1716
    }
5293 terminx 1717
 
1718
    if ((unsigned) y2 < ydim16+0u && (unsigned) (x1-2) < xdim2d+0u && (unsigned) (x2-2) < xdim2d+0u)
1719
    {
1720
        drawpixel((char *) (frameplace + ((y2) * bytesperline) + (x1-2)), border);
1721
        drawpixel((char *) (frameplace + ((y2) * bytesperline) + (x2-2)), border);
1722
    }
1723
 
6828 terminx 1724
    videoEndDrawing();
1790 helixhorne 1725
}
1726
 
1730 helixhorne 1727
// backup highlighted sectors with sprites as mapinfo for later restoration
1728
// return values:
1729
//  -1: highlightsectorcnt<=0
1730
//   0: ok
1731
static int32_t backup_highlighted_map(mapinfofull_t *mapinfo)
1732
{
1733
    int32_t i, j, k, m, tmpnumwalls=0, tmpnumsprites=0;
2276 helixhorne 1734
    int16_t *const otonsect = (int16_t *)tempxyar;  // STRICTALIASING
2136 helixhorne 1735
    int16_t *const otonwall = ((int16_t *)tempxyar) + MAXWALLS;
1736
#ifdef YAX_ENABLE
1737
    int16_t otonbunch[YAX_MAXBUNCHES];
1738
    int16_t numsectsofbunch[YAX_MAXBUNCHES];  // ceilings + floors
1739
#endif
1730 helixhorne 1740
 
1741
    if (highlightsectorcnt <= 0)
1742
        return -1;
1743
 
2136 helixhorne 1744
#ifdef YAX_ENABLE
1745
    for (i=0; i<numyaxbunches; i++)
1746
        numsectsofbunch[i] = 0;
1747
#endif
1748
 
2135 helixhorne 1749
    // set up old-->new mappings
2132 helixhorne 1750
    j = 0;
1751
    k = 0;
1752
    for (i=0; i<numsectors; i++)
1753
    {
1754
        int32_t startwall, endwall;
1755
 
7876 terminx 1756
        if (hlsectorbitmap[i>>3]&pow2char[i&7])
2132 helixhorne 1757
        {
2136 helixhorne 1758
#ifdef YAX_ENABLE
1759
            int16_t bn[2], cf;
1760
 
1761
            yax_getbunches(i, &bn[0], &bn[1]);
1762
            for (cf=0; cf<2; cf++)
1763
                if (bn[cf] >= 0)
1764
                    numsectsofbunch[bn[cf]]++;
1765
#endif
2132 helixhorne 1766
            otonsect[i] = j++;
1767
 
1768
            for (WALLS_OF_SECTOR(i, m))
1769
                otonwall[m] = k++;
1770
        }
1771
        else
1772
        {
1773
            otonsect[i] = -1;
1774
 
1775
            for (WALLS_OF_SECTOR(i, m))
1776
                otonwall[m] = -1;
1777
        }
1778
    }
1779
 
2136 helixhorne 1780
#ifdef YAX_ENABLE
1781
    j = 0;
1782
    for (i=0; i<numyaxbunches; i++)
1783
    {
1784
        // only back up complete bunches
1785
        if (numsectsofbunch[i] == yax_numsectsinbunch(i, 0)+yax_numsectsinbunch(i, 1))
2963 helixhorne 1786
            otonbunch[i] = j++;  // kept bunch
2136 helixhorne 1787
        else
2963 helixhorne 1788
            otonbunch[i] = -1;  // discarded bunch
2136 helixhorne 1789
    }
1790
    mapinfo->numyaxbunches = j;
1791
#endif
1792
 
1730 helixhorne 1793
    // count walls & sprites
1794
    for (i=0; i<highlightsectorcnt; i++)
1795
    {
1796
        tmpnumwalls += sector[highlightsector[i]].wallnum;
1797
 
1798
        m = headspritesect[highlightsector[i]];
1799
        while (m != -1)
1800
        {
1801
            tmpnumsprites++;
1802
            m = nextspritesect[m];
1803
        }
1804
    }
1805
 
1806
    // allocate temp storage
5796 terminx 1807
    mapinfo->sector = (usectortype *)Xmalloc(highlightsectorcnt * sizeof(sectortype));
1808
    mapinfo->wall = (uwalltype *)Xmalloc(tmpnumwalls * sizeof(walltype));
2135 helixhorne 1809
 
2136 helixhorne 1810
#ifdef YAX_ENABLE
1811
    if (mapinfo->numyaxbunches > 0)
1812
    {
4491 helixhorne 1813
        mapinfo->bunchnum = (int16_t *)Xmalloc(highlightsectorcnt*2*sizeof(int16_t));
1814
        mapinfo->ynextwall = (int16_t *)Xmalloc(tmpnumwalls*2*sizeof(int16_t));
2136 helixhorne 1815
    }
1816
    else
1817
    {
1818
        mapinfo->bunchnum = mapinfo->ynextwall = NULL;
1819
    }
1820
#endif
1821
 
1730 helixhorne 1822
    if (tmpnumsprites>0)
1823
    {
5796 terminx 1824
        mapinfo->sprite = (uspritetype *)Xmalloc(tmpnumsprites * sizeof(spritetype));
1730 helixhorne 1825
    }
2135 helixhorne 1826
    else
1827
    {
1828
        // would never be accessed because mapinfo->numsprites is 0, but cleaner
1829
        mapinfo->sprite = NULL;
1830
    }
1730 helixhorne 1831
 
1832
 
1833
    // copy everything over
1834
    tmpnumwalls = 0;
1835
    tmpnumsprites = 0;
1836
    for (i=0; i<highlightsectorcnt; i++)
1837
    {
1838
        k = highlightsector[i];
1839
        Bmemcpy(&mapinfo->sector[i], &sector[k], sizeof(sectortype));
1840
        mapinfo->sector[i].wallptr = tmpnumwalls;
1841
 
2136 helixhorne 1842
#ifdef YAX_ENABLE
2963 helixhorne 1843
        if (mapinfo->numyaxbunches > 0 || numyaxbunches > 0)
2136 helixhorne 1844
        {
1845
            int16_t bn[2];
1846
 
1847
            yax_getbunches(k, &bn[0], &bn[1]);
1848
            for (j=0; j<2; j++)
2963 helixhorne 1849
            {
1850
                // old bunchnum, new bunchnum
1851
                int32_t obn=bn[j], nbn=(obn>=0) ? otonbunch[obn] : -1;
1852
 
1853
                if (mapinfo->numyaxbunches > 0)
1854
                    mapinfo->bunchnum[2*i + j] = nbn;
4011 helixhorne 1855
 
2963 helixhorne 1856
                if (obn >= 0 && nbn < 0)
1857
                {
4011 helixhorne 1858
                    // A bunch was discarded.
7603 terminx 1859
                    auto const sec = &mapinfo->sector[i];
4011 helixhorne 1860
# if !defined NEW_MAP_FORMAT
3174 helixhorne 1861
                    uint16_t *const cs = j==YAX_CEILING ? &sec->ceilingstat : &sec->floorstat;
2963 helixhorne 1862
                    uint8_t *const xp = j==YAX_CEILING ? &sec->ceilingxpanning : &sec->floorxpanning;
1863
 
1864
                    *cs &= ~YAX_BIT;
1865
                    *xp = 0;
4011 helixhorne 1866
# else
1867
                    if (j == YAX_CEILING)
1868
                        sec->ceilingbunch = -1;
1869
                    else
1870
                        sec->floorbunch = -1;
1871
# endif
2963 helixhorne 1872
                }
1873
            }
2136 helixhorne 1874
        }
1875
#endif
1876
 
1730 helixhorne 1877
        for (j=0; j<sector[k].wallnum; j++)
1878
        {
2136 helixhorne 1879
            m = sector[k].wallptr;
1880
            Bmemcpy(&mapinfo->wall[tmpnumwalls+j], &wall[m+j], sizeof(walltype));
1881
            mapinfo->wall[tmpnumwalls+j].point2 += (tmpnumwalls-m);
2132 helixhorne 1882
 
2136 helixhorne 1883
#ifdef YAX_ENABLE
4012 helixhorne 1884
            if (mapinfo->numyaxbunches > 0 || numyaxbunches > 0)
2136 helixhorne 1885
            {
2965 helixhorne 1886
                int32_t cf;
2136 helixhorne 1887
 
1888
                for (cf=0; cf<2; cf++)
1889
                {
2965 helixhorne 1890
                    const int32_t ynw = yax_getnextwall(m+j, cf);
1891
                    const int32_t nynw = (ynw >= 0) ? otonwall[ynw] : -1;
1892
 
1893
                    if (mapinfo->numyaxbunches > 0)
1894
                        mapinfo->ynextwall[2*(tmpnumwalls+j) + cf] = nynw;
1895
 
1896
                    if (ynw >= 0 && nynw < 0)  // CLEAR_YNEXTWALLS
1897
                        YAX_PTRNEXTWALL(mapinfo->wall, tmpnumwalls+j, cf) = YAX_NEXTWALLDEFAULT(cf);
2136 helixhorne 1898
                }
1899
            }
1900
#endif
2132 helixhorne 1901
            m = mapinfo->wall[tmpnumwalls+j].nextsector;
1902
            if (m < 0 || otonsect[m] < 0)
1903
            {
1904
                mapinfo->wall[tmpnumwalls+j].nextsector = -1;
1905
                mapinfo->wall[tmpnumwalls+j].nextwall = -1;
1906
            }
1907
            else
1908
            {
1909
                mapinfo->wall[tmpnumwalls+j].nextsector = otonsect[m];
1910
                m = mapinfo->wall[tmpnumwalls+j].nextwall;
1911
                mapinfo->wall[tmpnumwalls+j].nextwall = otonwall[m];
1912
            }
1730 helixhorne 1913
        }
1914
        tmpnumwalls += j;
1915
 
1916
        m = headspritesect[highlightsector[i]];
1917
        while (m != -1)
1918
        {
1919
            Bmemcpy(&mapinfo->sprite[tmpnumsprites], &sprite[m], sizeof(spritetype));
2132 helixhorne 1920
            mapinfo->sprite[tmpnumsprites].sectnum = otonsect[highlightsector[i]];
1730 helixhorne 1921
            m = nextspritesect[m];
1922
            tmpnumsprites++;
1923
        }
1924
    }
1925
 
1926
 
1927
    mapinfo->numsectors = highlightsectorcnt;
1928
    mapinfo->numwalls = tmpnumwalls;
1929
    mapinfo->numsprites = tmpnumsprites;
1930
 
1931
    return 0;
1932
}
1933
 
1934
static void mapinfofull_free(mapinfofull_t *mapinfo)
1935
{
7705 terminx 1936
    Xfree(mapinfo->sector);
2136 helixhorne 1937
#ifdef YAX_ENABLE
1938
    if (mapinfo->numyaxbunches > 0)
1939
    {
7705 terminx 1940
        Xfree(mapinfo->bunchnum);
1941
        Xfree(mapinfo->ynextwall);
2136 helixhorne 1942
    }
1943
#endif
7705 terminx 1944
    Xfree(mapinfo->wall);
1730 helixhorne 1945
    if (mapinfo->numsprites>0)
7705 terminx 1946
        Xfree(mapinfo->sprite);
1730 helixhorne 1947
}
1948
 
1949
// restore map saved with backup_highlighted_map, also
1950
// frees mapinfo's sector, wall, (sprite) in any case.
1951
// return values:
1952
//  -1: limits exceeded
1953
//   0: ok
2138 helixhorne 1954
// forreal: if 0, only test if we have enough space (same return values)
1955
static int32_t restore_highlighted_map(mapinfofull_t *mapinfo, int32_t forreal)
1730 helixhorne 1956
{
2963 helixhorne 1957
    int32_t i, j, onumsectors=numsectors, newnumsectors, newnumwalls;
1730 helixhorne 1958
 
1959
    if (numsectors+mapinfo->numsectors>MAXSECTORS || numwalls+mapinfo->numwalls>MAXWALLS
2136 helixhorne 1960
#ifdef YAX_ENABLE
1961
            || numyaxbunches+mapinfo->numyaxbunches > YAX_MAXBUNCHES
1962
#endif
2478 helixhorne 1963
            || Numsprites+mapinfo->numsprites>MAXSPRITES)
1730 helixhorne 1964
    {
1965
        mapinfofull_free(mapinfo);
1966
        return -1;
1967
    }
1968
 
2138 helixhorne 1969
    if (!forreal)
1970
        return 0;
1971
 
1730 helixhorne 1972
    newnumsectors = numsectors + mapinfo->numsectors;
1973
    newnumwalls = numwalls + mapinfo->numwalls;
1974
 
1975
    // copy sectors & walls
1976
    Bmemcpy(&sector[numsectors], mapinfo->sector, mapinfo->numsectors*sizeof(sectortype));
1977
    Bmemcpy(&wall[numwalls], mapinfo->wall, mapinfo->numwalls*sizeof(walltype));
1978
 
1979
    // tweak index members
1980
    for (i=numwalls; i<newnumwalls; i++)
1981
    {
1982
        wall[i].point2 += numwalls;
2132 helixhorne 1983
 
1984
        if (wall[i].nextsector >= 0)
1985
        {
1986
            wall[i].nextsector += numsectors;
1987
            wall[i].nextwall += numwalls;
1988
        }
2136 helixhorne 1989
#ifdef YAX_ENABLE
1990
        for (j=0; j<2; j++)
1991
        {
1992
            if (mapinfo->numyaxbunches > 0)
4011 helixhorne 1993
            {
2136 helixhorne 1994
                yax_setnextwall(i, j, mapinfo->ynextwall[2*(i-numwalls) + j]>=0 ?
1995
                                numwalls+mapinfo->ynextwall[2*(i-numwalls) + j] : -1);
4011 helixhorne 1996
            }
1997
            else
1998
            {
3658 helixhorne 1999
# if !defined NEW_MAP_FORMAT
4011 helixhorne 2000
                // XXX: When copying a TROR portion into a non-TROR map (e.g. a
2001
                // new one), tags denoting ynextwalls are left in place.
2965 helixhorne 2002
                wall[i].cstat &= ~YAX_NEXTWALLBIT(j);  // CLEAR_YNEXTWALLS
4011 helixhorne 2003
# else
2004
                yax_setnextwall(i, j, -1);
3658 helixhorne 2005
# endif
4011 helixhorne 2006
            }
2136 helixhorne 2007
        }
2008
#endif
1730 helixhorne 2009
    }
2136 helixhorne 2010
    for (i=numsectors; i<newnumsectors; i++)
2011
        sector[i].wallptr += numwalls;
1730 helixhorne 2012
 
2132 helixhorne 2013
    // highlight copied sectors
2136 helixhorne 2014
 
2132 helixhorne 2015
    numsectors = newnumsectors;
2016
 
1730 helixhorne 2017
    Bmemset(hlsectorbitmap, 0, sizeof(hlsectorbitmap));
2018
    for (i=onumsectors; i<newnumsectors; i++)
2135 helixhorne 2019
    {
7876 terminx 2020
        hlsectorbitmap[i>>3] |= pow2char[i&7];
2136 helixhorne 2021
 
2135 helixhorne 2022
#ifdef YAX_ENABLE
2136 helixhorne 2023
        for (j=0; j<2; j++)
2963 helixhorne 2024
        {
2136 helixhorne 2025
            if (mapinfo->numyaxbunches > 0)
2963 helixhorne 2026
            {
2027
                int32_t bn = mapinfo->bunchnum[2*(i-onumsectors)+j];
2028
                yax_setbunch(i, j, bn>=0 ? numyaxbunches+bn : -2);
2029
                // -2 clears forward yax-nextwall links.
2030
                // XXX: still may wrongly reset xpanning.
2031
            }
2136 helixhorne 2032
            else
2963 helixhorne 2033
                Bassert(yax_getbunch(i, j) < 0);
2034
        }
2135 helixhorne 2035
#endif
2036
    }
1730 helixhorne 2037
 
2038
    // insert sprites
2039
    for (i=0; i<mapinfo->numsprites; i++)
2040
    {
7603 terminx 2041
        uspriteptr_t srcspr = &mapinfo->sprite[i];
3897 helixhorne 2042
        int32_t sect = onumsectors + srcspr->sectnum;
2043
 
2044
        j = insertsprite(sect, srcspr->statnum);
2045
        Bassert(j >= 0);
2046
        Bmemcpy(&sprite[j], srcspr, sizeof(spritetype));
1730 helixhorne 2047
        sprite[j].sectnum = sect;
2048
    }
2049
 
2136 helixhorne 2050
    mapinfofull_free(mapinfo);
2051
 
1730 helixhorne 2052
    numwalls = newnumwalls;
2053
 
2054
    update_highlightsector();
2055
 
2136 helixhorne 2056
#ifdef YAX_ENABLE
2057
    if (mapinfo->numyaxbunches > 0)
2058
        yax_update(0);
2059
#endif
2060
    yax_updategrays(pos.z);
2061
 
1730 helixhorne 2062
    return 0;
2063
}
2064
 
2065
 
7078 terminx 2066
static int16_t newnumwalls=-1;
1622 helixhorne 2067
 
1927 helixhorne 2068
void ovh_whiteoutgrab(int32_t restoreredwalls)
1644 helixhorne 2069
{
2070
    int32_t i, j, k, startwall, endwall;
1887 helixhorne 2071
#if 0
2072
//def YAX_ENABLE
1886 helixhorne 2073
    int16_t cb, fb;
2074
#endif
1644 helixhorne 2075
 
1927 helixhorne 2076
    if (restoreredwalls)
2077
    {
2078
        // restore onextwalls first
2079
        for (i=0; i<numsectors; i++)
2080
            for (WALLS_OF_SECTOR(i, j))
2081
                checksectorpointer(j, i);
2082
    }
2083
 
1886 helixhorne 2084
    for (i=0; i<MAXWALLS; i++)
2085
        onextwall[i] = -1;
2086
 
1644 helixhorne 2087
    //White out all bordering lines of grab that are
2088
    //not highlighted on both sides
2089
    for (i=highlightsectorcnt-1; i>=0; i--)
1866 helixhorne 2090
        for (WALLS_OF_SECTOR(highlightsector[i], j))
1644 helixhorne 2091
        {
1886 helixhorne 2092
            if (wall[j].nextwall < 0)
2093
                continue;
1866 helixhorne 2094
 
1886 helixhorne 2095
            k = wall[j].nextsector;
2096
 
7876 terminx 2097
            if (hlsectorbitmap[k>>3]&pow2char[k&7])
1886 helixhorne 2098
                continue;
2099
#if 0
2100
//def YAX_ENABLE
2101
            // internal red walls are kept red
2102
            yax_getbunches(highlightsector[i], &cb, &fb);
2103
            if (cb>=0 && yax_getbunch(k, YAX_CEILING)>=0)
2104
                continue;
2105
            if (fb>=0 && yax_getbunch(k, YAX_FLOOR)>=0)
2106
                continue;
2107
#endif
2108
            onextwall[j] = wall[j].nextwall;
2109
 
2110
            NEXTWALL(j).nextwall = -1;
2111
            NEXTWALL(j).nextsector = -1;
2112
            wall[j].nextwall = -1;
2113
            wall[j].nextsector = -1;
1644 helixhorne 2114
        }
1886 helixhorne 2115
 
2121 helixhorne 2116
    if (highlightsectorcnt > 0)
2117
        mkonwvalid();
2118
    else
2716 helixhorne 2119
        mkonwinvalid_keeptempsect();
1644 helixhorne 2120
}
2121
 
1854 helixhorne 2122
static void duplicate_selected_sectors(void)
1701 helixhorne 2123
{
2138 helixhorne 2124
    mapinfofull_t mapinfo;
2125
    int32_t i, j, onumsectors;
2126
#ifdef YAX_ENABLE
2127
    int32_t onumyaxbunches;
2128
#endif
2129
    int32_t minx=INT32_MAX, maxx=INT32_MIN, miny=INT32_MAX, maxy=INT32_MIN, dx, dy;
2130
 
2131
    i = backup_highlighted_map(&mapinfo);
2132
 
2133
    if (i < 0)
2134
    {
2135
        message("Out of memory!");
2136
        return;
2137
    }
2138
 
2139
    i = restore_highlighted_map(&mapinfo, 0);
2140
    if (i < 0)
2141
    {
2142
        // XXX: no, might be another limit too.  Better message needed.
2143
        printmessage16("Copying sectors would exceed sector or wall limit.");
2144
        return;
2145
    }
2146
 
2147
    // restoring would succeed, tweak things...
2148
    Bmemset(hlsectorbitmap, 0, sizeof(hlsectorbitmap));
2149
    for (i=0; i<highlightsectorcnt; i++)
2150
    {
2151
        int32_t startwall, endwall;
2152
 
2153
        // first, make red lines of old selected sectors, effectively
2154
        // restoring the original state
2155
        for (WALLS_OF_SECTOR(highlightsector[i], j))
2156
        {
2157
            if (wall[j].nextwall >= 0)
2158
                checksectorpointer(wall[j].nextwall,wall[j].nextsector);
2159
            checksectorpointer(j, highlightsector[i]);
2160
 
7078 terminx 2161
            minx = min(minx, TrackerCast(wall[j].x));
2162
            maxx = max(maxx, TrackerCast(wall[j].x));
2163
            miny = min(miny, TrackerCast(wall[j].y));
2164
            maxy = max(maxy, TrackerCast(wall[j].y));
2138 helixhorne 2165
        }
2166
    }
2167
 
2168
    // displace walls & sprites of new sectors by a small amount:
2169
    // calculate displacement
2170
    if (grid>0 && grid<9)
2171
        dx = max(2048>>grid, 128);
2172
    else
2173
        dx = 512;
2174
    dy = -dx;
2175
    if (maxx+dx >= editorgridextent) dx*=-1;
2176
    if (minx+dx <= -editorgridextent) dx*=-1;
2177
    if (maxy+dy >= editorgridextent) dy*=-1;
2178
    if (miny+dy <= -editorgridextent) dy*=-1;
2179
 
2180
    onumsectors = numsectors;
2204 helixhorne 2181
#ifdef YAX_ENABLE
2138 helixhorne 2182
    onumyaxbunches = numyaxbunches;
2204 helixhorne 2183
#endif
2138 helixhorne 2184
    // restore! this will not fail.
2185
    restore_highlighted_map(&mapinfo, 1);
2186
 
2187
    // displace
2188
    for (i=onumsectors; i<numsectors; i++)
2189
    {
2190
        for (j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
2191
        {
2192
            wall[j].x += dx;
2193
            wall[j].y += dy;
2194
        }
2195
 
2196
        for (j=headspritesect[i]; j>=0; j=nextspritesect[j])
2197
        {
2198
            sprite[j].x += dx;
2199
            sprite[j].y += dy;
2200
        }
2201
    }
2202
 
2203
#ifdef YAX_ENABLE
2204
    if (numyaxbunches > onumyaxbunches)
2205
        printmessage16("Sectors duplicated, creating %d new bunches.", numyaxbunches-onumyaxbunches);
2206
    else
2207
#endif
5302 terminx 2208
        printmessage16("Sectors duplicated.");
2138 helixhorne 2209
    asksave = 1;
2210
 
2211
#ifdef YAX_ENABLE
2212
    if (numyaxbunches > onumyaxbunches)
2213
        yax_update(0);
2214
#endif
2215
    yax_updategrays(pos.z);
2216
}
2217
 
1886 helixhorne 2218
 
1854 helixhorne 2219
static void duplicate_selected_sprites(void)
1701 helixhorne 2220
{
1730 helixhorne 2221
    int32_t i, j, k=0;
1701 helixhorne 2222
 
1730 helixhorne 2223
    for (i=0; i<highlightcnt; i++)
2479 helixhorne 2224
        if ((highlight[i]&0xc000) == 16384)
2225
            k++;
1730 helixhorne 2226
 
2479 helixhorne 2227
    if (Numsprites + k <= MAXSPRITES)
1701 helixhorne 2228
    {
2229
        for (i=0; i<highlightcnt; i++)
2230
            if ((highlight[i]&0xc000) == 16384)
2231
            {
2232
                //duplicate sprite
2233
                k = (highlight[i]&16383);
2234
                j = insertsprite(sprite[k].sectnum,sprite[k].statnum);
2235
                Bmemcpy(&sprite[j],&sprite[k],sizeof(spritetype));
1730 helixhorne 2236
//                sprite[j].sectnum = sprite[k].sectnum;   //Don't let memcpy overwrite sector!
2237
//                setsprite(j,(vec3_t *)&sprite[j]);
1701 helixhorne 2238
            }
2478 helixhorne 2239
 
5302 terminx 2240
        printmessage16("Sprites duplicated.");
1701 helixhorne 2241
        asksave = 1;
2242
    }
2243
    else
2244
    {
2245
        printmessage16("Copying sprites would exceed sprite limit.");
2246
    }
2247
}
2248
 
1801 helixhorne 2249
static void correct_ornamented_sprite(int32_t i, int32_t hitw)
2250
{
2251
    int32_t j;
2252
 
2253
    if (hitw >= 0)
3038 helixhorne 2254
    {
1801 helixhorne 2255
        sprite[i].ang = (getangle(POINT2(hitw).x-wall[hitw].x,
2256
                                  POINT2(hitw).y-wall[hitw].y)+512)&2047;
2257
 
3038 helixhorne 2258
        //Make sure sprite's in right sector
2259
        if (inside(sprite[i].x, sprite[i].y, sprite[i].sectnum) != 1)
2260
        {
2261
            j = wall[hitw].point2;
2262
            sprite[i].x -= ksgn(wall[j].y-wall[hitw].y);
2263
            sprite[i].y += ksgn(wall[j].x-wall[hitw].x);
2264
        }
1801 helixhorne 2265
    }
2266
}
2267
 
2268
void DoSpriteOrnament(int32_t i)
2269
{
2877 helixhorne 2270
    hitdata_t hit;
1801 helixhorne 2271
 
2272
    hitscan((const vec3_t *)&sprite[i],sprite[i].sectnum,
2273
            sintable[(sprite[i].ang+1536)&2047],
2274
            sintable[(sprite[i].ang+1024)&2047],
2275
            0,
2877 helixhorne 2276
            &hit,CLIPMASK1);
1801 helixhorne 2277
 
4901 terminx 2278
    if (hit.sect == -1)
2279
        return;
2280
 
2877 helixhorne 2281
    sprite[i].x = hit.pos.x;
2282
    sprite[i].y = hit.pos.y;
2283
    sprite[i].z = hit.pos.z;
2284
    changespritesect(i, hit.sect);
1801 helixhorne 2285
 
2877 helixhorne 2286
    correct_ornamented_sprite(i, hit.wall);
1801 helixhorne 2287
}
2288
 
1854 helixhorne 2289
void update_highlight(void)
1701 helixhorne 2290
{
2291
    int32_t i;
2292
 
2293
    highlightcnt = 0;
2294
    for (i=0; i<numwalls; i++)
7876 terminx 2295
        if (show2dwall[i>>3]&pow2char[i&7])
1701 helixhorne 2296
            highlight[highlightcnt++] = i;
2297
    for (i=0; i<MAXSPRITES; i++)
2298
        if (sprite[i].statnum < MAXSTATUS)
2299
        {
7876 terminx 2300
            if (show2dsprite[i>>3]&pow2char[i&7])
1701 helixhorne 2301
                highlight[highlightcnt++] = i+16384;
2302
        }
2303
        else
7876 terminx 2304
            show2dsprite[i>>3] &= ~pow2char[i&7];
1701 helixhorne 2305
 
2306
    if (highlightcnt == 0)
2307
        highlightcnt = -1;
2308
}
2309
 
1854 helixhorne 2310
void update_highlightsector(void)
1728 helixhorne 2311
{
2312
    int32_t i;
2313
 
1901 helixhorne 2314
    minhlsectorfloorz = INT32_MAX;
2144 helixhorne 2315
    numhlsecwalls = 0;
1901 helixhorne 2316
 
1728 helixhorne 2317
    highlightsectorcnt = 0;
2318
    for (i=0; i<numsectors; i++)
7876 terminx 2319
        if (hlsectorbitmap[i>>3]&pow2char[i&7])
1901 helixhorne 2320
        {
1728 helixhorne 2321
            highlightsector[highlightsectorcnt++] = i;
7078 terminx 2322
            minhlsectorfloorz = min(minhlsectorfloorz, TrackerCast(sector[i].floorz));
2144 helixhorne 2323
            numhlsecwalls += sector[i].wallnum;
1901 helixhorne 2324
        }
1728 helixhorne 2325
 
2326
    if (highlightsectorcnt==0)
1901 helixhorne 2327
    {
2328
        minhlsectorfloorz = 0;
1728 helixhorne 2329
        highlightsectorcnt = -1;
1901 helixhorne 2330
    }
1728 helixhorne 2331
}
2332
 
1801 helixhorne 2333
// Get average point of sectors
2334
static void get_sectors_center(const int16_t *sectors, int32_t numsecs, int32_t *cx, int32_t *cy)
2335
{
2336
    int32_t i, j, k=0, dax = 0, day = 0;
2337
    int32_t startwall, endwall;
1760 helixhorne 2338
 
1801 helixhorne 2339
    for (i=0; i<numsecs; i++)
2340
    {
2341
        for (WALLS_OF_SECTOR(sectors[i], j))
2342
        {
2343
            dax += wall[j].x;
2344
            day += wall[j].y;
2345
            k++;
2346
        }
2347
    }
2348
 
2349
    if (k > 0)
2350
    {
2351
        dax /= k;
2352
        day /= k;
2353
    }
2354
 
2355
    *cx = dax;
2356
    *cy = day;
2357
}
2358
 
2088 helixhorne 2359
static int32_t insert_sprite_common(int32_t sectnum, int32_t dax, int32_t day)
1801 helixhorne 2360
{
2361
    int32_t i, j, k;
2362
 
2088 helixhorne 2363
    i = insertsprite(sectnum,0);
1801 helixhorne 2364
    if (i < 0)
2365
        return -1;
2366
 
2367
    sprite[i].x = dax, sprite[i].y = day;
8440 hendricks2 2368
    sprite[i].cstat = defaultspritecstat;
1801 helixhorne 2369
    sprite[i].shade = 0;
2370
    sprite[i].pal = 0;
2371
    sprite[i].xrepeat = 64, sprite[i].yrepeat = 64;
2372
    sprite[i].xoffset = 0, sprite[i].yoffset = 0;
2373
    sprite[i].ang = 1536;
2374
    sprite[i].xvel = 0; sprite[i].yvel = 0; sprite[i].zvel = 0;
2375
    sprite[i].owner = -1;
2376
    sprite[i].clipdist = 32;
2377
    sprite[i].lotag = 0;
2378
    sprite[i].hitag = 0;
2379<