code:
/* This implementation of SHA-256 is based on an implementation in the
 * public domain, which was in turn based on another public domain
 * implementation of SHA-1 by Adam Back.
 *
 * 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 "sha256.h"

#include "../platform_endian.h"
#include "../util.h"

#include <string.h>

#define S(x,n)     (((x) >> (n)) | ((x) << (32 - (n))))
#define R(x,n)     ((x) >> (n))

#define Ch(x,y,z)  (((x) & (y)) | (~(x) & (z)))
#define Maj(x,y,z) (((x) & (y)) |  ((x) & (z)) | ((y) & (z)))

#define SIG0(x)    (S(x, 2) ^ S(x,13) ^ S(x,22))
#define SIG1(x)    (S(x, 6) ^ S(x,11) ^ S(x,25))
#define sig0(x)    (S(x, 7) ^ S(x,18) ^ R(x, 3))
#define sig1(x)    (S(x,17) ^ S(x,19) ^ R(x,10))

static const Uint32 K[] =
{
  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

static const Uint32 H_initial[] = {
  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};

#if PLATFORM_BYTE_ORDER == PLATFORM_LIL_ENDIAN

static void convert_to_bigendian(void *data, int len)
{
  Uint32 *data_as_words = data;
  Uint8 *data_as_bytes;
  Uint32 temp;
  Uint8 *temp_as_bytes = (Uint8 *)&temp;
  int i;

  for(i = 0; i < len / 4; i++)
  {
    temp = data_as_words[i];
    data_as_bytes = (Uint8 *)&data_as_words[i];

    data_as_bytes[0] = temp_as_bytes[3];
    data_as_bytes[1] = temp_as_bytes[2];
    data_as_bytes[2] = temp_as_bytes[1];
    data_as_bytes[3] = temp_as_bytes[0];
  }
}

#else

static inline void convert_to_bigendian(void *data, int len) { }

#endif

static void SHA256_transform(struct SHA256_ctx *ctx)
 {
  Uint32 A = ctx->H[0];
  Uint32 B = ctx->H[1];
  Uint32 C = ctx->H[2];
  Uint32 D = ctx->H[3];
  Uint32 E = ctx->H[4];
  Uint32 F = ctx->H[5];
  Uint32 G = ctx->H[6];
  Uint32 H = ctx->H[7];
  Uint32 T1, T2;
  Uint32 W[64];
  int t;

  memcpy(W, ctx->M, 64);

  for(t = 16; t < 64; t++)
    W[t] = sig1(W[t - 2]) + W[t - 7] + sig0(W[t - 15]) + W[t - 16];

  for(t = 0; t < 64; t++)
  {
    T1 = H + SIG1(E) + Ch(E,F,G) + K[t] + W[t];
    T2 = SIG0(A) + Maj(A,B,C);
    H = G;
    G = F;
    F = E;
    E = D + T1;
    D = C;
    C = B;
    B = A;
    A = T1 + T2;
  }

  ctx->H[0] += A;
  ctx->H[1] += B;
  ctx->H[2] += C;
  ctx->H[3] += D;
  ctx->H[4] += E;
  ctx->H[5] += F;
  ctx->H[6] += G;
  ctx->H[7] += H;
}

void SHA256_init(struct SHA256_ctx *ctx)
{
  memcpy(ctx->H, H_initial, 8 * sizeof(Uint32));
  ctx->lbits = 0;
  ctx->hbits = 0;
  ctx->mlen = 0;
}

void SHA256_update(struct SHA256_ctx *ctx, const void *vdata, Uint32 data_len)
{
  const Uint8 *data = vdata;
  Uint32 low_bits;
  Uint32 use;

  /* convert data_len to bits and add to the 64 bit word
   * formed by lbits and hbits
   */

  ctx->hbits += data_len >> 29;
  low_bits = data_len << 3;
  ctx->lbits += low_bits;

  if(ctx->lbits < low_bits)
    ctx->hbits++;

  /* deal with first block */

  use = MIN((Uint32)(64 - ctx->mlen), data_len);
  memcpy(ctx->M + ctx->mlen, data, use );
  ctx->mlen += use;
  data_len -= use;
  data += use;

  while(ctx->mlen == 64)
  {
    convert_to_bigendian(ctx->M, 64);
    SHA256_transform(ctx);
    use = MIN(64, data_len);
    memcpy(ctx->M, data, use);
    ctx->mlen = use;
    data_len -= use;
    data += use; /* was missing */
  }
}

void SHA256_final(struct SHA256_ctx *ctx)
{
  if(ctx->mlen < 56)
  {
    ctx->M[ctx->mlen++] = 0x80;
    memset(ctx->M + ctx->mlen, 0x00, 56 - ctx->mlen);
    convert_to_bigendian(ctx->M, 56);
  }
  else
  {
    ctx->M[ctx->mlen++] = 0x80;
    memset(ctx->M + ctx->mlen, 0x00, 64 - ctx->mlen);
    convert_to_bigendian(ctx->M, 64);
    SHA256_transform(ctx);
    memset(ctx->M, 0x00, 56);
  }

  memcpy(ctx->M + 56, &ctx->hbits, 8);
  SHA256_transform(ctx);
}

#ifdef SHA256TEST

int main(void)
{
  struct SHA256_ctx ctx;
  int i;

  const char *test1 = "abc";
  const Uint32 result1[8] = {
    0xba7816bf, 0x8f01cfea, 0x414140de, 0x5dae2223,
    0xb00361a3, 0x96177a9c, 0xb410ff61, 0xf20015ad
  };

  const char *test2 =
    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
  const Uint32 result2[8] = {
    0x248d6a61, 0xd20638b8, 0xe5c02693, 0x0c3e6039,
    0xa33ce459, 0x64ff2167, 0xf6ecedd4, 0x19db06c1
  };

  printf("test 1\n\n");
  SHA256_init(&ctx);
  SHA256_update(&ctx, test1, strlen(test1));
  SHA256_final(&ctx);

  printf("SHA256(\"%s\") = \n\t", test1);

  for(i = 0; i < 8; i++)
    printf("%08x", ctx.H[i]);

  if(memcmp(ctx.H, result1, 32) == 0)
    printf(" test ok\n\n");
  else
    printf(" test failed\n\n");

  printf("test 2\n\n");
  SHA256_init(&ctx);
  SHA256_update(&ctx, test2, strlen(test2));
  SHA256_final(&ctx);

  printf("SHA256(\"%s\") = \n\t", test2);

  for(i = 0; i < 8; i++)
    printf("%08x", ctx.H[i]);

  if(memcmp(ctx.H, result2, 32) == 0)
    printf(" test ok\n\n");
  else
    printf(" test failed\n\n");

  return 0;
}

#endif // SHA256TEST


code:
/* This implementation of SHA-256 is based on an implementation in the
 * public domain, which was in turn based on another public domain
 * implementation of SHA-1 by Adam Back.
 *
 * 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 __SHA256_H
#define __SHA256_H

#include "../compat.h"

__M_BEGIN_DECLS

#include "../platform.h"

struct SHA256_ctx
{
  Uint32 H[8];
  Uint32 hbits;
  Uint32 lbits;
  Uint8 M[64];
  Uint8 mlen;
};

void SHA256_init(struct SHA256_ctx *ctx);
void SHA256_update(struct SHA256_ctx *ctx, const void *vdata, Uint32 data_len);
void SHA256_final(struct SHA256_ctx *ctx);

__M_END_DECLS

#endif // __SHA256_H

repo_name: pgimeno/megazeux

license: mit


code:
/* MegaZeux
 *
 * Copyright (C) 1996 Greg Janson
 *
 * 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 <string.h>
#include <stdio.h>
#include <dir.h>

char magic_code[16]="\xe6\x52\xeb\xf2\x6d\x4d\x4a\xb7\x87\xb2\x92\x88\xde\x91\x24";
long brd_pos[150];

void skip_layer(FILE *fp,unsigned char xor) {
  int xsiz,ysiz;
  int x=0,y=0;
  int runs;
  xsiz=fgetc(fp)^xor;
  xsiz+=(fgetc(fp)^xor)<<8;
  ysiz=fgetc(fp)^xor;
  ysiz+=(fgetc(fp)^xor)<<8;
  do {
    runs=fgetc(fp)^xor;
    if(runs<128) runs=1;
    else {
      runs^=128;
      fgetc(fp);
      }
    x+=runs;
  recap:
    if(x>=xsiz) {
      x-=xsiz;
      y++;
      goto recap;
      }
  } while(y<ysiz);
}

void main(void) {
  FILE *fp;
  ffblk ff;
  int t1;
  int t2,t3;
  char temp[5]="   \0";
  int pro_method;
  char password[15]="              ";
  int xor;
  unsigned int num_boards;

  printf("Fixing all version 2.00 .MZX and .MZB files...\n");

  //.MZX
  if(findfirst("*.MZX",&ff,0)) goto no_mzx;
  do {
    printf("\t%s... ",ff.ff_name);
    fp=fopen(ff.ff_name,"rb+");
    if(fp==NULL) {
      printf("Error opening file.\n");
      continue;
      }
    fseek(fp,25,SEEK_SET);
    pro_method=fgetc(fp);
    if(pro_method) fread(password,1,15,fp);
    fread(temp,1,3,fp);
    if(strcmp(temp,"MZ2")) {
      printf("Not a version 2.0? file.\n");
      fclose(fp);
      continue;
      }
    //xor code?
    if(pro_method) {
      for(t1=0;t1<15;t1++) {
        password[t1]^=magic_code[t1];
        password[t1]-=0x12+pro_method;
        password[t1]^=0x8D;
        }
      for(t1=strlen(password);t1<16;t1++)
        password[t1]=0;
      xor=85;
      for(t1=0;t1<15;t1++) {
        //For each byte, roll once to the left and xor in pw byte if it
        //is an odd character, or add in pw byte if it is an even character.
        xor<<=1;
        if(xor>255) xor^=257;//Wraparound from roll
        if(t1&1) {
          xor+=password[t1];//Add (even byte)
          if(xor>255) xor^=257;//Wraparound from add
          }
        else xor^=password[t1];//XOR (odd byte);
        }
      //To factor in protection method, add it in and roll one last time
      xor+=pro_method;
      if(xor>255) xor^=257;
      xor<<=1;
      if(xor>255) xor^=257;
      //Can't be 0-
      if(xor==0) xor=86;//(01010110)
      }
    else xor=0;
    //Jump to # of boards
    fseek(fp,4234,SEEK_SET);
    if(pro_method) fseek(fp,15,SEEK_CUR);
    if(!(num_boards=xor^fgetc(fp))) {
      num_boards=fgetc(fp)^xor;
      num_boards+=(fgetc(fp)^xor)<<8;
      fseek(fp,num_boards,SEEK_CUR);
      num_boards=fgetc(fp)^xor;
      }
    //Skip board names
    fseek(fp,num_boards*25,SEEK_CUR);
    //Get board positions
    for(t1=0;t1<num_boards;t1++) {
      t3=1;
      for(t2=0;t2<4;t2++) {
        if(fgetc(fp)!=xor) t3=0;
        }
      brd_pos[t1]=0;
      if(t3) //Deleted board
        fseek(fp,4,SEEK_CUR);
      else {
        for(t2=0;t2<4;t2++)
          brd_pos[t1]+=((long)(fgetc(fp)^xor))<<(t2*8);
        }
      }
    //Do each board
    for(t1=0;t1<num_boards;t1++) {
      if(!brd_pos[t1]) continue;
      fseek(fp,brd_pos[t1],SEEK_SET);
      fgetc(fp);//Overall size
      //Overlay?
      if(!(fgetc(fp)^xor)) {
        //Yep.
        fgetc(fp);
        //Skip two layers
        skip_layer(fp,xor);
        skip_layer(fp,xor);
        }
      else fseek(fp,-1,SEEK_CUR);
      //Skip normal six layers
      skip_layer(fp,xor);
      skip_layer(fp,xor);
      skip_layer(fp,xor);
      skip_layer(fp,xor);
      skip_layer(fp,xor);
      skip_layer(fp,xor);
      //In regular info.
      fseek(fp,206,SEEK_CUR);
      //Write a 00 00 00 00 scroll, and a FF FF FF FF lock
      //then a 00 00 00 player lock
      for(t2=0;t2<4;t2++)
        fputc(xor,fp);
      for(t2=0;t2<4;t2++)
        fputc(255^xor,fp);
      for(t2=0;t2<3;t2++)
        fputc(xor,fp);
      //Next board!
      printf("*");
      }
    fclose(fp);
    //Next file!
    printf(" Done!\n");
  } while(!findnext(&ff));
no_mzx:
  //.MZB
  if(findfirst("*.MZB",&ff,0)) return;
  do {
    printf("\t%s... ",ff.ff_name);
    fp=fopen(ff.ff_name,"rb+");
    if(fp==NULL) {
      printf("Error opening file.\n");
      continue;
      }
    fread(temp,1,4,fp);
    if(strcmp(temp,"\xFFMB2")) {
      printf("Not a version 2.0? file.\n");
      fclose(fp);
      continue;
      }
    fgetc(fp);//Overall size
    //Overlay?
    if(!fgetc(fp)) {
      //Yep.
      fgetc(fp);
      //Skip two layers
      skip_layer(fp,0);
      skip_layer(fp,0);
      }
    else fseek(fp,-1,SEEK_CUR);
    //Skip normal six layers
    skip_layer(fp,0);
    skip_layer(fp,0);
    skip_layer(fp,0);
    skip_layer(fp,0);
    skip_layer(fp,0);
    skip_layer(fp,0);
    //In regular info.
    fseek(fp,206,SEEK_CUR);
    //Write a 00 00 00 00 scroll, and a FF FF FF FF lock
    //then a 00 00 00 player lock
    for(t2=0;t2<4;t2++)
      fputc(0,fp);
    for(t2=0;t2<4;t2++)
      fputc(255,fp);
    for(t2=0;t2<3;t2++)
      fputc(0,fp);
    fclose(fp);
    //Next file!
    printf("Done!\n");
  } while(!findnext(&ff));
  //Done!
  printf("\nDone with all files.\n\n");
}


code:
/* MegaZeux
 *
 * Copyright (C) 1996 Greg Janson
 *
 * 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 <stdio.h>
#include <dir.h>
#include <string.h>

char magic_code[16]="\xe6\x52\xeb\xf2\x6d\x4d\x4a\xb7\x87\xb2\x92\x88\xde\x91\x24";
int pro_method, pw_size;
char password[16], xor_val;

int get_pw_xor_code(void)
{
  int work = 85; // Start with 85... (01010101)
  int t1;
  if(pro_method == 0)
    return 0;
  // Clear pw after first null
  for(t1 = strlen(password); t1 < 16; t1++)
    password[t1] = 0;

  for(t1 = 0; t1 < 15; t1++)
  {
    //For each byte, roll once to the left and xor in pw byte if it
    //is an odd character, or add in pw byte if it is an even character.
    work <<= 1;
    if(work > 255)
      work ^= 257;//Wraparound from roll

    if(t1 & 1)
    {
      work += password[t1]; // Add (even byte)
      if(work > 255)
       work ^= 257;//Wraparound from add
    }
    else
    {
      work ^= password[t1]; // XOR (odd byte);
    }
  }
  // To factor in protection method, add it in and roll one last time
  work += pro_method;
  if(work > 255)
    work ^= 257;

  work <<= 1;
  if(work > 255)
    work ^= 257;

  // Can't be 0-
  if(work == 0)
    work = 86;//(01010110)
  // Done!
  return work;
}

int main(int argc, char *argv[])
{
  FILE *source;
  FILE *dest;

  int i;
  int len;
  printf("\n\n");
  if(argc < 2)
  {
    printf("Usage:\n\nGETPW file.mzx [-d]\n\n-d will de-protect the file.\n\n\a");
    return 0;
  }

  source = fopen(argv[1], "rb");
  fseek(source, 25, SEEK_CUR);
  pro_method = fgetc(source);//Protection method

  if(pro_method)
  {
    // Password
    fread(password, 1, 15, source);

    // First, normalize password...
    for(i = 0; i < 15; i++)
    {
      password[i] ^= magic_code[i];
      password[i] -= 0x12 + pro_method;
      password[i] ^= 0x8D;
    }

    // Show!
    printf("Password: %s\n", password);

    // Deprotect?
    if((argc > 2) && ((argv[2][1] == 'd') || (argv[2][1] == 'D')))
    {
      int num_boards;
      int offset_low_byte;

      printf("Deprotecting... (to file NO_PW.MZX)\n");
      // Xor code
      xor_val = get_pw_xor_code();
      printf("xor val: %d\n", xor_val);
      // De-xor entire file
      dest = fopen("NO_PW.MZX", "wb");
      fseek(source, 0, SEEK_END);
      len = ftell(source);
      fseek(source, 0, SEEK_SET);

      for(i = 0; i < 25; i++)
      {
        fputc(fgetc(source), dest);
      }

      fputc(0, dest);
      fseek(source, 19, SEEK_CUR);

      fputs("M\x02\x11", dest);
      len -= 44;

      for(; len > 0; len--)
      {
        fputc(fgetc(source) ^ xor_val, dest);
      }

      // Must fix all the absolute file positions so that they're 15
      // less now
      fseek(source, 4245, SEEK_SET);
      fseek(dest, 4230, SEEK_SET);

      offset_low_byte = (fgetc(source) ^ xor_val) & 0xFF;
      fputc(offset_low_byte - 15, dest);
      if(offset_low_byte < 15)
      {
        fputc((fgetc(source) ^ xor_val) - 1, dest);
      }
      else
      {
        fputc(fgetc(source) ^ xor_val, dest);
      }

      fputc(fgetc(source) ^ xor_val, dest);
      fputc(fgetc(source) ^ xor_val, dest);

      num_boards = (fgetc(source) ^ xor_val) & 0xFF;

      // If custom SFX is there, run through and skip it
      if(!num_boards)
      {
        int sfx_length = (fgetc(source) ^ xor_val) & 0xFF;
        sfx_length |= ((fgetc(source) ^ xor_val) & 0xFF) << 8;
        fseek(source, sfx_length, SEEK_CUR);
        printf("%d\n", sfx_length);
        num_boards = (fgetc(source) ^ xor_val) & 0xFF;
      }

      // Skip titles
      fseek(source, 25 * num_boards, SEEK_CUR);

      // Synchronize source and dest positions
      fseek(dest, ftell(source) - 15, SEEK_SET);
      printf("dest %d\n", ftell(dest));

      // Offset boards
      for(i = 0; i < num_boards; i++)
      {
        // Skip length
        fseek(source, 4, SEEK_CUR);
        fseek(dest, 4, SEEK_CUR);

        // Get offset
        offset_low_byte = (fgetc(source) ^ xor_val) & 0xFF;
        fputc(offset_low_byte - 15, dest);
        if(offset_low_byte < 15)
        {
          fputc((fgetc(source) ^ xor_val) - 1, dest);
        }
        else
        {
          fputc(fgetc(source) ^ xor_val, dest);
        }
        fputc(fgetc(source) ^ xor_val, dest);
        fputc(fgetc(source) ^ xor_val, dest);
      }

      fclose(dest);
    }
  }

  fclose(source);

  return 0;
}


code:
/* MegaZeux
 *
 * Copyright (C) 1996 Greg Janson
 *
 * 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
 */

/* Converts a version 1.0? .MZX or .MZB file to a version 2.00 file. */

#include <stdio.h>
#include <dir.h>
#include <string.h>
#include <alloc.h>

void convert(char far *fn);
void rle_to_rle2(unsigned char huge *&source,unsigned char huge *&dest);
long convert_board(unsigned char huge *loc);//Returns size
void convert_robot_line(unsigned char far *source,unsigned char far *dest);
extern char far *cmd_formats[256];

//Destination for board conversion
unsigned char huge *newboard;//Must allocate 210000 bytes

void main(int argc,char *argv[]) {
  int t1;
  printf("\n\n");
  newboard=(unsigned char huge *)farmalloc(210000L);
  if(newboard==NULL) {
    printf("ERROR: Out of memory\n\n\a");
    return;
    }
  if(argc<2) {
    printf("VER1TO2.EXE converts MegaZeux worlds (.MZX) and boards (.MZB) from version\n");
    printf("1.00g, 1.01, 1.02, or 1.03 of MegaZeux to version 2.00 of MegaZeux. It is\n");
    printf("run from the command line as follows:\n\n");
    printf("VER1TO2 file.ext [file.ext ...]\n\n");
    printf("VER1TO2 can accept multiple files and they may include wildcards. The files\n");
    printf("do not all have to be the same type. Corrupted files, non-board/non-world\n");
    printf("files, and version 2.00 files will all be skipped over with an error. Note\n");
    printf("that VER1TO2 verifies the extension of the file, so the file must have the\n");
    printf("proper extension of .MZX or .MZB.\n\n\a");
    return;
    }
  //Do files
  for(t1=1;t1<argc;t1++)
    convert(argv[t1]);
  //Done
  printf("\nAll files converted!\n\n");
  farfree(newboard);
}

unsigned char far magic_code[16]="\xe6\x52\xeb\xf2\x6d\x4d\x4a\xb7\x87\xb2\x92\x88\xde\x91\x24";
unsigned char far id_dmg[128]={
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,
  0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,10,0,10,5,5,
  0,0,0,0,0,0,0,0,0,0,0,10,10,0,10,10,
  10,0,0,10,10,10,10,10,10,10,10,10,0,0,10,10,
  0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0 };
unsigned char far palette[48]={
  0,0,0,0,0,42,0,42,0,0,42,42,
  42,0,0,42,0,42,42,21,0,42,42,42,
  21,21,21,21,21,63,21,63,21,21,63,63,
  63,21,21,63,21,63,63,63,21,63,63,63 };
unsigned char far global_robot[43]={
  2,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,1,0,0,1,
  0,0,0,1,0,0,0,0,0,0,0,0,
  0,0,1,0,0,255,0 };

long orig_board_size[150];
long orig_board_location[150];
long new_board_stat_ptr[150];

void convert(char far *fn) {
  int t1,t2;
  char type=1;//1=board, 0=world
  char temp_name[13];
  FILE *source;
  FILE *dest;
  unsigned char huge *cboard=NULL;

  //Verify extension
  t2=1;//Problem
  for(t1=0;t1<strlen(fn);t1++)
    if(fn[t1]=='.') break;
  if(t1<strlen(fn)) {
    if(!stricmp(&fn[++t1],"MZX")) type=t2=0;
    else if(!stricmp(&fn[t1],"MZB")) {
      type=1;
      t2=0;
      }
    }
  if(t2) {
    printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
    return;
    }
  //Make sure it exists
  source=fopen(fn,"rb+");
  if(source==NULL) {
    printf("ERROR: Non-existant file- %s\n",fn);
    return;
    }
  //Verify file type
  if(type) {
    //Verify board file
    fseek(source,0,SEEK_SET);
    t1=fgetc(source);
    if(t1==255) {
      fclose(source);
      printf("ERROR: File is already a version 2.00 or greater .MZB file (%s)\n",fn);
      return;
      }
    //Our only way of file type verification for older .MZB files-
    //   Make sure x/y sizes are 1-100
    //   Make sure next byte is NOT a 0
    if((t1>100)||(t1==0)) {
      fclose(source);
      printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
      return;
      }
    t1=fgetc(source);
    if((t1>100)||(t1==0)) {
      fclose(source);
      printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
      return;
      }
    if(fgetc(source)==0) {
      fclose(source);
      printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
      return;
      }
    }
  else {
    fseek(source,25,SEEK_SET);
    t1=fgetc(source);
    if(t1) fseek(source,16,SEEK_CUR);//Skip over pw
    if(fgetc(source)!='M') type=1;
    if(fgetc(source)!='Z') type=1;
    t1=fgetc(source);
    if(((t1>='2')&&(t1<='9'))) {
      printf("ERROR: File is already a version 2.00 or greater .MZX file (%s)\n",fn);
      fclose(source);
      return;
      }
    if(t1!='X') type=1;
    if(type) {
      fclose(source);
      printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
      return;
      }
    }
  //We now know whether it is a .MZB or .MZX file, and that it is the
  //right version.
  fclose(source);
  //Rename to a temp file
  strcpy(temp_name,"~V1TO2XXXXXX");
  mktemp(temp_name);
  rename(fn,temp_name);
  //Open both files
  dest=fopen(fn,"wb+");
  if(dest==NULL) {
    printf("ERROR: Error opening file for output (%s)\n",fn);
    rename(temp_name,fn);
    return;
    }
  source=fopen(temp_name,"rb");
  if(source==NULL) {
    fclose(dest);
    printf("ERROR: Error opening file for input (%s, originally %s)\n",
      temp_name,fn);
    rename(temp_name,fn);
    return;
    }
  //Everything is ready!
  printf("Converting %s file %s... ",type?"board":"world",fn);
  switch(type) {
    case 0:
      //World file conversion
int _cpt;
#define copy_bytes(num) { for(_cpt=0;_cpt<num;_cpt++) fputc(fgetc(source),dest); }

      int pro_method,pw_size;
      unsigned char password[16];

      copy_bytes(25);//Title
      fputc(pro_method=fgetc(source),dest);//Protection method
      if(pro_method) {//Password
        pw_size=fgetc(source);
        fread(password,1,15,source);
        //First, normalize password...
        for(t1=0;t1<15;t1++) {
          password[t1]^=magic_code[t1];
          password[t1]-=0x12+pro_method;
          password[t1]^=0x8D;
          }
        password[pw_size]=0;
        for(t1=strlen(password);t1<16;t1++)
          password[t1]=0;
        //Write the new password
        for(t1=0;t1<15;t1++) {
          t2=password[t1]^0x8D;
          t2+=pro_method+0x12;
          t2^=magic_code[t1];
          fputc(t2,dest);
          }
        }
      fseek(source,3,SEEK_CUR);
      fwrite("MZ2",1,3,dest);//Code
      copy_bytes(3584);//Character set
      copy_bytes(34);//Idchars, before goop
      fputc(176,dest);
      fgetc(source);//Idchars, goop
      copy_bytes(271);//Idchars, after goop

      //We WILL be writing the rest of the Idchars.
      //First, we need to read the entire remainder into variables.

      unsigned char status_counters[60];
      unsigned char bullet_chars[4];
      unsigned char player_char;
      unsigned char edge_color,player_color,bullet_color,missile_color;
      unsigned char first_board,eg_board,die_board;
      int eg_x,eg_y,die_x,die_y;
      int lives,lives_limit,health,health_limit;
      int nme_hurt_nme,gosfx;

      fread(status_counters,1,60,source);
      fread(bullet_chars,1,4,source);
      player_char=fgetc(source);
      fseek(source,3,SEEK_CUR);//Skip saved player position
      edge_color=fgetc(source);
      player_color=fgetc(source);
      bullet_color=fgetc(source);
      missile_color=fgetc(source);
      first_board=fgetc(source);
      eg_board=fgetc(source);
      die_board=fgetc(source);
      eg_x=fgetc(source);
      eg_y=fgetc(source);
      die_x=fgetc(source);
      die_y=fgetc(source);
      fread(&lives,2,1,source);
      fread(&lives_limit,2,1,source);
      fread(&health,2,1,source);
      fread(&health_limit,2,1,source);
      nme_hurt_nme=fgetc(source);
      gosfx=fgetc(source);
      fgetc(source);//Blank spot

      //Source is at # of boards. Now we complete the Idchars, inserting
      //proper info. Then spew remainder of info as well.

      for(t1=0;t1<3;t1++)
        fwrite(bullet_chars,1,4,dest);//Bullet char arrays x3
      for(t1=0;t1<4;t1++)
        fputc(player_char,dest);//Player char x4
      fputc(player_color,dest);
      fputc(missile_color,dest);
      for(t1=0;t1<3;t1++)
        fputc(bullet_color,dest);//Bullet color x3
      fwrite(id_dmg,1,128,dest);//Id dmg portion

      //Stuff after idchars...

      fwrite(status_counters,1,60,dest);
      for(t1=0;t1<30;t1++)
        fputc(0,dest);//Blank status counters x2
      fputc(edge_color,dest);
      fputc(first_board,dest);
      if(eg_board==128) eg_board=255;
      fputc(eg_board,dest);
      if(die_board>=128) die_board=383-die_board;//128 -> 255, 129 -> 254
      fputc(die_board,dest);
      fwrite(&eg_x,2,1,dest);
      fwrite(&eg_y,2,1,dest);
      fputc(gosfx,dest);
      fwrite(&die_x,2,1,dest);
      fwrite(&die_y,2,1,dest);
      fwrite(&lives,2,1,dest);
      fwrite(&lives_limit,2,1,dest);
      fwrite(&health,2,1,dest);
      fwrite(&health_limit,2,1,dest);
      fputc(nme_hurt_nme,dest);
      fputc(0,dest);//Clear projectiles (no)
      fputc(0,dest);//Only from swap world (no)
      fwrite(palette,1,48,dest);

      //Now we need to store the position of the global robot.
      //We'll reserve space, save the location, and wait...

      long glrob_pos_ptr=ftell(dest);
      fwrite("\0\0\0\0",1,4,dest);

      //Now get and copy number of boards...

      int num_boards=fgetc(source);
      fputc(num_boards,dest);

      //...copy names of boards...

      copy_bytes(num_boards*25);

      //...and get old board sizes and positions. Also reserve dest
      //space for the new stats at this time.

      for(t1=0;t1<num_boards;t1++) {
        fread(&orig_board_size[t1],4,1,source);
        fread(&orig_board_location[t1],4,1,source);
        new_board_stat_ptr[t1]=ftell(dest);
        fwrite("\0\0\0\0\0\0\0\0",1,8,dest);
        }

      //Global robot...

      long glrob_pos=ftell(dest);
      fseek(dest,glrob_pos_ptr,SEEK_SET);
      fwrite(&glrob_pos,4,1,dest);
      fseek(dest,glrob_pos,SEEK_SET);
      fwrite(global_robot,1,43,dest);

      //Do boards.

      for(t1=0;t1<num_boards;t1++) {
        printf("\n   Board #%d... ",t1);
        //Empty board?
        if(!orig_board_size[t1]) {
          printf("(blank)");
          continue;
          }
        //Do board t1- Reserve space...
        cboard=(unsigned char huge *)farmalloc(orig_board_size[t1]);
        if(cboard==NULL) {
          printf("ERROR: Out of memory (board %d, file %s) Conversion aborted\n",t1,fn);
          goto abort;
          }
        //Seek to board
        fseek(source,orig_board_location[t1],SEEK_SET);
        //Read in board
        long done=0;
        unsigned char huge *tptr=cboard;
        do {
          if((orig_board_size[t1]-done)>65535U) {
            fread(tptr,65535U,1,source);
            tptr+=65535U;
            done+=65535U;
            }
          else {
            fread(tptr,orig_board_size[t1]-done,1,source);
            break;
            }
        } while(done<orig_board_size[t1]);
        //Convert board
        long new_size=convert_board(cboard);
        if(!new_size) {
          //Board was aborted- No need to change stats.
          farfree(cboard);
          continue;
          }
        //Remember location for new board
        long new_loc=ftell(dest);
        //Write new board
        done=0;
        tptr=newboard;
        do {
          if((new_size-done)>65535U) {
            fwrite(tptr,65535U,1,dest);
            tptr+=65535U;
            done+=65535U;
            }
          else {
            fwrite(tptr,new_size-done,1,dest);
            break;
            }
        } while(done<new_size);
        //Save stats of new board
        fseek(dest,new_board_stat_ptr[t1],SEEK_SET);
        fwrite(&new_size,4,1,dest);
        fwrite(&new_loc,4,1,dest);
        fseek(dest,0,SEEK_END);
        //Next board!
        farfree(cboard);
        }

      //Password convert file
      if(pro_method) {
        printf("\n   Password encoding...");
        //Calculate xor code for file
        int xor=85;
        for(t1=0;t1<15;t1++) {
          //For each byte, roll once to the left and xor in pw byte if it
          //is an odd character, or add in pw byte if it is an even character.
          xor<<=1;
          if(xor>255) xor^=257;//Wraparound from roll
          if(t1&1) {
            xor+=password[t1];//Add (even byte)
            if(xor>255) xor^=257;//Wraparound from add
            }
          else xor^=password[t1];//XOR (odd byte);
          }
        //To factor in protection method, add it in and roll one last time
        xor+=pro_method;
        if(xor>255) xor^=257;
        xor<<=1;
        if(xor>255) xor^=257;
        //Can't be 0-
        if(xor==0) xor=86;//(01010110)
        //NOW convert entire dest file, after MZ2.
        long end=ftell(dest),cur;
        unsigned char bfr[512];
        int bfrsiz;
        fseek(dest,44,SEEK_SET);
        do {
          fseek(dest,0,SEEK_CUR);
          cur=ftell(dest);
          if((end-cur)<512) {
            bfrsiz=end-cur;
            fread(bfr,1,bfrsiz,dest);
            }
          else {
            fread(bfr,1,512,dest);
            bfrsiz=512;
            }
          for(t1=0;t1<512;t1++)
            bfr[t1]^=xor;
          fseek(dest,-bfrsiz,SEEK_CUR);
          fwrite(bfr,1,bfrsiz,dest);
        } while(end!=ftell(dest));
        }
      //Done!
      break;
    case 1:
      //Board file conversion
      //Header for new file

      fwrite("\xFFMB2",1,4,dest);

      //Get size of old board

      fseek(source,0,SEEK_END);
      long size=ftell(source)-25;
      fseek(source,0,SEEK_SET);

      //Allocate memory

      cboard=(unsigned char huge *)farmalloc(size);
      if(cboard==NULL) {
        printf("ERROR: Out of memory, conversion aborted (%s)\n",fn);
        goto abort;
        }

      //Read in board

      long done=0;
      unsigned char huge *tptr=cboard;
      do {
        if((size-done)>65535U) {
          fread(tptr,65535U,1,source);
          tptr+=65535U;
          done+=65535U;
          }
        else {
          fread(tptr,size-done,1,source);
          break;
          }
      } while(done<size);

      //Convert board

      long new_size=convert_board(cboard);

      if(!new_size) goto abort;//Board was aborted

      //Write new board

      done=0;
      tptr=newboard;
      do {
        if((new_size-done)>65535U) {
          fwrite(tptr,65535U,1,dest);
          tptr+=65535U;
          done+=65535U;
          }
        else {
          fwrite(tptr,new_size-done,1,dest);
          break;
          }
      } while(done<new_size);

      //Copy board title

      fseek(source,-25,SEEK_END);
      copy_bytes(25);
      farfree(cboard);
      break;
    }
  printf("\n   Done!\n");
  fclose(source);
  fclose(dest);
  unlink(temp_name);
  return;
abort:
  fclose(source);
  fclose(dest);
  unlink(fn);
  rename(temp_name,fn);
}

void rle_to_rle2(unsigned char huge *&source,unsigned char huge *&dest) {
  //Converts an rle compressed layer from source to an rle2 compressed
  //layer on dest.
  int xsiz,ysiz;
  int runs,runb;
  int size,done=0;
  //Check for lonely run of 0 from last rle
  if(*source==0) source=source+2;
  //Sizes
  xsiz=*source; source=source+1;
  ysiz=*source; source=source+1;
  *dest=xsiz; dest=dest+1;
  *dest=0; dest=dest+1;
  *dest=ysiz; dest=dest+1;
  *dest=0; dest=dest+1;
  size=xsiz*ysiz;
  //Convert. Source format- RUNSIZE, RUNBYTE, ...
  //Dest format- ( BYTE ) | ( RUNSIZE+128, RUNBYTE ), ...

  //Conversion method- Read RUNSIZE and RUNBYTE. If RUNSIZE is one,
  // write RUNBYTE unless it is >127, then instead write 129,RUNBYTE.
  // If RUNSIZE is from two to 127, write RUNSIZE+128,RUNBYTE. If
  // RUNSIZE is from 127 to 254, write 255,RUNBYTE,RUNSIZE+1,RUNBYTE.
  // If RUNSIZE is 255, write 255,RUNBYTE,255,RUNBYTE then write
  // RUNBYTE as if RUNSIZE were 1 (see above)

  do {
    runs=*source; source=source+1;
    runb=*source; source=source+1;
    if(!runs) continue;
    else if(runs==1) {
    single_byte:
      if(runb<128) {
        *dest=runb; dest=dest+1;
        }
      else {
        *dest=129; dest=dest+1;
        *dest=runb; dest=dest+1;
        }
      goto end_byte;
      }
    else if(runs<128) {
      *dest=runs|128; dest=dest+1;
      *dest=runb; dest=dest+1;
      }
    else if(runs<255) {
      *dest=255; dest=dest+1;
      *dest=runb; dest=dest+1;
      *dest=runs+1; dest=dest+1;
      *dest=runb; dest=dest+1;
      }
    else {
      *dest=255; dest=dest+1;
      *dest=runb; dest=dest+1;
      *dest=255; dest=dest+1;
      *dest=runb; dest=dest+1;
      goto single_byte;
      }
  end_byte:
    done+=runs;
  } while(done<size);
  //Done!
}

long convert_board(unsigned char huge *loc) {//Return size
  //Converts a stripped board (no header) in loc[] to newboard[].
  //Both are already allocated.
  int t1,t2,t3;
  unsigned char huge *brd=newboard;//use brd[] not newboard[]
  unsigned char huge *robptr;//Pointer to robot size storage
  int num_robots,num_scrolls,num_sensors;
  unsigned int item_size,new_isize,done;//Program/scroll size, position within
  unsigned char robold_line[256];
  unsigned char robnew_line[256];

  *brd=2; brd=brd+1;//2 for a 100x100 board
  //Translate all 6 layers
  printf("Layers");
  for(t1=0;t1<6;t1++) {
    printf(".");
    rle_to_rle2(loc,brd);
    }
  printf(" Misc... ");
  //Next 39 characters (up thru input_size) are copied exactly
  for(t1=0;t1<39;t1++) {
    *brd=*loc;
    brd=brd+1;
    loc=loc+1;
    }
  //Rememer next info
  unsigned char mod_vol=*loc; loc=loc+1;
  unsigned char pl_lock_ns=*loc; loc=loc+1;
  unsigned char pl_lock_ew=*loc; loc=loc+1;
  unsigned char pl_lock_att=*loc; loc=loc+1;
  //Copy input string
  for(t1=0;t1<81;t1++) {
    *brd=*loc;
    brd=brd+1;
    loc=loc+1;
    }
  //Skip 9 bytes (blanks and effect durations which are now global)
  loc=loc+9;
  //Copy last dir moved, adding in a faced dir of south (+16)
  *brd=(*loc)|16;
  brd=brd+1;
  loc=loc+1;
  //Copy bottom message
  for(t1=0;t1<81;t1++) {
    *brd=*loc;
    brd=brd+1;
    loc=loc+1;
    }
  //Copy bmesg cycle, lazer cycle, and mesg row
  *brd=*loc; brd=brd+1; loc=loc+1;
  *brd=*loc; brd=brd+1; loc=loc+1;
  *brd=*loc; brd=brd+1; loc=loc+1;
  //Copy bmesg column, changing 0 to 255
  unsigned char bmesg_col=*loc; loc=loc+1;
  if((bmesg_col==0)||(bmesg_col>79)) bmesg_col=255;
  *brd=bmesg_col; brd=brd+1;
  //Copy x and y scroll bytes, converting to words
  unsigned int scroll_x=(unsigned int)(signed char)*loc; loc=loc+1;
  unsigned int scroll_y=(unsigned int)(signed char)*loc; loc=loc+1;
  *brd=scroll_x&255; brd=brd+1;
  *brd=scroll_x>>8; brd=brd+1;
  *brd=scroll_y&255; brd=brd+1;
  *brd=scroll_y>>8; brd=brd+1;
  //Write misc. info and saved info
  for(t1=0;t1<4;t1++) {
    *brd=255;//Locked x/y info
    brd=brd+1;
    }
  *brd=pl_lock_ns; brd=brd+1;
  *brd=pl_lock_ew; brd=brd+1;
  *brd=pl_lock_att; brd=brd+1;
  *brd=mod_vol; brd=brd+1;
  *brd=0; brd=brd+1;//Volume increase (none)
  *brd=mod_vol; brd=brd+1;//Volume target (same as current vol)
  //Convert robots
  *brd=num_robots=*loc; loc=loc+1; brd=brd+1;
  printf("Robots... ");
  if(num_robots) {
    for(t1=0;t1<num_robots;t1++) {
      //Convert a robot
      //Copy and annotate structure, saving robot's size
      item_size=*loc; loc=loc+1;
      item_size+=(*loc)<<8; loc=loc+7;
      robptr=brd;//Pointer to robot size
      *brd=item_size&255; brd=brd+1;
      *brd=item_size>>8; brd=brd+3;
      if(item_size>31744) {
        printf("\n   ERROR: Robot over 31k in length, board aborted %d",item_size);
        return 0;
        }
      //Name, char, first word of curr.line
      for(t2=0;t2<18;t2++) {
        *brd=*loc; brd=brd+1; loc=loc+1;
        }
      //Skip second word of curr.line
      loc=loc+2;
      //Copy remaining 9 bytes
      for(t2=0;t2<9;t2++) {
        *brd=*loc; brd=brd+1; loc=loc+1;
        }
      //Fill in remainder of v2.00 struct (x, y, future x3, used, loop)
      for(t2=0;t2<7;t2++) {
        *brd=0; brd=brd+1;
        }
      *brd=(item_size!=0); brd=brd+1;
      *brd=0; brd=brd+1;
      *brd=0; brd=brd+1;
      //Now convert program.
      if(item_size) {
        new_isize=done=0;
        do {
          t2=*loc; loc=loc+1; done++;//Cmd size
          if((!t2)||(t2==255)) {
            //Same thing
            *brd=t2;
            brd=brd+1;
            new_isize++;
            continue;
            }
          //Read in actual line
          robold_line[0]=t2;
          for(t3=0;t3<t2;) {
            robold_line[++t3]=*loc; loc=loc+1;
            }
          robold_line[++t3]=*loc; loc=loc+1;
          done+=t3;
          //Convert line
          convert_robot_line(robold_line,robnew_line);
          //Write line
          t2=robnew_line[0];
          for(t3=0;t3<t2+2;t3++) {
            *brd=robnew_line[t3]; brd=brd+1;
            }
          new_isize+=t2+2;
          //Loop
        } while(done<item_size);
        //Write new size
        robptr[0]=new_isize&255;
        robptr[1]=new_isize>>8;
        }
      }
    }
  //Convert scrolls
  printf("Scrolls... ");
  *brd=num_scrolls=*loc; loc=loc+1; brd=brd+1;
  if(num_scrolls) {
    for(t1=0;t1<num_scrolls;t1++) {
      //Convert a scroll
      //Copy and annotate structure, saving scroll's size
      *brd=*loc; brd=brd+1; loc=loc+1;
      *brd=*loc; brd=brd+3; loc=loc+5;
      item_size=*loc; loc=loc+1;
      item_size+=(*loc)<<8; loc=loc+3;
      *brd=item_size&255; brd=brd+1;
      *brd=item_size>>8; brd=brd+1;
      *brd=(item_size!=0); brd=brd+1;
      if(item_size>31744) {
        printf("\n   ERROR: Scroll over 31k in length, board aborted");
        return 0;
        }
      //Now copy message, of length item_size
      if(item_size) {
        for(t2=0;t2<item_size;t2++) {
          *brd=*loc; brd=brd+1; loc=loc+1;
          if((loc[-1]=='\n')||(loc[-1]==1)) {
            //Check for '!' lines w/o \n or 0.
            if(*loc=='!') {
              if((loc[1]!='\n')&&(loc[1]!=0)) {
                *brd=' '; brd=brd+1; loc=loc+1;
                *brd=' '; brd=brd+1; loc=loc+1;
                t2+=2;
                }
              }
            }
          }
        }
      }
    }
  //Convert sensors
  printf("Sensors... ");
  *brd=num_sensors=*loc; loc=loc+1; brd=brd+1;
  if(num_sensors) {
    for(t1=0;t1<num_sensors;t1++) {
      //Convert a sensor
      //Copy and annotate structure
      for(t2=0;t2<31;t2++) {
        *brd=*loc; brd=brd+1; loc=loc+1;
        }
      *brd=1; brd=brd+1;
      }
    }
  //Return bytes used
  printf("Done!");
  return brd-newboard;
}

void convert_robot_line(unsigned char far *source,unsigned char far *dest) {
  int cmd=source[1];
  int sp=2,dp=2,cp=0;//Source/Dest/Cmd position ptr
  int t1,t2;
  dest[1]=cmd;
  //Format- LEN CMD PARAMS LEN
  //New param format- 0 then 2 byte number OR # then #-length string
  if(cmd_formats[cmd][0]=='O') {
    //Outdated
    if(cmd_formats[cmd][1]=='S') {
      //Special case- if player (not) [dir] [str]
      //Becomes-  if (not) touching [dir] [str]
      dest[1]=cmd-46;//cmd 18 or 19
      dest[dp++]=0;
      dest[dp++]=3;//Condition of touching
      dest[dp++]=source[sp++];//Direction
      //Now we need to convert a string
      cp=2;//So we exit the loop afterwards
      goto str_conv;
      }
    else {
      //Change dest cmd, then use remainder of format
      cp=1;
      switch(cmd) {
        case 13:
        case 14:
        case 15:
          dest[1]=cmd-3;
          break;
        case 17:
          dest[1]=16;
          break;
        case 158:
          dest[1]=40;
          break;
        case 166:
          dest[1]=153;
          break;
        case 167:
          dest[1]=139;
          break;
        }
      goto normal_conv;
      }
    }
  else {
  normal_conv:
    //Normal conversion
    while(cmd_formats[cmd][cp]) {
      //Get type of parameter
      t1=cmd_formats[cmd][cp++];
      //Convert
      switch(t1) {
        case 1:
        case 10:
          //Two byte number conversion (also works for conditions)
          dest[dp++]=0;
          dest[dp++]=source[sp++];
          dest[dp++]=source[sp++];
          break;
        case 2:
        case 4:
        case 6:
        case 7:
        case 8:
        case 9:
          //One byte unsigned number conversion
          dest[dp++]=0;
          dest[dp++]=source[sp++];
          dest[dp++]=0;
          break;
        case 3:
        str_conv:
          //String conversion (old format- null terminated)
          t1=dp++;//Save location for size
          t2=0;//Size of string
          while(source[sp]) {
            if(source[sp]=='&') {//Replcae & with &&
              if((cmd==38)||(cmd==102)||(cmd==109)||(cmd==111)||
                (cmd==121)||(cmd==122)||(cmd==145)||(cmd==103)||
                (cmd==104)||(cmd==105)||(cmd==116)||(cmd==117)) {
                  dest[dp++]='&';
                  t2++;
                  }
              }
            dest[dp++]=source[sp++];
            t2++;
            };
          dest[dp++]=source[sp++];
          dest[t1]=t2+1;
          break;
        case 5:
          //Color (next source byte holds bit 256)
          dest[dp++]=0;
          dest[dp++]=source[sp++];
          dest[dp++]=source[sp]>>7;
          break;
        case 11:
          //Thing conversion
          dest[dp++]=0;
          dest[dp++]=source[sp++]&127;
          dest[dp++]=0;
          break;
        case 12:
          //Parameter conversion
          dest[dp++]=0;
          t1=source[sp++];
          if(t1) {
            dest[dp++]=t1;
            dest[dp++]=0;
            }
          else {
            dest[dp++]=0;
            dest[dp++]=1;
            }
          break;
        case 13:
          //Missing parameter conversion
          dest[dp++]=0;
          dest[dp++]=0;
          dest[dp++]=1;
          break;
        case 14:
          //Signed number (1-byte) conversion
          dest[dp++]=0;
          t1=(signed int)(signed char)source[sp++];
          dest[dp++]=((unsigned int)t1)&255;
          dest[dp++]=((unsigned int)t1)>>8;
          break;
        }
      //Loop until done
      };
    }
  //Done with this line- store new size
  dest[0]=dp-1;
  dest[dp]=dp-1;
}

//New (and old, usually) command formats.
//1- number
//2- number (one-byte originally)
//3- string
//4- char
//5- color (see thing for bit 256 originally)
//6- color NOT with a thing
//7- direction
//8- item
//9- conditional
//A- condition
//B- thing
//C- param (convert 0 to 256)
//D- param (originally not there, use a 256)
//E- number (one-byte signed originally)

//Only commands avail. in ver 1.03 are listed.

char far *cmd_formats[256]={
  "",
  "",
  "\x02",
  "\x02",
  "\x07\x02",
  "\x07",
  "\x05\x0B\x0C",
  "\x04",
  "\x05",
  "\x0E\x0E",
  "\x03\x01",
  "\x03\x01",
  "\x03\x01",
  "O\x03\x03",//ODT
  "O\x03\x03",//ODT
  "O\x03\x03",//ODT
  "\x03\x09\x01\x03",
  "O\x03\x09\x03\x03",//ODT
  "\x0A\x03",
  "\x0A\x03",
  "\x05\x0B\x0D\x03",
  "\x05\x0B\x0D\x03",
  "\x05\x0B\x0D\x07\x03",
  "\x05\x0B\x0D\x07\x03",
  "\x05\x0B\x0D\x0E\x0E\x03",
  "\x0E\x0E\x03",
  "\x07\x05\x0B\x0D\x03",
  "\x03",
  "\x03",
  "\x03",
  "\x03\x03",
  "\x02",
  "\x05\x0B\x0C\x07",
  "\x01\x08",
  "\x01\x08",
  "\x01\x08\x03",
  "",
  "",
  "\x03",
  "\x01\x03",
  "\x02",
  "",
  "",
  "\x03",
  "",
  "\x03",
  "",
  "",//BLANK LINE
  "\x02",
  "\x03",
  "\x07",
  "",
  "",
  "\x07\x03",
  "\x03\x02",
  "\x03\x02",
  "",
  "",
  "",
  "",
  "",
  "\x07",
  "\x07\x03",
  "\x0E\x0E",
  "OS",//ODT SPECIAL
  "OS",//ODT SPECIAL
  "\x0E\x0E\x03",
  "\x07",
  "\x07\x03",
  "",
  "",
  "\x07\x07",
  "\x07",
  "\x07",
  "\x07",
  "\x07",
  "\x07",
  "\x07",
  "\x07\x02",
  "\x05\x0B\x0C\x0E\x0E",
  "",
  "\x0E\x0E\x03",
  "\x03",
  "\x0E\x0E",
  "\x07",
  "\x07",
  "\x0E\x0E",
  "\x04",
  "\x04",
  "\x04",
  "\x04",
  "\x05",
  "\x05\x03",
  "\x05",
  "\x05\x03",
  "\x03\x01\x01",
  "\x03\x01\x01",
  "\x03\x01\x01",
  "\x01\x08\x01\x08\x03",
  "\x07\x03",
  "\x05\x0B\x0C\x07",
  "\x03",
  "\x03",
  "\x03",
  "\x03\x03",
  "\x03\x03\x03",
  "\x03",
  "\x03",
  "\x03",
  "\x03\x0E\x0E",
  "\x07\x02",
  "\x03",
  "\x03\x03",
  "\x03\x03",
  "\x03\x03",
  "\x04",
  "\x03",
  "\x03",
  "\x05\x0B\x0D\x07",
  "\x0E\x0E\x0E\x0E",
  "\x05",
  "\x07\x03",
  "\x07",
  "\x04\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02",
  "",
  "",
  "\x02",
  "\x02",
  "\x02",
  "\x02",
  "\x02",
  "",
  "\x07\x07",
  "",
  "",
  "\x05\x0B\x0D\x05\x0B\x0C",
  "\x05",
  "\x05",
  "\x05",
  "\x02",
  "",
  "",
  "",
  "\x01\x04",
  "\x02",
  "\x03",
  "",
  "\x07\x04",
  "\x07\x04",
  "\x01",
  "",
  "",
  "",
  "\x02",
  "",
  "",
  "",
  "\x01\x02",
  "O\x03",//ODT
  "\x05",
  "\x05",
  "\x05",
  "\x05",
  "\x05",
  "\x02\x02",
  "\x02\x02",
  "O\x3",//ODT
  "O\x3" };//ODT


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 __PLATFORM_H
#define __PLATFORM_H

#include "compat.h"

__M_BEGIN_DECLS

#include "platform_endian.h"

#ifdef CONFIG_SDL

#include "SDL.h"

#else // !CONFIG_SDL

#include <inttypes.h>

typedef uint8_t Uint8;
typedef int8_t Sint8;
typedef uint16_t Uint16;
typedef int16_t Sint16;
typedef uint32_t Uint32;
typedef int32_t Sint32;
typedef uint64_t Uint64;
typedef int64_t Sint64;

#if defined(CONFIG_WII) || defined(CONFIG_NDS)
int real_main(int argc, char *argv[]);
#define main real_main
#endif // CONFIG_WII || CONFIG_NDS

#endif // CONFIG_SDL

// Normally only need mutexes for audio, but the Wii port
// uses them for events too

#if defined(CONFIG_WII) || defined(CONFIG_AUDIO)

#ifdef CONFIG_PTHREAD_MUTEXES
#include "mutex_pthread.h"
#elif defined(CONFIG_SDL)
#include "mutex_sdl.h"
#elif defined(CONFIG_WII)
#include "../arch/wii/mutex.h"
#else
#error Provide a valid mutex implementation for this platform!
#endif

#endif // defined(CONFIG_WII) || defined(CONFIG_AUDIO)

CORE_LIBSPEC void delay(Uint32 ms);
CORE_LIBSPEC Uint32 get_ticks(void);
CORE_LIBSPEC bool platform_init(void);
CORE_LIBSPEC void platform_quit(void);

__M_END_DECLS

#endif // __PLATFORM_H


code:
/* MegaZeux
 *
 * Copyright (C) 2009 Alistair John Strachan <alistair@devzero.co.uk>
 *
 * 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
 */

// Below is a very simple example of the stubs you must implement to port
// to another non-SDL platform. Please note that this file exists to have
// non-SDL builds compile, but is in no way functional.

#include "platform.h"
#include "event.h"

#ifdef CONFIG_AUDIO
#include "audio.h"
#endif

#include <sys/time.h>

#include <unistd.h>
#include <stdio.h>
#include <time.h>

void delay(Uint32 ms)
{
  usleep(1000 * ms);
}

Uint32 get_ticks(void)
{
  struct timeval tv;

  if(gettimeofday(&tv, NULL) < 0)
  {
    perror("gettimeofday");
    return 0;
  }

  return (Uint32)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
}

bool platform_init(void)
{
  // stub
  return true;
}

void platform_quit(void)
{
  // stub
}

void initialize_joysticks(void)
{
  // stub
}

Uint32 __update_event_status(void)
{
  // stub
  return 0;
}

void real_warp_mouse(Uint32 x, Uint32 y)
{
  // stub
}

void __wait_event(void)
{
  // stub
}

#ifdef CONFIG_AUDIO

void init_audio_platform(struct config_info *conf)
{
  // stub
}

void quit_audio_platform(void)
{
  // stub
}

#endif // CONFIG_AUDIO


code:
/* MegaZeux
 *
 * Copyright (C) 2008 Alistair John Strachan <alistair@devzero.co.uk
 *
 * 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 __ENDIAN_H
#define __ENDIAN_H

/* If SDL is available, include the header and use SDL's configured
 * endianness. If it's not available, use a list of architectures (actually
 * borrowed from SDL 1.2.13) to figure out our likely endianness.
 */

#define PLATFORM_LIL_ENDIAN 0x1234
#define PLATFORM_BIG_ENDIAN 0x4321

#ifdef CONFIG_SDL

#include <SDL.h>

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define PLATFORM_BYTE_ORDER PLATFORM_BIG_ENDIAN
#else
#define PLATFORM_BYTE_ORDER PLATFORM_LIL_ENDIAN
#endif

#else // !CONFIG_SDL

#if defined(__BIG_ENDIAN__)
#define PLATFORM_BYTE_ORDER PLATFORM_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN__)
#define PLATFORM_BYTE_ORDER PLATFORM_LIL_ENDIAN
#elif defined(__hppa__) || \
    defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
    (defined(__MIPS__) && defined(__MISPEB__)) || \
    defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
    defined(__sparc__)
#define PLATFORM_BYTE_ORDER PLATFORM_BIG_ENDIAN
#else
#define PLATFORM_BYTE_ORDER PLATFORM_LIL_ENDIAN
#endif

#endif // CONFIG_SDL

/* ModPlug uses this bizarre name to find out about endianness. It's not too
 * bad to pollute our namespace with it, so just do so here.
 */
#if PLATFORM_BYTE_ORDER == PLATFORM_BIG_ENDIAN
#define WORDS_BIGENDIAN
#endif

#endif // __ENDIAN_H


code:
/* MegaZeux
 *
 * Copyright (C) 2002 Gilead Kutnick <exophase@adelphia.net>
 * Copyright (C) 2008 Alan Williams <mralert@gmail.com>
 * Copyright (C) 2008 Simon Parzer <simon.parzer@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 "compat.h"

#ifdef CONFIG_PSP
#define _COMPILING_NEWLIB
#endif

#include "platform.h"
#include "util.h"

#include "SDL.h"

#ifdef CONFIG_PSP
#include <pspsdk.h>
#include <psppower.h>
PSP_MAIN_THREAD_STACK_SIZE_KB(512);
#endif

#ifdef CONFIG_GP2X
#include <unistd.h> //for chdir, execl
#endif

void delay(Uint32 ms)
{
  SDL_Delay(ms);
}

Uint32 get_ticks(void)
{
  return SDL_GetTicks();
}

bool platform_init(void)
{
  Uint32 flags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK;

#ifdef CONFIG_PSP
  scePowerSetClockFrequency(333, 333, 166);
#endif

#ifdef DEBUG
  flags |= SDL_INIT_NOPARACHUTE;
#endif

#ifdef CONFIG_AUDIO
  flags |= SDL_INIT_AUDIO;
#endif

  if(SDL_Init(flags) < 0)
  {
    warn("Failed to initialize SDL: %s\n", SDL_GetError());
    return false;
  }

  SDL_EnableUNICODE(1);
  return true;
}

void platform_quit(void)
{
  SDL_Quit();

#ifdef CONFIG_GP2X
  chdir("/usr/gp2x");
  execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
#endif
}

#ifdef CONFIG_PSP
int _isatty(int fd)
{
  return isatty(fd);
}
#endif


code:
/* MegaZeux
 *
 * Copyright (C) 2008 Alistair Strachan <alistair@devzero.co.uk>
 *
 * 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 "pngops.h"
#include "util.h"

#include <stdlib.h>

int png_write_screen(Uint8 *pixels, struct rgb_color *pal, int count,
 const char *name)
{
  png_structp png_ptr = NULL;
  png_bytep *row_ptrs = NULL;
  png_colorp pal_ptr = NULL;
  png_infop info_ptr = NULL;
  int i, type, ret = false;
  FILE *f;

  f = fopen_unsafe(name, "wb");
  if(!f)
    goto exit_out;

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if(!png_ptr)
    goto exit_close;

  info_ptr = png_create_info_struct(png_ptr);
  if(!info_ptr)
    goto exit_free_close;

  if(setjmp(png_jmpbuf(png_ptr)))
    goto exit_free_close;

  png_init_io(png_ptr, f);

  // we know we have an 8-bit surface; save a palettized PNG
  type = PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE;
  png_set_IHDR(png_ptr, info_ptr, 640, 350, 8, type,
   PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
   PNG_FILTER_TYPE_DEFAULT);

  pal_ptr = cmalloc(count * sizeof(png_color));
  if(!pal_ptr)
    goto exit_free_close;

  for(i = 0; i < count; i++)
  {
    pal_ptr[i].red = pal[i].r;
    pal_ptr[i].green = pal[i].g;
    pal_ptr[i].blue = pal[i].b;
  }
  png_set_PLTE(png_ptr, info_ptr, pal_ptr, count);

  // do the write of the header
  png_write_info(png_ptr, info_ptr);
  png_set_packing(png_ptr);

  row_ptrs = cmalloc(sizeof(png_bytep) * 350);
  if(!row_ptrs)
    goto exit_free_close;

  // and then the surface
  for(i = 0; i < 350; i++)
    row_ptrs[i] = (png_bytep)(Uint8 *)pixels + i * 640;
  png_write_image(png_ptr, row_ptrs);
  png_write_end(png_ptr, info_ptr);

  // all done
  ret = true;

exit_free_close:
  png_destroy_write_struct(&png_ptr, &info_ptr);
  free(pal_ptr);
  free(row_ptrs);
exit_close:
  fclose(f);
exit_out:
  return ret;
}

#ifdef NEED_PNG_READ_FILE

void *png_read_file(const char *name, png_uint_32 *_w, png_uint_32 *_h,
 check_w_h_constraint_t constraint, rgba_surface_allocator_t allocator)
{
  png_uint_32 i, w, h, stride;
  png_structp png_ptr = NULL;
  png_bytep *row_ptrs = NULL;
  png_infop info_ptr = NULL;
  void *pixels, *s = NULL;
  png_byte header[8];
  int type, bpp;
  FILE *f;

  f = fopen_unsafe(name, "rb");
  if(!f)
    goto exit_out;

  if(fread(header, 1, 8, f) < 8)
    goto exit_close;

  if(png_sig_cmp(header, 0, 8))
    goto exit_close;

  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if(!png_ptr)
    goto exit_close;

  info_ptr = png_create_info_struct(png_ptr);
  if(!info_ptr)
    goto exit_free_close;

  if(setjmp(png_jmpbuf(png_ptr)))
    goto exit_free_close;

  png_init_io(png_ptr, f);
  png_set_sig_bytes(png_ptr, 8);
  png_read_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &w, &h, &bpp, &type, NULL, NULL, NULL);

  if(!constraint(w, h))
  {
    warn("Requested image '%s' failed dimension checks.\n", name);
    goto exit_free_close;
  }

  if(type == PNG_COLOR_TYPE_PALETTE)
    png_set_palette_to_rgb(png_ptr);

  else if(type == PNG_COLOR_TYPE_GRAY_ALPHA || !(type & PNG_COLOR_MASK_COLOR))
    png_set_gray_to_rgb(png_ptr);

  else if(!(type & PNG_COLOR_MASK_COLOR) && bpp < 8)
    png_set_expand_gray_1_2_4_to_8(png_ptr);

  if(bpp == 16)
    png_set_strip_16(png_ptr);

  else if(bpp < 8)
    png_set_packing(png_ptr);

  if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(png_ptr);

  else if(!(type & PNG_COLOR_MASK_ALPHA))
    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);

  // FIXME: Are these necessary?
  png_read_update_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &w, &h, &bpp, &type, NULL, NULL, NULL);

  row_ptrs = cmalloc(sizeof(png_bytep) * h);
  if(!row_ptrs)
    goto exit_free_close;

  s = allocator(w, h, &stride, &pixels);
  if(!s)
    goto exit_free_close;

  for(i = 0; i < h; i++)
    row_ptrs[i] = (png_bytep)(unsigned char *)pixels + i * stride;

  png_read_image(png_ptr, row_ptrs);

  if(_w)
    *_w = w;
  if(_h)
    *_h = h;

exit_free_close:
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  free(row_ptrs);
exit_close:
  fclose(f);
exit_out:
  return s;
}

#endif // NEED_PNG_READ_FILE


code:
/* MegaZeux
 *
 * Copyright (C) 2008 Alistair Strachan <alistair@devzero.co.uk>
 *
 * 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 __PNGOPS_H
#define __PNGOPS_H

#include "compat.h"

__M_BEGIN_DECLS

#include <png.h>

#if (defined(CONFIG_SDL) && defined(CONFIG_ICON) && !defined(__WIN32__)) || \
    defined(CONFIG_UTILS)
#define NEED_PNG_READ_FILE
#endif

#ifdef NEED_PNG_WRITE_SCREEN

#include "graphics.h"

int png_write_screen(Uint8 *pixels, struct rgb_color *pal, int count,
 const char *name);

#endif // NEED_PNG_WRITE_SCREEN

#ifdef NEED_PNG_READ_FILE

typedef bool (*check_w_h_constraint_t)(png_uint_32 w, png_uint_32 h);
typedef void *(*rgba_surface_allocator_t)(png_uint_32 w, png_uint_32 h,
                                          png_uint_32 *stride, void **pixels);

void *png_read_file(const char *name, png_uint_32 *_w, png_uint_32 *_h,
 check_w_h_constraint_t constraint, rgba_surface_allocator_t allocator);

#endif // NEED_PNG_READ_FILE

__M_END_DECLS

#endif // __PNGOPS_H