
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <fcntl.h>

#include "file.h"

#define FMVOLUME 30

#define SHIFT 10                /* 固定小数演算用 */
#define FSHIFT (SHIFT >> 1)
#define DEGMAX 180              /* 向きの細かさ   */
#define SPMAX 100
#define PLAYERS 3
#define SLIP 96                 /* スリップ       */
/* map size */
#define MSX 10
#define MSY 8
#define MMASK ((1 << (SHIFT + MSX)) - (1 << SHIFT))
#define MMASK2 ((1 << (SHIFT + MSX + MSY)) - (1 << (SHIFT + MSX)))
#define DATASIZE (1 << (MSX + MSY - 8))
/* screen size */

#define SX 160                  /* ３Ｄスクリーンの横ドット数     */
#define SY 120


/* 3D PARAM */
#define VS 10
#define YC (SY * .85)
#define V1 (VS * .1)
#define V2 (VS * 1.2)
#define HS (V2 - V1)
#define ZS (VS)
#define MAP(x) (*(gr1 + (x)))
#define LOOPMAX 100
#define STMAX 16
#define STEPMAX 3600*6
#define GLOOP 3                     /* ************** */
#define PAD (pad(0) & pad(1))

static short chip[320 * 240 + 256];
static short data[DATASIZE * STMAX + 10000];
static short gr1[1 << (MSX + MSY)];
static int stage;
static int totalstep;
static int gloop;
static int players;
static int human;
static int demo_mode;
static int scan_mode;
static int page_limit;


#define ZC (int)((VS * ZS / (V1 + YC * (double)(V2 - V1) / SY)) * (1 << SHIFT))

static struct {
    int px;
    int py;
    int dwx;
    int dwy;
} table[DEGMAX * SY];

static struct {
    int st;
    int pos;
    char pad[STEPMAX];
} paddata[STMAX], npaddata[PLAYERS], paddata_another[STMAX];

static int slsize[SY];

static int px1[PLAYERS], py1[PLAYERS], pdeg[PLAYERS], psp[PLAYERS];
static int ploop[PLAYERS];
static int bcol[PLAYERS], pdx[PLAYERS], pdy[PLAYERS];
static int ph[PLAYERS], pdh[PLAYERS];
static int pki[PLAYERS];
static int startpos[PLAYERS];
static int step[PLAYERS][LOOPMAX];
static int runstate[PLAYERS];
static int nowpad[PLAYERS];
static int tst[PLAYERS];

const int sinb[DEGMAX] = {
    0x00000000, 0x00000023, 0x00000047, 0x0000006b,
    0x0000008e, 0x000000b1, 0x000000d4, 0x000000f7,
    0x0000011a, 0x0000013c, 0x0000015e, 0x0000017f,
    0x000001a0, 0x000001c0, 0x000001e0, 0x00000200,
    0x0000021e, 0x0000023c, 0x00000259, 0x00000276,
    0x00000292, 0x000002ad, 0x000002c7, 0x000002e0,
    0x000002f8, 0x00000310, 0x00000326, 0x0000033c,
    0x00000350, 0x00000364, 0x00000376, 0x00000388,
    0x00000398, 0x000003a7, 0x000003b5, 0x000003c2,
    0x000003cd, 0x000003d8, 0x000003e1, 0x000003e9,
    0x000003f0, 0x000003f6, 0x000003fa, 0x000003fd,
    0x000003ff, 0x00000400, 0x000003ff, 0x000003fd,
    0x000003fa, 0x000003f6, 0x000003f0, 0x000003e9,
    0x000003e1, 0x000003d8, 0x000003cd, 0x000003c2,
    0x000003b5, 0x000003a7, 0x00000398, 0x00000388,
    0x00000376, 0x00000364, 0x00000350, 0x0000033c,
    0x00000326, 0x00000310, 0x000002f8, 0x000002e0,
    0x000002c7, 0x000002ad, 0x00000292, 0x00000276,
    0x00000259, 0x0000023c, 0x0000021e, 0x000001ff,
    0x000001e0, 0x000001c0, 0x000001a0, 0x0000017f,
    0x0000015e, 0x0000013c, 0x0000011a, 0x000000f7,
    0x000000d4, 0x000000b1, 0x0000008e, 0x0000006b,
    0x00000047, 0x00000023, 0x00000000, 0xffffffdd,
    0xffffffb9, 0xffffff95, 0xffffff72, 0xffffff4f,
    0xffffff2c, 0xffffff09, 0xfffffee6, 0xfffffec4,
    0xfffffea2, 0xfffffe81, 0xfffffe60, 0xfffffe40,
    0xfffffe20, 0xfffffe00, 0xfffffde2, 0xfffffdc4,
    0xfffffda7, 0xfffffd8a, 0xfffffd6e, 0xfffffd53,
    0xfffffd39, 0xfffffd20, 0xfffffd08, 0xfffffcf0,
    0xfffffcda, 0xfffffcc4, 0xfffffcb0, 0xfffffc9c,
    0xfffffc8a, 0xfffffc78, 0xfffffc68, 0xfffffc59,
    0xfffffc4b, 0xfffffc3e, 0xfffffc33, 0xfffffc28,
    0xfffffc1f, 0xfffffc17, 0xfffffc10, 0xfffffc0a,
    0xfffffc06, 0xfffffc03, 0xfffffc01, 0xfffffc00,
    0xfffffc01, 0xfffffc03, 0xfffffc06, 0xfffffc0a,
    0xfffffc10, 0xfffffc17, 0xfffffc1f, 0xfffffc28,
    0xfffffc33, 0xfffffc3e, 0xfffffc4b, 0xfffffc59,
    0xfffffc68, 0xfffffc78, 0xfffffc8a, 0xfffffc9c,
    0xfffffcb0, 0xfffffcc4, 0xfffffcda, 0xfffffcf0,
    0xfffffd08, 0xfffffd20, 0xfffffd39, 0xfffffd53,
    0xfffffd6e, 0xfffffd8a, 0xfffffda7, 0xfffffdc4,
    0xfffffde2, 0xfffffe00, 0xfffffe20, 0xfffffe40,
    0xfffffe60, 0xfffffe81, 0xfffffea2, 0xfffffec4,
    0xfffffee6, 0xffffff09, 0xffffff2c, 0xffffff4f,
    0xffffff72, 0xffffff95, 0xffffffb9, 0xffffffdd,
};
const int cosb[DEGMAX] = {
    0x00000400, 0x000003ff, 0x000003fd, 0x000003fa,
    0x000003f6, 0x000003f0, 0x000003e9, 0x000003e1,
    0x000003d8, 0x000003cd, 0x000003c2, 0x000003b5,
    0x000003a7, 0x00000398, 0x00000388, 0x00000376,
    0x00000364, 0x00000350, 0x0000033c, 0x00000326,
    0x00000310, 0x000002f8, 0x000002e0, 0x000002c7,
    0x000002ad, 0x00000292, 0x00000276, 0x00000259,
    0x0000023c, 0x0000021e, 0x000001ff, 0x000001e0,
    0x000001c0, 0x000001a0, 0x0000017f, 0x0000015e,
    0x0000013c, 0x0000011a, 0x000000f7, 0x000000d4,
    0x000000b1, 0x0000008e, 0x0000006b, 0x00000047,
    0x00000023, 0x00000000, 0xffffffdd, 0xffffffb9,
    0xffffff95, 0xffffff72, 0xffffff4f, 0xffffff2c,
    0xffffff09, 0xfffffee6, 0xfffffec4, 0xfffffea2,
    0xfffffe81, 0xfffffe60, 0xfffffe40, 0xfffffe20,
    0xfffffe00, 0xfffffde2, 0xfffffdc4, 0xfffffda7,
    0xfffffd8a, 0xfffffd6e, 0xfffffd53, 0xfffffd39,
    0xfffffd20, 0xfffffd08, 0xfffffcf0, 0xfffffcda,
    0xfffffcc4, 0xfffffcb0, 0xfffffc9c, 0xfffffc8a,
    0xfffffc78, 0xfffffc68, 0xfffffc59, 0xfffffc4b,
    0xfffffc3e, 0xfffffc33, 0xfffffc28, 0xfffffc1f,
    0xfffffc17, 0xfffffc10, 0xfffffc0a, 0xfffffc06,
    0xfffffc03, 0xfffffc01, 0xfffffc00, 0xfffffc01,
    0xfffffc03, 0xfffffc06, 0xfffffc0a, 0xfffffc10,
    0xfffffc17, 0xfffffc1f, 0xfffffc28, 0xfffffc33,
    0xfffffc3e, 0xfffffc4b, 0xfffffc59, 0xfffffc68,
    0xfffffc78, 0xfffffc8a, 0xfffffc9c, 0xfffffcb0,
    0xfffffcc4, 0xfffffcda, 0xfffffcf0, 0xfffffd08,
    0xfffffd20, 0xfffffd39, 0xfffffd53, 0xfffffd6e,
    0xfffffd8a, 0xfffffda7, 0xfffffdc4, 0xfffffde2,
    0xfffffe01, 0xfffffe20, 0xfffffe40, 0xfffffe60,
    0xfffffe81, 0xfffffea2, 0xfffffec4, 0xfffffee6,
    0xffffff09, 0xffffff2c, 0xffffff4f, 0xffffff72,
    0xffffff95, 0xffffffb9, 0xffffffdd, 0x00000000,
    0x00000023, 0x00000047, 0x0000006b, 0x0000008e,
    0x000000b1, 0x000000d4, 0x000000f7, 0x0000011a,
    0x0000013c, 0x0000015e, 0x0000017f, 0x000001a0,
    0x000001c0, 0x000001e0, 0x00000200, 0x0000021e,
    0x0000023c, 0x00000259, 0x00000276, 0x00000292,
    0x000002ad, 0x000002c7, 0x000002e0, 0x000002f8,
    0x00000310, 0x00000326, 0x0000033c, 0x00000350,
    0x00000364, 0x00000376, 0x00000388, 0x00000398,
    0x000003a7, 0x000003b5, 0x000003c2, 0x000003cd,
    0x000003d8, 0x000003e1, 0x000003e9, 0x000003f0,
    0x000003f6, 0x000003fa, 0x000003fd, 0x000003ff,
};


static short buffer_32768[SX * SY];
static unsigned char buffer_2[(160*120/8) * 32];
static unsigned char buffer_2_old[160*120/8];
static int buffer_count = 0;
static int page_count = 0;
static int out_fd;
static int color_exchange_table[32768];    /* ２色への変換テーブル */


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void tableset()
{
    int a;
    int deg, y;
    double z, v, degx, dw, zc;
    int x, i;

    degx = atan2(HS, ZS);

    v = V1 + YC * (double) (V2 - V1) / SY;
    zc = VS * ZS / v;

    for (y = 0; y < SY; y++) {
        v = V1 + y * (double) (V2 - V1) / SY;
        z = VS * ZS / v;
        dw = HS * z / (ZS * SX);
        for (deg = 0; deg < DEGMAX; deg++) {
            a = deg * SY + y;
            table[a].px = (z - zc) * sinb[deg];
            table[a].py = (zc - z) * cosb[deg];
            table[a].dwx = dw * cosb[deg] + .5;
            table[a].dwy = dw * sinb[deg] + .5;
            table[a].px -= table[a].dwx * (SX / 2);
            table[a].py -= table[a].dwy * (SX / 2);
        }
    }

    x = table[SY - 1].dwx;
    for (i = 0; i < SY; i++) {
        slsize[i] = (31 << SHIFT) * x / table[i].dwx;
    }
}

#define MAPPOINT(x, y) MAP((((x) & MMASK) | ((y) & MMASK2)) >> SHIFT)

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/* map3d() の原型 */
void map3d_old(short *block, int mx, int my, int deg)
{
    register int poxs, poys, dx, dy;
    int x, y;
    int p = deg * SY;
    
    for (y = 0; y < SY; y++){
        dx = table[p].dwx;
        dy = (table[p].dwy) << MSX;
        poxs = table[p].px + mx;
        poys = (table[p].py + my) << MSX;
        poxs -= dx;
        poys -= dy;
        p++;
        for (x = 0; x < (SX / 4); x++){
            *(block++) = MAPPOINT((poxs += dx), (poys += dy));
            *(block++) = MAPPOINT((poxs += dx), (poys += dy));
            *(block++) = MAPPOINT((poxs += dx), (poys += dy));
            *(block++) = MAPPOINT((poxs += dx), (poys += dy));
        }
    }
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void set_color_exchange_table()
{
    int i, r, g, b;

    for (i=0; i<32768; i++){
        if ((i==31) || (i==32*31) || (i==32767) ||
            (i==33*31) || (i==(7*(1024+32+1)))){
            color_exchange_table[i] = 1;
            continue;
        }
        b = i & 31;
        r = (i >> 5) & 31;
        g = i >> 10;
        if ((b == r) && (g == r)){
            color_exchange_table[i] = 0;
            continue;
        }
        if ((rand() % (96 - 0)) <= r+g+b - 0)
            color_exchange_table[i] = 1;
        else
            color_exchange_table[i] = 0;
    }
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void flush_output()
{
    int x;

    x = write(out_fd, buffer_2, buffer_count * (160*120/8));
    page_count += x / (160*120/8);
    buffer_count = 0;
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void output_a_page()
{
    int i, j, k;
    short *inp;
    unsigned char *outp, *old_outp, x;
    for (i=0; i<SY; i++){
        outp = buffer_2 + buffer_count * (160*120/8) + i * (160/8);
        old_outp = buffer_2_old + i * (160/8);
        inp  = buffer_32768 + (SX * i);
        for (j=0; j<SX; j+=8){
            x = 0;
            for (k=7; k>=0; k--){
                if (color_exchange_table[(*inp++)])
                    x |= (1<<k);
            }
            (*outp++) = (*old_outp) ^ x;
            (*old_outp++) = x;
        }
    }
    if ((++buffer_count) >= 32)
        flush_output();
}

#define ABS(x) ((x) > 0 ? (x) : ( - (x)))

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
int judge(int x, int y)
{
    int col, cr, cg, cb;

    col = MAPPOINT(x, y << MSX);
    cr = col >> 5;
    cg = col >> 10;
    cb = col;
    cr &= 31;
    cg &= 31;
    cb &= 31;
    if ((cr == cg) && (cg == cb)) {
        /* safe */
        return 1;
    }
    /* hit */
    return 0;
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/* スライムの移動および地面の当たり判定 */
static void move_step_1(int pl)
{
    int col = 0, cr, cg, cb;
    int dx = pdx[pl], dy = pdy[pl];
    int dh = pdh[pl], h = ph[pl];
    int slip = (1 << SHIFT) / SLIP;
    int ddx, ddy;
    int sp = psp[pl];
    int x = px1[pl], y = py1[pl], deg = pdeg[pl];

    ddx = (sinb[deg] >> FSHIFT) * ((sp) >> FSHIFT);
    ddy = -((cosb[deg] >> FSHIFT) * ((sp) >> FSHIFT));

    x += dx;
    y += dy;

    if ((sp < (1 << (SHIFT - 3))) && (runstate[pl] == 1)) {
        runstate[pl] = 3;
    }
    if (bcol[pl] == 1024 * 31 + 31) {
        slip >>= 2;
    }
    col = MAPPOINT(x, y << MSX);
    cr = col >> 5;
    cg = col >> 10;
    cb = col;
    cr &= 31;
    cg &= 31;
    cb &= 31;

    h += dh;
    if (h) {
        dh -= (1 << (SHIFT - 3));
        /* jumping now */
        slip >>= 2;
        if (h <= 0) {
            h = 0;             /* 着地 */
            dh = 0;
            if ((cr == cg) && (cg == cb)) {
                ;
            }
            else if (((cr == 0) || (cr == 31)) &&
                     ((cb == 0) || (cb == 31)) &&
                     ((cg == 0) || (cg == 31))) {
                ;
            }
            else {
                /* lost */
                runstate[pl] = 2;
                sp = 0;
                dx = 0;
                dy = 0;
                ddx = 0;
                ddy = 0;
            }
        }
    }
    if (!h){
        /* running */
        if ((cr == cg) && (cg == cb)) {
            if ((cr == 31) && (sp > (1 << (SHIFT - 3)))) {
                /* side */
                sp -= (1 << (SHIFT - 8));
            }
            else if ((cr == 7) && (sp > (1 << (SHIFT - 3)))) {
                /* black */
                sp -= (1 << (SHIFT - 7));
            }
        }
        else {
            switch (col) {
              case 31:{
                      /* blue */
                      if (bcol[pl] == 32 * 31) {
                          /* goalline */
                          step[pl][ploop[pl]] = -step[pl][ploop[pl]];
                          ploop[pl]++;
                          if (ploop[pl] == gloop) {
                              /* goal !! */
                              runstate[pl] = 1;
                          }
                      }
                      else if (bcol[pl] != 31) {
                          dx = -dx;
                          dy = -dy;
                          x = px1[pl];
                          y = py1[pl];
                          col = bcol[pl];
                          sp >>= 1;
                      }
                      break;
                  }
              case 31 * 32:{
                      if (bcol[pl] == 31) {
                          dx = -dx;
                          dy = -dy;
                          x = px1[pl];
                          y = py1[pl];
                          col = bcol[pl];
                          sp >>= 1;
                      }
                      break;
                  }
              case 31 * 32 + 31:{
                      /* jump */
                      dh = (1 << (SHIFT - 3)) * 32;
                      h += dh;
                      break;
                  }
              case 31 * 1024 + 31:{
                      break;
                  }
              default:{
                      x = px1[pl];
                      y = py1[pl];
                      if (judge(x + dx, y) != 1) {
                          dx = -dx;
                      }
                      if (judge(x, y + dy) != 1) {
                          dy = -dy;
                      }
                      col = bcol[pl];
                      sp >>= 1;
                  }
            }
        }
    }

    if (ABS(ddx - dx) < slip) {
        dx = ddx;
    }
    else if (ddx > dx) {
        dx += slip;
    }
    else {
        dx -= slip;
    }

    if (ABS(ddy - dy) < slip) {
        dy = ddy;
    }
    else if (ddy > dy) {
        dy += slip;
    }
    else {
        dy -= slip;
    }

    px1[pl] = x;
    py1[pl] = y;
    pdeg[pl] = deg;
    psp[pl] = sp;

    pdx[pl] = dx;
    pdy[pl] = dy;
    bcol[pl] = col;
    ph[pl] = h;
    pdh[pl] = dh;
    step[pl][ploop[pl]]++;
}

#define TIMES 1000
#define UP 1
#define DOWN 2
#define LEFT 4
#define RIGHT 8
#define T1 16
#define T2 32

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void padread()
{
    int i;

    for (i = 0; i < PLAYERS; i++) {
        switch (pki[i]) {
          case 0:{
                  /* human */
                  nowpad[i] = 255;   /*pad(i)*/
                  break;
              }
          case 1:{
                  /* com */
                  nowpad[i] = paddata[stage].pad[totalstep];
                  break;
              }
          case 2:{
                  /* com 2 */
                  nowpad[i] = paddata_another[stage].pad[totalstep];
                  break;
              }
          default:{
                  nowpad[i] = 255;
              }
        }
        if (runstate[i] > 0)
            nowpad[i] |= T1;
        if (nowpad[i] == 0)
            nowpad[i] = 255;

        npaddata[i].pad[totalstep] = nowpad[i];
    }
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
static void move_step_2(int pl)
{
    int p = nowpad[pl], sp = psp[pl];
    int x = px1[pl], y = py1[pl], deg = pdeg[pl];

    if ((p & LEFT) == 0) {
        deg -= 1;
        if (deg < 0)
            deg += DEGMAX;
    }
    if ((p & RIGHT) == 0) {
        deg += 1;
        if (deg >= DEGMAX)
            deg -= DEGMAX;
    }
    if (((p & T1) == 0) && (sp < ((ph[pl] != 0) ? ((1 << (SHIFT - 3)) * 8) :
                                  (1 << (SHIFT - 3))) * 6)) {
        sp += (1 << (SHIFT - 8));
    }
    else if (((p & T2) == 0)) {
        sp -= (1 << (SHIFT - 7));    /* ブレ−キ */
    }
    else {
        sp -= (1 << (SHIFT - 8));    /* 緩やかに減速 */
    }
    if (sp < -(1 << (SHIFT - 4))) {
        sp = -(1 << (SHIFT - 4));
    }
    else if (sp < 0) {
        sp += (1 << (SHIFT - 8));
    }
    pdeg[pl] = deg;
    psp[pl] = sp;
    if (pl == 0) {
        map3d_old(buffer_32768, x, y, deg);
        output_a_page();
    }
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void chiptobit(short *bitmap, short *chip, short *data, int x, int y) 
{
    int i, j, k, l;
    int a, d, h, v;
     
    for (j = 0; j < x; j++){
        for (i = 0; i < y; i++){
            a = data[j * y + i];
            h = (a % 20) * 16;
            v = (a / 20) * 16;
            for (l = 0; l < 16; l++){
                for (k = 0; k < 16; k++){
                    d = chip[(l + v) * 320 + (k + h)];
                    bitmap[(i * 16 + l) * (x * 16) + (j * 16 + k)] = d;
                }
            }
        }
    }
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
void roop()
{
    int i, j, a;

    chiptobit(gr1, chip + 256, 
              data + (stage * DATASIZE), 1 << (MSX - 4), 1 << (MSY - 4));

    /* start position */
    for (i = 0; i < DATASIZE; i++) {
        if (data[i + (stage * DATASIZE)] == 20) {
            break;
        }
    }
    /*gloop = GLOOP;*/
    for (j = 0; j < PLAYERS; j++) {
        pki[j] = -1;
        /* ki=  0 : human / 1 :com / 2 :com2 */
    }
    
    /* demo mode */
    players = 2;
    demo_mode = 1;
    pki[0] = 1;
    pki[1] = 2;
    pki[2] = 0;
    startpos[0] = paddata[stage].pos;
    startpos[1] = paddata_another[stage].pos;
    
    for (j = 0; j < PLAYERS; j++) {
        py1[j] = ((i & 15) << (SHIFT + 4))
            + ((startpos[j] + 2) << (SHIFT + 1));
        px1[j] = ((i >> 4) << (SHIFT + 4)) + (6 << SHIFT);
        pdeg[j] = (DEGMAX * 3) / 4;
        psp[j] = 0;
        ploop[j] = 0;
        bcol[j] = 0;
        pdx[j] = 0;
        pdy[j] = 0;
        pdh[j] = 0;
        ph[j] = 0;
        for (a = 0; a < LOOPMAX; a++) {
            step[j][a] = 0;
        }
        runstate[j] = 0;
    }
    
    runstate[1] = 3;
    runstate[2] = 3;

    /* main roop */

    totalstep = 0;
    while (1) {
        if (totalstep >= STEPMAX) {
            /* time up */
            break;
        }
        if (totalstep >= page_limit) {
            /* time up */
            break;
        }
        i = 0;
        for (j = 0; j < PLAYERS; j++) {
            i += (runstate[j] < 2) ? 1 : 0;
        }
        if (i == 0) {
            /* goal or out */
            break;
        }
        totalstep++;
        padread();
        
        for (j = 0; j < PLAYERS; j++) {
            move_step_1(j);
            move_step_1(j);
        }
        
        for (j = 0; j < PLAYERS; j++) {
            move_step_2(j);
        }
        /*printf("%d %d %d\n",px1[0],py1[0],runstate[0]);*/
    }

    /* count total step */
    for (j = 0; j < PLAYERS; j++) {
        tst[j] = 0;
        if (step[j][gloop - 1] < 0) {
            for (i = 0; i < gloop; i++) {
                tst[j] -= step[j][i];
            }
        }
    }
    /* top player */
    i = -1;
    a = 100000;
    for (j = 0; j < PLAYERS; j++) {
        if ((tst[j] > 0) && (tst[j] < a)) {
            a = tst[j];
            i = j;
        }
    }
}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
int main(int argc, char *argv[])
{
    int fd;
    char file_name[1024] = "";
    int i, j, x;
    int arg_count = 1;
    char mapfile[255] = "sca.map";
    char buff[12] = "he1";

    tableset();
    set_color_exchange_table();
    
    stage = 0;       /* stage */
    page_limit = 10000;
    gloop = GLOOP;
    while (arg_count < argc){
        if (strcmp(argv[arg_count], "-stage") == 0){
            stage = atoi(argv[++arg_count]);
            if (stage == 0){
                stage = argv[arg_count][0] - 'a';
            }
        }
        else if (strcmp(argv[arg_count], "-limit") == 0){
            page_limit = atoi(argv[++arg_count]);
        }
        else if (strcmp(argv[arg_count], "-loop") == 0){
            gloop = atoi(argv[++arg_count]);
            if ((gloop >= GLOOP) || (gloop <= 0))
                gloop = GLOOP;
        }
        else {
            strcpy(file_name, argv[arg_count]);
        }
        arg_count++;
    }
    if (strlen(file_name) == 0){
        fd = 1;         /* stdout */
    }
    else {
        fd = creat(file_name, 0644);
        if (fd == -1) exit(-1);
    }
    for (i=0; i<160*120/8; i++) buffer_2_old[i] = 0;
    buff[4] = 1;
    for (i=5; i<12; i++) buff[i] = 0;
    write(fd, buff, 12);
    out_fd = fd;
    
    human = 1;
    demo_mode = 1;
    scan_mode = 0;
    load_block("chip.tif", (char *) chip);
    load_block("fz.tim", (char *) paddata);
    load_block("fz_ano.tim", (char *) paddata_another);
    for (i = 0; i < STMAX; i++) {
        load_block(mapfile, (char *) data + (i * DATASIZE * 2));
        mapfile[2]++;
        x = data[i * DATASIZE];
        for (j = 0; j < (1 << (MSX-4)); j++) {
            data[i * DATASIZE + j * 16 + 15] = x;
        }
    }
    roop();

    flush_output();
    page_count--;
    lseek(fd, 0, 0);
    buff[8]  = 0;
    buff[9]  = 4;
    buff[8]  = page_count         & 255;
    buff[9]  = (page_count >> 8)  & 255;
    buff[10] = (page_count >> 16) & 255;
    buff[11] = (page_count >> 24) & 255;
    write(fd, buff, 12);
    
    if (fd != 1) close(fd);
    return 0;
}
