code:
/* MegaZeux
 *
 * Copyright (C) 2008 Alan Williams <mralert@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "event.h"
#include "graphics.h"

#include <stdlib.h>
#include <stdio.h>

#define BOOL _BOOL
#include <gcutil.h>
#include <ogc/lwp.h>
#include <ogc/message.h>
#include <ogc/pad.h>
#include <ogc/ipc.h>
#include <ogc/video.h>
#include <ogc/usbmouse.h>
#include <wiikeyboard/keyboard.h>
// Use of anonymous union in wiiuse header
#pragma GCC diagnostic ignored "-pedantic"
#include <wiiuse/wpad.h>
#undef BOOL

#define PTR_BORDER_W 128
#define PTR_BORDER_H 70

#define USB_MOUSE_BTN_LEFT   0x01
#define USB_MOUSE_BTN_RIGHT  0x02
#define USB_MOUSE_BTN_MIDDLE 0x04

#define USB_MOUSE_BTN_MASK (USB_MOUSE_BTN_LEFT | USB_MOUSE_BTN_RIGHT | \
 USB_MOUSE_BTN_MIDDLE)

extern struct input_status input;

enum event_type
{
  EVENT_BUTTON_DOWN,
  EVENT_BUTTON_UP,
  EVENT_AXIS_MOVE,
  EVENT_CHANGE_EXT,
  EVENT_POINTER_MOVE,
  EVENT_POINTER_OUT,
  EVENT_KEY_DOWN,
  EVENT_KEY_UP,
  EVENT_KEY_LOCKS,
  EVENT_MOUSE_MOVE,
  EVENT_MOUSE_BUTTON_DOWN,
  EVENT_MOUSE_BUTTON_UP
};

struct button_event
{
  enum event_type type;
  Uint32 pad;
  Uint32 button;
};

struct axis_event
{
  enum event_type type;
  Uint32 pad;
  Uint32 axis;
  Sint16 pos;
};

struct ext_event
{
  enum event_type type;
  Uint32 pad;
  int ext;
};

struct pointer_event
{
  enum event_type type;
  Sint32 x;
  Sint32 y;
};

struct key_event
{
  enum event_type type;
  Uint32 key;
  Uint16 unicode;
};

struct locks_event
{
  enum event_type type;
  Uint16 locks;
};

struct mouse_move_event
{
  enum event_type type;
  Sint32 dx;
  Sint32 dy;
};

struct mouse_button_event
{
  enum event_type type;
  Uint32 button;
};

union event
{
  enum event_type type;
  struct button_event button;
  struct axis_event axis;
  struct ext_event ext;
  struct pointer_event pointer;
  struct key_event key;
  struct locks_event locks;
  struct mouse_move_event mmove;
  struct mouse_button_event mbutton;
};

#define STACKSIZE 8192
static u8 poll_stack[STACKSIZE];
static lwp_t poll_thread;

#define EVENT_QUEUE_SIZE 64
static mqbox_t eq;
static int eq_inited = 0;

static int pointing = 0;
static int ext_type[4] =
{
  WPAD_EXP_NONE, WPAD_EXP_NONE,
  WPAD_EXP_NONE, WPAD_EXP_NONE
};

static int write_eq(union event *ev)
{
  union event *new_ev;
  new_ev = malloc(sizeof(union event));
  if(!new_ev)
    return false;
  *new_ev = *ev;
  return MQ_Send(eq, (mqmsg_t)(&new_ev), MQ_MSG_NOBLOCK);
}

static int read_eq(union event *ev)
{
  mqmsg_t new_ev = NULL;
  if(MQ_Receive(eq, &new_ev, MQ_MSG_NOBLOCK))
  {
    *ev = *(union event *)new_ev;
    free(new_ev);
    return true;
  }
  else
    return false;
}

static void scan_buttons(Uint32 pad, Uint32 old_btns, Uint32 new_btns)
{
  Uint32 chg_btns;
  union event ev;
  int i;

  if(old_btns != new_btns)
  {
    chg_btns = old_btns ^ new_btns;
    ev.button.pad = pad;
    for(i = 1; i != 0; i <<= 1)
    {
      if(chg_btns & i)
      {
        ev.button.button = i;
        if(new_btns & i)
          ev.type = EVENT_BUTTON_DOWN;
        else
          ev.type = EVENT_BUTTON_UP;
        write_eq(&ev);
      }
    }
  }
}

static Sint16 adjust_axis(Uint8 pos, Uint8 min, Uint8 cen, Uint8 max)
{
  Sint32 temp;
  temp = (pos - cen) * 32767 / ((cen - min) + (max - cen) / 2);
  if(temp < -32767) temp = -32767;
  if(temp > 32767) temp = 32767;
  return temp;
}

static void scan_joystick(Uint32 pad, Uint32 xaxis, joystick_t js, Sint16 axes[])
{
  union event ev;
  Sint16 temp;

  ev.type = EVENT_AXIS_MOVE;
  ev.axis.pad = pad;
  temp = adjust_axis(js.pos.x, js.min.x, js.center.x, js.max.x);
  if(temp != axes[0])
  {
    ev.axis.axis = xaxis;
    ev.axis.pos = temp;
    write_eq(&ev);
    axes[0] = temp;
  }
  temp = -adjust_axis(js.pos.y, js.min.y, js.center.y, js.max.y);
  if(temp != axes[1])
  {
    ev.axis.axis = xaxis + 1;
    ev.axis.pos = temp;
    write_eq(&ev);
    axes[1] = temp;
  }
}

static void poll_input(void)
{
  static Sint32 old_x = 1000, old_y = 1000;
  static Uint32 old_point = 0;
  static Uint32 old_btns[4] = {0};
  static Sint16 old_axes[4][4] = {{0}};
  static int old_type[4] =
  {
    WPAD_EXP_NONE, WPAD_EXP_NONE,
    WPAD_EXP_NONE, WPAD_EXP_NONE
  };
  static Uint32 old_gcbtns[4] = {0};
  static Sint8 old_gcaxes[4][4] = {{0}};
  static Uint16 old_modifiers = 0;
  static Uint8 old_mousebtns = 0;

  WPADData *wd;
  PADStatus pad[4];
  keyboard_event ke;
  mouse_event me;
  u32 type;
  union event ev;
  Uint32 i, j;

  WPAD_ScanPads();
  for(i = 0; i < 4; i++)
  {
    if(WPAD_Probe(i, &type) == WPAD_ERR_NONE)
    {
      wd = WPAD_Data(i);
      if((int)type != old_type[i])
      {
        scan_buttons(i, old_btns[i], 0);
        old_btns[i] = 0;
        ev.type = EVENT_AXIS_MOVE;
        ev.axis.pad = i;
        ev.axis.pos = 0;
        for(j = 0; j < 4; j++)
        {
          if(old_axes[i][j])
          {
            ev.axis.axis = j;
            write_eq(&ev);
            old_axes[i][j] = 0;
          }
        }
        ev.type = EVENT_CHANGE_EXT;
        ev.ext.pad = i;
        old_type[i] = ev.ext.ext = type;
        write_eq(&ev);
      }
      if(i == 0)
      {
        if(wd->ir.valid)
        {
          ev.pointer.x = wd->ir.x - PTR_BORDER_W;
          ev.pointer.y = wd->ir.y - PTR_BORDER_H;
          if (ev.pointer.x < 0)
            ev.pointer.x = 0;
          if (ev.pointer.y < 0)
            ev.pointer.y = 0;
          if (ev.pointer.x >= 640)
            ev.pointer.x = 639;
          if (ev.pointer.y >= 350)
            ev.pointer.y = 349;
          if ((ev.pointer.x != old_x) || (ev.pointer.y != old_y))
          {
            ev.type = EVENT_POINTER_MOVE;
            write_eq(&ev);
            old_point = 1;
            old_x = ev.pointer.x;
            old_y = ev.pointer.y;
          }
        }
        else
        {
          if(old_point)
          {
            ev.type = EVENT_POINTER_OUT;
            write_eq(&ev);
            old_point = 0;
            old_x = old_y = 1000;
          }
        }
      }
      scan_buttons(i, old_btns[i], wd->btns_h);
      old_btns[i] = wd->btns_h;
      switch(type)
      {
        case WPAD_EXP_NUNCHUK:
        {
          scan_joystick(i, 0, wd->exp.nunchuk.js, old_axes[i]);
          break;
        }
        case WPAD_EXP_CLASSIC:
        {
          scan_joystick(i, 0, wd->exp.classic.ljs, old_axes[i]);
          scan_joystick(i, 2, wd->exp.classic.rjs, old_axes[i] + 2);
          break;
        }
        case WPAD_EXP_GUITARHERO3:
        {
          scan_joystick(i, 0, wd->exp.gh3.js, old_axes[i]);
          j = (int)(wd->exp.gh3.whammy_bar * 32767.0);
          if((int)j != old_axes[i][2])
          {
            ev.type = EVENT_AXIS_MOVE;
            ev.axis.pad = i;
            ev.axis.pos = j;
            write_eq(&ev);
          }
          break;
        }
        default: break;
      }
    }
    else
    {
      scan_buttons(i, old_btns[i], 0);
      old_btns[i] = 0;
      ev.type = EVENT_AXIS_MOVE;
      ev.axis.pad = i;
      ev.axis.pos = 0;
      for(j = 0; j < 4; j++)
      {
        if(old_axes[i][j])
        {
          ev.axis.axis = j;
          write_eq(&ev);
          old_axes[i][j] = 0;
        }
      }
    }
  }

  PAD_Read(pad);
  for(i = 0; i < 4; i++)
  {
    if(pad[i].err == PAD_ERR_NONE)
    {
      scan_buttons(i + 4, old_gcbtns[i], pad[i].button);
      old_gcbtns[i] = pad[i].button;
      ev.type = EVENT_AXIS_MOVE;
      ev.axis.pad = i + 4;
      if(pad[i].stickX != old_gcaxes[i][0])
      {
        ev.axis.axis = 0;
        ev.axis.pos = pad[i].stickX << 8;
        write_eq(&ev);
        old_gcaxes[i][0] = pad[i].stickX;
      }
      if(pad[i].stickY != old_gcaxes[i][1])
      {
        ev.axis.axis = 1;
        ev.axis.pos = -(pad[i].stickY << 8);
        write_eq(&ev);
        old_gcaxes[i][1] = pad[i].stickY;
      }
      if(pad[i].substickX != old_gcaxes[i][2])
      {
        ev.axis.axis = 2;
        ev.axis.pos = pad[i].substickX << 8;
        write_eq(&ev);
        old_gcaxes[i][0] = pad[i].substickX;
      }
      if(pad[i].substickY != old_gcaxes[i][3])
      {
        ev.axis.axis = 3;
        ev.axis.pos = -(pad[i].substickY << 8);
        write_eq(&ev);
        old_gcaxes[i][1] = pad[i].substickY;
      }
    }
    else
    {
      scan_buttons(i + 4, old_gcbtns[i], 0);
      old_gcbtns[i] = 0;
      ev.type = EVENT_AXIS_MOVE;
      ev.axis.pad = i + 4;
      ev.axis.pos = 0;
      for(j = 0; j < 4; j++)
      {
        if(old_gcaxes[i][j])
        {
          ev.axis.axis = j;
          write_eq(&ev);
          old_gcaxes[i][j] = 0;
        }
      }
    }
  }

  while(KEYBOARD_GetEvent(&ke))
  {
    ke.modifiers &= MOD_CAPSLOCK | MOD_NUMLOCK;
    if(ke.modifiers != old_modifiers)
    {
      ev.type = EVENT_KEY_LOCKS;
      ev.locks.locks = ke.modifiers;
      write_eq(&ev);
      old_modifiers = ke.modifiers;
    }
    ev.key.key = ke.keycode;
    // Non-character keys mapped to the private use area
    if((ke.symbol >= 0xE000) && (ke.symbol < 0xF900))
      ev.key.unicode = 0;
    else
      ev.key.unicode = ke.symbol;
    switch(ke.type)
    {
      default:
      case KEYBOARD_CONNECTED:
      case KEYBOARD_DISCONNECTED:
        break;
      case KEYBOARD_PRESSED:
        ev.type = EVENT_KEY_DOWN;
        write_eq(&ev);
        break;
      case KEYBOARD_RELEASED:
        ev.type = EVENT_KEY_UP;
        write_eq(&ev);
        break;
    }
  }

  ev.type = EVENT_MOUSE_MOVE;
  ev.mmove.dx = ev.mmove.dy = 0;
  while(MOUSE_GetEvent(&me))
  {
    ev.mmove.dx += me.rx;
    ev.mmove.dy += me.ry;
    me.button &= USB_MOUSE_BTN_MASK;
    if(me.button != old_mousebtns)
    {
      if(ev.mmove.dx || ev.mmove.dy)
        write_eq(&ev);
      for(i = 1; i <= (me.button | old_mousebtns); i <<= 1)
      {
        if(i & (me.button ^ old_mousebtns))
        {
          if(i & me.button)
            ev.type = EVENT_MOUSE_BUTTON_DOWN;
          else
            ev.type = EVENT_MOUSE_BUTTON_UP;
          ev.mbutton.button = i;
          write_eq(&ev);
        }
      }
      old_mousebtns = me.button;
      ev.type = EVENT_MOUSE_MOVE;
      ev.mmove.dx = ev.mmove.dy = 0;
    }
  }
  if(ev.mmove.dx || ev.mmove.dy)
    write_eq(&ev);
}

static void *wii_poll_thread(void *dud)
{
  WPAD_Init();
  WPAD_SetDataFormat(WPAD_CHAN_ALL, WPAD_FMT_BTNS);
  WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
  WPAD_SetVRes(0, 640 + PTR_BORDER_W * 2, 350 + PTR_BORDER_H * 2);

  PAD_Init();

  KEYBOARD_Init(NULL);
  MOUSE_Init();

  while(1)
  {
    VIDEO_WaitVSync();
    poll_input();
  }

  return 0;
}

static Uint32 map_button(Uint32 pad, Uint32 button)
{
  Uint32 rval = 256;
  if(pad < 4)
  {
    switch(button)
    {
      case WPAD_BUTTON_A: rval = 0; break;
      case WPAD_BUTTON_B: rval = 1; break;
      case WPAD_BUTTON_1: rval = 2; break;
      case WPAD_BUTTON_2: rval = 3; break;
      case WPAD_BUTTON_LEFT: rval = 4; break;
      case WPAD_BUTTON_RIGHT: rval = 5; break;
      case WPAD_BUTTON_UP: rval = 6; break;
      case WPAD_BUTTON_DOWN: rval = 7; break;
      case WPAD_BUTTON_MINUS: rval = 8; break;
      case WPAD_BUTTON_PLUS: rval = 9; break;
      default: break;
    }

    switch(ext_type[pad])
    {
      case WPAD_EXP_NONE: break;
      case WPAD_EXP_NUNCHUK:
      {
        switch(button)
        {
          case WPAD_NUNCHUK_BUTTON_C: rval = 10; break;
          case WPAD_NUNCHUK_BUTTON_Z: rval = 11; break;
          default: break;
        }
        rval += 10;
        break;
      }
      case WPAD_EXP_CLASSIC:
      {
        switch(button)
        {
          case WPAD_CLASSIC_BUTTON_A: rval = 10; break;
          case WPAD_CLASSIC_BUTTON_B: rval = 11; break;
          case WPAD_CLASSIC_BUTTON_X: rval = 12; break;
          case WPAD_CLASSIC_BUTTON_Y: rval = 13; break;
          case WPAD_CLASSIC_BUTTON_FULL_L: rval = 14; break;
          case WPAD_CLASSIC_BUTTON_FULL_R: rval = 15; break;
          case WPAD_CLASSIC_BUTTON_ZL: rval = 16; break;
          case WPAD_CLASSIC_BUTTON_ZR: rval = 17; break;
          case WPAD_CLASSIC_BUTTON_LEFT: rval = 18; break;
          case WPAD_CLASSIC_BUTTON_RIGHT: rval = 19; break;
          case WPAD_CLASSIC_BUTTON_UP: rval = 20; break;
          case WPAD_CLASSIC_BUTTON_DOWN: rval = 21; break;
          case WPAD_CLASSIC_BUTTON_MINUS: rval = 22; break;
          case WPAD_CLASSIC_BUTTON_PLUS: rval = 23; break;
          default: break;
        }
        rval += 22;
        break;
      }
      case WPAD_EXP_GUITARHERO3:
      {
        switch(button)
        {
          case WPAD_GUITAR_HERO_3_BUTTON_GREEN: rval = 10; break;
          case WPAD_GUITAR_HERO_3_BUTTON_RED: rval = 11; break;
          case WPAD_GUITAR_HERO_3_BUTTON_YELLOW: rval = 12; break;
          case WPAD_GUITAR_HERO_3_BUTTON_BLUE: rval = 13; break;
          case WPAD_GUITAR_HERO_3_BUTTON_ORANGE: rval = 14; break;
          case WPAD_GUITAR_HERO_3_BUTTON_STRUM_UP: rval = 15; break;
          case WPAD_GUITAR_HERO_3_BUTTON_STRUM_DOWN: rval = 16; break;
          case WPAD_GUITAR_HERO_3_BUTTON_MINUS: rval = 17; break;
          case WPAD_GUITAR_HERO_3_BUTTON_PLUS: rval = 18; break;
          default: break;
        }
        rval += 46;
        break;
      }
      default:
        rval = 256; // Unsupported extension controller
        break;
    }
  }
  else
  {
    switch(button)
    {
      case PAD_BUTTON_A: rval = 0; break;
      case PAD_BUTTON_B: rval = 1; break;
      case PAD_BUTTON_X: rval = 2; break;
      case PAD_BUTTON_Y: rval = 3; break;
      case PAD_TRIGGER_L: rval = 4; break;
      case PAD_TRIGGER_R: rval = 5; break;
      case PAD_TRIGGER_Z: rval = 6; break;
      case PAD_BUTTON_LEFT: rval = 7; break;
      case PAD_BUTTON_RIGHT: rval = 8; break;
      case PAD_BUTTON_UP: rval = 9; break;
      case PAD_BUTTON_DOWN: rval = 10; break;
      case PAD_BUTTON_START: rval = 11; break;
      default: break;
    }
  }

  if (rval < 256)
    return rval;
  else
    return 256;
}

static enum keycode convert_USB_internal(Uint32 key)
{
  switch(key)
  {
    case 0x04: return IKEY_a;
    case 0x05: return IKEY_b;
    case 0x06: return IKEY_c;
    case 0x07: return IKEY_d;
    case 0x08: return IKEY_e;
    case 0x09: return IKEY_f;
    case 0x0A: return IKEY_g;
    case 0x0B: return IKEY_h;
    case 0x0C: return IKEY_i;
    case 0x0D: return IKEY_j;
    case 0x0E: return IKEY_k;
    case 0x0F: return IKEY_l;
    case 0x10: return IKEY_m;
    case 0x11: return IKEY_n;
    case 0x12: return IKEY_o;
    case 0x13: return IKEY_p;
    case 0x14: return IKEY_q;
    case 0x15: return IKEY_r;
    case 0x16: return IKEY_s;
    case 0x17: return IKEY_t;
    case 0x18: return IKEY_u;
    case 0x19: return IKEY_v;
    case 0x1A: return IKEY_w;
    case 0x1B: return IKEY_x;
    case 0x1C: return IKEY_y;
    case 0x1D: return IKEY_z;
    case 0x1E: return IKEY_1;
    case 0x1F: return IKEY_2;
    case 0x20: return IKEY_3;
    case 0x21: return IKEY_4;
    case 0x22: return IKEY_5;
    case 0x23: return IKEY_6;
    case 0x24: return IKEY_7;
    case 0x25: return IKEY_8;
    case 0x26: return IKEY_9;
    case 0x27: return IKEY_0;
    case 0x28: return IKEY_RETURN;
    case 0x29: return IKEY_ESCAPE;
    case 0x2A: return IKEY_BACKSPACE;
    case 0x2B: return IKEY_TAB;
    case 0x2C: return IKEY_SPACE;
    case 0x2D: return IKEY_MINUS;
    case 0x2E: return IKEY_EQUALS;
    case 0x2F: return IKEY_LEFTBRACKET;
    case 0x30: return IKEY_RIGHTBRACKET;
    case 0x31: return IKEY_BACKSLASH;
    case 0x33: return IKEY_SEMICOLON;
    case 0x34: return IKEY_QUOTE;
    case 0x35: return IKEY_BACKQUOTE;
    case 0x36: return IKEY_COMMA;
    case 0x37: return IKEY_PERIOD;
    case 0x38: return IKEY_SLASH;
    case 0x39: return IKEY_CAPSLOCK;
    case 0x3A: return IKEY_F1;
    case 0x3B: return IKEY_F2;
    case 0x3C: return IKEY_F3;
    case 0x3D: return IKEY_F4;
    case 0x3E: return IKEY_F5;
    case 0x3F: return IKEY_F6;
    case 0x40: return IKEY_F7;
    case 0x41: return IKEY_F8;
    case 0x42: return IKEY_F9;
    case 0x43: return IKEY_F10;
    case 0x44: return IKEY_F11;
    case 0x45: return IKEY_F12;
    case 0x46: return IKEY_SYSREQ;
    case 0x47: return IKEY_SCROLLOCK;
    case 0x48: return IKEY_BREAK;
    case 0x49: return IKEY_INSERT;
    case 0x4A: return IKEY_HOME;
    case 0x4B: return IKEY_PAGEUP;
    case 0x4C: return IKEY_DELETE;
    case 0x4D: return IKEY_END;
    case 0x4E: return IKEY_PAGEDOWN;
    case 0x4F: return IKEY_RIGHT;
    case 0x50: return IKEY_LEFT;
    case 0x51: return IKEY_DOWN;
    case 0x52: return IKEY_UP;
    case 0x53: return IKEY_NUMLOCK;
    case 0x54: return IKEY_KP_DIVIDE;
    case 0x55: return IKEY_KP_MULTIPLY;
    case 0x56: return IKEY_KP_MINUS;
    case 0x57: return IKEY_KP_PLUS;
    case 0x58: return IKEY_KP_ENTER;
    case 0x59: return IKEY_KP1;
    case 0x5A: return IKEY_KP2;
    case 0x5B: return IKEY_KP3;
    case 0x5C: return IKEY_KP4;
    case 0x5D: return IKEY_KP5;
    case 0x5E: return IKEY_KP6;
    case 0x5F: return IKEY_KP7;
    case 0x60: return IKEY_KP8;
    case 0x61: return IKEY_KP9;
    case 0x62: return IKEY_KP0;
    case 0x63: return IKEY_KP_PERIOD;
    case 0x65: return IKEY_MENU;
    case 0xE0: return IKEY_LCTRL;
    case 0xE1: return IKEY_LSHIFT;
    case 0xE2: return IKEY_LALT;
    case 0xE3: return IKEY_LSUPER;
    case 0xE4: return IKEY_RCTRL;
    case 0xE5: return IKEY_RSHIFT;
    case 0xE6: return IKEY_RALT;
    case 0xE7: return IKEY_RSUPER;
    default: return IKEY_UNKNOWN;
  }
}

static bool process_event(union event *ev)
{
  struct buffered_status *status = store_status();
  bool rval = true;

  switch(ev->type)
  {
    case EVENT_BUTTON_DOWN:
    {
      Uint32 button = map_button(ev->button.pad, ev->button.button);
      rval = false;
      if((ev->button.pad == 0) && pointing)
      {
        Uint32 mousebutton;
        switch(ev->button.button)
        {
          case WPAD_BUTTON_A: mousebutton = MOUSE_BUTTON_LEFT; break;
          case WPAD_BUTTON_B: mousebutton = MOUSE_BUTTON_RIGHT; break;
          default: mousebutton = 0; break;
        }
        if(mousebutton)
        {
          status->mouse_button = mousebutton;
          status->mouse_repeat = mousebutton;
          status->mouse_button_state |= MOUSE_BUTTON(mousebutton);
          status->mouse_repeat_state = 1;
          status->mouse_drag_state = -1;
          status->mouse_time = get_ticks();
          button = 256;
          rval = true;
        }
      }
      if((button < 256))
      {
        enum keycode skey = input.joystick_button_map[ev->button.pad][button];
        if(skey && (status->keymap[skey] == 0))
        {
          key_press(status, skey, skey);
          rval = true;
        }
      }
      else
      {
        if((ev->button.pad < 4) && ((ev->button.button == WPAD_BUTTON_HOME) ||
         ((ext_type[ev->button.pad] == WPAD_EXP_CLASSIC) &&
         (ev->button.button == WPAD_CLASSIC_BUTTON_HOME))))
        {
          status->keymap[IKEY_ESCAPE] = 1;
          status->key = IKEY_ESCAPE;
          status->keypress_time = get_ticks();
          rval = true;
          break;
        }
      }
      break;
    }
    case EVENT_BUTTON_UP:
    {
      Uint32 button = map_button(ev->button.pad, ev->button.button);
      rval = false;
      if((ev->button.pad == 0) && status->mouse_button_state)
      {
        Uint32 mousebutton;
        switch(ev->button.button)
        {
          case WPAD_BUTTON_A: mousebutton = MOUSE_BUTTON_LEFT; break;
          case WPAD_BUTTON_B: mousebutton = MOUSE_BUTTON_RIGHT; break;
          default: mousebutton = 0; break;
        }
        if(mousebutton &&
         (status->mouse_button_state & MOUSE_BUTTON(mousebutton)))
        {
          status->mouse_button_state &= ~MOUSE_BUTTON(mousebutton);
          status->mouse_repeat = 0;
          status->mouse_drag_state = 0;
          status->mouse_repeat_state = 0;
          button = 256;
          rval = true;
        }
      }
      if((button < 256))
      {
        enum keycode skey = input.joystick_button_map[ev->button.pad][button];
        if(skey)
        {
          key_release(status, skey);
          rval = true;
        }
      }
      break;
    }
    case EVENT_AXIS_MOVE:
    {
      int digital_value = -1;
      int axis = ev->axis.axis;
      int last_axis;
      enum keycode skey;
      if(ev->axis.pad < 4)
      {
        switch(ext_type[ev->axis.pad])
        {
          case WPAD_EXP_NUNCHUK: break;
          case WPAD_EXP_CLASSIC: axis += 2; break;
          case WPAD_EXP_GUITARHERO3: axis += 6; break;
          default: axis = 256; break; // Not supposed to happen
        }
      }
      if(axis == 256) break;
      last_axis = status->axis[ev->axis.pad][axis];

      if(ev->axis.pos > 10000)
        digital_value = 1;
      else if(ev->axis.pos < -10000)
        digital_value = 0;

      if(digital_value != -1)
      {
        skey = input.joystick_axis_map[ev->axis.pad][axis][digital_value];
        if(skey)
        {
          if(status->keymap[skey] == 0)
            key_press(status, skey, skey);

          if(last_axis == (digital_value ^ 1))
          {
            skey = input.joystick_axis_map[ev->axis.pad][axis][last_axis];
            key_release(status, skey);
          }
        }
      }
      else
      {
        if(last_axis != -1)
        {
          skey = input.joystick_axis_map[ev->axis.pad][axis][last_axis];
          if(skey)
            key_release(status, skey);
        }
      }
      status->axis[ev->axis.pad][axis] = digital_value;
      break;
    }
    case EVENT_CHANGE_EXT:
    {
      ext_type[ev->ext.pad] = ev->ext.ext;
      break;
    }
    case EVENT_POINTER_MOVE:
    {
      pointing = 1;
      status->mouse_moved = true;
      status->real_mouse_x = ev->pointer.x;
      status->real_mouse_y = ev->pointer.y;
      status->mouse_x = ev->pointer.x / 8;
      status->mouse_y = ev->pointer.y / 14;
      break;
    }
    case EVENT_POINTER_OUT:
    {
      pointing = 0;
      break;
    }
    case EVENT_KEY_DOWN:
    {
      enum keycode ckey = convert_USB_internal(ev->key.key);
      if(!ckey)
      {
        if(ev->key.unicode)
          ckey = IKEY_UNICODE;
        else
        {
          rval = false;
          break;
        }
      }

      if((ckey == IKEY_RETURN) &&
       get_alt_status(keycode_internal) &&
       get_ctrl_status(keycode_internal))
      {
        toggle_fullscreen();
        break;
      }

      if(ckey == IKEY_F12)
      {
        dump_screen();
        break;
      }

      if(status->key_repeat &&
       (status->key_repeat != IKEY_LSHIFT) &&
       (status->key_repeat != IKEY_RSHIFT) &&
       (status->key_repeat != IKEY_LALT) &&
       (status->key_repeat != IKEY_RALT) &&
       (status->key_repeat != IKEY_LCTRL) &&
       (status->key_repeat != IKEY_RCTRL))
      {
        // Stack current repeat key if it isn't shift, alt, or ctrl
        if(input.repeat_stack_pointer != KEY_REPEAT_STACK_SIZE)
        {
          input.key_repeat_stack[input.repeat_stack_pointer] =
           status->key_repeat;
          input.unicode_repeat_stack[input.repeat_stack_pointer] =
           status->unicode_repeat;
          input.repeat_stack_pointer++;
        }
      }

      key_press(status, ckey, ev->key.unicode);
      break;
    }
    case EVENT_KEY_UP:
    {
      enum keycode ckey = convert_USB_internal(ev->key.key);
      if(!ckey)
      {
        if(status->keymap[IKEY_UNICODE])
          ckey = IKEY_UNICODE;
        else
        {
          rval = false;
          break;
        }
      }

      status->keymap[ckey] = 0;
      if(status->key_repeat == ckey)
      {
        status->key_repeat = IKEY_UNKNOWN;
        status->unicode_repeat = 0;
      }
      status->key_release = ckey;
      break;
    }
    case EVENT_KEY_LOCKS:
    {
      status->numlock_status = !!(ev->locks.locks & MOD_NUMLOCK);
      status->caps_status = !!(ev->locks.locks & MOD_CAPSLOCK);
      break;
    }
    case EVENT_MOUSE_MOVE:
    {
      int mx = status->real_mouse_x + ev->mmove.dx;
      int my = status->real_mouse_y + ev->mmove.dy;

      if(mx < 0)
        mx = 0;
      if(my < 0)
        my = 0;
      if(mx >= 640)
        mx = 639;
      if(my >= 350)
        my = 349;

      status->real_mouse_x = mx;
      status->real_mouse_y = my;
      status->mouse_x = mx / 8;
      status->mouse_y = my / 14;
      status->mouse_moved = true;
      break;
    }
    case EVENT_MOUSE_BUTTON_DOWN:
    {
      Uint32 button = 0;
      switch (ev->mbutton.button)
      {
        case USB_MOUSE_BTN_LEFT:
          button = MOUSE_BUTTON_LEFT;
          break;
        case USB_MOUSE_BTN_RIGHT:
          button = MOUSE_BUTTON_RIGHT;
          break;
        case USB_MOUSE_BTN_MIDDLE:
          button = MOUSE_BUTTON_MIDDLE;
          break;
        default:
          break;
      }

      if(!button)
        break;

      status->mouse_button = button;
      status->mouse_repeat = button;
      status->mouse_button_state |= MOUSE_BUTTON(button);
      status->mouse_repeat_state = 1;
      status->mouse_drag_state = -1;
      status->mouse_time = get_ticks();
      break;
    }
    case EVENT_MOUSE_BUTTON_UP:
    {
      Uint32 button = 0;
      switch (ev->mbutton.button)
      {
        case USB_MOUSE_BTN_LEFT:
          button = MOUSE_BUTTON_LEFT;
          break;
        case USB_MOUSE_BTN_RIGHT:
          button = MOUSE_BUTTON_RIGHT;
          break;
        case USB_MOUSE_BTN_MIDDLE:
          button = MOUSE_BUTTON_MIDDLE;
          break;
        default:
          break;
      }

      if(!button)
        break;

      status->mouse_button_state &= ~MOUSE_BUTTON(button);
      status->mouse_repeat = 0;
      status->mouse_drag_state = 0;
      status->mouse_repeat_state = 0;
      break;
    }
    default:
    {
      rval = false;
      break;
    }
  }

  return rval;
}

bool __update_event_status(void)
{
  bool rval = false;
  union event ev;

  if(!eq_inited)
    return false;

  while(read_eq(&ev))
    rval |= process_event(&ev);

  return rval;
}

void __wait_event(void)
{
  mqmsg_t ev;

  if(!eq_inited)
    return;

  if(MQ_Receive(eq, &ev, MQ_MSG_BLOCK))
  {
    process_event((union event *)ev);
    free(ev);
  }
}

void real_warp_mouse(Uint32 x, Uint32 y)
{
  // Mouse warping doesn't work too well with the Wiimote
}

void initialize_joysticks(void)
{
  MQ_Init(&eq, EVENT_QUEUE_SIZE);
  eq_inited = 1;
  LWP_CreateThread(&poll_thread, wii_poll_thread, NULL, poll_stack, STACKSIZE,
   40);
}


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1">
	<name>MegaZeux</name>
	<version>%VERSION%</version>
	<release_date>%DATE%</release_date>
	<short_description>A simple game creation system (GCS)</short_description>
	<long_description>MegaZeux is a Game Creation System (GCS), inspired by
	Epic MegaGames' ZZT, first released by Gregory Janson in 1994. It was
	recently ported from 16bit MSDOS C/ASM to portable C/C++, improving its
	platform support and hardware compatibility.
	Many features have been added since the original DOS version, and with
	the help of an intuitive editor and a simple but powerful
	object-oriented programming language, MegaZeux allows you to create your
	own ANSI-esque games regardless of genre. It is actively maintained by a
	thriving community.
	See http://digitalmzx.net/ for more information.</long_description>
</app>

repo_name: pgimeno/megazeux

license: mit


code:
/* MegaZeux
 *
 * Copyright (C) 2008 Alan Williams <mralert@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef __MUTEX_WII_H
#define __MUTEX_WII_H

#include "compat.h"

__M_BEGIN_DECLS

#define BOOL _BOOL
#include <ogc/mutex.h>
#undef BOOL

typedef mutex_t platform_mutex;

static inline void platform_mutex_init(platform_mutex *mutex)
{
  // FIXME: Okay to ignore retval?
  LWP_MutexInit(mutex, false);
}

static inline bool platform_mutex_lock(platform_mutex *mutex)
{
  if(LWP_MutexLock(*mutex))
    return false;
  return true;
}

static inline bool platform_mutex_unlock(platform_mutex *mutex)
{
  if(LWP_MutexUnlock(*mutex))
    return false;
  return true;
}

__M_END_DECLS

#endif // __MUTEX_WII_H


code:
### Wiimotes (1 to 4) ###

# The button mappings differ depending on the extension controller attached.
#
# Button      None  Nunchuk  Classic  Guitar Hero 3
# ---------------------------------------------------
# A           1     11       23       47
# B           2     12       24       48
# 1           3     13       25       49
# 2           4     14       26       50
# Left        5     15       27       51
# Right       6     16       28       52
# Up          7     17       29       53
# Down        8     18       30       54
# Minus       9     19       31       55
# Plus        10    20       32       56
#
# C           -     21       -        -
# Z           -     22       -        -
#
# a           -     -        33       -
# b           -     -        34       -
# x           -     -        35       -
# y           -     -        36       -
# L           -     -        37       -
# R           -     -        38       -
# ZL          -     -        39       -
# ZR          -     -        40       -
# Left        -     -        41       -
# Right       -     -        42       -
# Up          -     -        43       -
# Down        -     -        44       -
# Select      -     -        45       -
# Start       -     -        46       -
#
# Green       -     -        -        57
# Red         -     -        -        58
# Yellow      -     -        -        59
# Blue        -     -        -        60
# Orange      -     -        -        61
# Strum Up    -     -        -        62
# Strum Down  -     -        -        63
# Minus       -     -        -        64
# Plus        -     -        -        65
#
# The home buttons on the Wiimote and the Classic Controller are currently
# hardcoded to the escape key.
#
# 1/2 Nunchuk
# 3/4 Classic L
# 5/6 Classic R
# 7/8 Guitar stick
# 9   Guitar whammy bar (positive only)

# None
joy1button1 = 284
joy1button2 = 285
joy1button3 = 13
joy1button4 = 32
joy1button5 = 274
joy1button6 = 273
joy1button7 = 276
joy1button8 = 275
joy1button9 = 115
joy1button10 = 112

# Nunchuk
joy1axis1 = 276, 275
joy1axis2 = 273, 274
joy1button11 = 32
joy1button12 = 13
joy1button13 = 284
joy1button14 = 285
joy1button15 = 276
joy1button16 = 275
joy1button17 = 273
joy1button18 = 274
joy1button19 = 115
joy1button20 = 112
joy1button21 = 127
joy1button22 = 32

# Classic
joy1axis3 = 276, 275
joy1axis4 = 273, 274
joy1axis5 = 276, 275
joy1axis6 = 273, 274
joy1button33 = 32
joy1button34 = 13
joy1button35 = 115
joy1button36 = 127
joy1button37 = 284
joy1button38 = 285
joy1button39 = 27
joy1button40 = 27
joy1button41 = 276
joy1button42 = 275
joy1button43 = 273
joy1button44 = 274
joy1button45 = 27
joy1button46 = 112

# Guitar Hero 3
joy1axis7 = 276, 275
joy1axis8 = 273, 274
joy1axis9 = 0, 127
joy1button57 = 32
joy1button58 = 13
joy1button59 = 115
joy1button60 = 284
joy1button61 = 285
joy1button62 = 273
joy1button63 = 274
joy1button64 = 27
joy1button65 = 112

### GameCube controllers (5 to 8) ###

#  1 A
#  2 B
#  3 X
#  4 Y
#  5 L
#  6 R
#  7 Z
#  8 Left
#  9 Right
# 10 Up
# 11 Down
# 12 Start/Pause

# 1/2 Analog stick
# 3/4 C stick

joy5axis1 = 276, 275
joy5axis2 = 273, 274
joy5axis3 = 276, 275
joy5axis4 = 273, 274
joy5button1 = 32
joy5button2 = 13
joy5button3 = 115
joy5button4 = 127
joy5button5 = 284
joy5button6 = 285
joy5button7 = 27
joy5button8 = 276
joy5button9 = 275
joy5button10 = 273
joy5button11 = 274
joy5button12 = 112


code:
/* MegaZeux
 *
 * Copyright (C) 2008 Alan Williams <mralert@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "../../src/platform.h"
#undef main

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include <sys/iosupport.h>

#define BOOL _BOOL
#include <ogc/system.h>
#include <ogc/lwp.h>
#include <ogc/lwp_threads.h>
#include <ogc/lwp_watchdog.h>
#include <fat.h>
#undef BOOL

#define STACKSIZE 8192

static lwpq_t reset_queue;
static lwp_t reset_thread;
static u8 reset_stack[STACKSIZE];

void c_default_exceptionhandler(frame_context *pCtx);

// Emergency exit
static void *wii_reset_thread(void *dud)
{
  LWP_ThreadSleep(reset_queue);
  platform_quit();
  delay(1000);
  c_default_exceptionhandler(&_thr_main->context);
  exit(0);
  return 0;
}

static void reset_callback(void)
{
  static volatile int callcount = 0;
  callcount++;
  if(callcount > 5)
    *(int *)NULL = 0xDEADCAFE; // Try to cause an exception if pressed 6 times
  LWP_ThreadSignal(reset_queue);
}

static u64 timebase_offset;

void delay(Uint32 ms)
{
  u64 end = gettime() - timebase_offset + millisecs_to_ticks(ms);
  while (gettime() - timebase_offset < end);
}

Uint32 get_ticks(void)
{
  return ticks_to_millisecs(gettime() - timebase_offset);
}

bool platform_init(void)
{
  timebase_offset = gettime();

  LWP_InitQueue(&reset_queue);
  LWP_CreateThread(&reset_thread, wii_reset_thread, NULL, reset_stack,
   STACKSIZE, 127);
  SYS_SetResetCallback(reset_callback);

  if(!fatInitDefault())
    return false;

  return true;
}

void platform_quit(void)
{
  int i;

  for(i = 0; i < STD_MAX; i++)
    if(devoptab_list[i] && devoptab_list[i]->chdir_r)
      fatUnmount(devoptab_list[i]->name);
}

// argc may be 0 if the loader doesn't set args
int main(int argc, char *argv[])
{
  static char _argv0[] = SHAREDIR "megazeux";
  static char *_argv[] = {_argv0};

  if(!argc)
    real_main(1, _argv);
  else
    real_main(argc, argv);
}


code:
ifeq (${SUBARCH},)
SUBARCH := ${SUBPLATFORM}
endif

archive: build
	${RM} -r build/dist/${SUBPLATFORM}
	${MKDIR} -p build/dist/${SUBPLATFORM}
	@cd build/${SUBPLATFORM} && \
	 7za a -tzip ../dist/${SUBPLATFORM}/${TARGET}-${SUBARCH}.zip *


code:
varying vec3 vColor;

void main(void)
{
  gl_FragColor = vec4(vColor.x, vColor.y, vColor.z, 1.0);
}


code:
attribute vec2 Position;
attribute vec3 Color;

varying vec3 vColor;

void main(void)
{
    gl_Position = vec4(Position.x, Position.y, 0.0, 1.0);
    vColor = Color;
}


code:
These are alternative scaler fragment shaders which you can use instead
of the default. Simply replace "scaler.frag" in the directory above with
one of the files in this directory.

--ajs.


code:
uniform sampler2D baseMap;

varying vec2 vTexcoord;

void main( void )
{
    gl_FragColor = texture2D( baseMap, vec2(vTexcoord.x, vTexcoord.y))*2 - texture2D( baseMap, vec2(vTexcoord.x - 0.0005, vTexcoord.y + 0.0007))*2 + texture2D( baseMap, vec2(vTexcoord.x + 0.0006, vTexcoord.y - 0.001));

}


code:
uniform sampler2D baseMap;

varying vec2 vTexcoord;
#define XS 1024.0
#define YS 512.0
#define AX1 -0.5/XS
#define AY1 -0.5/YS
#define AX2 0.5/XS
#define AY2 0.5/YS
#define POW 7.5
#define PADD 0.0000002
#define XBLUR1 -0.5/XS
#define YBLUR1 -0.5/YS
#define XBLUR2 0.5/XS
#define YBLUR2 0.5/YS
#define XBLUR3 -.5/XS
#define YBLUR3 -.5/YS
#define XBLUR4 .5/XS
#define YBLUR4 .5/YS
#define F1 8.0
#define F2 0.0
#define F3 0.0
#define F4 0.0
#define F5 7.0
#define F6 0.0
#define F7 0.0
#define F8 -2.0
#define F9 0.0
#define FT 13.0
void main( void )
{

   vec4 c = (texture2D( baseMap, vTexcoord+vec2(((XBLUR1+XBLUR2)/2.0), (YBLUR1+YBLUR2)/2.0)) *F5 +
               /*texture2D( baseMap, vTexcoord+vec2(((XBLUR1+XBLUR2)/2.0), YBLUR1))              *F2 +*/
             texture2D( baseMap, vTexcoord+vec2(((XBLUR1+XBLUR2)/2.0), YBLUR2))              *F8 +
               /*texture2D( baseMap, vTexcoord+vec2(XBLUR1,                (YBLUR1+YBLUR2)/2.0)) *F4 +*/
               /*texture2D( baseMap, vTexcoord+vec2(XBLUR2,                (YBLUR1+YBLUR2)/2.0)) *F6 +*/
             texture2D( baseMap, vTexcoord+vec2(XBLUR3,                YBLUR3))              *F1
               /*texture2D( baseMap, vTexcoord+vec2(XBLUR4,                YBLUR3))              *F3 +*/
               /*texture2D( baseMap, vTexcoord+vec2(XBLUR3,                YBLUR4))              *F7 +*/
               /*texture2D( baseMap, vTexcoord+vec2(XBLUR4,                YBLUR4))              *F9  */
													)/FT;
   float d1, d2, d3, d4, dt, w1, w2, w3, w4, wt;
   vec4 final;
   vec4 c1 = texture2D( baseMap, vec2(floor(vTexcoord.x*XS)/XS+AX1,
floor(vTexcoord.y*YS)/YS+AY1));
   vec4 c2 = texture2D( baseMap, vec2(floor(vTexcoord.x*XS)/XS+AX2,
floor(vTexcoord.y*YS)/YS+AY1));
   vec4 c3 = texture2D( baseMap, vec2(floor(vTexcoord.x*XS)/XS+AX1,
floor(vTexcoord.y*YS)/YS+AY2));
   vec4 c4 = texture2D( baseMap, vec2(floor(vTexcoord.x*XS)/XS+AX2,
floor(vTexcoord.y*YS)/YS+AY2));
   d1 = (c1.x - c.x)*(c1.x - c.x) + (c1.y - c.y)*(c1.y - c.y) + (c1.z - c.z)*(c1.z - c.z);
   d2 = (c2.x - c.x)*(c2.x - c.x) + (c2.y - c.y)*(c2.y - c.y) + (c2.z - c.z)*(c2.z - c.z);
   d3 = (c3.x - c.x)*(c3.x - c.x) + (c3.y - c.y)*(c3.y - c.y) + (c3.z - c.z)*(c3.z - c.z);
   d4 = (c4.x - c.x)*(c4.x - c.x) + (c4.y - c.y)*(c4.y - c.y) + (c4.z - c.z)*(c4.z - c.z);
   dt = d1+d2+d3+d4;
   w1 = pow(dt-d1, POW)+PADD;
   w2 = pow(dt-d2, POW)+PADD;
   w3 = pow(dt-d3, POW)+PADD;
   w4 = pow(dt-d4, POW)+PADD;
   wt = w1+w2+w3+w4;
   final = ((c1*w1 + c2*w2 + c3*w3 + c4*w4) / wt);
   gl_FragColor = final;

}


code:
uniform sampler2D baseMap;

varying vec2 vTexcoord;
#define XS 1024.0
#define YS 512.0
#define AX 0.5/XS
#define AY 0.5/YS
void main( void )
{
    gl_FragColor = texture2D( baseMap, vec2(floor(vTexcoord.x*XS)/XS+AX, floor(vTexcoord.y*YS)/YS+AY));
}


code:
uniform sampler2D baseMap;

varying vec2 vTexcoord;

void main( void )
{
    gl_FragColor = texture2D( baseMap, vTexcoord );
}


code:
void main(void)
{
  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}


code:
attribute vec2 Position;

void main(void)
{
    gl_Position = vec4(Position.x, Position.y, 0.0, 1.0);
}


code:
attribute vec2 Position;
attribute vec2 Texcoord;

varying vec2 vTexcoord;

void main(void)
{
    gl_Position = vec4(Position.x, Position.y, 0.0, 1.0);
    vTexcoord = Texcoord;
}


code:
uniform sampler2D baseMap;

varying vec2 vTexcoord;

void main( void )
{
    vec4 tileinfo = texture2D( baseMap, vec2(vTexcoord.x, (vTexcoord.y+225.0)/256.0));
    if(texture2D(baseMap, vec2(fract(tileinfo.z*7.96875) + (fract(vTexcoord.x*256.0)*0.03125), (floor(tileinfo.z*7.9689) + fract(vTexcoord.y) + tileinfo.w*2048.0) * 0.0546875)).x > 0.5)
    {
      gl_FragColor = texture2D( baseMap, vec2(tileinfo.x, 224.0/256.0));
    }
    else
    {
      gl_FragColor = texture2D( baseMap, vec2(tileinfo.y, 224.0/256.0));
    }
}


code:
uniform sampler2D baseMap;

varying vec2 vTexcoord;

void main( void )
{
    vec4 tileinfo = texture2D( baseMap, vec2(vTexcoord.x, (vTexcoord.y+225.0)/256.0));
    bool b1 = (texture2D(baseMap, vec2(tileinfo.z*7.96875 + (mod(vTexcoord.x - mod(vTexcoord.x, 0.0009765625), 0.00390625)*8.0), (floor(tileinfo.z*7.9689) + mod(vTexcoord.y, 1.0) + tileinfo.w*2048.0) * 0.0546875)).x > 0.5);
    bool b2 = (texture2D(baseMap, vec2(0.00390625 + tileinfo.z*7.96875 + (mod(vTexcoord.x - mod(vTexcoord.x, 0.0009765625), 0.00390625)*8.0), (floor(tileinfo.z*7.9689) + mod(vTexcoord.y, 1.0) + tileinfo.w*2048.0) * 0.0546875)).x > 0.5);

        float cval;

    if(b2)
    {
        if(b1)
        {
            cval = 3.0/256.0;
        }
        else
        {
            cval = 2.0/256.0;
        }
    }
    else
    {
        if(b1)
        {
            cval = 1.0/256.0;
        }
        else
        {
            cval = 0.0;
        }
    }

        gl_FragColor = texture2D( baseMap, vec2(mod(tileinfo.x, 16.0627/256.0) + mod(tileinfo.y, 16.0627/256.0) * 15.9999 + cval, 224.0/256.0));
}


code:
#!/bin/sh

### CONFIG.SH HELP TEXT #######################################################

usage() {
	echo "usage: ./config.sh --platform [platform] <--prefix [dir]> <--sysconfdir [dir]>"
	echo "                                         <--gamesdir [dir]> <--bindir [dir]>"
	echo "                                         <--sharedir [dir]> <options..>"
	echo
	echo "  --prefix       Where dependencies should be found."
	echo "  --sysconfdir   Where the config should be read from."
	echo "  --gamesdir     Where binaries should be installed."
	echo "  --bindir       Where utilities should be installed."
	echo "  --sharedir     Where resources should be installed."
	echo
	echo "Supported [platform] values:"
	echo
	echo "  win32          Microsoft Windows (x86)"
	echo "  win64          Microsoft Windows (x64)"
	echo "  mingw32        Use MinGW32 on Linux, to build for win32"
	echo "  mingw64        Use MinGW64 on Linux, to build for win64"
	echo "  unix           Unix-like / Linux / Solaris / BSD / Embedded"
	echo "  unix-devel     As above, but for running from current dir"
	echo "  darwin         Macintosh OS X (not Classic)"
	echo "  psp            Experimental PSP port"
	echo "  gp2x           Experimental GP2X port"
	echo "  nds            Experimental NDS port"
	echo "  wii            Experimental Wii port"
	echo "  amiga          Experimental AmigaOS 4 port"
	echo "  android        Experimental Android port"
	echo "  pandora        Experimental Pandora port"
	echo
	echo "Supported <option> values (negatives can be used):"
	echo
	echo "  --as-needed-hack      Pass --as-needed through to GNU ld."
	echo "  --enable-release      Optimize and remove debugging code."
	echo "  --enable-verbose      Build system is always verbose (V=1)."
	echo "  --optimize-size       Perform size optimizations (-Os)."
	echo "  --disable-datestamp   Disable adding date to version."
	echo "  --disable-editor      Disable the built-in editor."
	echo "  --disable-mzxrun      Disable generation of separate MZXRun."
	echo "  --disable-helpsys     Disable the built-in help system."
	echo "  --disable-utils       Disable compilation of utils."
	echo "  --disable-x11         Disable X11, removing binary dependency."
	echo "  --disable-software    Disable software renderer."
	echo "  --disable-gl          Disable all GL renderers."
	echo "  --disable-gl-fixed    Disable GL renderers for fixed-function h/w."
	echo "  --disable-gl-prog     Disable GL renderers for programmable h/w."
	echo "  --disable-overlay     Disable all overlay renderers."
	echo "  --enable-gp2x         Enables half-res software renderer."
	echo "  --disable-modplug     Disable ModPlug music engine."
	echo "  --enable-mikmod       Enables MikMod music engine."
	echo "  --disable-libpng      Disable PNG screendump support."
	echo "  --disable-audio       Disable all audio (sound + music)."
	echo "  --enable-tremor       Switches out libvorbis for libtremor."
	echo "  --disable-pthread     Use SDL's locking instead of pthread."
	echo "  --disable-icon        Do not try to brand executable."
	echo "  --disable-modular     Disable dynamically shared objects."
	echo "  --disable-updater     Disable built-in updater."
	echo "  --disable-network     Disable networking abilities."
	echo "  --enable-meter        Enable load/save meter display."
	echo "  --disable-sdl         Disables SDL dependencies and features."
	echo "  --enable-egl          Enables EGL backend (if SDL disabled)."
	echo "  --disable-check-alloc Disables memory allocator error handling."
	echo "  --enable-debytecode   Enable experimental 'debytecode' transform."
	echo
	echo "e.g.: ./config.sh --platform unix --prefix /usr"
	echo "                  --sysconfdir /etc --disable-x11"
	echo "e.g.: ./config.sh --platform win32"
	echo
}

### CHOMP CONFIG.SH FLAGS #####################################################

#
# Default settings for flags (used if unspecified)
#
PLATFORM=""
PREFIX="/usr"
SYSCONFDIR="/etc"
GAMESDIR="${PREFIX}/games"
BINDIR="${PREFIX}/bin"
SHAREDIR="${PREFIX}/share"
SYSCONFDIR_SET="false"
DATE_STAMP="true"
AS_NEEDED="false"
RELEASE="false"
OPT_SIZE="false"
EDITOR="true"
MZXRUN="true"
HELPSYS="true"
UTILS="true"
X11="true"
SOFTWARE="true"
GL_FIXED="true"
GL_PROGRAM="true"
OVERLAY="true"
GP2X="false"
MODPLUG="true"
MIKMOD="false"
LIBPNG="true"
AUDIO="true"
TREMOR="false"
PTHREAD="true"
ICON="true"
MODULAR="true"
UPDATER="true"
NETWORK="true"
VERBOSE="false"
METER="false"
SDL="true"
EGL="false"
CHECK_ALLOC="true"
DEBYTECODE="false"

#
# User may override above settings
#
while [ "$1" != "" ]; do
	# e.g. --platform unix-devel
	if [ "$1" = "--platform" ]; then
		shift
		PLATFORM="$1"
	fi

	# e.g. --prefix /usr
	if [ "$1" = "--prefix" ]; then
		shift
		PREFIX="$1"
	fi

	# e.g. --sysconfdir /etc
	if [ "$1" = "--sysconfdir" ]; then
		shift
		SYSCONFDIR="$1"
		SYSCONFDIR_SET="true"
	fi

	# e.g. --gamesdir /usr/games
	if [ "$1" = "--gamesdir" ]; then
		shift
		GAMESDIR="$1"
	fi

	# e.g. --bindir /usr/bin
	if [ "$1" = "--bindir" ]; then
		shift
		BINDIR="$1"
	fi

	# e.g. --sharedir /usr/share
	if [ "$1" = "--sharedir" ]; then
		shift
		SHAREDIR="$1"
	fi

	[ "$1" = "--as-needed-hack" ] && AS_NEEDED="true"

	[ "$1" = "--enable-release" ]  && RELEASE="true"
	[ "$1" = "--disable-release" ] && RELEASE="false"

	[ "$1" = "--optimize-size" ]  && OPT_SIZE="true"
	[ "$1" = "--optimize-speed" ] && OPT_SIZE="false"

	[ "$1" = "--disable-datestamp" ] && DATE_STAMP="false"
	[ "$1" = "--enable-datestamp" ]  && DATE_STAMP="true"

	[ "$1" = "--disable-editor" ] && EDITOR="false"
	[ "$1" = "--enable-editor" ]  && EDITOR="true"

	[ "$1" = "--disable-mzxrun" ] && MZXRUN="false"
	[ "$1" = "--enable-mzxrun" ]  && MZXRUN="true"

	[ "$1" = "--disable-helpsys" ] && HELPSYS="false"
	[ "$1" = "--enable-helpsys" ]  && HELPSYS="true"

	[ "$1" = "--disable-utils" ] && UTILS="false"
	[ "$1" = "--enable-utils" ] && UTILS="true"

	[ "$1" = "--disable-x11" ] && X11="false"
	[ "$1" = "--enable-x11" ]  && X11="true"

	[ "$1" = "--disable-software" ] && SOFTWARE="false"
	[ "$1" = "--enable-software" ]  && SOFTWARE="true"

	[ "$1" = "--disable-gl" ] && GL="false"
	[ "$1" = "--enable-gl" ]  && GL="true"

	[ "$1" = "--disable-gl-fixed" ] && GL_FIXED="false"
	[ "$1" = "--enable-gl-fixed" ]  && GL_FIXED="true"

	[ "$1" = "--disable-gl-prog" ] && GL_PROGRAM="false"
	[ "$1" = "--enable-gl-prog" ]  && GL_PROGRAM="true"

	[ "$1" = "--disable-overlay" ] && OVERLAY="false"
	[ "$1" = "--enable-overlay" ]  && OVERLAY="true"

	[ "$1" = "--disable-gp2x" ] && GP2X="false"
	[ "$1" = "--enable-gp2x" ]  && GP2X="true"

	[ "$1" = "--disable-modplug" ] && MODPLUG="false"
	[ "$1" = "--enable-modplug" ]  && MODPLUG="true"

	[ "$1" = "--disable-mikmod" ] && MIKMOD="false"
	[ "$1" = "--enable-mikmod" ]  && MIKMOD="true"

	[ "$1" = "--disable-libpng" ] && LIBPNG="false"
	[ "$1" = "--enable-libpng" ]  && LIBPNG="true"

	[ "$1" = "--disable-audio" ] && AUDIO="false"
	[ "$1" = "--enable-audio" ]  && AUDIO="true"

	[ "$1" = "--disable-tremor" ] && TREMOR="false"
	[ "$1" = "--enable-tremor" ]  && TREMOR="true"

	[ "$1" = "--disable-pthread" ] && PTHREAD="false"
	[ "$1" = "--enable-pthread" ]  && PTHREAD="true"

	[ "$1" = "--disable-icon" ] && ICON="false"
	[ "$1" = "--enable-icon" ]  && ICON="true"

	[ "$1" = "--disable-modular" ] && MODULAR="false"
	[ "$1" = "--enable-modular" ]  && MODULAR="true"

	[ "$1" = "--disable-updater" ] && UPDATER="false"
	[ "$1" = "--enable-updater" ]  && UPDATER="true"

	[ "$1" = "--disable-network" ] && NETWORK="false"
	[ "$1" = "--enable-network" ]  && NETWORK="true"

	[ "$1" = "--disable-verbose" ] && VERBOSE="false"
	[ "$1" = "--enable-verbose" ]  && VERBOSE="true"

	[ "$1" = "--enable-meter" ]  && METER="true"
	[ "$1" = "--disable-meter" ] && METER="false"

	[ "$1" = "--disable-sdl" ] && SDL="false"
	[ "$1" = "--enable-sdl" ]  && SDL="true"

	[ "$1" = "--enable-egl" ]  && EGL="true"
	[ "$1" = "--disable-egl" ] && EGL="false"

	[ "$1" = "--disable-check-alloc" ] && CHECK_ALLOC="false"
	[ "$1" = "--enable-check-alloc" ]  && CHECK_ALLOC="true"

	[ "$1" = "--enable-debytecode" ]  && DEBYTECODE="true"
	[ "$1" = "--disable-debytecode" ] && DEBYTECODE="false"

	if [ "$1" = "--help" ]; then
		usage
		exit 0
	fi

	shift
done

#
# Platform cannot be sanely omitted
#
if [ "$PLATFORM" = "" ]; then
	usage
	exit 0
fi

### PLATFORM DEFINITION #######################################################

echo "PREFIX?=$PREFIX" > platform.inc

if [ "$PLATFORM" = "win32"   -o "$PLATFORM" = "win64" \
  -o "$PLATFORM" = "mingw32" -o "$PLATFORM" = "mingw64" ]; then
	[ "$PLATFORM" = "win32" -o "$PLATFORM" = "mingw32" ] && ARCHNAME=x86
	[ "$PLATFORM" = "win64" -o "$PLATFORM" = "mingw64" ] && ARCHNAME=x64
	[ "$PLATFORM" = "mingw32" ] && MINGWBASE=i686-w64-mingw32-
	[ "$PLATFORM" = "mingw64" ] && MINGWBASE=x86_64-w64-mingw32-
	PLATFORM="mingw"
	echo "#define PLATFORM \"windows-$ARCHNAME\"" > src/config.h
	echo "SUBPLATFORM=windows-$ARCHNAME"         >> platform.inc
	echo "PLATFORM=$PLATFORM"                    >> platform.inc
	echo "MINGWBASE=$MINGWBASE"                  >> platform.inc
elif [ "$PLATFORM" = "unix" -o "$PLATFORM" = "unix-devel" ]; then
	OS="`uname -s`"
	MACH="`uname -m`"

	case "$OS" in
		"Linux")
			UNIX="linux"
			;;
		"FreeBSD")
			UNIX="freebsd"
			;;
		*)
			echo "WARNING: Should define proper UNIX name here!"
			UNIX="unix"
			;;
	esac

	if [ "$MACH" = "x86_64" -o "$MACH" = "amd64" ]; then
		ARCHNAME=amd64
		LIBDIR=lib64
		# FIXME: FreeBSD amd64 hack
		[ "$UNIX" = "freebsd" ] && LIBDIR=lib
		if [ "$MODULAR" = "true" ]; then
			echo "ARCH_CFLAGS+=-fPIC" >> platform.inc
			echo "ARCH_CXXFLAGS+=-fPIC" >> platform.inc
		fi
	elif [ "`echo $MACH | sed 's,i.86,x86,'`" = "x86" ]; then
		ARCHNAME=x86
		LIBDIR=lib
	elif [ "`echo $MACH | sed 's,^arm.*,arm,'`" = "arm" ]; then
		ARCHNAME=arm
		LIBDIR=lib
	else
		echo "Add a friendly MACH to config.sh."
		exit 1
	fi

	echo "#define PLATFORM \"$UNIX-$ARCHNAME\"" > src/config.h
	echo "SUBPLATFORM=$UNIX-$ARCHNAME"         >> platform.inc
	echo "PLATFORM=unix"                       >> platform.inc
else
	if [ ! -d arch/$PLATFORM ]; then
		echo "Invalid platform selection (see arch/)."
		exit 1
	fi

	echo "#define PLATFORM \"$PLATFORM\"" > src/config.h
	echo "SUBPLATFORM=$PLATFORM"         >> platform.inc
	echo "PLATFORM=$PLATFORM"            >> platform.inc
fi

if [ "$PLATFORM" = "unix" -o "$PLATFORM" = "unix-devel" ]; then
	echo "RAWLIBDIR=${LIBDIR}" >> platform.inc
fi

if [ "$PLATFORM" = "unix" ]; then
	echo "LIBDIR=\${PREFIX}/${LIBDIR}/megazeux" >> platform.inc
elif [ "$PLATFORM" = "android" ]; then
	echo "LIBDIR=/data/megazeux" >> platform.inc
else
	echo "LIBDIR=." >> platform.inc
fi

### SYSTEM CONFIG DIRECTORY ###################################################

if [ "$PLATFORM" = "darwin" ]; then
	SYSCONFDIR="../Resources"
elif [ "$PLATFORM" = "android" ]; then
	SYSCONFDIR="/data/megazeux"
elif [ "$PLATFORM" != "unix" ]; then
	if [ "$SYSCONFDIR_SET" != "true" ]; then
		SYSCONFDIR="."
	fi
fi

### SUMMARY OF OPTIONS ########################################################

echo "Building for platform:   $PLATFORM"
echo "Using prefix:            $PREFIX"
echo "Using sysconfdir:        $SYSCONFDIR"
echo

### GENERATE CONFIG.H HEADER ##################################################

. ./version.inc

#
# Set the version to build with
#

echo "#define VERSION \"$VERSION\"" >> src/config.h

if [ "$DATE_STAMP" = "true" ]; then
	echo "Stamping version with today's date."
	echo "#define VERSION_DATE \" (`date -u +%Y%m%d`)\"" >> src/config.h
else
	echo "Not stamping version with today's date."
fi

echo "#define CONFDIR \"$SYSCONFDIR/\"" >> src/config.h

#
# Some platforms may have filesystem hierarchies they need to fit into
# FIXME: SHAREDIR should be hardcoded in fewer cases
#
if [ "$PLATFORM" = "unix" ]; then
	echo "#define CONFFILE \"megazeux-config\""    >> src/config.h
	echo "#define SHAREDIR \"$SHAREDIR/megazeux/\"" >> src/config.h
elif [ "$PLATFORM" = "nds" ]; then
	SHAREDIR=/games/megazeux
	GAMESDIR=$SHAREDIR
	BINDIR=$SHAREDIR
	echo "#define CONFFILE \"config.txt\"" >> src/config.h
	echo "#define SHAREDIR \"$SHAREDIR\""  >> src/config.h
elif [ "$PLATFORM" = "wii" ]; then
	SHAREDIR=/apps/megazeux
	GAMESDIR=$SHAREDIR
	BINDIR=$SHAREDIR
	echo "#define CONFFILE \"config.txt\"" >> src/config.h
	echo "#define SHAREDIR \"$SHAREDIR\""  >> src/config.h
elif [ "$PLATFORM" = "darwin" ]; then
	SHAREDIR=../Resources
	GAMESDIR=$SHAREDIR
	BINDIR=$SHAREDIR
	echo "#define CONFFILE \"config.txt\"" >> src/config.h
	echo "#define SHAREDIR \"$SHAREDIR\""  >> src/config.h
elif [ "$PLATFORM" = "android" ]; then
	SHAREDIR=/data/megazeux
	GAMESDIR=/data/megazeux
	BINDIR=/data/megazeux
	echo "#define CONFFILE \"config.txt\"" >> src/config.h
	echo "#define SHAREDIR \"$SHAREDIR\""  >> src/config.h
else
	SHAREDIR=.
	GAMESDIR=.
	BINDIR=.
	echo "#define CONFFILE \"config.txt\"" >> src/config.h
	echo "#define SHAREDIR \"$SHAREDIR\""  >> src/config.h
fi

#
# Some architectures define an "install" target, and need these.
#
echo "SYSCONFDIR=$SYSCONFDIR" >> platform.inc
echo "GAMESDIR=$GAMESDIR"     >> platform.inc
echo "BINDIR=$BINDIR"         >> platform.inc
echo "SHAREDIR=$SHAREDIR"     >> platform.inc

#
# Platform-specific libraries, or SDL?
#
if [ "$PLATFORM" = "wii" ]; then
	echo "#define CONFIG_WII" >> src/config.h
	echo "BUILD_WII=1" >> platform.inc
fi

if [ "$PLATFORM" = "wii" ]; then
	echo "Disabling SDL (Wii)."
	SDL="false"
fi

if [ "$PLATFORM" = "nds" ]; then
	echo "Disabling SDL (NDS)."
	SDL="false"
fi

if [ "$PLATFORM" = "android" ]; then
	echo "Disabling SDL (Android), force-enabling EGL."
	SDL="false"
	EGL="true"
fi

if [ "$PLATFORM" = "pandora" ]; then
	echo "#define CONFIG_PANDORA" >> src/config.h
	echo "BUILD_PANDORA=1" >> platform.inc
fi

#
# SDL was disabled above; must also disable SDL-dependent modules
#
if [ "$SDL" = "false" ]; then
	echo "Force-disabling SDL dependent components:"
	echo " -> SOFTWARE, OVERLAY, MIKMOD"
	SOFTWARE="false"
	OVERLAY="false"
	MIKMOD="false"
else
	echo "#define CONFIG_SDL" >> src/config.h
	echo "BUILD_SDL=1" >> platform.inc
	EGL="false"
fi

#
# We have EGL support
#
if [ "$EGL" = "true" ]; then
	echo "#define CONFIG_EGL" >> src/config.h
	echo "BUILD_EGL=1" >> platform.inc
fi

#
# We need either SDL or EGL for OpenGL
#
if [ "$SDL" = "false" -a "$EGL" = "false" ]; then
	echo "Force-disabling OpenGL (no SDL or EGL support)."
	GL="false"
fi

#
# If the NDS arch is enabled, some code has to be compile time
# enabled too.
#
# Additionally, AUDIO must be disabled on NDS as it is currently
# broken (please fix this!).
#
if [ "$PLATFORM" = "nds" ]; then
	echo "Enabling NDS-specific hacks."
	echo "#define CONFIG_NDS" >> src/config.h
	echo "BUILD_NDS=1" >> platform.inc

	echo "Force-disabling audio on NDS (fixme)."
	AUDIO="false"

	echo "Force-disabling software renderer on NDS."
	echo "Building custom NDS renderer."
	SOFTWARE="false"
fi

#
# If the PSP arch is enabled, some code has to be compile time
# enabled too.
#
if [ "$PLATFORM" = "psp" ]; then
	echo "Enabling PSP-specific hacks."
	echo "#define CONFIG_PSP" >> src/config.h
	echo "BUILD_PSP=1" >> platform.inc
fi

#
# If the GP2X arch is enabled, some code has to be compile time
# enabled too.
#
# Additionally, the software renderer is replaced with the gp2x
# renderer on this platform.
#
if [ "$PLATFORM" = "gp2x" ]; then
	echo "Enabling GP2X-specific hacks."
	echo "#define CONFIG_GP2X" >> src/config.h
	echo "BUILD_GP2X=1" >> platform.inc

	echo "Force disabling software renderer on GP2X."
	SOFTWARE="false"

	echo "Force-enabling GP2X 320x240 renderer."
	GP2X="true"

	echo "Force-disabling Modplug audio."
	MODPLUG="false"
fi

#
# Force-disable OpenGL and overlay renderers on PSP, GP2X and NDS
#
if [ "$PLATFORM" = "psp" -o "$PLATFORM" = "gp2x" \
  -o "$PLATFORM" = "nds" -o "$PLATFORM" = "wii" ]; then
  	echo "Force-disabling OpenGL and overlay renderers."
	GL="false"
	OVERLAY="false"
fi

#
# Must have at least one OpenGL renderer enabled
#
[ "$GL_FIXED" = "false" -a "$GL_PROGRAM" = "false" ] && GL="false"

#
# If OpenGL is globally disabled, disable all renderers
#
if [ "$GL" = "false" ]; then
	echo "Force-disabling OpenGL."
	GL_FIXED="false"
	GL_PROGRAM="false"
fi

#
# Force-enable tremor on PSP/GP2X
#
if [ "$PLATFORM" = "psp" -o "$PLATFORM" = "gp2x" \
  -o "$PLATFORM" = "android" ]; then
	echo "Force-switching ogg/vorbis to tremor."
	TREMOR="true"
fi

#
# Force-disable modplug/mikmod if audio is disabled
#
if [ "$AUDIO" = "false" ]; then
	MODPLUG="false"
	MIKMOD="false"
fi

#
# Force-disable pthread on non-POSIX platforms
#
if [ "$PLATFORM" != "unix" -a "$PLATFORM" != "unix-devel" \
  -a "$PLATFORM" != "gp2x" -a "$PLATFORM" != "android" ]; then
	echo "Force-disabling pthread on non-POSIX platforms."
	PTHREAD="false"
fi

#
# Force disable modular DSOs.
#
if [ "$PLATFORM" = "gp2x" -o "$PLATFORM" = "nds" \
  -o "$PLATFORM" = "psp"  -o "$PLATFORM" = "wii" ]; then
	echo "Force-disabling modular build (nonsensical or unsupported)."
	MODULAR="false"
fi

#
# Force disable networking.
#
if [ "$EDITOR" = "false" -o "$PLATFORM" = "unix" -o "$PLATFORM" = "psp" \
  -o "$PLATFORM" = "nds" -o "$PLATFORM" = "wii" ]; then
	echo "Force-disabling networking (nonsensical or unsupported)."
	NETWORK="false"
fi

#
# Force disable updater.
#
if [ "$UPDATER" = "true" -a "$NETWORK" = "false" ]; then
	echo "Force-disabling updater (networking disabled)."
	UPDATER="false"
fi

#
# Force disable utils.
#
if [ "$DEBYTECODE" = "true" ]; then
	echo "Force-disabling utils (debytecode)."
	UTILS="false"
fi

#
# As GNU ld supports recursive dylib dependency tracking, we don't need to
# explicitly link to as many libraries as the authors would have us provide.
#
# Instead, pass the linker --as-needed to discard libraries explicitly
# passed through but not directly used. Fixes warnings with the Debian
# packaging infrastructure.
#
if [ "$AS_NEEDED" = "true" ]; then
	echo "Assuming GNU ld and passing --as-needed through."
	echo "LDFLAGS+=-Wl,--as-needed" >> platform.inc
fi

#
# Users may enable release mode
#
if [ "$RELEASE" = "true" ]; then
	#
	# Users may want size optimizations
	#
	if [ "$OPT_SIZE" = "true" ]; then
		echo "Optimizing for size."
		echo "OPTIMIZE_CFLAGS=-Os" >> platform.inc
	else
		echo "Optimizing for speed."
	fi
else
	echo "Disabling optimization, debug enabled."
	echo "DEBUG=1" >> platform.inc
fi

#
# User may disable the built-in editor
#
if [ "$EDITOR" = "true" ]; then
	echo "Built-in editor enabled."
	echo "BUILD_EDITOR=1" >> platform.inc
	echo "#define CONFIG_EDITOR" >> src/config.h
else
	echo "Built-in editor disabled."
fi

#
# User may disable `MZXRun' component
#
if [ "$MZXRUN" = "true" ]; then
	echo "Building MZXRun executable."
	echo "BUILD_MZXRUN=1" >> platform.inc
else
	echo "Not building MZXRun executable."
fi

#
# User may disable the built-in help system.
#
if [ "$HELPSYS" = "true" ]; then
	echo "Built-in help system enabled."
	echo "BUILD_HELPSYS=1" >> platform.inc
	echo "#define CONFIG_HELPSYS" >> src/config.h
else
	echo "Built-in help system disabled."
fi

#
# User may want to compile utils (checkres, downver, txt2hlp)
#
if [ "$UTILS" = "true" ]; then
	echo "Building utils (checkres, downver, hlp2txt, txt2hlp)."
	echo "BUILD_UTILS=1" >> platform.inc
	echo "#define CONFIG_UTILS" >> src/config.h
else
	echo "Disabled utils (checkres, downver, hlp2txt, txt2hlp)."
fi

#
# X11 support (linked against and needs headers installed)
#
if [ "$PLATFORM" = "unix" -o "$PLATFORM" = "unix-devel" \
  -o "$PLATFORM" = "pandora" ]; then
	#
	# Confirm the user's selection of X11, if they enabled it
	#
	if [ "$X11" = "true" ]; then
		for XBIN in X Xorg; do
			# try to run X
			$XBIN -version >/dev/null 2>&1

			# X/Xorg queried successfully
			[ "$?" = "0" ] && break
		done

		if [ "$?" != "0" ]; then
			echo "Force-disabling X11 (could not be queried)."
			X11="false"
		fi
	fi

	if [ "$ICON" = "true" -a "$X11" = "false" ]; then
		echo "Force-disabling icon branding (X11 disabled)."
		ICON="false"
	fi
else
	echo "Force-disabling X11 (unsupported platform)."
	X11="false"
fi

if [ "$X11" = "true" ]; then
	echo "X11 support enabled."

	# enable the C++ bits
	echo "#define CONFIG_X11" >> src/config.h

	# figure out where X11 is prefixed
	X11PATH=`which $XBIN`
	X11DIR=`dirname $X11PATH`

	# pass this along to the build system
	echo "X11DIR=${X11DIR}" >> platform.inc
fi

#
# Force disable icon branding.
#
if [ "$ICON" = "true" ]; then
	if [ "$PLATFORM" = "darwin" -o "$PLATFORM" = "gp2x" \
	  -o "$PLATFORM" = "psp" -o "$PLATFORM" = "nds" \
	  -o "$PLATFORM" = "wii" ]; then
		echo "Force-disabling icon branding (redundant)."
		ICON="false"
	fi
fi

#
# Software renderer
#
if [ "$SOFTWARE" = "true" ]; then
	echo "Software renderer enabled."
	echo "#define CONFIG_RENDER_SOFT" >> src/config.h
	echo "BUILD_RENDER_SOFT=1" >> platform.inc
else
	echo "Software renderer disabled."
fi

#
# Fixed-function H/W OpenGL renderers
#
if [ "$GL_FIXED" = "true" ]; then
	echo "Fixed-function H/W OpenGL renderers enabled."
	echo "#define CONFIG_RENDER_GL_FIXED" >> src/config.h
	echo "BUILD_RENDER_GL_FIXED=1" >> platform.inc
else
	echo "Fixed-function OpenGL renderers disabled."
fi

#
# Programmable H/W OpenGL renderers
#
if [ "$GL_PROGRAM" = "true" ]; then
	echo "Programmable H/W OpenGL renderer enabled."
	echo "#define CONFIG_RENDER_GL_PROGRAM" >> src/config.h
	echo "BUILD_RENDER_GL_PROGRAM=1" >> platform.inc
else
	echo "Programmable H/W OpenGL renderer disabled."
fi

#
# Overlay renderers
#
if [ "$OVERLAY" = "true" ]; then
	echo "Overlay renderers enabled."
	echo "#define CONFIG_RENDER_YUV" >> src/config.h
	echo "BUILD_RENDER_YUV=1" >> platform.inc
else
	echo "Overlay renderers disabled."
fi

#
# GX renderer (Wii and GameCube)
#
if [ "$PLATFORM" = "wii" ]; then
	echo "Building custom GX renderer."
	echo "#define CONFIG_RENDER_GX" >> src/config.h
	echo "BUILD_RENDER_GX=1" >> platform.inc
fi

#
# GP2X renderer
#
if [ "$GP2X" = "true" ]; then
	echo "GP2X half-res renderer enabled."
	echo "#define CONFIG_RENDER_GP2X" >> src/config.h
	echo "BUILD_RENDER_GP2X=1" >> platform.inc
else
	echo "GP2X half-res renderer disabled."
fi

#
# GP2X needs Mikmod, other platforms can pick
#
if [ "$MODPLUG" = "true" ]; then
	echo "Selected Modplug music engine."
	echo "#define CONFIG_MODPLUG" >> src/config.h
	echo "BUILD_MODPLUG=1" >> platform.inc
elif [ "$MIKMOD" = "true" ]; then
	echo "Selected Mikmod music engine."
	echo "#define CONFIG_MIKMOD" >> src/config.h
	echo "BUILD_MIKMOD=1" >> platform.inc
else
	echo "Music engine disabled."
fi

#
# Handle audio subsystem, if enabled
#
if [ "$AUDIO" = "true" ]; then
	echo "Audio subsystem enabled."
	echo "#define CONFIG_AUDIO" >> src/config.h
	echo "BUILD_AUDIO=1" >> platform.inc
else
	echo "Audio subsystem disabled."
fi

#
# Handle PNG screendump support, if enabled
#
if [ "$LIBPNG" = "true" ]; then
	echo "PNG screendump support enabled."
	echo "#define CONFIG_PNG" >> src/config.h
	echo "LIBPNG=1" >> platform.inc
else
	echo "PNG screendump support disabled."
fi

#
# Handle libtremor support, if enabled
#
if [ "$TREMOR" = "true" ]; then
	echo "Using tremor in place of ogg/vorbis."
	echo "#define CONFIG_TREMOR" >> src/config.h
	echo "TREMOR=1" >> platform.inc
else
	echo "Not using tremor in place of ogg/vorbis."
fi

#
# Handle pthread mutexes, if enabled
#
if [ "$PTHREAD" = "true" ]; then
	echo "Using pthread for locking primitives."
	echo "#define CONFIG_PTHREAD_MUTEXES" >> src/config.h
	echo "PTHREAD=1" >> platform.inc
else
	echo "Not using pthread for locking primitives."
fi

#
# Handle icon branding, if enabled
#
if [ "$ICON" = "true" ]; then
	echo "Icon branding enabled."
	echo "#define CONFIG_ICON" >> src/config.h

	#
	# On Windows we want the icons to be compiled in
	#
	if [ "$PLATFORM" = "mingw" ]; then
		echo "EMBED_ICONS=1" >> platform.inc
	fi
else
	echo "Icon branding disabled."
fi

#
# Inform build system of modular build, if appropriate
#
if [ "$MODULAR" = "true" ]; then
	echo "Modular build enabled."
	echo "BUILD_MODULAR=1" >> platform.inc
	echo "#define CONFIG_MODULAR" >> src/config.h

else
	echo "Modular build disabled."
fi

#
# Handle networking, if enabled
#
if [ "$NETWORK" = "true" ]; then
        echo "Networking enabled."
	echo "#define CONFIG_NETWORK" >> src/config.h
	echo "BUILD_NETWORK=1" >> platform.inc
else
	echo "Networking disabled."
fi

#
# Handle built-in updater, if enabled
#
if [ "$UPDATER" = "true" ]; then
	echo "Built-in updater enabled."
	echo "#define CONFIG_UPDATER" >> src/config.h
	echo "BUILD_UPDATER=1" >> platform.inc
else
	echo "Built-in updater disabled."
fi

#
# Some users may prefer the build system to ALWAYS be verbose
#
if [ "$VERBOSE" = "true" ]; then
	echo "Verbose build system (always)."
	echo "export V=1" >> platform.inc
fi

#
# Users may enable the load/save meter display.
#
if [ "$METER" = "true" ]; then
	echo "Load/save meter display enabled."
	echo "#define CONFIG_LOADSAVE_METER" >> src/config.h
else
	echo "Load/save meter display disabled."
fi

#
# Memory allocation error handling, if enabled
#
if [ "$CHECK_ALLOC" = "true" ]; then
	echo "Memory allocation error checking enabled."
	echo "#define CONFIG_CHECK_ALLOC" >> src/config.h
else
	echo "Memory allocation error checking disabled."
fi

#
# Experimental 'debytecode' transformation, if enabled
#
if [ "$DEBYTECODE" = "true" ]; then
	echo "Experimental 'debytecode' transform enabled."
	echo "#define CONFIG_DEBYTECODE" >> src/config.h
	echo "BUILD_DEBYTECODE=1" >> platform.inc
else
	echo "Experimental 'debytecode' transform disabled."
fi

echo
echo "Now type \"make\" (or \"gmake\" on BSD)."


code:
# Configuration file for MegaZeux
# Jun 5th, 2012

# Comments begin with #. Whitespace is ignored. Empty lines are
# ignored as well.
# Options are set in the following format:
# option = value
# If value is not given, then it is assumed to be 1.
# You can include spaces in values by escaping them with \s.
# (see the default macros for examples)
# For directories, use forward slashes (/) instead of back-slashes,
# as they work more reliably.
# Note that even if the option is given to change the values
# in MZX, this text file will NOT be modified, and hence the
# values will revert to what they are here when you restart MZX.

# NOTE: All of the options below have sane defaults. Changes to
# these options will only take effect if you uncomment them.

# In many cases, the current default value has been written in,
# but this is not guaranteed (for example with video_output).

### Video options ###

# Rendering engine to use to display MegaZeux. The fastest renderer
# is "software", due to the way MegaZeux is drawn internally. However,
# due to MegaZeux's strange default resolution (640x350), many video
# cards have difficulty with supporting it correctly in fullscreen mode.
#
# Using another renderer that supports scaling will be slower, but not
# necessarily by much, depending on your video hardware and CPU. Very
# often, MZX uses so little CPU during software rendering that scaling
# is an inexpensive feature.
#
# The software renderer is the default renderer and has very good
# windowed and non-windowed performance. In addition, this renderer
# correctly supports 8 bit colour modes, should you be using antiquated
# hardware. It also requires no overlay or 3D hardware support. If you're
# on a slow computer or a handheld portable, you definitely want to use
# this. To use it, either do nothing, or uncomment the line below.

# video_output = software

# The YUV overlay renderer is a good substitute if you want scaling
# at low cost. The quality of the scaling is poor, and can sometimes be
# very poor depending on your video hardware. On video hardware that
# interpolates or filters the YUV overlay, such as NVIDIA or ATI hardware,
# this method can be fairly high quality (comparable to GL with linear
# filtering), and yields good performance, with low OS driver requirements.
# On Intel Integrated video, and other similar solutions, the YUV overlay
# will use nearest neighbour and the quality will be atrocious.
#
# Uncomment either of the lines below (but not both) if you want to try it.
# The "overlay2" mode is cheaper, but will be less accurate due to the use
# of chroma subsampling instead of a full YUV encode.

# video_output = overlay1
# video_output = overlay2

# An OpenGL renderer is a good choice if you want a highly configurable,
# cheap (in terms of CPU cycles) renderer and have a fairly good video
# card. This method provides the highest quality scaler and should work
# on all platforms with OpenGL or OpenGL ES support.
#
# MegaZeux provides two fixed-function scalers. The first, by Exophase,
# renders the whole game to a texture and uses OpenGL to stretch it.
# This renderer is called "opengl1" and is high quality but quite slow.
#
# The second fixed-function scaler was written by Logicow, and it uses the
# features of GL more extensively, remapping the character sets to a texture,
# tiling entirely in OpenGL. This yields a performance increase, at the cost
# of some compatibility. This renderer is called "opengl2".
#
# MegaZeux also provides a scaler for programmable hardware. If you have
# OpenGL 2.0 or OpenGL ES 2.0 capable hardware, you should use this renderer.
# Written by Logicow, it uses shaders to do the tiling and scaling. There
# are four shader programs that can be customized. This renderer is called
# "glsl". It is the highest quality and best performing renderer.
#
# Uncomment ONE of the lines below:

# video_output = opengl1
# video_output = opengl2
# video_output = glsl

# The OpenGL and YUV overlay renderers can be configured to preserve aspect
# ratio where possible, in window and fullscreen modes. The supported
# ratios are "classic" (4:3) and "modern" (64:35). The ratio type "stretch"
# disables any aspect ratio preservation, and is the default.

# video_ratio = stretch

# OpenGL will, by default, linearly interpolate pixels as it upscales
# to your requested resolution. This creates an output with more "blur",
# which some people dislike. If you are using a sufficiently high target
# resolution, preferably an integer multiple of 640x350, you may find
# "nearest" more pleasing, which will have no "blur". The default
# setting is "linear".

# gl_filter_method = nearest

# Some OpenGL driver settings may default vertical sync on, which looks
# visually better (especially on CRTs) but can cause "speed 1" to run
# noticably slower than with other renderers. For consistency with other
# renderers, and for correctness, MegaZeux will attempt to disable vsync
# when gl_vsync is the default value of 0. Conversely, a value >= 1 forces
# MegaZeux to override the driver settings and enable vsync, which
# decreases tearing. A value < 0 can be used to tell MegaZeux to obey the
# driver default, which is unlikely to be useful.

# gl_vsync = 1

# Resolution MZX uses for fullscreen. With the software renderer, this
# will center MZX on the screen, and will not scale it.
# However, with the hardware renderers above, MZX will attempt to scale
# itself to match this resolution. Best results are obtained with
# multiples of 640x350, but any supported screen mode should work.
# Give in x,y format. Use this if the defaults are giving you problems,
# especially in the software renderer.
# This resolution may not actually work; if it doesn't, you will
# get the nearest that does.

# fullscreen_resolution = 640,480

# The resolution MZX uses in a window. If you renderer supports
# it, MZX will be scaled to fit this specification. Otherwise
# the setting is ignored.

# window_resolution = 640,350

# Use this to toggle whether MZX can be scaled while in window
# mode, if your renderer supports it. If you use a renderer which
# supports scaling, but don't want to accidentally scale it (which
# may distort the image), you can switch this off here.

# enable_resizing = 1

# MZX is limited internally to 8bit colour, but it can upmix its
# rendering to 32bit if your video card has difficulty with 8bit
# resolutions. Using 32bit colour is slower, but not by much.
# NOTE: This option may be ignored by one or more of the above
# renderers, but it is guaranteed to apply to "software". Valid
# settings are usually '8' or '32'.

# force_bpp = 32

# Whether MZX should start up in fullscreen or not.
# Press ctrl-alt-enter to toggle fullscreen as MZX runs.

# fullscreen = 1

### Audio options ###

# Sampling rate to output audio at. Higher values will sound
# better but use more resources and may not be supported by
# your audio card/drivers. Typical values include 22050, 44100,
# and 48000. If your card supports it you might get away with
# 96000, or even 192000.

# audio_sample_rate = 44100

# Audio buffer size. Setting this to lower can improve latency,
# so audio will be heard sooner after it is set to be changed.
# It is also possible to change PC speaker effects more rapidly
# with lower values. Lower buffer sizes need more CPU power to
# process. 2048 is adequete for PC speaker playback every
# command at speed 4.

# audio_buffer = 4096

# Allow music to be sampled at higher precision. Increases CPU
# usage but increases audio quality as well.

# enable_oversampling = 0

# Set master resample mode. This affects how OGGs and
# frequency shifted modules sound. Choices are:
# none (fastest, poor quality)
# linear (fast, good quality)
# cubic (slow, great quality)

# resample_mode = linear

# Set resample mode for modplug. This affects how modules
# and WAVs sound. Choices are:
# none (fastest, poor quality)
# linear (fast, good quality)
# cubic (slow, great quality)
# fir (very slow, excellent quality)

# modplug_resample_mode = linear

# Whether music/samples should be played or not.
# Does not include PC speaker effects.

# music_on = 1

# Whether PC speaker effects should be played or not.

# pc_speaker_on = 1

# Volume music plays at

# music_volume = 8

# Volume samples play at

# sample_volume = 8

# Volume PC speaker SFX play at

# pc_speaker_volume = 8

### Game options ###

# Name of the directory where MegaZeux should start.

# startup_path = /home/username/MegaZeux

# Name of world file that should be loaded when MZX starts.

# startup_file = caverns.mzx

# Default save file name given when you first try to save.

# save_file = saved.sav

# Speed MZX should start at (1 through 9)

# mzx_speed = 4

# Start in the editor by default

# startup_editor = 1

### Board editor options ###

# Whether or not the spacebar can be used to toggle between
# your active buffer and the meta character "SPACE". If you
# set this, it will behave like older MegaZeux's, but it will
# allow you to overwrite robots, for instance.
#
# If the setting is disabled (the default), replacing params
# will your new buffer will not require a toggle, and robots
# can only be deleted with the Delete key.

# editor_space_toggles = 1

# If this is set to 1 (the default), enter can be used to split
# a line in the robot editor. However, the classic behaviour is
# that enter moves the cursor down a line. If you would like to
# restore the old behaviour, please set this to 0.

# editor_enter_splits = 1

# Set to 1 if you want the board editor to not show the hotkey
# help by default.

# board_editor_hide_help = 1

### Robot editor options ###

# Enable or disable color coding in the editor.
# If color coding is off, ccode_string is used for the entire
# line.

# color_coding_on = 0

# Color codes for various types.
# For colors, use 255 to show a color box.

# ccode_colors = 255
# ccode_commands = 15
# ccode_conditions = 15
# ccode_current_line = 11
# ccode_directions = 3
# ccode_equalities = 0
# ccode_extras = 7
# ccode_immediates = 10
# ccode_items = 11
# ccode_params = 2
# ccode_strings = 14
# ccode_things = 11

# Whether or not "extra words" should be displayed.
# For instance, if turned on, a line like "wait 1" will
# become "wait for 1."

# disassemble_extras = 0

# The base numbers should be displayed as. Valid options
# are 10 and 16 (decimal and hexidecimal). Hex numbers are
# prefixed with a dollar sign ($).

# disassemble_base = 16

# Changing this will allow invalid comments to automatically
# be marked to "delete" or "comment" instead of "ignore".
# Don't change this unless you know what you're doing.

# default_invalid_status = ignore

# Single line macros
# These are the traditional MZX macros; they may only
# occupy one line in their definition in this file. They
# correspond to parameter-less macros: when you press
# F6 through F10 the following strings are printed to
# the editor, verbatim. For instance if you set macro_1 to
# * "hello", * "hello" will be inserted every time you
# press F6 in the robot editor.
# The following are the default singe-line macros.

# macro_1 = char\s
# macro_2 = color\s
# macro_3 = goto\s
# macro_4 = send\s
# macro_5 = :\splayershot^

# Extended macros:
# See macro.txt.

# The following is an example extended macro.
# It sets up a sprite. If you find it useful, remove the #'s.

#macro_sprite = Sprite\sSetup
# (number255 spr_num)
# (number255 w, h, rx, ry)
# (number255 cx, cy, cw, ch)
# (number255 x, y)
# set spr!spr_num!_width !w!
# set spr!spr_num!_height !h!
# set spr!spr_num!_refx !rx!
# set spr!spr_num!_refy !ry!
# set spr!spr_num!_cwidth !cw!
# set spr!spr_num!_cheight !ch!
# set spr!spr_num!_cx !cx!
# set spr!spr_num!_cy !cy!
# put !x1! sprite p!#spr_num! !x! !y!

# Whether or not the palette should be reverted to default
# when the robot editor is load. If set, SMZX mode 0 will
# also be enforced.

# robot_editor_default_palette = 0

# Set to 1 if you want the robot editor to not show the hotkey
# help and horizontal border by default.

# robot_editor_hide_help = 0

# Backup options

# Backups are save files made in the editor. They will only be made
# while in the main editor, not while in a sub-editor or a dialogue
# box of sorts. Note that this can cause slight pauses while editing,
# as the game saves.
# If you have multiple backups you should check the modified date in
# a console or file properties to determine which was most recently
# modified. The number will not indicate most recently saved.

# How many backups to be made. Set to zero to disable backups.

# backup_count = 3

# How often (in seconds) backups should be made

# backup_interval = 60

# The name of the backup file. If you choose "backup" with 3 backups
# the backups will be named backup1.mzx, backup2.mzx, and backup3.mzx.

# backup_name = backup

# The extension of backup files (keep this .mzx if you want to be able
# to easily load them)

# backup_ext = .mzx

# Joystick options

# It is possible to emulate key presses using a joystick. If this file
# is config.txt these options will apply as a default to all games -
# you can put them in game.cnf to apply specifically to game.mzx.

# A joystick is first specified as joyN where N is the number from
# 1 onwards identifying the joystick in your system. You may have
# to experiment to find which joystick is which number, if you have
# multiple ones, otherwise just use 1. Up to 16 joysticks are
# recognized.
# You can currently map two things, axes and buttons.
# Axes/buttons are mapped to keys given by number. You can find out
# a key's number by printing key_pressed in a loop (NOT key_code).
# Axis mapping looks as follows:

# joyXaxisY = A, B

# Where X is the number of the joystick, Y is the number of the axis
# (1 is typically left/right, 2 is typically up/down), A is the key
# for one extreme (such as left) and B is the key for the other
# (such as right).

# Button mapping looks as follows:

# joyXbuttonY = A

# Where X is the number of the joystick, Y is the number of the button
# (you may have to experiment to find out which button is which number),
# and A is the key whose press is emulated when this button is pressed.

# Misc Options

# Set to 1 if you want MZX to pause when key focus is lost. Useful for
# when another app (such as someone IM'ing you) steals the screen. This
# might cause MZX to lock up sometimes on some machines - if you have
# problems with it don't enable it.

# pause_on_unfocus = 0

# Set to 0 if you want input boxes and strings in the robot editor
# to use the game set for characters 32-127, as opposed to the protected
# GUI set.

# mask_midchars = 1

# Set to 1 if you would rather MZX's mouse pointer used the
# system mouse cursor.

# system_mouse = 0

###################
# NETWORK OPTIONS #
###################

# If networking is enabled, MZX is permitted to bind ports and connect
# out to the network or Internet. This option is a global kill switch
# for the paranoid and allows the entire network layer to be disabled.

# network_enabled = 1

# MegaZeux can support connections via a SOCKS4/5 proxy to punch through
# connections that would otherwise require some sort of pipe intermediary.

# socks_host = localhost
# socks_port = 1080

# The update host is an HTTP server containing all data and metadata
# associated with updates for MegaZeux. You normally won't want to
# change this, but it may be useful if you are a third party distributing
# unofficial updates. You may specify this up to times 16; connections will
# be attempted in the order they are defined. Please note, this is not a
# URL and should not contain protocol specifiers such as http://

update_host = updates.digitalmzx.net
update_host = updates.mzx.devzero.co.uk

# The update "branch" is consulted each time the updater runs. Typically,
# there are only two branches, "Stable" and "Unstable". Please note, this
# option is case sensitive. The "Stable" branch is the default, but if
# you are interested in helping find bugs in the latest development
# version, or are instructed to follow development, you will need to
# change this to "Unstable". Third parties may use different branch names.

# update_branch_pin = Stable

include pad.config


code:
-- Alistair John Strachan (ajs)  <alistair@devzero.co.uk>

Principle developer of the utility.

-- Gilead Kutnick (Exophase)  <exophase@adelphia.net>

For porting MegaZeux from DOS to Windows/Linux, and for convincing me to
finish this utility.

-- Hubert Lamontagne (MadBrain)  <madbrain@videotron.ca>

For supporting me during the writing of this utility and for providing
documentation on s3m's effects and the included test GDMs.

-- MenTaLguY  <>

For writing the gdm.txt reverse engineered GDM specification. Find the
file included herein.


code:
CONTACT

Name:       Alistair John Strachan
Email:      <alistair@devzero.co.uk>
Secondary:  <ajs@bitpack.net>
Website:    http://www.bitpack.net/

GDM2S3M UTILITY V1.7

This utility is designed to convert GDM, a format developed by the ALSA
developer Edward Schlunder, many years ago, into the ScreamTracker 3 file
format (S3M).

It is likely to contain bugs. See the CREDITS file for contact details
should you isolate a bug.

BUILDING AND INSTALLING

Build the software with "make":

On Linux:
make BUILD=linux

On Windows MINGW:
make

As of version 1.3, compiling with Microsoft's free Visual C++ 2003 toolkit
compiler is supported. You can obtain this from:

http://msdn.microsoft.com/visualc/vctoolkit2003/

At the time of writing, this compiler was free. A crappy batch file is
provided for building both a static library, and the standalone EXE.

Under the toolkit shell, type:
build.bat

USAGE

cd src
./gdm2s3m <file.gdm> <file.s3m>

SOFTWARE LICENSE

The entire contents of this archive are released under the terms of the
GNU General Public License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.

The only exceptions to this are the provided GDM/S3M/MTM files under the
test/ directory, which are "borrowed" from various music archives and
are believed to be unlicensed.

Additionally, the document gdm.txt is released under the OpenContent
License (OPL), version 1.0.

All redistributions of this package must contain the above boilerplate text.


code:
@echo off

rem clean up afterwards ;p
del src\*.obj lib\gdm2s3m.lib bin\gdm2s3m.exe

rem build it!
cd src
cl /c /O2 /I . error.c gdm.c s3m.c utility.c gdm2s3m.c
link /LIB /OUT:..\lib\gdm2s3m.lib error.obj gdm.obj s3m.obj utility.obj
link /OUT:..\bin\gdm2s3m.exe error.obj gdm.obj s3m.obj utility.obj gdm2s3m.obj
cd ..