code:
BUILD SOURCE CODE LICENSE TERMS:                             06/20/2000

[1] I give you permission to make modifications to my Build source and
       distribute it, BUT:

[2] Any derivative works based on my Build source may be distributed ONLY
       through the INTERNET.

[3] Distribution of any derivative works MUST be done completely FREE of
       charge - no commercial exploitation whatsoever.

[4] Anything you distribute which uses a part of my Build Engine source
       code MUST include:

   [A] The following message somewhere in the archive:

       // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
       // Ken Silverman's official web site: "http://www.advsys.net/ken"
       // See the included license file "BUILDLIC.TXT" for license info.

   [B] This text file "BUILDLIC.TXT" along with it.

   [C] Any source files that you modify must include this message as well:

       // This file has been modified from Ken Silverman's original release

[5] The use of the Build Engine for commercial purposes will require an
       appropriate license arrangement with me. Contact information is
       on my web site.

[6] I take no responsibility for damage to your system.

[7] Technical support: Before contacting me with questions, please read
       and do ALL of the following!

   [A] Look through ALL of my text files. There are 7 of them (including this
          one). I like to think that I wrote them for a reason. You will find
          many of your answers in the history section of BUILD.TXT and
          BUILD2.TXT (they're located inside SRC.ZIP).

   [B] If that doesn't satisfy you, then try going to:

             "http://www.advsys.net/ken/buildsrc"

          where I will maintain a Build Source Code FAQ (or perhaps I might
          just provide a link to a good FAQ).

   [C] I am willing to respond to questions, but ONLY if they come at a rate
          that I can handle.

             PLEASE TRY TO AVOID ASKING DUPLICATE QUESTIONS!

          As my line of defense, I will post my current policy about
          answering Build source questions (right below the E-mail address
          on my web site.) You can check there to see if I'm getting
          overloaded with questions or not.

          If I'm too busy, it might say something like this:

               I'm too busy to answer Build source questions right now.
               Sorry, but don't expect a reply from me any time soon.

          If I'm open for Build source questions, please state your question
             clearly and don't include any unsolicited attachments unless
             they're really small (like less than 50k). Assume that I have
             a 28.8k modem. Also, don't leave out important details just
             to make your question appear shorter - making me guess what
             you're asking doesn't save me time!

----------------------------------------------------------------------------
-Ken S. (official web site: http://www.advsys.net/ken)


code:
#define NEED_COMMCTRL_H
#include "../../build/include/windows_inc.h"
#include "../../build/include/startwin.editor.h"

RSRC_ICON ICON "build_icon.ico"
RSRC_BMP BITMAP "build.bmp"

WIN_STARTWIN DIALOGEX DISCARDABLE  20, 40, 260, 200
STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE | WS_SYSMENU
CAPTION "Startup"
FONT 8, "MS Shell Dlg"
BEGIN
	CONTROL "", WIN_STARTWIN_BITMAP, "STATIC", SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 32, 32
	CONTROL "", WIN_STARTWIN_TABCTL, WC_TABCONTROL, WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 5, 250, 170
	CONTROL "&Start", WIN_STARTWIN_START, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 180, 48, 14
	CONTROL "&Cancel", WIN_STARTWIN_CANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 207, 180, 48, 14

	CONTROL "", WIN_STARTWIN_MESSAGES, "EDIT", ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VSCROLL, 0, 0, 32, 32
END

WIN_STARTWINPAGE_CONFIG DIALOGEX DISCARDABLE  20, 40, 279, 168
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
CAPTION "Dialog"
FONT 8, "MS Shell Dlg"
BEGIN
	CONTROL "&2D Video mode:",   -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 8, 50, 8
	CONTROL "",            IDC2DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 6, 80, 56
	CONTROL "&Fullscreen", IDCFULLSCREEN, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 148, 8, 49, 10
	CONTROL "&3D Video mode:",   -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 24, 50, 8
	CONTROL "",            IDC3DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 22, 80, 56
	CONTROL "&Always show configuration on start", IDCALWAYSSHOW, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 118, 116, 140, 8
END

#define VER        2,0,0,4

#if defined EDUKE32_FAKE_DATE || defined EDUKE32_FAKE_TIME
# define VERSTR     REVSTR
#else
# define VERSTR     REVSTR " built " __DATE__ " " __TIME__
#endif

VS_VERSION_INFO VERSIONINFO
 FILEVERSION VER
 PRODUCTVERSION VER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x3L
#else
 FILEFLAGS 0x2L
#endif
 FILEOS 0x40004L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "Editor for EKenBuild"
            VALUE "FileVersion", VERSTR
            VALUE "InternalName", "EKenBuild-Editor"
            VALUE "LegalCopyright", "Copyright © EDuke32 Developers, 2000, 2003 Ken Silverman"
            VALUE "OriginalFilename", "ekenbuild-editor.exe"
            VALUE "ProductName", "EKenBuild-Editor"
            VALUE "ProductVersion", VERSTR
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

1 24 "manifest.build.xml"

repo_name: orochi/nblood

license: mit


code:
#define NEED_COMMCTRL_H
#include "../../build/include/windows_inc.h"
#include "../src/startwin.game.h"

RSRC_ICON ICON "game_icon.ico"
RSRC_BMP BITMAP "game.bmp"

WIN_STARTWIN DIALOGEX DISCARDABLE  20, 40, 260, 200
STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE | WS_SYSMENU
CAPTION "Startup"
FONT 8, "MS Shell Dlg"
BEGIN
	CONTROL "", WIN_STARTWIN_BITMAP, "STATIC", SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 32, 32
	CONTROL "", WIN_STARTWIN_TABCTL, WC_TABCONTROL, WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 5, 250, 170
	CONTROL "&Start", WIN_STARTWIN_START, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 180, 48, 14
	CONTROL "&Cancel", WIN_STARTWIN_CANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 207, 180, 48, 14

	CONTROL "", WIN_STARTWIN_MESSAGES, "EDIT", ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VSCROLL, 0, 0, 32, 32
END

WIN_STARTWINPAGE_CONFIG DIALOGEX DISCARDABLE  20, 40, 279, 168
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
CAPTION "Dialog"
FONT 8, "MS Shell Dlg"
BEGIN
	CONTROL "&Video mode:",   -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 8, 50, 8
	CONTROL "",            IDC3DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 6, 80, 56
	CONTROL "&Fullscreen", IDCFULLSCREEN, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 148, 8, 49, 10
	CONTROL "&Always show configuration on start", IDCALWAYSSHOW, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 118, 116, 140, 8
END

#define VER        2,0,0,4

#if defined EDUKE32_FAKE_DATE || defined EDUKE32_FAKE_TIME
# define VERSTR     REVSTR
#else
# define VERSTR     REVSTR " built " __DATE__ " " __TIME__
#endif

VS_VERSION_INFO VERSIONINFO
 FILEVERSION VER
 PRODUCTVERSION VER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x3L
#else
 FILEFLAGS 0x2L
#endif
 FILEOS 0x40004L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "EKenBuild"
            VALUE "FileVersion", VERSTR
            VALUE "InternalName", "EKenBuild"
            VALUE "LegalCopyright", "Copyright © EDuke32 Developers, 2000, 2003 Ken Silverman"
            VALUE "OriginalFilename", "ekenbuild.exe"
            VALUE "ProductName", "EKenBuild"
            VALUE "ProductVersion", VERSTR
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

1 24 "manifest.game.xml"


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true/pm</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
    </asmv3:windowsSettings>
  </asmv3:application>
  <assemblyIdentity
      version="1.0.0.0"
      processorArchitecture="*"
      name="EKenBuild.Editor"
      type="win32"
/>
  <description>Editor for EKenBuild</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true/pm</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
    </asmv3:windowsSettings>
  </asmv3:application>
  <assemblyIdentity
      version="1.0.0.0"
      processorArchitecture="*"
      name="EKenBuild"
      type="win32"
/>
  <description>EKenBuild</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>


code:
#import <Cocoa/Cocoa.h>

#include "compat.h"
#include "baselayer.h"
#include "build.h"

static struct
{
    int fullscreen;
    int xdim3d, ydim3d, bpp3d;
    int forcesetup;
} settings;

@interface StartupWinController : NSWindowController
{
    NSMutableArray *modeslist3d;

    IBOutlet NSButton *alwaysShowButton;
    IBOutlet NSButton *fullscreenButton;
    IBOutlet NSTextView *messagesView;
    IBOutlet NSTabView *tabView;
    IBOutlet NSPopUpButton *videoMode3DPUButton;

    IBOutlet NSButton *cancelButton;
    IBOutlet NSButton *startButton;
}

- (void)dealloc;
- (void)populateVideoModes:(BOOL)firstTime;

- (IBAction)alwaysShowClicked:(id)sender;
- (IBAction)fullscreenClicked:(id)sender;

- (IBAction)cancel:(id)sender;
- (IBAction)start:(id)sender;

- (void)setupRunMode;
- (void)setupMessagesMode;
- (void)putsMessage:(NSString *)str;
- (void)setTitle:(NSString *)str;
@end

@implementation StartupWinController

- (void)dealloc
{
    [modeslist3d release];
    [super dealloc];
}

- (void)populateVideoModes:(BOOL)firstTime
{
    int i, mode3d, fullscreen = ([fullscreenButton state] == NSOnState);
    int idx3d = -1;
    int xdim = 0, ydim = 0, bpp = 0;

    if (firstTime)
    {
        xdim = settings.xdim3d;
        ydim = settings.ydim3d;
        bpp  = settings.bpp3d;
    }
    else
    {
        mode3d = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue];
        if (mode3d >= 0)
        {
            xdim = validmode[mode3d].xdim;
            ydim = validmode[mode3d].ydim;
            bpp = validmode[mode3d].bpp;
        }
    }

    mode3d = videoCheckMode(&xdim, &ydim, bpp, fullscreen, 1);
    if (mode3d < 0)
    {
        int i, cd[] = { 32, 24, 16, 15, 8, 0 };
        for (i=0; cd[i]; ) { if (cd[i] >= bpp) i++; else break; }
        for (; cd[i]; i++)
        {
            mode3d = videoCheckMode(&xdim, &ydim, cd[i], fullscreen, 1);
            if (mode3d < 0) continue;
            break;
        }
    }

    [modeslist3d release];
    [videoMode3DPUButton removeAllItems];

    modeslist3d = [[NSMutableArray alloc] init];

    for (i = 0; i < validmodecnt; i++)
    {
        if (fullscreen == validmode[i].fs)
        {
            if (i == mode3d) idx3d = [modeslist3d count];
            [modeslist3d addObject:[NSNumber numberWithInt:i]];
            [videoMode3DPUButton addItemWithTitle:[NSString stringWithFormat:@"%d %C %d %d-bpp",
                                                   validmode[i].xdim, 0xd7, validmode[i].ydim, validmode[i].bpp]];
        }
    }

    if (idx3d >= 0) [videoMode3DPUButton selectItemAtIndex:idx3d];
}

- (IBAction)alwaysShowClicked:(id)sender
{
    UNREFERENCED_PARAMETER(sender);
}

- (IBAction)fullscreenClicked:(id)sender
{
    [self populateVideoModes:NO];

    UNREFERENCED_PARAMETER(sender);
}

- (IBAction)cancel:(id)sender
{
    [NSApp abortModal];

    UNREFERENCED_PARAMETER(sender);
}

- (IBAction)start:(id)sender
{
    int mode = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue];
    if (mode >= 0)
    {
        settings.xdim3d = validmode[mode].xdim;
        settings.ydim3d = validmode[mode].ydim;
        settings.bpp3d = validmode[mode].bpp;
        settings.fullscreen = validmode[mode].fs;
    }

    settings.forcesetup = [alwaysShowButton state] == NSOnState;

    [NSApp stopModal];

    UNREFERENCED_PARAMETER(sender);
}

- (void)setupRunMode
{
    getvalidmodes();

    [fullscreenButton setState: (settings.fullscreen ? NSOnState : NSOffState)];
    [alwaysShowButton setState: (settings.forcesetup ? NSOnState : NSOffState)];
    [self populateVideoModes:YES];

    // enable all the controls on the Configuration page
    NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator];
    NSControl *control;
    while (control = [enumerator nextObject]) [control setEnabled:true];

    [cancelButton setEnabled:true];
    [startButton setEnabled:true];

    [tabView selectTabViewItemAtIndex:0];
    [NSCursor unhide];  // Why should I need to do this?
}

- (void)setupMessagesMode
{
    [tabView selectTabViewItemAtIndex:1];

    // disable all the controls on the Configuration page except "always show", so the
    // user can enable it if they want to while waiting for something else to happen
    NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator];
    NSControl *control;
    while (control = [enumerator nextObject])
    {
        if (control == alwaysShowButton) continue;
        [control setEnabled:false];
    }

    [cancelButton setEnabled:false];
    [startButton setEnabled:false];
}

- (void)putsMessage:(NSString *)str
{
    NSRange end;
    NSTextStorage *text = [messagesView textStorage];
    BOOL shouldAutoScroll;

    shouldAutoScroll = ((int)NSMaxY([messagesView bounds]) == (int)NSMaxY([messagesView visibleRect]));

    end.location = [text length];
    end.length = 0;

    [text beginEditing];
    [messagesView replaceCharactersInRange:end withString:str];
    [text endEditing];

    if (shouldAutoScroll)
    {
        end.location = [text length];
        end.length = 0;
        [messagesView scrollRangeToVisible:end];
    }
}

- (void)setTitle:(NSString *)str
{
    [[self window] setTitle:str];
}

@end

static StartupWinController *startwin = nil;

int startwin_open(void)
{
    if (startwin != nil) return 1;

    startwin = [[StartupWinController alloc] initWithWindowNibName:@"startwin.game"];
    if (startwin == nil) return -1;

    [startwin setupMessagesMode];
    [startwin showWindow:nil];

    return 0;
}

int startwin_close(void)
{
    if (startwin == nil) return 1;

    [startwin close];
    [startwin release];
    startwin = nil;

    return 0;
}

int startwin_puts(const char *s)
{
    NSString *ns;

    if (!s) return -1;
    if (startwin == nil) return 1;

    ns = [[NSString alloc] initWithUTF8String:s];
    [startwin putsMessage:ns];
    [ns release];

    return 0;
}

int startwin_settitle(const char *s)
{
    NSString *ns;

    if (!s) return -1;
    if (startwin == nil) return 1;

    ns = [[NSString alloc] initWithUTF8String:s];
    [startwin setTitle:ns];
    [ns release];

    return 0;
}

int startwin_idle(void *v)
{
    if (startwin) [[startwin window] displayIfNeeded];
    UNREFERENCED_PARAMETER(v);
    return 0;
}

extern int xdimgame, ydimgame, bppgame, forcesetup;

int startwin_run(void)
{
    int retval;

    if (startwin == nil) return 0;

    settings.fullscreen = fullscreen;
    settings.xdim3d = xdimgame;
    settings.ydim3d = ydimgame;
    settings.bpp3d = bppgame;
    settings.forcesetup = forcesetup;

    [startwin setupRunMode];

    switch ([NSApp runModalForWindow:[startwin window]])
    {
#ifdef MAC_OS_X_VERSION_10_9
    case NSModalResponseStop: retval = 1; break;
    case NSModalResponseAbort: retval = 0; break;
#else
    case NSRunStoppedResponse: retval = 1; break;
    case NSRunAbortedResponse: retval = 0; break;
#endif
    default: retval = -1;
    }

    [startwin setupMessagesMode];

    if (retval)
    {
        fullscreen = settings.fullscreen;
        xdimgame = settings.xdim3d;
        ydimgame = settings.ydim3d;
        bppgame = settings.bpp3d;
        forcesetup = settings.forcesetup;
    }

    return retval;
}


code:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
//
// This file has been modified from Ken Silverman's original release
// by Jonathon Fowler (jf@jonof.id.au)

#include "compat.h"
#include "build.h"
#include "editor.h"
#include "pragmas.h"
#include "baselayer.h"
#include "names.h"
#include "osd.h"
#include "cache1d.h"
#include "common.h"
#include "m32script.h"
#include "keys.h"

#include "common_game.h"

const char *AppProperName = "EKenBuild Editor";
const char *AppTechnicalName = "ekenbuild-editor";

#if defined(_WIN32)
#define DEFAULT_GAME_EXEC "ekenbuild.exe"
#define DEFAULT_GAME_LOCAL_EXEC "ekenbuild.exe"
#else
#define DEFAULT_GAME_EXEC "ekenbuild"
#define DEFAULT_GAME_LOCAL_EXEC "./ekenbuild"
#endif

const char *DefaultGameExec = DEFAULT_GAME_EXEC;
const char *DefaultGameLocalExec = DEFAULT_GAME_LOCAL_EXEC;

#define SETUPFILENAME "ekenbuild-editor.cfg"
const char *defaultsetupfilename = SETUPFILENAME;
char setupfilename[BMAX_PATH] = SETUPFILENAME;

#define eitherALT   (keystatus[KEYSC_LALT] || keystatus[KEYSC_RALT])
#define eitherCTRL  (keystatus[KEYSC_LCTRL] || keystatus[KEYSC_RCTRL])
#define eitherSHIFT (keystatus[KEYSC_LSHIFT] || keystatus[KEYSC_RSHIFT])

#define PRESSED_KEYSC(Key) (keystatus[KEYSC_##Key] && !(keystatus[KEYSC_##Key]=0))

static char tempbuf[256];

#define NUMOPTIONS 9
char option[NUMOPTIONS] = {0,0,0,0,0,0,1,0,0};
unsigned char default_buildkeys[NUMBUILDKEYS] =
{
    0xc8,0xd0,0xcb,0xcd,0x2a,0x9d,0x1d,0x39,
    0x1e,0x2c,0xd1,0xc9,0x33,0x34,
    0x9c,0x1c,0xd,0xc,0xf,0x29
};

//static int hang = 0;
//static int rollangle = 0;

//Detecting 2D / 3D mode:
//   qsetmode is 200 in 3D mode
//   qsetmode is 350/480 in 2D mode
//
//You can read these variables when F5-F8 is pressed in 3D mode only:
//
//   If (searchstat == 0)  WALL        searchsector=sector, searchwall=wall
//   If (searchstat == 1)  CEILING     searchsector=sector
//   If (searchstat == 2)  FLOOR       searchsector=sector
//   If (searchstat == 3)  SPRITE      searchsector=sector, searchwall=sprite
//   If (searchstat == 4)  MASKED WALL searchsector=sector, searchwall=wall
//
//   searchsector is the sector of the selected item for all 5 searchstat's
//
//   searchwall is undefined if searchstat is 1 or 2
//   searchwall is the wall if searchstat = 0 or 4
//   searchwall is the sprite if searchstat = 3 (Yeah, I know - it says wall,
//                                      but trust me, it's the sprite number)

int averagefps;
#define AVERAGEFRAMES 32
static unsigned int frameval[AVERAGEFRAMES];
static int framecnt = 0;

const char *ExtGetVer(void)
{
    return s_buildRev;
}

int32_t ExtPreInit(int32_t argc,char const * const * argv)
{
    UNREFERENCED_PARAMETER(argc);
    UNREFERENCED_PARAMETER(argv);

    OSD_SetLogFile("ekenbuild-editor.log");
    char tempbuf[256];
    snprintf(tempbuf, ARRAY_SIZE(tempbuf), "%s %s", AppProperName, s_buildRev);
    OSD_SetVersion(tempbuf, 10,0);
    buildprintf("%s\n", tempbuf);
    PrintBuildInfo();

    return 0;
}

int32_t ExtInit(void)
{
    int rv = 0;

    /*printf("------------------------------------------------------------------------------\n");
    printf("   BUILD.EXE copyright(c) 1996 by Ken Silverman.  You are granted the\n");
    printf("   right to use this software for your personal use only.  This is a\n");
    printf("   special version to be used with \"Happy Fun KenBuild\" and may not work\n");
    printf("   properly with other Build engine games.  Please refer to license.doc\n");
    printf("   for distribution rights\n");
    printf("------------------------------------------------------------------------------\n");
    getch();
    */

    OSD_SetParameters(0,2, 0,0, 4,0, 0, 0, 0, 0); // TODO

    bpp = 8;
    if (loadsetup(setupfilename) < 0) buildputs("Configuration file not found, using defaults.\n"), rv = 1;
    Bmemcpy(buildkeys, default_buildkeys, NUMBUILDKEYS);   //Trick to make build use setup.dat keys
    if (option[4] > 0) option[4] = 0;

    kensplayerheight = 32;
    zmode = 0;

    wm_msgbox("Pre-Release Software Warning", "%s is not ready for public use. Proceed with caution!", AppProperName);

#ifdef _WIN32
//  allowtaskswitching(0);
#endif
    return rv;
}

int32_t ExtPostStartupWindow(void)
{
    initgroupfile(G_GrpFile());

    if (engineInit())
    {
        initprintf("There was a problem initializing the engine.\n");
        return -1;
    }

    Ken_PostStartupWindow();

    return 0;
}

void ExtPostInit(void)
{
    Ken_LoadVoxels();
    palettePostLoadLookups();
}

void ExtUnInit(void)
{
    uninitgroupfile();
    writesetup(setupfilename);
}

//static int daviewingrange, daaspect, horizval1, horizval2;
void ExtPreCheckKeys(void)
{
    int /*cosang, sinang, dx, dy, mindx,*/ i, j, k;

    if (keystatus[0x3e])  //F4 - screen re-size
    {
        keystatus[0x3e] = 0;

        //cycle through all vesa modes, then screen-buffer mode
        if (keystatus[0x2a]|keystatus[0x36])
        {
            videoSetGameMode(!fullscreen, xdim, ydim, bpp, upscalefactor);
        }
        else
        {

            //cycle through all modes
            j=-1;

            // work out a mask to select the mode
            for (i=0; i<validmodecnt; i++)
                if ((validmode[i].xdim == xdim) &&
                    (validmode[i].ydim == ydim) &&
                    (validmode[i].fs == fullscreen) &&
                    (validmode[i].bpp == bpp))
                { j=i; break; }

            for (k=0; k<validmodecnt; k++)
                if (validmode[k].fs == fullscreen && validmode[k].bpp == bpp) break;

            if (j==-1) j=k;
            else
            {
                j++;
                if (j==validmodecnt) j=k;
            }
            videoSetGameMode(fullscreen, validmode[j].xdim, validmode[j].ydim, bpp, upscalefactor);
        }
    }

    if (keystatus[buildkeys[BK_MODE2D_3D]])  // Enter
    {
        getmessageleng = 0;
        getmessagetimeoff = 0;
    }

    if (getmessageleng > 0)
    {
        if (!in3dmode())
            printmessage16("%s", getmessage);
        if (totalclock > getmessagetimeoff)
            getmessageleng = 0;
    }

#if 0
    if (keystatus[0x2a]|keystatus[0x36])
    {
        if (keystatus[0xcf]) hang = max(hang-1,-182);
        if (keystatus[0xc7]) hang = min(hang+1,182);
    }
    else
    {
        if (keystatus[0xcf]) hang = max(hang-8,-182);
        if (keystatus[0xc7]) hang = min(hang+8,182);
    }
    if (keystatus[0x4c]) { hang = 0; horiz = 100; }
    if (hang != 0)
    {
        walock[4094] = 255;

        // JBF 20031117: scale each dimension by a factor of 1.2, and work out
        // the aspect of the screen. Anywhere you see 'i' below was the value
        // '200' before I changed it. NOTE: This whole trick crashes in resolutions
        // above 800x600. I'm not sure why, and fixing it is not something I intend
        // to do in a real big hurry.
        dx = (xdim + (xdim >> 3) + (xdim >> 4) + (xdim >> 6)) & (~7);
        dy = (ydim + (ydim >> 3) + (ydim >> 4) + (ydim >> 6)) & (~7);
        i = scale(320,ydim,xdim);

        if (waloff[4094] == 0) g_cache.allocateBlock(&waloff[4094],/*240L*384L*/ dx*dy,&walock[4094]);
        renderSetTarget(4094,/*240L,384L*/ dy,dx);

        cosang = sintable[(hang+512)&2047];
        sinang = sintable[hang&2047];

        dx = dmulscale1(320,cosang,i,sinang); mindx = dx;
        dy = dmulscale1(-i,cosang,320,sinang);
        horizval1 = dy*(320>>1)/dx-1;

        dx = dmulscale1(320,cosang,-i,sinang); mindx = min(dx,mindx);
        dy = dmulscale1(i,cosang,320,sinang);
        horizval2 = dy*(320>>1)/dx+1;

        daviewingrange = divscale30(xdim>>1, mindx-16);
        daaspect = scale(daviewingrange,scale(320,tilesiz[4094].x,tilesiz[4094].y),horizval2+6-horizval1);
        renderSetAspect(daviewingrange,scale(daaspect,ydim*320,xdim*i));
        horiz = 100-divscale15(horizval1+horizval2,daviewingrange);
    }
#endif
}

void ExtAnalyzeSprites(int32_t ourx, int32_t oury, int32_t ourz, int32_t oura, int32_t smoothr)
{
    int i, *longptr;
    tspriteptr_t tspr;

    UNREFERENCED_PARAMETER(ourx);
    UNREFERENCED_PARAMETER(oury);
    UNREFERENCED_PARAMETER(ourz);
    UNREFERENCED_PARAMETER(oura);
    UNREFERENCED_PARAMETER(smoothr);

    for (i=0,tspr=&tsprite[0]; i<spritesortcnt; i++,tspr++)
    {
        if (usevoxels && videoGetRenderMode() != REND_POLYMER)
        {
            switch (tspr->picnum)
            {
            case PLAYER:
                if (voxid_PLAYER == -1)
                    break;

                tspr->cstat |= 48;
                tspr->picnum = voxid_PLAYER;

                longptr = (int32_t *)voxoff[voxid_PLAYER][0];
                tspr->xrepeat = scale(tspr->xrepeat,56,longptr[2]);
                tspr->yrepeat = scale(tspr->yrepeat,56,longptr[2]);
                tspr->shade -= 6;
                break;
            case BROWNMONSTER:
                if (voxid_BROWNMONSTER == -1)
                    break;

                tspr->cstat |= 48;
                tspr->picnum = voxid_BROWNMONSTER;
                break;
            }
        }

        tspr->shade += 6;
        if (sector[tspr->sectnum].ceilingstat&1)
            tspr->shade += sector[tspr->sectnum].ceilingshade;
        else
            tspr->shade += sector[tspr->sectnum].floorshade;
    }
}

static void Keys2D()
{
    if (PRESSED_KEYSC(G))  // G (grid on/off)
    {
        if (autogrid)
        {
            grid = 8*eitherSHIFT;

            autogrid = 0;
        }
        else
        {
            grid += (1-2*eitherSHIFT);
            if (grid == -1 || grid == 9)
            {
                autogrid = 1;
                grid = 0;
            }
        }

        if (autogrid)
            printmessage16("Grid size: 9 (autosize)");
        else if (!grid)
            printmessage16("Grid off");
        else
            printmessage16("Grid size: %d (%d units)", grid, 2048>>grid);
    }

    if (autogrid)
    {
        grid = -1;

        while (grid++ < 7)
        {
            if (mulscale14((2048>>grid), zoom) <= 16)
                break;
        }
    }
}

void ExtCheckKeys(void)
{
    int i; //, p, y, dx, dy, cosang, sinang, bufplc, tsizy, tsizyup15;
    int j;

    if (in3dmode())
    {
#if 0
        if (hang != 0)
        {
            bufplc = waloff[4094]+(mulscale16(horiz-100,xdimenscale)+(tilesiz[4094].x>>1))*tilesiz[4094].y;
            renderRestoreTarget();
            cosang = sintable[(hang+512)&2047];
            sinang = sintable[hang&2047];
            dx = dmulscale1(xdim,cosang,ydim,sinang);
            dy = dmulscale1(-ydim,cosang,xdim,sinang);

            videoBeginDrawing();
            tsizy = tilesiz[4094].y;
            tsizyup15 = (tsizy<<15);
            dx = mulscale14(dx,daviewingrange);
            dy = mulscale14(dy,daaspect);
            sinang = mulscale14(sinang,daviewingrange);
            cosang = mulscale14(cosang,daaspect);
            p = ylookup[windowxy1.y]+frameplace+windowxy2.x+1;
            for (y=windowxy1.y; y<=windowxy2.y; y++)
            {
                i = divscale16(tsizyup15,dx);
                stretchhline(0,(xdim>>1)*i+tsizyup15,xdim>>2,i,mulscale32(i,dy)*tsizy+bufplc,p);
                dx -= sinang; dy += cosang; p += ylookup[1];
            }
            walock[4094] = 1;

            Bsprintf(tempbuf,"%d",(hang*180)>>10);
            printext256(0L,8L,31,-1,tempbuf,1);
            videoEndDrawing();
        }
#endif
        if (keystatus[0xa]) renderSetAspect(viewingrange+(viewingrange>>8),yxaspect+(yxaspect>>8));
        if (keystatus[0xb]) renderSetAspect(viewingrange-(viewingrange>>8),yxaspect-(yxaspect>>8));
        if (keystatus[0xc]) renderSetAspect(viewingrange,yxaspect-(yxaspect>>8));
        if (keystatus[0xd]) renderSetAspect(viewingrange,yxaspect+(yxaspect>>8));
        //if (keystatus[0x38]) renderSetRollAngle(rollangle+=((keystatus[0x2a]|keystatus[0x36])*6+2));
        //if (keystatus[0xb8]) renderSetRollAngle(rollangle-=((keystatus[0x2a]|keystatus[0x36])*6+2));
        //if (keystatus[0x1d]|keystatus[0x9d]) renderSetRollAngle(rollangle=0);

        videoBeginDrawing();

        i = frameval[framecnt&(AVERAGEFRAMES-1)];
        j = frameval[framecnt&(AVERAGEFRAMES-1)] = timerGetTicks(); framecnt++;
        if (i != j) averagefps = (averagefps*3 + (AVERAGEFRAMES*1000)/(j-i))>>2;
        Bsprintf((char *)tempbuf,"%d",averagefps);
        printext256(0L,0L,31,-1,(char *)tempbuf,1);

        videoEndDrawing();
        editinput();
    }
    else
    {
        Keys2D();
    }

    if ((in3dmode() && !m32_is2d3dmode()) || m32_is2d3dmode())
    {
#ifdef USE_OPENGL
        int bakrendmode = rendmode;

        if (m32_is2d3dmode())
            rendmode = REND_CLASSIC;
#endif

        m32_showmouse();

#ifdef USE_OPENGL
        rendmode = bakrendmode;
#endif
    }
}

void ExtCleanUp(void)
{
}

void ExtPreLoadMap(void)
{
}

void ExtSetupMapFilename(const char *mapname)
{
    UNREFERENCED_PARAMETER(mapname);
}

void ExtLoadMap(const char *mapname)
{
    UNREFERENCED_PARAMETER(mapname);
}

int32_t ExtPreSaveMap(void)
{
    return 0;
}

void ExtSaveMap(const char *mapname)
{
    UNREFERENCED_PARAMETER(mapname);
}

const char *ExtGetSectorCaption(short sectnum)
{
    if ((sector[sectnum].lotag|sector[sectnum].hitag) == 0)
    {
        tempbuf[0] = 0;
    }
    else
    {
        Bsprintf((char *)tempbuf,"%hu,%hu",(unsigned short)sector[sectnum].hitag,
                 (unsigned short)sector[sectnum].lotag);
    }
    return (char *)tempbuf;
}

const char *ExtGetWallCaption(short wallnum)
{
    if ((wall[wallnum].lotag|wall[wallnum].hitag) == 0)
    {
        tempbuf[0] = 0;
    }
    else
    {
        Bsprintf((char *)tempbuf,"%hu,%hu",(unsigned short)wall[wallnum].hitag,
                 (unsigned short)wall[wallnum].lotag);
    }
    return (char *)tempbuf;
}

const char *ExtGetSpriteCaption(short spritenum)
{
    if ((sprite[spritenum].lotag|sprite[spritenum].hitag) == 0)
    {
        tempbuf[0] = 0;
    }
    else
    {
        Bsprintf((char *)tempbuf,"%hu,%hu",(unsigned short)sprite[spritenum].hitag,
                 (unsigned short)sprite[spritenum].lotag);
    }
    return (char *)tempbuf;
}

//printext16 parameters:
//printext16(int xpos, int ypos, short col, short backcol,
//           char name[82], char fontsize)
//  xpos 0-639   (top left)
//  ypos 0-479   (top left)
//  col 0-15
//  backcol 0-15, -1 is transparent background
//  name
//  fontsize 0=8*8, 1=3*5

//editorDraw2dLine parameters:
// editorDraw2dLine(int x1, int y1, int x2, int y2, char col)
//  x1, x2  0-639
//  y1, y2  0-143  (status bar is 144 high, origin is top-left of STATUS BAR)
//  col     0-15

void ExtShowSectorData(short sectnum)   //F5
{
    int i;
    if (in3dmode())
    {
    }
    else
    {
        videoBeginDrawing();
        clearmidstatbar16();             //Clear middle of status bar

        Bsprintf((char *)tempbuf,"Sector %d",sectnum);
        printext16(8,ydim16+32,11,-1,(char *)tempbuf,0);

        printext16(8,ydim16+48,11,-1,"8*8 font: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789",0);
        printext16(8,ydim16+56,11,-1,"3*5 font: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789",1);

        i=ydim16; ydim16=ydim;
        editorDraw2dLine(320,i+68,344,i+80,4);       //Draw house
        editorDraw2dLine(344,i+80,344,i+116,4);
        editorDraw2dLine(344,i+116,296,i+116,4);
        editorDraw2dLine(296,i+116,296,i+80,4);
        editorDraw2dLine(296,i+80,320,i+68,4);
        ydim16=i;
        videoEndDrawing();
    }
}

void ExtShowWallData(short wallnum)       //F6
{
    if (in3dmode())
    {
    }
    else
    {
        videoBeginDrawing();
        clearmidstatbar16();             //Clear middle of status bar

        Bsprintf((char *)tempbuf,"Wall %d",wallnum);
        printext16(8,ydim16+32,11,-1,(char *)tempbuf,0);
        videoEndDrawing();
    }
}

void ExtShowSpriteData(short spritenum)   //F6
{
    if (in3dmode())
    {
    }
    else
    {
        videoBeginDrawing();
        clearmidstatbar16();             //Clear middle of status bar

        Bsprintf((char *)tempbuf,"Sprite %d",spritenum);
        printext16(8,ydim16+32,11,-1,(char *)tempbuf,0);
        videoEndDrawing();
    }
}

void ExtEditSectorData(short sectnum)    //F7
{
    short nickdata;

    if (in3dmode())
    {
        //Ceiling
        if (searchstat == 1)
            sector[searchsector].ceilingpicnum++;   //Just a stupid example

        //Floor
        if (searchstat == 2)
            sector[searchsector].floorshade++;      //Just a stupid example
    }
    else                    //In 2D mode
    {
        Bsprintf((char *)tempbuf,"Sector (%d) Nick's variable: ",sectnum);
        nickdata = 0;
        nickdata = getnumber16((char *)tempbuf,nickdata,65536L,0);

        printmessage16(" ");              //Clear message box (top right of status bar)
        ExtShowSectorData(sectnum);
    }
}

void ExtEditWallData(short wallnum)       //F8
{
    short nickdata;

    if (in3dmode())
    {
    }
    else
    {
        Bsprintf((char *)tempbuf,"Wall (%d) Nick's variable: ",wallnum);
        nickdata = 0;
        nickdata = getnumber16((char *)tempbuf,nickdata,65536L,0);

        printmessage16(" ");              //Clear message box (top right of status bar)
        ExtShowWallData(wallnum);
    }
}

void ExtEditSpriteData(short spritenum)   //F8
{
    short nickdata;

    if (in3dmode())
    {
    }
    else
    {
        Bsprintf((char *)tempbuf,"Sprite (%d) Nick's variable: ",spritenum);
        nickdata = 0;
        nickdata = getnumber16((char *)tempbuf,nickdata,65536L,0);
        printmessage16(" ");

        printmessage16(" ");              //Clear message box (top right of status bar)
        ExtShowSpriteData(spritenum);
    }
}

void faketimerhandler(void)
{
    timerUpdateClock();
}

void M32RunScript(const char *s) { UNREFERENCED_PARAMETER(s); }
void G_Polymer_UnInit(void) { }
void SetGamePalette(int32_t j) { UNREFERENCED_PARAMETER(j); }

int32_t AmbienceToggle, MixRate, ParentalLock;

int32_t taglab_linktags(int32_t spritep, int32_t num)
{
    int32_t link = 0;

    g_iReturnVar = link;
    VM_OnEvent(EVENT_LINKTAGS, spritep ? num : -1);
    link = g_iReturnVar;

    return link;
}

int32_t taglab_getnextfreetag(int32_t *duetoptr)
{
    int32_t i, nextfreetag=1;
    int32_t obj = -1;

    for (i=0; i<MAXSPRITES; i++)
    {
        int32_t tag;

        if (sprite[i].statnum == MAXSTATUS)
            continue;

        tag = select_sprite_tag(i);

        if (tag != INT32_MIN && nextfreetag <= tag)
        {
            nextfreetag = tag+1;
            obj = 32768 + i;
        }
    }

    for (i=0; i<numwalls; i++)
    {
        int32_t lt = taglab_linktags(0, i);

        if ((lt&1) && nextfreetag <= wall[i].lotag)
            nextfreetag = wall[i].lotag+1, obj = i;
        if ((lt&2) && nextfreetag <= wall[i].hitag)
            nextfreetag = wall[i].hitag+1, obj = i;
    }

    if (duetoptr != NULL)
        *duetoptr = obj;

    if (nextfreetag < 32768)
        return nextfreetag;

    return 0;
}

int32_t S_InvalidSound(int32_t num) {
    UNREFERENCED_PARAMETER(num); return 1;
};
int32_t S_CheckSoundPlaying(int32_t i, int32_t num) {
    UNREFERENCED_PARAMETER(i); UNREFERENCED_PARAMETER(num); return 0;
};
int32_t S_SoundsPlaying(int32_t i) {
    UNREFERENCED_PARAMETER(i); return -1;
}
int32_t S_SoundFlags(int32_t num) {
    UNREFERENCED_PARAMETER(num); return 0;
};
int32_t A_PlaySound(uint32_t num, int32_t i) {
    UNREFERENCED_PARAMETER(num); UNREFERENCED_PARAMETER(i); return 0;
};
void S_StopSound(int32_t num) {
    UNREFERENCED_PARAMETER(num);
};
void S_StopAllSounds(void) { }

//Just thought you might want my getnumber16 code
/*
getnumber16(char namestart[80], short num, int maxnumber)
{
    char buffer[80];
    int j, k, n, danum, oldnum;

    danum = (int)num;
    oldnum = danum;
    while ((keystatus[0x1c] != 2) && (keystatus[0x1] == 0))  //Enter, ESC
    {
        sprintf(&buffer,"%s%ld_ ",namestart,danum);
        printmessage16(buffer);

        for(j=2;j<=11;j++)                //Scan numbers 0-9
            if (keystatus[j] > 0)
            {
                keystatus[j] = 0;
                k = j-1;
                if (k == 10) k = 0;
                n = (danum*10)+k;
                if (n < maxnumber) danum = n;
            }
        if (keystatus[0xe] > 0)    // backspace
        {
            danum /= 10;
            keystatus[0xe] = 0;
        }
        if (keystatus[0x1c] == 1)   //L. enter
        {
            oldnum = danum;
            keystatus[0x1c] = 2;
            asksave = 1;
        }
    }
    keystatus[0x1c] = 0;
    keystatus[0x1] = 0;
    return((short)oldnum);
}
*/

/*
 * vim:ts=4:
 */


code:
#include "compat.h"
#include "build.h"

#include "names.h"
#include "common_game.h"

static const char *defaultgrpfilename = "STUFF.DAT";
static const char *defaultdeffilename = "kenbuild.def";

int g_useCwd;

const char *G_DefaultGrpFile(void)
{
    return defaultgrpfilename;
}
const char *G_GrpFile(void)
{
    return defaultgrpfilename;
}

const char *G_DefaultDefFile(void)
{
    return defaultdeffilename;
}
const char *G_DefFile(void)
{
    return defaultdeffilename;
}

static void Ken_InitMultiPsky()
{
    // default
    psky_t * const defaultsky = tileSetupSky(DEFAULTPSKY);
    defaultsky->lognumtiles = 1;
    defaultsky->horizfrac = 65536;

    // DAYSKY
    psky_t * const daysky = tileSetupSky(DAYSKY);
    daysky->lognumtiles = 1;
    daysky->horizfrac = 65536;

    // NIGHTSKY
    psky_t * const nightsky = tileSetupSky(NIGHTSKY);
    nightsky->lognumtiles = 3;
    nightsky->horizfrac = 65536;
}

void Ken_PostStartupWindow()
{
    Ken_InitMultiPsky();

    size_t i;
    char tempbuf[256];

    for (i=0; i<256; i++) tempbuf[i] = i;

    for (i=0; i<32; i++) tempbuf[i+192] = i+128; //green->red
    paletteMakeLookupTable(1,tempbuf,0,0,0,1);
    for (i=0; i<32; i++) tempbuf[i+192] = i+32; //green->blue
    paletteMakeLookupTable(2,tempbuf,0,0,0,1);
    for (i=0; i<32; i++) tempbuf[i+192] = i+224; //green->pink
    paletteMakeLookupTable(3,tempbuf,0,0,0,1);
    for (i=0; i<32; i++) tempbuf[i+192] = i+64; //green->brown
    paletteMakeLookupTable(4,tempbuf,0,0,0,1);
    for (i=0; i<32; i++) tempbuf[i+192] = i+96;
    paletteMakeLookupTable(5,tempbuf,0,0,0,1);
    for (i=0; i<32; i++) tempbuf[i+192] = i+160;
    paletteMakeLookupTable(6,tempbuf,0,0,0,1);
    for (i=0; i<32; i++) tempbuf[i+192] = i+192;
    paletteMakeLookupTable(7,tempbuf,0,0,0,1);

    for (i=0; i<256; i++)
        tempbuf[i] = ((i+32)&255);  //remap colors for screwy palette sectors
    paletteMakeLookupTable(16,tempbuf,0,0,0,1);

    for (i=0; i<256; i++) tempbuf[i] = i;
    paletteMakeLookupTable(17,tempbuf,96,96,96,1);

    for (i=0; i<256; i++) tempbuf[i] = i; //(i&31)+32;
    paletteMakeLookupTable(18,tempbuf,32,32,192,1);
}

int32_t voxid_PLAYER = -1, voxid_BROWNMONSTER = -1;

void Ken_LoadVoxels()
{
    if (!qloadkvx(nextvoxid,"voxel000.kvx"))
        voxid_PLAYER = nextvoxid++;
    if (!qloadkvx(nextvoxid,"voxel001.kvx"))
        voxid_BROWNMONSTER = nextvoxid++;
}


code:
#include "compat.h"

extern const char *G_DefaultGrpFile(void);
extern const char *G_GrpFile(void);

void Ken_PostStartupWindow(void);

extern int32_t voxid_PLAYER, voxid_BROWNMONSTER;
void Ken_LoadVoxels(void);


code:
// Evil and Nasty Configuration File Reader for KenBuild
// by Jonathon Fowler

#include "compat.h"
#include "build.h"
#include "editor.h"
#include "osd.h"

#include "game.h"

#include "renderlayer.h"
#include "baselayer.h"

#if defined RENDERTYPESDL && defined SDL_TARGET && SDL_TARGET > 1
# include "sdl_inc.h"
#endif

static void Ken_SetDefaults()
{
#if defined RENDERTYPESDL && SDL_MAJOR_VERSION > 1
    uint32_t inited = SDL_WasInit(SDL_INIT_VIDEO);
    if (inited == 0)
        SDL_Init(SDL_INIT_VIDEO);
    else if (!(inited & SDL_INIT_VIDEO))
        SDL_InitSubSystem(SDL_INIT_VIDEO);

    SDL_DisplayMode dm;
    if (SDL_GetDesktopDisplayMode(0, &dm) == 0)
    {
        xdim = dm.w;
        ydim = dm.h;
    }
    else
#endif
    {
        xdim = 1024;
        ydim = 768;
    }
}

static int vesares[13][2] = {{320,200},{360,200},{320,240},{360,240},{320,400},
                             {360,400},{640,350},{640,400},{640,480},{800,600},
                             {1024,768},{1280,1024},{1600,1200}};

static int readconfig(BFILE *fp, const char *key, char *value, unsigned len)
{
    char buf[1000], *k, *v, *eq;
    int x=0;

    if (len < 1) return 0;

    Brewind(fp);

    while (1)
    {
        if (!Bfgets(buf, 1000, fp)) return 0;

        if (buf[0] == ';') continue;

        eq = Bstrchr(buf, '=');
        if (!eq) continue;

        k = buf;
        v = eq+1;

        while (*k == ' ' || *k == '\t') k++;
        *(eq--) = 0;
        while ((*eq == ' ' || *eq == '\t') && eq>=k) *(eq--) = 0;

        if (Bstrcasecmp(k, key)) continue;

        while (*v == ' ' || *k == '\t') v++;
        eq = v + Bstrlen(v)-1;

        while ((*eq == ' ' || *eq == '\t' || *eq == '\r' || *eq == '\n') && eq>=v) *(eq--) = 0;

        value[--len] = 0;
        do value[x] = v[x]; while (v[x++] != 0 && len-- > 0);

        return x-1;
    }
}

double msens;

/*
 * SETUP.DAT
 * 0      = video mode (0:chained 1:vesa 2:screen buffered 3/4/5:tseng/paradise/s3 6:red-blue)
 * 1      = sound (0:none)
 * 2      = music (0:none)
 * 3      = input (0:keyboard 1:+mouse)
 * 4      = multiplayer (0:single 1-4:com 5-11:ipx)
 * 5&0xf0 = com speed
 * 5&0x0f = com irq
 * 6&0xf0 = chained y-res
 * 6&0x0f = chained x-res or vesa mode
 * 7&0xf0 = sound samplerate
 * 7&0x01 = sound quality
 * 7&0x02 = 8/16 bit
 * 7&0x04 = mono/stereo
 *
 * bytes 8 to 26 are key settings:
 * 0      = Forward (0xc8)
 * 1      = Backward (0xd0)
 * 2      = Turn left (0xcb)
 * 3      = Turn right (0xcd)
 * 4      = Run (0x2a)
 * 5      = Strafe (0x9d)
 * 6      = Fire (0x1d)
 * 7      = Use (0x39)
 * 8      = Stand high (0x1e)
 * 9      = Stand low (0x2c)
 * 10     = Look up (0xd1)
 * 11     = Look down (0xc9)
 * 12     = Strafe left (0x33)
 * 13     = Strafe right (0x34)
 * 14     = 2D/3D switch (0x9c)
 * 15     = View cycle (0x1c)
 * 16     = 2D Zoom in (0xd)
 * 17     = 2D Zoom out (0xc)
 * 18     = Chat (0xf)
 */

int Ken_loadsetup(const char *fn)
{
    Ken_SetDefaults();

    BFILE *fp;
#define VL 32
    char val[VL];
    int i;

    if ((fp = Bfopen(fn, "rt")) == NULL) return -1;

    if (readconfig(fp, "forcesetup", val, VL) > 0) { if (Batoi(val) != 0) forcesetup = 1; else forcesetup = 0; }
    if (readconfig(fp, "fullscreen", val, VL) > 0) { if (Batoi(val) != 0) fullscreen = 1; else fullscreen = 0; }
    if (readconfig(fp, "resolution", val, VL) > 0)
    {
        i = Batoi(val) & 0x0f;
        if ((unsigned)i<13) { xdim = vesares[i][0]; ydim = vesares[i][1]; }
    }
    if (readconfig(fp, "xdim", val, VL) > 0) xdim = Batoi(val);
    if (readconfig(fp, "ydim", val, VL) > 0) ydim = Batoi(val);
    if (readconfig(fp, "samplerate", val, VL) > 0) option[7] = (option[7] & (~(0x0f<<4))) |(Batoi(val) & 0x0f) << 4;
    if (readconfig(fp, "music", val, VL) > 0) { if (Batoi(val) != 0) option[2] = 1; else option[2] = 0; }
    if (readconfig(fp, "mouse", val, VL) > 0) { if (Batoi(val) != 0) option[3] = 1; else option[3] = 0; }
    if (readconfig(fp, "bpp", val, VL) > 0) bppgame = Batoi(val);
    if (readconfig(fp, "renderer", val, VL) > 0) { i = Batoi(val); videoSetRenderMode(i); }
    if (readconfig(fp, "brightness", val, VL) > 0) brightness = min(max(Batoi(val),0),15);

    if (readconfig(fp, "maxrefreshfreq", val, VL) > 0) maxrefreshfreq = Batoi(val);

    option[0] = 1;  // vesa all the way...
    option[1] = 1;  // sound all the way...
    option[4] = 0;  // no multiplayer
    option[5] = 0;

    if (readconfig(fp, "keyforward", val, VL) > 0) keys[0] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keybackward", val, VL) > 0) keys[1] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyturnleft", val, VL) > 0) keys[2] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyturnright", val, VL) > 0) keys[3] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyrun", val, VL) > 0) keys[4] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keystrafe", val, VL) > 0) keys[5] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyfire", val, VL) > 0) keys[6] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyuse", val, VL) > 0) keys[7] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keystandhigh", val, VL) > 0) keys[8] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keystandlow", val, VL) > 0) keys[9] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keylookup", val, VL) > 0) keys[10] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keylookdown", val, VL) > 0) keys[11] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keystrafeleft", val, VL) > 0) keys[12] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keystraferight", val, VL) > 0) keys[13] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "key2dmode", val, VL) > 0) keys[14] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyviewcycle", val, VL) > 0) keys[15] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "key2dzoomin", val, VL) > 0) keys[16] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "key2dzoomout", val, VL) > 0) keys[17] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keychat", val, VL) > 0) keys[18] = Bstrtol(val, NULL, 16);
    if (readconfig(fp, "keyconsole", val, VL) > 0) { keys[19] = Bstrtol(val, NULL, 16); OSD_CaptureKey(keys[19]); }

    if (readconfig(fp, "mousesensitivity", val, VL) > 0) msens = Bstrtod(val, NULL);

    Bfclose(fp);

    return 0;
}

int Ken_writesetup(const char *fn)
{
    BFILE *fp;

    fp = Bfopen(fn,"wt");
    if (!fp) return -1;

    Bfprintf(fp,
             "; Always show configuration options on startup\n"
             ";   0 - No\n"
             ";   1 - Yes\n"
             "forcesetup = %d\n"
             "\n"
             "; Video mode selection\n"
             ";   0 - Windowed\n"
             ";   1 - Fullscreen\n"
             "fullscreen = %d\n"
             "\n"
             "; Video resolution\n"
             "xdim = %d\n"
             "ydim = %d\n"
             "\n"
             "; 3D-mode colour depth\n"
             "bpp = %d\n"
             "\n"
#ifdef USE_OPENGL
             "; OpenGL mode options\n"
             "glusetexcache = %d\n"
             "\n"
#endif
             "; Maximum OpenGL mode refresh rate (Windows only, in Hertz)\n"
             "maxrefreshfreq = %d\n"
             "\n"
             "; 3D mode brightness setting\n"
             ";   0  - lowest\n"
             ";   15 - highest\n"
             "brightness = %d\n"
             "\n"
             "; Sound sample frequency\n"
             ";   0 - 6 KHz\n"
             ";   1 - 8 KHz\n"
             ";   2 - 11.025 KHz\n"
             ";   3 - 16 KHz\n"
             ";   4 - 22.05 KHz\n"
             ";   5 - 32 KHz\n"
             ";   6 - 44.1 KHz\n"
             "samplerate = %d\n"
             "\n"
             "; Music playback\n"
             ";   0 - Off\n"
             ";   1 - On\n"
             "music = %d\n"
             "\n"
             "; Enable mouse\n"
             ";   0 - No\n"
             ";   1 - Yes\n"
             "mouse = %d\n"
             "\n"
             "; Mouse sensitivity\n"
             "mousesensitivity = %g\n"
             "\n"
             "; Key Settings\n"
             ";  Here's a map of all the keyboard scan codes: NOTE: values are listed in hex!\n"
             "; +---------------------------------------------------------------------------------------------+\n"
             "; | 01   3B  3C  3D  3E   3F  40  41  42   43  44  57  58          46                           |\n"
             "; |ESC   F1  F2  F3  F4   F5  F6  F7  F8   F9 F10 F11 F12        SCROLL                         |\n"
             "; |                                                                                |\n"
             "; |29  02  03  04  05  06  07  08  09  0A  0B  0C  0D   0E     D2  C7  C9      45  B5  37  4A   |\n"
             "; | ` '1' '2' '3' '4' '5' '6' '7' '8' '9' '0'  -   =  BACK    INS HOME PGUP  NUMLK KP/ KP* KP-  |\n"
             "; |                                                                                |\n"
             "; | 0F  10  11  12  13  14  15  16  17  18  19  1A  1B  2B     D3  CF  D1      47  48  49  4E   |\n"
             "; |TAB  Q   W   E   R   T   Y   U   I   O   P   [   ]    \\    DEL END PGDN    KP7 KP8 KP9 KP+   |\n"
             "; |                                                                                |\n"
             "; | 3A   1E  1F  20  21  22  23  24  25  26  27  28     1C                     4B  4C  4D       |\n"
             "; |CAPS  A   S   D   F   G   H   J   K   L   ;   '   ENTER                    KP4 KP5 KP6    9C |\n"
             "; |                                                                                KPENTER|\n"
             "; |  2A    2C  2D  2E  2F  30  31  32  33  34  35    36            C8          4F  50  51       |\n"
             "; |LSHIFT  Z   X   C   V   B   N   M   ,   .   /   RSHIFT          UP         KP1 KP2 KP3       |\n"
             "; |                                                                                |\n"
             "; | 1D     38              39                  B8     9D       CB  D0   CD      52    53        |\n"
             "; |LCTRL  LALT           SPACE                RALT   RCTRL   LEFT DOWN RIGHT    KP0    KP.      |\n"
             "; +---------------------------------------------------------------------------------------------+\n"
             "\n"
             "keyforward = %X\n"
             "keybackward = %X\n"
             "keyturnleft = %X\n"
             "keyturnright = %X\n"
             "keyrun = %X\n"
             "keystrafe = %X\n"
             "keyfire = %X\n"
             "keyuse = %X\n"
             "keystandhigh = %X\n"
             "keystandlow = %X\n"
             "keylookup = %X\n"
             "keylookdown = %X\n"
             "keystrafeleft = %X\n"
             "keystraferight = %X\n"
             "key2dmode = %X\n"
             "keyviewcycle = %X\n"
             "key2dzoomin = %X\n"
             "key2dzoomout = %X\n"
             "keychat = %X\n"
             "keyconsole = %X\n"
             "\n",

             forcesetup, fullscreen, xdim, ydim, bppgame,
#ifdef USE_OPENGL
             glusetexcache,
#endif
             maxrefreshfreq,
             brightness, option[7]>>4, option[2],
             option[3], msens,
             keys[0], keys[1], keys[2], keys[3], keys[4], keys[5],
             keys[6], keys[7], keys[8], keys[9], keys[10], keys[11],
             keys[12], keys[13], keys[14], keys[15], keys[16], keys[17],
             keys[18], keys[19]
             );

    Bfclose(fp);

    return 0;
}