code:
#include "build.h"
#include "baselayer.h"
#include "cache1d.h"
#include "mmulti.h"

#include "tekwar.h"

#if 0

/***************************************************************************
 *   TEKTXT.C  - text based & MiSCcellaneous routines for Tekwar game      *
 *   Uses BIOS modes for compatibility and scrolling.                      *
 *   Includes CD code.                                                     *
 *                                                     12/14/94 Les Bird   *
 ***************************************************************************/

#define   CDRELEASE
#define   COPYRIGHTSTRING     "INTRACORP1995TW"

#endif

char      bypasscdcheck=0;

void
crash(const char *s,...)
{
     va_list argptr;

     musicoff();
     sendlogoff();
     uninitmultiplayers();
     uninitsb();
     cduninit();
     //uninittimer();
     uninitinput();
     engineUnInit();
     uninitgroupfile();
     teksavesetup();

     va_start(argptr,s);
     vprintf(s,argptr);
     va_end(argptr);
     printf("\n");
     exit(0);
}

repo_name: orochi/nblood

license: mit


code:
/***************************************************************************
 *   TEKWAR.H  -  for stuff that probably all modules would like to        *
 *                know about                                               *
 *                                                                         *
 ***************************************************************************/

#include "common_game.h"

#define TEKWAR

#define BETA   1
#define DEBUG  1

#define CLKIPS      120
#define MSGBUFSIZE  40
#define DOOMGUY     999
#define KENSPLAYERHEIGHT    34

#define TICSPERFRAME 3
#define MOVEFIFOSIZ 256

#define TEKTEMPBUFSIZE  256

#define GAMECVARSGLOBAL
#define NETNAMES

typedef struct
{
     int x, y, z;
} point3d;

extern int vel, svel, angvel;
extern int vel2, svel2, angvel2;

extern volatile int recsnddone, recsndoffs;
extern int recording;

extern int r_showfps;

#define   NUMOPTIONS          8
#define   NUMGAMEKEYS         32
#define   MAXMOREOPTIONS      21
#define   MAXTOGGLES          16
#define   MAXGAMESTUFF        16
extern int fullscreen, xdimgame, ydimgame, bppgame;
extern int forcesetup;
extern unsigned char option[NUMOPTIONS];
extern unsigned char keys[NUMGAMEKEYS];
extern unsigned char moreoptions[MAXMOREOPTIONS];
extern char toggles[MAXTOGGLES];
extern int  gamestuff[MAXGAMESTUFF];

extern char frame2draw[MAXPLAYERS];
extern int frameskipcnt[MAXPLAYERS];
extern char gundmost[320];

     //Shared player variables
extern int posx[MAXPLAYERS], posy[MAXPLAYERS], posz[MAXPLAYERS];
extern int horiz[MAXPLAYERS], zoom[MAXPLAYERS], hvel[MAXPLAYERS];
extern short ang[MAXPLAYERS], cursectnum[MAXPLAYERS], ocursectnum[MAXPLAYERS];
extern short playersprite[MAXPLAYERS], deaths[MAXPLAYERS];
extern int lastchaingun[MAXPLAYERS];
extern int health[MAXPLAYERS], score[MAXPLAYERS], saywatchit[MAXPLAYERS];
extern short numbombs[MAXPLAYERS], oflags[MAXPLAYERS];
extern char dimensionmode[MAXPLAYERS];
extern char revolvedoorstat[MAXPLAYERS];
extern short revolvedoorang[MAXPLAYERS], revolvedoorrotang[MAXPLAYERS];
extern int revolvedoorx[MAXPLAYERS], revolvedoory[MAXPLAYERS];

     //Local multiplayer variables
extern int locselectedgun;
extern signed char locvel, olocvel;
extern short locsvel, olocsvel;                          // Les 09/30/95
extern short locangvel, olocangvel;                      // Les 09/30/95
extern short locbits, olocbits;

     //Local multiplayer variables for second player
extern int locselectedgun2;
extern signed char locvel2, olocvel2;
extern short locsvel2, olocsvel2;                        // Les 09/30/95
extern short locangvel2, olocangvel2;                    // Les 09/30/95
extern short locbits2, olocbits2;

  //Multiplayer syncing variables
extern signed char fsyncvel[MAXPLAYERS], osyncvel[MAXPLAYERS], syncvel[MAXPLAYERS];
extern short fsyncsvel[MAXPLAYERS], osyncsvel[MAXPLAYERS], syncsvel[MAXPLAYERS];  // Les 09/30/95
extern short fsyncangvel[MAXPLAYERS], osyncangvel[MAXPLAYERS], syncangvel[MAXPLAYERS]; // Les 09/30/95
extern unsigned short fsyncbits[MAXPLAYERS], osyncbits[MAXPLAYERS], syncbits[MAXPLAYERS];

extern char frameinterpolate, detailmode, ready2send;
extern int ototalclock, gotlastpacketclock, smoothratio;
extern int oposx[MAXPLAYERS], oposy[MAXPLAYERS], oposz[MAXPLAYERS];
extern int ohoriz[MAXPLAYERS], ozoom[MAXPLAYERS];
extern short oang[MAXPLAYERS];

extern point3d osprite[MAXSPRITESONSCREEN];

extern int movefifoplc, movefifoend;
extern signed char baksyncvel[MOVEFIFOSIZ][MAXPLAYERS];
extern short baksyncsvel[MOVEFIFOSIZ][MAXPLAYERS];       // Les 09/30/95
extern short baksyncangvel[MOVEFIFOSIZ][MAXPLAYERS];     // Les 09/30/95
extern short baksyncbits[MOVEFIFOSIZ][MAXPLAYERS];

     //GAME.C sync state variables
extern short syncstat;
extern int syncvalplc, othersyncvalplc;
extern int syncvalend, othersyncvalend;
extern int syncvalcnt, othersyncvalcnt;
extern short syncval[MOVEFIFOSIZ], othersyncval[MOVEFIFOSIZ];

extern int crctable[256];
//#define updatecrc16(dacrc,dadat) dacrc = (((dacrc<<8)&65535)^crctable[((((unsigned short)dacrc)>>8)&65535)^dadat])
extern char playerreadyflag[MAXPLAYERS];

     //Game recording variables
extern int reccnt, recstat;
extern signed char recsyncvel[16384][2];
extern short recsyncsvel[16384][2];                      // Les 09/30/95
extern short recsyncangvel[16384][2];                    // Les 09/30/95
extern short recsyncbits[16384][2];

     //Miscellaneous variables
extern char tempbuf[];
extern uint8_t packetbuf[];
extern char boardfilename[80];
extern short screenpeek, oldmousebstatus, brightness;
extern short screensize, screensizeflag;
extern short neartagsector, neartagwall, neartagsprite;
extern int lockclock, neartagdist, neartaghitdist;
extern int masterslavetexttime;
extern int pageoffset, ydim16, chainnumpages;
extern int globhiz, globloz, globhihit, globlohit;
extern int stereofps, stereowidth, stereopixelwidth;

     //Board animation variables
extern short rotatespritelist[16], rotatespritecnt;
extern short warpsectorlist[64], warpsectorcnt;
extern short xpanningsectorlist[16], xpanningsectorcnt;
extern short ypanningwalllist[64], ypanningwallcnt;
extern short floorpanninglist[64], floorpanningcnt;
extern short dragsectorlist[16], dragxdir[16], dragydir[16], dragsectorcnt;
extern int dragx1[16], dragy1[16], dragx2[16], dragy2[16], dragfloorz[16];
extern short swingcnt, swingwall[32][5], swingsector[32];
extern short swingangopen[32], swingangclosed[32], swingangopendir[32];
extern short swingang[32], swinganginc[32];
extern int swingx[32][8], swingy[32][8];
extern short revolvesector[4], revolveang[4], revolvecnt;
extern int revolvex[4][16], revolvey[4][16];
extern int revolvepivotx[4], revolvepivoty[4];
extern short subwaytracksector[4][128], subwaynumsectors[4], subwaytrackcnt;
extern int subwaystop[4][8], subwaystopcnt[4];
extern int subwaytrackx1[4], subwaytracky1[4];
extern int subwaytrackx2[4], subwaytracky2[4];
extern int subwayx[4], subwaygoalstop[4], subwayvel[4], subwaypausetime[4];
extern short waterfountainwall[MAXPLAYERS], waterfountaincnt[MAXPLAYERS];
extern short slimesoundcnt[MAXPLAYERS];

     //Variables that let you type messages to other player
extern char getmessage[162], getmessageleng;
extern int getmessagetimeoff;
extern char typemessage[162];
extern int typemessageleng, typemode;
extern char scantoasc[128];
extern char scantoascwithshift[128];

     //These variables are for animating x, y, or z-coordinates of sectors,
     //walls, or sprites (They are NOT to be used for changing the [].picnum's)
     //See the setanimation(), and getanimategoal() functions for more details.
#define MAXANIMATES 512
extern int *animateptr[MAXANIMATES], animategoal[MAXANIMATES];
extern int animatevel[MAXANIMATES], animateacc[MAXANIMATES], animatecnt;

#define   FT_FULLSCREEN   0
#define   FT_DATALINK     1

#define   MAXHEALTH      1000
#define   MAXSTUN        1000
#define   MAXAMMO        100

#define   CLASS_NULL               0
#define   CLASS_FCIAGENT           1
#define   CLASS_CIVILLIAN          2
#define   CLASS_SPIDERDROID        3
#define   CLASS_COP                4
#define   CLASS_MECHCOP            5
#define   CLASS_TEKBURNOUT         6
#define   CLASS_TEKGOON            7
#define   CLASS_ASSASSINDROID      8
#define   CLASS_SECURITYDROID      9
#define   CLASS_TEKBOSS            10
#define   CLASS_TEKLORD            11

#define   MAPXT        1

struct    picattribtype  {
     unsigned  char      numframes;
     unsigned  char      animtype;
     signed    char      ycenteroffset,xcenteroffset;
     unsigned  char      animspeed;
};

#ifdef __GNUC__
#  if __GNUC__ == 4 && __GNUC_MINOR__ >= 7
#    define TPACK __attribute__ ((packed, gcc_struct))
#  else
#    define TPACK __attribute__ ((packed))
#  endif
#else
#define TPACK
#endif

#ifdef _MSC_VER
#pragma pack(1)
#endif

#ifdef __WATCOMC__
#pragma pack(push,1);
#endif

struct TPACK spriteextension {
     unsigned  char      classification;
     signed    char      hitpoints;
     unsigned  short     target;
     unsigned  short     fxmask;
     unsigned  short     aimask;
     short     basestat;
     unsigned  short     basepic;
     unsigned  short     standpic;
     unsigned  short     walkpic;
     unsigned  short     runpic;
     unsigned  short     attackpic;
     unsigned  short     deathpic;
     unsigned  short     painpic;
     unsigned  short     squatpic;
     unsigned  short     morphpic;
     unsigned  short     specialpic;
     unsigned  char      lock;
     unsigned  char      weapon;
     short     ext2;
     };

#ifdef _MSC_VER
#pragma pack()
#endif

#ifdef __WATCOMC__
#pragma pack(pop)
#endif

#undef TPACK

// use this function whenever you need to verify your
// extension index
extern    int       seconds;
extern    int       minutes;
extern    int       hours;
extern    int       messageon;
extern    unsigned  criticalerror;
extern    char      messagebuf[MSGBUFSIZE];
extern    char      tektempbuf[TEKTEMPBUFSIZE];
extern    char      notininventory;
extern    struct    picattribtype       *picinfoptr;
extern    sectortype          *sectptr[MAXSECTORS];
extern    spritetype          *sprptr[MAXSPRITES];
extern    walltype            *wallptr[MAXWALLS];
extern    struct    spriteextension     spriteXT[MAXSPRITES];
extern    struct    spriteextension     *sprXTptr[MAXSPRITES];

// additional player arrays
extern    int      fallz[],stun[];
extern    int      invredcards[MAXPLAYERS], invbluecards[MAXPLAYERS];
extern    int      invaccutrak[MAXPLAYERS];
extern    int       fireseq[MAXPLAYERS];
extern    short     ammo1[MAXPLAYERS];
extern    short     ammo2[MAXPLAYERS];
extern    short     ammo3[MAXPLAYERS];
extern    short     ammo4[MAXPLAYERS];
extern    short     ammo5[MAXPLAYERS];
extern    short     ammo6[MAXPLAYERS];
extern    short     ammo7[MAXPLAYERS];
extern    short     ammo8[MAXPLAYERS];
extern    int      weapons[MAXPLAYERS];
extern    char      dead[MAXPLAYERS];
extern    int      firedonetics[MAXPLAYERS];
extern    int      lastgun[MAXPLAYERS];
extern    int       drawweap[MAXPLAYERS];

extern    uint32_t      flags32[];

#define   TOGGLE_RETICULE     0
#define   TOGGLE_TIME         1
#define   TOGGLE_SCORE        2
#define   TOGGLE_SOUND        3
#define   TOGGLE_MUSIC        4
#define   TOGGLE_REARVIEW     5
#define   TOGGLE_UPRT         6
#define   TOGGLE_GODMODE      7
#define   TOGGLE_HEALTH       8
#define   TOGGLE_OVERSCAN     9
#define   TOGGLE_INVENTORY    10

#define   GUN1FLAG            1
#define   GUN2FLAG            2
#define   GUN3FLAG            3
#define   GUN4FLAG            4
#define   GUN5FLAG            5
#define   GUN6FLAG            6
#define   GUN7FLAG            7
#define   GUN8FLAG            8

#define   BASESONG      0

#define   ST_NULL                  0x0000
#define   ST_IMMEDIATE             0x0001
#define   ST_UPDATE                0x0002
#define   ST_NOUPDATE              0x0004
#define   ST_UNIQUE                0x0008
#define   ST_DELAYED               0x0010
#define   ST_VARPITCH              0x0020
#define   ST_BACKWARDS             0x0040
#define   ST_AMBUPDATE             0x0060
#define   ST_VEHUPDATE             0x0080
#define   ST_TOGGLE                0x0100

#define   MAXSOUNDS                     16
#define   TOTALSOUNDS                   208

#define   S_WATERFALL                   0
#define   S_ALARM                       1

#define   S_SEWERLOOP1                  2          //sewer sounds
#define   S_SEWERLOOP2                  3
#define   S_SEWERLOOP3                  4
#define   S_SEWERLOOP4                  5
#define   S_SEWERSPLASH1                6
#define   S_SEWERSPLASH2                7
#define   S_SEWERSPLASH3                8
#define   S_SPLASH2                     9
#define   S_SPLASH3                     10
#define   S_SPLASH                      11

#define   S_MATRIX1                     12        //matrix sounds
#define   S_MATRIX2                     13
#define   S_MATRIX3                     14
#define   S_MATRIX4                     15
#define   S_MATRIX5                     16
#define   S_MATRIX6                     17
#define   S_MATRIX7                     18
#define   S_MATRIX8                     19
#define   S_MATRIX9                     20
#define   S_MATRIX10                    21
#define   S_MATRIX11                    22
#define   S_MATRIX12                    23

#define   S_WH_SWITCH                   24        //warehouse
#define   S_WH_GRINDING                 25
#define   S_WH_TRACKSTOP                26
#define   S_WH_STEAMPRESS               27
#define   S_WH_CLANK                    28
#define   S_WH_6                        29
#define   S_WH_7                        30
#define   S_WH_8                        31

#define   S_WAVES1                      32        //beach and city
#define   S_WAVES2                      33
#define   S_BIRDIES                     34

#define   S_STEAM                       35
#define   S_FIRELOOP                    36
#define   S_SPINNING_DOOR               37

#define   S_TRUCKHORN                   38
#define   S_CITY_AMBIENCE               39
#define   S_WIND                        40
#define   S_AMBULANCE                   41

#define   S_ROBOT_ACCESS                42        //matrix voices
#define   S_ROBOT_INTRUDER              43
#define   S_ROBOT_VIRUS                 44

#define   S_SUBWAY_TRACK                45
#define   S_ALARM2                      46
#define   S_ALARM3                      47

#define   S_STATUS1                     48        //menus and status
#define   S_STATUS2                     49
#define   S_HEALTHMONITOR               50
#define   S_REARMONITOR                 51
#define   S_MENUSOUND1                  52
#define   S_MENUSOUND2                  53
#define   S_BEEP                        54
#define   S_BOOP                        55

#define   S_MATRIXDOOR1                 56      //doors
#define   S_MATRIXDOOR2                 57
#define   S_MATRIXDOOR3                 58
#define   S_SIDEDOOR1                   59
#define   S_SIDEDOOR2                   60
#define   S_BIGSWINGOP                  61
#define   S_BIGSWINGCL                  62
#define   S_FLOOROPEN                   63
#define   S_BAYDOOR_OPEN                64
#define   S_BAYDOOR_CLOSE               65
#define   S_BAYDOORLOOP                 66
#define   S_UPDOWNDR2_OP                67
#define   S_UPDOWNDR2_CL                68
#define   S_DOORKLUNK                   69
#define   S_AIRDOOR                     70
#define   S_AIRDOOR_OPEN                71
#define   S_AIRDOOR_CLOSE               72
#define   S_ELEVATOR_DOOR               73

#define   S_SUBSTATIONLOOP              74        //vehicles
#define   S_SUBWAYLOOP                  75
#define   S_SUBWAYSTART                 76
#define   S_SUBWAYSTOP                  77
#define   S_TRUCKLOOP                   78
#define   S_TRUCKSTART                  79
#define   S_TRUCKSTOP                   80
#define   S_TRAMBUSLOOP                 81
#define   S_BOATLOOP                    82
#define   S_CARTLOOP                    83
#define   S_FORKLIFTLOOP                84

#define   S_RIC1                        85        //guns
#define   S_RIC2                        86
#define   S_WEAPON1                     87
#define   S_WEAPON2                     88
#define   S_WEAPON3                     89

#define   S_WEAPON4                     90
#define   S_WEAPON5                     91
#define   S_WEAPON6                     92
#define   S_WEAPON7                     93
#define   S_WEAPON8                     94

#define   S_ENEMYGUN1                   95
#define   S_ENEMYGUN2                   96
#define   S_ENEMYGUN3                   97
#define   S_ENEMYGUN4                   98
#define   S_WITCH                       99
#define   S_PLATFORMSTART               100
#define   S_PLATFORMSTOP                101
#define   S_PLATFORMLOOP                102
#define   S_FORCEFIELD1                 103
#define   S_FORCEFIELD2                 104
#define   S_AUTOGUN                     105
#define   S_AUTOGUNEXPLODE              106
#define   S_BUSHIT                      107
#define   S_FORCEFIELDHUMLOOP           108
#define   S_KEYCARDBLIP                 109
#define   S_PICKUP_BONUS                110
#define   S_JUMP                        111
#define   S_GLASSBREAK1                 112
#define   S_GLASSBREAK2                 113
#define   S_EXPLODE1                    114
#define   S_EXPLODE2                    115
#define   S_SMALLGLASS1                 116
#define   S_SMALLGLASS2                 117
#define   S_GORE1                       118
#define   S_GORE2                       119
#define   S_GORE3                       120
#define   S_FLUSH                       121
#define   S_REVOLVEDOOR                 122
#define   S_PAIN1                       123
#define   S_PAIN2                       124
#define   S_SCREAM1                     125
#define   S_SCREAM2                     126
#define   S_SCREAM3                     127
#define   S_PLAYERDIE                   128
#define   S_MANDIE1                     129
#define   S_MANDIE2                     130
#define   S_MANDIE3                     131
#define   S_MANDIE4                     132
#define   S_MANDIE5                     133
#define   S_MANDIE6                     134
#define   S_MANDIE7                     135
#define   S_MANDIE8                     136
#define   S_MANDIE9                     137
#define   S_MANDIE10                    138
#define   S_GIRLDIE1                    139
#define   S_GIRLDIE2                    140
#define   S_GIRLDIE3                    141
#define   S_GIRLDIE4                    142
#define   S_GIRLDIE5                    143
#define   S_GIRLDIE6                    144
#define   S_ANDROID_DIE                 145
#define   S_MATRIX_ATTACK               146
#define   S_MATRIX_ATTACK2              147
#define   S_MATRIX_DIE1                 148
#define   S_MATRIX_DIE2                 149
#define   S_TRANSITION                  150
#define   S_MALE_COMEONYOU              151
#define   S_MALE_TAKEYOUINSLEEP         152
#define   S_MALE_YOULOSER               153
#define   S_MALE_YOUPUNK                154
#define   S_MALE_YOUMORON               155
#define   S_MALE_LIKESHOOTINGDUX        156
#define   S_MALE_SCRAPEBOTBARREL        157
#define   S_MALE_DONTHURT               158
#define   S_MALE_DONTSHOOT              159
#define   S_MALE_PLEASEDONTSHOOT        160
#define   S_MALE_DONTSHOOT2             161
#define   S_MALE_PLEASEDONTSHOOT2       162
#define   S_MALE_OHMYGOD                163
#define   S_MALE_GETDOWNTAKECOVER       164
#define   S_MALE_HESGOTGUN              165
#define   S_MALE_IDONTBELIEVE           166
#define   S_MALE_RUNAWAY                167
#define   S_MALE_TAKECOVER              168
#define   S_MALE_HESGOTGUN2             169
#define   S_MALE_ICANTBELIEVE           170
#define   S_MALE_CALLTHEPOLICE          171
#define   S_MALE_HELPCALLPOLICE         172
#define   S_MALE_HEYBACKOFF             173
#define   S_MALE_HESGOTAGUN             174
#define   S_FEM_RUNHEGOTGUN             175
#define   S_FEM_RUN                     176
#define   S_FEM_EVRYRUNHEGOTGUN         177
#define   S_FEM_CALLACOP                178
#define   S_FEM_OHNO                    179
#define   S_FEM_MOVEHEKILLUS            180
#define   S_FEM_HESGOTAGUN1             181
#define   S_FEM_EEKRUN                  182
#define   S_FEM_PSYCHOGOTGUN            183
#define   S_FEM_OHMYGOD                 184
#define   S_FEM_HURRYOUTAMYWAY          185
#define   S_FEM_CALLAMBULANCE           186
#define   S_DIANE_DONTSHOOTP            187
#define   S_DIANE_HELPMEPLEASE          188
#define   S_DIANE_OHH                   189
#define   S_DIANE_PLEASEDONTSHOOT       190
#define   S_DIANE_DONTSHOOTP2           191
#define   S_KATIE_DONTSHOOT             192
#define   S_KATIE_PLEASEDONTSHOOT       193
#define   S_MAR_THINKYOUTAKE            194
#define   S_MAR_ISTHATALL               195
#define   S_MAR_KISSYOURASS             196
#define   S_GRD_WHATDOINGHERE           197
#define   S_GRD_IDLEAVE                 198
#define   S_GRD_HANDSUP                 199
#define   S_GRD_HOLDIT                  200
#define   S_GRD_DROPIT                  201
#define   S_DIM_WANTSOMETHIS            202
#define   S_DIM_THINOUCANTAKEME         203
#define   S_DIM_LAUGHTER                204
#define   S_DIM_CANTSTOPTEKLORDS        205
#define   S_DIM_TEKRULES                206
#define   S_HOLOGRAMDIE                 207

#define   AI_NULL             0x0000
#define   AI_FRIEND           0x0001
#define   AI_FOE              0x0002
#define   AI_JUSTSHOTAT       0x0004
#define   AI_CRITICAL         0x0008
#define   AI_WASDRAWN         0x0010
#define   AI_WASATTACKED      0x0020
#define   AI_GAVEWARNING      0x0040
#define   AI_ENCROACHMENT     0x0080
#define   AI_DIDFLEESCREAM    0x0100
#define   AI_DIDAMBUSHYELL    0x0200
#define   AI_DIDHIDEPLEA      0x0400
#define   AI_TIMETODODGE      0x0800

#define   lm(_str_) printf(" %s...\n", _str_);

#define fillsprite(newspriteindex2,x2,y2,z2,cstat2,shade2,pal2,            \
          clipdist2,xrepeat2,yrepeat2,xoffset2,yoffset2,picnum2,ang2,      \
          xvel2,yvel2,zvel2,owner2,sectnum2,statnum2,lotag2,hitag2,extra2) \
{                                                                          \
     spritetype *spr2;                                                     \
     spr2 = &sprite[newspriteindex2];                                      \
     spr2->x = x2; spr2->y = y2; spr2->z = z2;                             \
     spr2->cstat = cstat2; spr2->shade = shade2;                           \
     spr2->pal = pal2; spr2->clipdist = clipdist2;                         \
     spr2->xrepeat = xrepeat2; spr2->yrepeat = yrepeat2;                   \
     spr2->xoffset = xoffset2; spr2->yoffset = yoffset2;                   \
     spr2->picnum = picnum2; spr2->ang = ang2;                             \
     spr2->xvel = xvel2; spr2->yvel = yvel2; spr2->zvel = zvel2;           \
     spr2->owner = owner2;                                                 \
     spr2->lotag = lotag2; spr2->hitag = hitag2; spr2->extra = -1;         \
     copybuf(&spr2->x,&osprite[newspriteindex2].x,3);                      \
}                                                                          \

// b5compat.c

void overwritesprite(int thex, int they, short tilenum, signed char shade,
                     char stat, unsigned char dapalnum);
void permanentwritesprite(int thex, int they, short tilenum, signed char shade,
        int cx1, int cy1, int cx2, int cy2, unsigned char dapalnum);
void permanentwritespritetile(int thex, int they, short tilenum, signed char shade,
        int cx1, int cy1, int cx2, int cy2, unsigned char dapalnum);
void printext(int x, int y, const char *buffer, short tilenum, char invisiblecol);
void precache();
void resettiming();
void setbrightness(int32_t brightness);

// config.c
//int loadsetup(const char *fn);
//int writesetup(const char *fn);

// tekcdr.c

int cdpreinit(void);
void cduninit(void);

// tekchng.c

int changehealth(short snum, short deltahealth);
void changescore(short snum, short deltascore);
void tekchangefallz(short snum,int loz,int hiz);
void tekhealstun(short snum);

// tekgame.c

#define   MAXNAMESIZE    11

extern int       dbgflag;
extern int       dbgcolumn;
extern FILE      *dbgfp;

extern short     biasthreshhold;
extern char      biasthreshholdon;
extern int      headbob;
extern char      localname[MAXNAMESIZE];
extern char      netnames[MAXPLAYERS][MAXNAMESIZE];

extern int32_t   g_noSetup;

void checkmasterslaveswitch();
void doanimations();
void domovethings();
void drawscreen(short snum, int dasmoothratio);
void getpackets();
void playback();
int setanimation(int *animptr, int thegoal, int thevel, int theacc);

// tekgun.c

extern short dieframe[MAXPLAYERS];
extern int       goreflag;

void gunstatuslistcode(void);
void killscore(short hs, short snum, char guntype);
void playerpainsound(int p);
void restockammo(int snum);
void tekanimweap(int gun,short p);
void tekdrawgun(int gun,short p);
int tekexplodebody(int i);
void tekfiregun(int gun,short p);
int tekgundamage(int gun,int x,int y,int z,int hitsprite);
void tekgunload(int fil);
void tekgunsave(int fil);
int tekhasweapon(int gun,short snum);
int validplayer(int snum);

// tekldsv.c

int loadgame(int loadno);
int savegame(int saveno);

// tekmap.c

void drawoverheadmap(int cposx, int cposy, int czoom, short cang);

// tekmsc.c

#define   MAXLOADSAVEOPTS     5
#define   MAXLOADSAVESIZE     12
#define   TOTALMAPS      32

extern int       activemenu;
extern int       autocenter[MAXPLAYERS];
extern char      debrief;
extern int       difficulty;
extern char      dofadein;
extern char      gameover;
extern char      generalplay;
extern char      loadsavenames[MAXLOADSAVEOPTS][MAXLOADSAVESIZE];
extern const char      *mapnames[TOTALMAPS];
extern int       mission;
extern int       mousesensitivity;
extern int       nochaseflag;
extern int       noenemiesflag;
extern int       noguardflag;
extern int       nostalkflag;
extern int       nostrollflag;
extern char      rearviewdraw;
extern char      singlemapmode;

int accessiblemap(int mn);
void bonusflash();
int choosemap();
int choosemission();
void copyrightscreen();
void criticalflash();
void debriefing();
void depositsymbol(int snum);
void domenu(void);
void domenuinput(void);
void fadein(int start, int end, int steps);
void fadeout(int start, int end, int red, int green, int blue, int steps);
void finishpaletteshifts(void);
void holyoff();
void holyon();
void initmenu(void);
void initmoreoptions();
int initpaletteshifts(void);
void missionaccomplished(int  sn);
int missionfailed();
void newgame(const char *mapname);
void newmap(int mapno);
void nextnetlevel();
void rearview(int snum);
void redrawbackfx(void);
void teksavemissioninfo(int fil);
void setup3dscreen();
void showmessage(const char *fmt,...);
void tekargv(int argc,char const * const argv[]);
void tekgamestarted(void);
void tekloadmissioninfo(int fil);
void tekloadmoreoptions(int fil);
int tekprivatekeys(void);
void teksavemoreoptions(int fil);
int tekscreenfx(void);
void tektime(void);
void woundflash();

// tekprep.c

extern int  coopmode;
extern int      startx,starty,startz;
extern short starta,starts;
extern int      switchlevelsflag;
extern int       subwaysound[4];

void initplayersprite(short snum);
void netstartspot(int *x, int *y,short *sectnum);
void placerandompic(int picnum);
void prepareboard(char *daboardfilename);
void tekinitmultiplayers(int argc, char const * const argv[]);
void tekloadsetup();
void teknetpickmap(void);
int tekpreinit(void);
void tekrestoreplayer(short snum);
void teksavesetup(void);
void tekview(int *x1,int *y1, int *x2,int *y2);

// teksmk.c

void smkclosemenu();
void smkmenuframe(int fn);
void smkopenmenu(const char *name);
void smkplayseq(const char *name);
void smkshowmenu();

// teksnd.c

extern int          digiloopflag;

void initsb(char option1,char option2,int digihz,char option7a,char option7b,int val,char option7c);
void menusong(int insubway);
void musicfade();
void musicoff(void);
int playsound(int sn, int sndx,int sndy, int loop, short type);
void songmastervolume(int vol);
void soundmastervolume(int vol);
void startmusic(int level);
void stopallsounds();
void stopsound(int i);
void uninitsb(void);
void updatesounds(int snum);
void updatevehiclesnds(int i, int sndx, int sndy);

// tekspr.c

void analyzesprites(int dax, int day);
void checktouchsprite(short snum, short sectnum);
short floatmovesprite(short spritenum, int dx, int dy, int dz, int ceildist, int flordist, char cliptype);
short flymovesprite(short spritenum, int dx, int dy, int dz, int ceildist, int flordist, char cliptype);
short kenmovesprite(short spritenum, int dx, int dy, int dz, int ceildist, int flordist, char cliptype);
short movesprite(short spritenum, int dx, int dy, int dz, int ceildist, int flordist, char cliptype);
void playerdropitems(int snum);

// tekstat.c

#define   NORMALCLIP          0
#define   PROJECTILECLIP      1
#define   CLIFFCLIP           2

extern uspritetype     pickup;

void ambushyell(short sn, short ext);
void androidexplosion(int i);
int attachvirus(short i, int pic);
void blastmark(int i);
void bloodonwall(int wn, int x,int y,int z, short sect, short daang, int hitx, int hity, int hitz);
void bombexplosion(int i);
int damagesprite(int hitsprite, int points);
void dosectorflash();
void forceexplosion(int i);
void genexplosion1(int i);
void genexplosion2(int i);
void givewarning(short i, short ext);
int initsprites();
int initspriteXTs();
int isahologram(int i);
int isanandroid(int i);
short jsdeletesprite(short spritenum);
short jsinsertsprite(short sect, short stat);
void newstatus(short sn, int  seq);
int pickupsprite(short sn);
void playergunshot(int snum);
int playerhit(int hitsprite, int *pnum);
int playervirus(short pnum, int pic);
void sectorflash(short s);
void sectortriggersprites(short snum);
int spewblood(int sprnum, int hitz, short daang);
void statuslistcode();
void tekstatload(int fh);
void tekstatsave(int fh);
void toss(short snum);
int validext(int ext);

// tektag.c

extern int       headbobon;
extern char onelev[MAXPLAYERS];

void checkmapsndfx(short p);
int krand_intercept(const char *stg);
void movedoors(int d);
void movefloordoor(int d);
void movesprelevs(int e);
void movevehicles(int v);
void operatesector(short dasector);
void operatesprite(short dasprite);
void setanimpic(short *pic,short tics,short frames);
void tagcode();
void tekdoanimpic(void);
void tekdodelayfuncs(void);
void tekheadbob(void);
void teknewsector(short p);
void tekoperatesector(short dasector);
void tekpreptags();
void teksetdelayfunc(void (*delayfunc)(short),int tics,short parm);
void tekswitchtrigger(short snum);
void tektagcode(void);
void tektagload(int fil);
void tektagsave(int fil);
int testneighborsectors(short sect1, short sect2);
void warp(int *x, int *y, int *z, short *daang, short *dasector);
void warpsprite(short spritenum);

// tektxt.c

extern char      bypasscdcheck;

void crash(const char *s,...);


code:
/**
 * BUILD ART file editing tool
 * @author Jonathon Fowler
 * @license Artistic License 2.0 (http://www.perlfoundation.org/artistic_license_2_0)
 */
// Bstring and C++ STL --> C conversion by Hendricks266

#include "compat.h"

////////// Bstring //////////

class Bstring {
    public:
        Bstring(void);
        Bstring(const char*);
        Bstring(const Bstring&);
        ~Bstring(void);

        operator const char*() const;
        const char* operator()(void) const;
        char& operator[](int);

        Bstring& operator=(const char*);
        Bstring& operator=(const Bstring&);

        Bstring& operator+=(const char*);
        Bstring& operator+=(const Bstring&);

        bool operator==(const Bstring&) const;
        bool operator!=(const Bstring&) const;
        bool operator< (const Bstring&) const;
        bool operator<=(const Bstring&) const;
        bool operator> (const Bstring&) const;
        bool operator>=(const Bstring&) const;

        bool operator==(const char*) const;
        bool operator!=(const char*) const;
        bool operator< (const char*) const;
        bool operator<=(const char*) const;
        bool operator> (const char*) const;
        bool operator>=(const char*) const;

        int compare(const char*) const;
        int compare(const Bstring&) const;

        unsigned length(void) const;

        void clear(void);

    protected:
        char* data;
};

Bstring::Bstring(void) { data = NULL; }
Bstring::Bstring(const Bstring &value) {
    if (&value != this)
        (*this)=value();
}
Bstring::Bstring(const char *str) {
    data = NULL;
    (*this)=str;
}

Bstring::~Bstring(void) { clear(); }

Bstring::operator const char*() const { return data; }
const char* Bstring::operator()(void) const { return data; }
char& Bstring::operator[](int index) { return data[index]; }

Bstring& Bstring::operator=(const Bstring &value)
{
    if (&value != this)
        (*this)=value();

    return *this;
}
Bstring& Bstring::operator=(const char *str)
{
    clear();
    data = Bstrdup(str);

    return *this;
}

Bstring& Bstring::operator+=(const Bstring &value)
{
    (*this)+=value();

    return *this;
}
Bstring& Bstring::operator+=(const char *str)
{
    data = (char*) Brealloc(data, (Bstrlen(data) + Bstrlen(str) + 1) * sizeof(char));
    Bstrcat(data, str);

    return *this;
}

bool Bstring::operator==(const Bstring &value) const { return Bstrcmp(data, value()) == 0; }
bool Bstring::operator!=(const Bstring &value) const { return Bstrcmp(data, value()) != 0; }
bool Bstring::operator< (const Bstring &value) const { return Bstrcmp(data, value())  < 0; }
bool Bstring::operator<=(const Bstring &value) const { return Bstrcmp(data, value()) <= 0; }
bool Bstring::operator> (const Bstring &value) const { return Bstrcmp(data, value())  > 0; }
bool Bstring::operator>=(const Bstring &value) const { return Bstrcmp(data, value()) >= 0; }

bool Bstring::operator==(const char *str) const { return Bstrcmp(data, str) == 0; }
bool Bstring::operator!=(const char *str) const { return Bstrcmp(data, str) != 0; }
bool Bstring::operator< (const char *str) const { return Bstrcmp(data, str)  < 0; }
bool Bstring::operator<=(const char *str) const { return Bstrcmp(data, str) <= 0; }
bool Bstring::operator> (const char *str) const { return Bstrcmp(data, str)  > 0; }
bool Bstring::operator>=(const char *str) const { return Bstrcmp(data, str) >= 0; }

int Bstring::compare(const Bstring &value) const { return Bstrcmp(data,value()); }
int Bstring::compare(const char *str) const { return Bstrcmp(data,str); }

unsigned Bstring::length(void) const { return Bstrlen(data); }

void Bstring::clear(void)
{
    DO_FREE_AND_NULL(data);
}

////////// arttool //////////

void usage()
{
    Bprintf("BUILD ART file editing tool\n");
    Bprintf("Copyright (C) 2008 Jonathon Fowler <jf@jonof.id.au>\n");
    Bprintf("Released under the Artistic License 2.0\n");
    Bprintf("\n");
    Bprintf("  arttool info [tilenum]\n");
    Bprintf("    Display information about a specific tile, or all if none is specified\n");
    Bprintf("\n");
    Bprintf("  arttool create [options]\n");
    Bprintf("    -f <filenum>   Selects which numbered ART file to create (default 0)\n");
    Bprintf("    -o <offset>    Specifies the first tile in the file (default 0)\n");
    Bprintf("    -n <ntiles>    The number of tiles for the art file (default 256)\n");
    Bprintf("    Creates an empty ART file named 'tilesXXX.art'\n");
    Bprintf("\n");
    Bprintf("  arttool addtile [options] <tilenum> <filename>\n");
    Bprintf("    -x <pixels>    X-centre\n");
    Bprintf("    -y <pixels>    Y-centre\n");
    Bprintf("    -ann <frames>  Animation frame span\n");
    Bprintf("    -ant <type>    Animation type (0=none, 1=oscillate, 2=forward, 3=reverse)\n");
    Bprintf("    -ans <speed>   Animation speed\n");
    Bprintf("    Adds a tile to the 'tilesXXX.art' set from a TGA or PCX source\n");
    Bprintf("\n");
    Bprintf("  arttool rmtile <tilenum>\n");
    Bprintf("    Removes a tile from the 'tilesXXX.art' set\n");
    Bprintf("\n");
    Bprintf("  arttool exporttile <tilenum>\n");
    Bprintf("    Exports a tile from the 'tilesXXX.art' set to a PCX file\n");
    Bprintf("\n");
    Bprintf("  arttool tileprop [options] <tilenum>\n");
    Bprintf("    -x <pixels>    X-centre\n");
    Bprintf("    -y <pixels>    Y-centre\n");
    Bprintf("    -ann <frames>  Animation frame span, may be negative\n");
    Bprintf("    -ant <type>    Animation type (0=none, 1=oscillate, 2=forward, 3=reverse)\n");
    Bprintf("    -ans <speed>   Animation speed\n");
    Bprintf("    Changes tile properties\n");
    Bprintf("\n");
}

class ARTFile {
private:
    Bstring filename_;
    int localtilestart_;
    int localtileend_;
    short * tilesizx_;
    short * tilesizy_;
    int * picanm_;
    int datastartoffset_;

    // for removing or replacing tile data
    int markprelength_, markskiplength_, markpostlength_;
    char * insert_;
    int insertlen_;

    void writeShort(BFILE *ofs, short s)
    {
        Bassert(ofs);
        char d[2] = { static_cast<char>(s&255), static_cast<char>((s>>8)&255) };
        Bfwrite(d,1,2,ofs); // 2 == sizeof(d)
    }

    void writeLong(BFILE *ofs, int l)
    {
        Bassert(ofs);
        char d[4] = { static_cast<char>(l&255), static_cast<char>((l>>8)&255), static_cast<char>((l>>16)&255), static_cast<char>((l>>24)&255) };
        Bfwrite(d,1,4,ofs); // 4 == sizeof(d)
    }

    short readShort(BFILE *ifs)
    {
        Bassert(ifs);
        unsigned char d[2];
        unsigned short s;
        Bfread(d,1,2,ifs); // 2 == sizeof(d)
        s = (unsigned short)d[0];
        s |= (unsigned short)d[1] << 8;
        return (short)s;
    }

    int readLong(BFILE *ifs)
    {
        Bassert(ifs);
        unsigned char d[4];
        unsigned int l;
        Bfread(d,1,4,ifs); // 4 == sizeof(d)
        l = (unsigned int)d[0];
        l |= (unsigned int)d[1] << 8;
        l |= (unsigned int)d[2] << 16;
        l |= (unsigned int)d[3] << 24;
        return (int)l;
    }

    void dispose()
    {
        if (tilesizx_) delete [] tilesizx_;
        if (tilesizy_) delete [] tilesizy_;
        if (picanm_) delete [] picanm_;
        if (insert_) delete [] insert_;

        insert_ = 0;
        insertlen_ = 0;
    }

    void load()
    {
        BFILE *infile = Bfopen(filename_(),"rb");
        int i, ntiles;

        if (infile != NULL && readLong(infile) == 1)
        {
            readLong(infile);    // skip the numtiles
            dispose();

            localtilestart_ = readLong(infile);
            localtileend_   = readLong(infile);
            ntiles = localtileend_ - localtilestart_ + 1;

            tilesizx_ = new short[ntiles];
            tilesizy_ = new short[ntiles];
            picanm_   = new int[ntiles];

            for (i = 0; i < ntiles; ++i) {
                tilesizx_[i] = readShort(infile);
            }
            for (i = 0; i < ntiles; ++i) {
                tilesizy_[i] = readShort(infile);
            }
            for (i = 0; i < ntiles; ++i) {
                picanm_[i] = readLong(infile);
            }

            datastartoffset_ = Bftell(infile);

            Bfclose(infile);
        }
    }

public:
    ARTFile(Bstring const & filename)
     : filename_(filename), localtilestart_(0), localtileend_(-1),
       tilesizx_(0), tilesizy_(0), picanm_(0), datastartoffset_(0),
       markprelength_(0), markskiplength_(0), markpostlength_(0),
       insert_(0), insertlen_(0)
    {
        load();
    }

    ~ARTFile()
    {
        dispose();
    }

    /**
     * Sets up for an empty file
     * @param start the starting tile
     * @param ntiles the number of tiles total
     */
    void init(int start, int ntiles)
    {
        dispose();

        localtilestart_ = start;
        localtileend_ = start + ntiles - 1;
        tilesizx_ = new short[ntiles];
        tilesizy_ = new short[ntiles];
        picanm_   = new int[ntiles];
        datastartoffset_ = 0;

        memset(tilesizx_, 0, sizeof(short)*ntiles);
        memset(tilesizy_, 0, sizeof(short)*ntiles);
        memset(picanm_, 0, sizeof(int)*ntiles);

        markprelength_ = 0;
        markskiplength_ = 0;
        markpostlength_ = 0;
        insert_ = 0;
        insertlen_ = 0;
    }

    /**
     * Returns the number of tiles in the loaded file
     * @return 0 means no file loaded
     */
    int getNumTiles()
    {
        return (localtileend_ - localtilestart_ + 1);
    }

    int getFirstTile()
    {
        return localtilestart_;
    }

    int getLastTile()
    {
        return localtileend_;
    }

    void removeTile(int tile)
    {
        int i, end;

        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        end   = localtileend_ - tile;
        tile -= localtilestart_;

        markprelength_ = markpostlength_ = 0;

        for (i = 0; i < tile; ++i) {
            markprelength_ += tilesizx_[i] * tilesizy_[i];
        }
        markskiplength_ = tilesizx_[tile] * tilesizy_[tile];
        for (i = tile + 1; i <= end; ++i) {
            markpostlength_ += tilesizx_[i] * tilesizy_[i];
        }

        tilesizx_[tile] = tilesizy_[tile] = 0;
    }

    void replaceTile(int tile, char * replace, int replacelen)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        removeTile(tile);

        insert_ = replace;
        insertlen_ = replacelen;
    }

    void getTileSize(int tile, int& x, int &y)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            x = y = -1;
            return;
        }

        tile -= localtilestart_;
        x = tilesizx_[tile];
        y = tilesizy_[tile];
    }

    void setTileSize(int tile, int x, int y)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        tile -= localtilestart_;
        tilesizx_[tile] = x;
        tilesizy_[tile] = y;
    }

    void setXOfs(int tile, int x)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        tile -= localtilestart_;
        picanm_[tile] &= ~(255<<8);
        picanm_[tile] |= ((int)((unsigned char)x) << 8);
    }

    void setYOfs(int tile, int y)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        tile -= localtilestart_;
        picanm_[tile] &= ~(255<<16);
        picanm_[tile] |= ((int)((unsigned char)y) << 16);
    }

    int getXOfs(int tile)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return 0;
        }

        tile -= localtilestart_;
        return (picanm_[tile] >> 8) & 255;
    }

    int getYOfs(int tile)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return 0;
        }

        tile -= localtilestart_;
        return (picanm_[tile] >> 16) & 255;
    }

    void setAnimType(int tile, int type)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        tile -= localtilestart_;
        picanm_[tile] &= ~(3<<6);
        picanm_[tile] |= ((int)(type&3) << 6);
    }

    int getAnimType(int tile)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return 0;
        }

        tile -= localtilestart_;
        return (picanm_[tile] >> 6) & 3;
    }

    void setAnimFrames(int tile, int frames)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        tile -= localtilestart_;
        picanm_[tile] &= ~(63);
        picanm_[tile] |= ((int)(frames&63));
    }

    int getAnimFrames(int tile)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return 0;
        }

        tile -= localtilestart_;
        return picanm_[tile] & 63;
    }

    void setAnimSpeed(int tile, int speed)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return;
        }

        tile -= localtilestart_;
        picanm_[tile] &= ~(15<<24);
        picanm_[tile] |= ((int)(speed&15) << 24);
    }

    int getAnimSpeed(int tile)
    {
        if (tile < localtilestart_ || tile > localtileend_) {
            return 0;
        }

        tile -= localtilestart_;
        return (picanm_[tile] >> 24) & 15;
    }

    int write()
    {
        BFILE *outfile = tmpfile();

        BFILE *infile = Bfopen(filename_(),"rb");
        int tmp, left;
        static const unsigned int blksize = 4096;
        char blk[blksize];

        if (infile == NULL && (markprelength_ > 0 || markskiplength_ > 0 || markpostlength_ > 0)) {
            return -1;    // couldn't open the original file for copying
        } else if (infile != NULL) {
            // skip to the start of the existing ART data
            int ofs = 4+4+4+4+(2+2+4)*(localtileend_-localtilestart_+1);
            Bfseek(infile, ofs, SEEK_CUR);
        }

        // write a header to the temporary file
        writeLong(outfile, 1);    // version
        writeLong(outfile, 0);    // numtiles
        writeLong(outfile, localtilestart_);
        writeLong(outfile, localtileend_);
        for (int i = 0; i < localtileend_ - localtilestart_ + 1; ++i) {
            writeShort(outfile, tilesizx_[i]);
        }
        for (int i = 0; i < localtileend_ - localtilestart_ + 1; ++i) {
            writeShort(outfile, tilesizy_[i]);
        }
        for (int i = 0; i < localtileend_ - localtilestart_ + 1; ++i) {
            writeLong(outfile, picanm_[i]);
        }

        // copy the existing leading tile data to be kept
        left = markprelength_;
        while (left > 0) {
            tmp = left;
            if ((unsigned int)tmp > blksize) {
                tmp = blksize;
            }
            Bfread(blk, 1, tmp, infile);
            Bfwrite(blk, 1, tmp, outfile);
            left -= tmp;
        }

        // insert the replacement data
        if (insertlen_ > 0) {
            Bfwrite(insert_, 1, insertlen_, outfile);
        }

        if (markskiplength_ > 0) {
            Bfseek(infile, markskiplength_, SEEK_CUR);
        }

        // copy the existing trailing tile data to be kept
        left = markpostlength_;
        while (left > 0) {
            tmp = left;
            if ((unsigned int)tmp > blksize) {
                tmp = blksize;
            }
            Bfread(blk, 1, tmp, infile);
            Bfwrite(blk, 1, tmp, outfile);
            left -= tmp;
        }

        // clean up
        const long int tempsize = Bftell(outfile);
        Brewind(outfile);

        Bfclose(infile);

        infile = Bfopen(filename_(),"wb");

        char * buffer = (char*)Bmalloc(tempsize * sizeof(char));

        Bfread(buffer, 1, tempsize, outfile);
        Bfwrite(buffer, 1, tempsize, infile);

        Bfclose(infile);
        Bfclose(outfile);

        return 0;
    }

    char * readTile(int tile, int& bytes)
    {
        bytes = -1;

        if (tile < localtilestart_ || tile > localtileend_) {
            return 0;
        }
        tile -= localtilestart_;

        if (tilesizx_[tile] == 0 || tilesizy_[tile] == 0) {
            bytes = 0;
            return 0;
        }

        BFILE *infile = Bfopen(filename_(),"rb");
        if (infile == NULL) {
            return 0;
        } else {
            // skip to the start of the existing ART data
            Bfseek(infile, datastartoffset_, SEEK_SET);
        }

        bytes = tilesizx_[tile] * tilesizy_[tile];
        char * data = new char[bytes];

        for (int i = 0; i < tile; i++) {
            Bfseek(infile, tilesizx_[i] * tilesizy_[i], SEEK_CUR);
        }
        if (Bfread(data, bytes, 1, infile) != 1) {
            delete [] data;
            data = 0;
        }

        Bfclose(infile);

        return data;
    }
};

class PCX {
private:
    static int writebyte(unsigned char colour, unsigned char count, BFILE *ofs)
    {
        if (!count) return 0;
        if (count == 1 && (colour & 0xc0) != 0xc0) {
            Bfputc(colour, ofs);
            return 1;
        } else {
            Bfputc(0xc0 | count, ofs);
            Bfputc(colour, ofs);
            return 2;
        }
    }

    static void writeline(unsigned char *buf, int bytes, int step, BFILE *ofs)
    {
        unsigned char ths, last;
        int srcIndex;
        unsigned char runCount;

        runCount = 1;
        last = *buf;

        for (srcIndex=1; srcIndex<bytes; srcIndex++) {
            buf += step;
            ths = *buf;
            if (ths == last) {
                runCount++;
                if (runCount == 63) {
                    writebyte(last, runCount, ofs);
                    runCount = 0;
                }
            } else {
                if (runCount)
                    writebyte(last, runCount, ofs);

                last = ths;
                runCount = 1;
            }
        }

        if (runCount) writebyte(last, runCount, ofs);
        if (bytes&1) writebyte(0, 1, ofs);
    }

public:
    /**
     * Decodes a PCX file to BUILD's column-major pixel order
     * @param data the raw file data
     * @param datalen the length of the raw file data
     * @param imgdata receives a pointer to the decoded image data
     * @param imgdataw receives the decoded image width
     * @param imgdatah receives the decoded image height
     * @return 0 on success, 1 if the format is invalid
     */
    static int decode(unsigned char * data, int datalen, char ** imgdata, int& imgdataw, int& imgdatah)
    {
        if (datalen < 128 ||
            data[0] != 10 ||
            data[1] != 5 ||
            data[2] != 1 ||
            data[3] != 8 ||
            data[64] != 0 ||
            data[65] != 1) {
            return 1;
        }

        int bpl = data[66] + ((int)data[67] << 8);
        int x, y, repeat, colour;
        unsigned char *wptr;
        int roff;

        imgdataw = (data[8] + ((int)data[9] << 8)) - (data[4] + ((int)data[5] << 8)) + 1;
        imgdatah = (data[10] + ((int)data[11] << 8)) - (data[6] + ((int)data[7] << 8)) + 1;

        *imgdata = new char [imgdataw * imgdatah];

        roff = 128;
        for (y = 0; y < imgdatah; y++) {
            wptr = (unsigned char *) (*imgdata + y);
            x = 0;
            do {
                if (EDUKE32_PREDICT_FALSE(roff >= datalen))
                    return 1;
                repeat = *(data + roff++);

                if ((repeat & 192) == 192) {
                    if (EDUKE32_PREDICT_FALSE(roff >= datalen))
                        return 1;
                    colour = *(data + roff++);
                    repeat = repeat & 63;
                } else {
                    colour = repeat;
                    repeat = 1;
                }

                for (; repeat > 0; repeat--, x++) {
                    if (x < imgdataw) {
                        *wptr = (unsigned char) colour;
                        wptr += imgdatah;   // next column
                    }
                }
            } while (x < bpl);
        }

        return 0;
    }

    /**
     * Writes a PCX file from data in BUILD's column-major pixel order
     * @param ofs the output file stream
     * @param imgdata a pointer to the image data
     * @param imgdataw the image width
     * @param imgdatah the image height
     * @param palette the image palette, 256*3 bytes
     * @return 0 on success
     */
    static int write(BFILE *ofs, unsigned char * imgdata, int imgdataw, int imgdatah, unsigned char * palette)
    {
        unsigned char head[128];
        int bpl = imgdataw + (imgdataw&1);

        memset(head,0,128);
        head[0] = 10;
        head[1] = 5;
        head[2] = 1;
        head[3] = 8;
        head[8] = (imgdataw-1) & 0xff;
        head[9] = ((imgdataw-1) >> 8) & 0xff;
        head[10] = (imgdatah-1) & 0xff;
        head[11] = ((imgdatah-1) >> 8) & 0xff;
        head[12] = 72; head[13] = 0;
        head[14] = 72; head[15] = 0;
        head[65] = 1;   // 8-bit
        head[66] = bpl & 0xff;
        head[67] = (bpl >> 8) & 0xff;
        head[68] = 1;

        Bfwrite(head, sizeof(head), 1, ofs);
        for (int i = 0; i < imgdatah; i++) {
            writeline(imgdata + i, imgdataw, imgdatah, ofs);
        }

        Bfputc(12, ofs);
        Bfwrite(palette, 768, 1, ofs);

        return 0;
    }
};

/**
 * Loads a tile from a picture file into memory
 * @param filename the filename
 * @param imgdata receives a pointer to the decoded image data
 * @param imgdataw receives the decoded image width
 * @param imgdatah receives the decoded image height
 * @return 0 on success
 */
int loadimage(Bstring const & filename, char ** imgdata, int& imgdataw, int& imgdatah)
{
    BFILE *infile = Bfopen(filename(),"rb");
    unsigned char * data = 0;
    int datalen = 0, err = 0;

    if (infile == NULL)
        return 1;

    struct Bstat stbuf;
    if (Bfstat(Bfileno(infile), &stbuf) == -1)
        return 1;

    datalen = stbuf.st_size;

    data = new unsigned char [datalen];
    Bfread(data, 1, datalen, infile);
    Bfclose(infile);

    err = PCX::decode(data, datalen, imgdata, imgdataw, imgdatah);

    delete [] data;

    return err;
}

/**
 * Saves a tile from memory to disk, taking the palette from palette.dat
 * @param filename the filename
 * @param imgdata a pointer to the image data
 * @param imgdataw the image width
 * @param imgdatah the image height
 * @return 0 on success
 */
int saveimage(Bstring const & filename, char * imgdata, int imgdataw, int imgdatah)
{
    BFILE *outfile = Bfopen(filename(), "wb");
    BFILE *palfile = Bfopen("palette.dat", "rb");
    unsigned char palette[768];

    if (palfile != NULL) {
        Bfread(palette, 768, 1, palfile);
        for (int i=0; i<256*3; i++) {
            palette[i] <<= 2;
        }
        Bfclose(palfile);
    } else {
        Bfprintf(stderr, "warning: palette.dat could not be loaded\n");
        for (int i=0; i<256; i++) {
            palette[i*3+0] = i;
            palette[i*3+1] = i;
            palette[i*3+2] = i;
        }
    }

    if (outfile == NULL) {
        return 1;
    }

    PCX::write(outfile, (unsigned char *)imgdata, imgdataw, imgdatah, palette);

    Bfclose(outfile);

    return 0;
}

class Operation {
protected:
    Bstring makefilename(int n)
    {
        Bstring filename("tilesXXX.art");
        filename[5] = '0' + (n / 100) % 10;
        filename[6] = '0' + (n / 10) % 10;
        filename[7] = '0' + (n / 1) % 10;
        return filename;
    }

public:
    typedef enum {
        ERR_NO_ERROR = 0,
        ERR_BAD_OPTION = 1,
        ERR_BAD_VALUE = 2,
        ERR_TOO_MANY_PARAMS = 3,
        ERR_NO_ART_FILE = 4,
        ERR_INVALID_IMAGE = 5,
    } Result;

    static char const * translateResult(Result r)
    {
        switch (r) {
            case ERR_NO_ERROR: return "no error";
            case ERR_BAD_OPTION: return "bad option";
            case ERR_BAD_VALUE: return "bad value";
            case ERR_TOO_MANY_PARAMS: return "too many parameters given";
            case ERR_NO_ART_FILE: return "no ART file was found";
            case ERR_INVALID_IMAGE: return "a nonexistent, corrupt, or unrecognised image was given";
            default: return "unknown error";
        }
    }

    virtual ~Operation()
    {
    }

    /**
     * Sets an option
     * @param opt the option name
     * @param value the option value
     * @return a value from the Result enum
     */
    virtual Result setOption(const Bstring &opt, const Bstring &value) = 0;

    /**
     * Sets a parameter from the unnamed sequence
     * @param number the parameter number
     * @param value the parameter value
     * @return a value from the Result enum
     */
    virtual Result setParameter(const int &number, const Bstring &value) = 0;

    /**
     * Do the operation
     * @return a value from the Result enum
     */
    virtual Result perform() = 0;
};
class InfoOp : public Operation {
private:
    int tilenum_;

    void outputInfo(ARTFile& art, int tile)
    {
        Bprintf("  Tile %i: ", tile);

        int w, h;
        art.getTileSize(tile, w, h);
        Bprintf("%ix%i ", w, h);

        Bprintf("Xofs: %i, ", art.getXOfs(tile));
        Bprintf("Yofs: %i, ", art.getYOfs(tile));
        Bprintf("AnimType: %i, ", art.getAnimType(tile));
        Bprintf("AnimFrames: %i, ", art.getAnimFrames(tile));
        Bprintf("AnimSpeed: %i\n", art.getAnimSpeed(tile));
    }

public:
    InfoOp() : tilenum_(-1) { }

    virtual Result setOption(const Bstring &opt ATTRIBUTE((unused)), const Bstring &value ATTRIBUTE((unused)))
    {
        return ERR_BAD_OPTION;
    }

    virtual Result setParameter(const int &number, const Bstring &value)
    {
        switch (number) {
            case 0:
                tilenum_ = atoi(value());
                return ERR_NO_ERROR;
            default:
                return ERR_TOO_MANY_PARAMS;
        }
    }

    virtual Result perform()
    {
        int filenum = 0, tile;

        for (filenum = 0; filenum < 1000; filenum++) {
            Bstring filename = makefilename(filenum);
            ARTFile art(filename);

            if (art.getNumTiles() == 0) {
                // no file exists, so give up
                if (tilenum_ < 0) {
                    return ERR_NO_ERROR;
                }
                break;
            }

            if (tilenum_ >= 0) {
                if (tilenum_ > art.getLastTile()) {
                    // Not in this file.
                    continue;
                } else {
                    Bprintf("File %s\n", filename());
                    outputInfo(art, tilenum_);
                }
                return ERR_NO_ERROR;
            } else {
                Bprintf("File %s\n", filename());
                for (tile = art.getFirstTile(); tile <= art.getLastTile(); tile++) {
                    outputInfo(art, tile);
                }
            }
        }

        return ERR_NO_ART_FILE;
    }
};

class CreateOp : public Operation {
private:
    int filen_, offset_, ntiles_;
public:
    CreateOp() : filen_(0), offset_(0), ntiles_(256) { }

    virtual Result setOption(const Bstring &opt, const Bstring &value)
    {
        if (opt == "f") {
            filen_ = atoi(value());
            if (filen_ < 0 || filen_ > 999) {
                return ERR_BAD_VALUE;
            }
        } else if (opt == "o") {
            offset_ = atoi(value());
            if (offset_ < 0) {
                return ERR_BAD_VALUE;
            }
        } else if (opt == "n") {
            ntiles_ = atoi(value());
            if (ntiles_ < 1) {
                return ERR_BAD_VALUE;
            }
        } else {
            return ERR_BAD_OPTION;
        }
        return ERR_NO_ERROR;
    }

    virtual Result setParameter(const int &number ATTRIBUTE((unused)), const Bstring &value ATTRIBUTE((unused)))
    {
        return ERR_TOO_MANY_PARAMS;
    }

    virtual Result perform()
    {
        ARTFile art(makefilename(filen_));

        art.init(offset_, ntiles_);
        art.write();

        return ERR_NO_ERROR;
    }
};

class AddTileOp : public Operation {
private:
    int xofs_, yofs_;
    int animframes_, animtype_, animspeed_;
    int tilenum_;
    Bstring filename_;
public:
    AddTileOp()
     : xofs_(0), yofs_(0),
       animframes_(0), animtype_(0), animspeed_(0),
       tilenum_(-1), filename_("")
    { }

    virtual Result setOption(const Bstring &opt, const Bstring &value)
    {
        if (opt == "x") {
            xofs_ = atoi(value());
        } else if (opt == "y") {
            yofs_ = atoi(value());
        } else if (opt == "ann") {
            animframes_ = atoi(value());
            if (animframes_ < 0 || animframes_ > 63) {
                return ERR_BAD_VALUE;
            }
        } else if (opt == "ant") {
            animtype_ = atoi(value());
            if (animtype_ < 0 || animtype_ > 3) {
                return ERR_BAD_VALUE;
            }
        } else if (opt == "ans") {
            animspeed_ = atoi(value());
            if (animspeed_ < 0 || animspeed_ > 15) {
                return ERR_BAD_VALUE;
            }
        } else {
            return ERR_BAD_OPTION;
        }
        return ERR_NO_ERROR;
    }

    virtual Result setParameter(const int &number, const Bstring &value)
    {
        switch (number) {
            case 0:
                tilenum_ = atoi(value());
                return ERR_NO_ERROR;
            case 1:
                filename_ = value;
                return ERR_NO_ERROR;
            default:
                return ERR_TOO_MANY_PARAMS;
        }
    }

    virtual Result perform()
    {
        int tilesperfile = 0, nextstart = 0;
        int filenum = 0;
        char * imgdata = 0;
        int imgdataw = 0, imgdatah = 0;

        // open the first art file to get the file size used by default
        {
            ARTFile art(makefilename(0));
            tilesperfile = art.getNumTiles();
            if (tilesperfile == 0) {
                return ERR_NO_ART_FILE;
            }
        }

        // load the tile image into memory
        switch (loadimage(filename_, &imgdata, imgdataw, imgdatah)) {
            case 0: break;    // win
            default: return ERR_INVALID_IMAGE;
        }

        // open art files until we find one that encompasses the range we need
        // and when we find it, make the change
        for (filenum = 0; filenum < 1000; filenum++) {
            ARTFile art(makefilename(filenum));
            bool dirty = false, done = false;

            if (art.getNumTiles() == 0) {
                // no file exists, so we treat it as though it does
                art.init(nextstart, tilesperfile);
                dirty = true;
            }

            if (tilenum_ >= art.getFirstTile() && tilenum_ <= art.getLastTile()) {
                art.replaceTile(tilenum_, imgdata, imgdataw * imgdatah);
                art.setTileSize(tilenum_, imgdataw, imgdatah);
                art.setXOfs(tilenum_, xofs_);
                art.setYOfs(tilenum_, yofs_);
                art.setAnimFrames(tilenum_, animframes_);
                art.setAnimSpeed(tilenum_, animspeed_);
                art.setAnimType(tilenum_, animtype_);
                done = true;
                dirty = true;

                imgdata = 0;    // ARTFile.replaceTile took ownership of the pointer
            }

            nextstart += art.getNumTiles();

            if (dirty) {
                art.write();
            }
            if (done) {
                return ERR_NO_ERROR;
            }
        }

        if (imgdata) {
            delete [] imgdata;
        }

        return ERR_NO_ART_FILE;
    }
};

class RmTileOp : public Operation {
private:
    int tilenum_;
public:
    RmTileOp() : tilenum_(-1) { }

    virtual Result setOption(const Bstring &opt ATTRIBUTE((unused)), const Bstring &value ATTRIBUTE((unused)))
    {
        return ERR_BAD_OPTION;
    }

    virtual Result setParameter(const int &number, const Bstring &value)
    {
        switch (number) {
            case 0:
                tilenum_ = atoi(value());
                return ERR_NO_ERROR;
            default:
                return ERR_TOO_MANY_PARAMS;
        }
    }

    virtual Result perform()
    {
        int filenum = 0;

        // open art files until we find one that encompasses the range we need
        // and when we find it, remove the tile
        for (filenum = 0; filenum < 1000; filenum++) {
            ARTFile art(makefilename(filenum));

            if (art.getNumTiles() == 0) {
                // no file exists, so give up
                break;
            }

            if (tilenum_ >= art.getFirstTile() && tilenum_ <= art.getLastTile()) {
                art.removeTile(tilenum_);
                art.write();
                return ERR_NO_ERROR;
            }
        }

        return ERR_NO_ART_FILE;
    }
};

class ExportTileOp : public Operation {
private:
    int tilenum_;
public:
    ExportTileOp() : tilenum_(-1) { }

    virtual Result setOption(const Bstring &opt ATTRIBUTE((unused)), const Bstring &value ATTRIBUTE((unused)))
    {
        return ERR_BAD_OPTION;
    }

    virtual Result setParameter(const int &number, const Bstring &value)
    {
        switch (number) {
            case 0:
                tilenum_ = atoi(value());
                return ERR_NO_ERROR;
            default:
                return ERR_TOO_MANY_PARAMS;
        }
    }

    virtual Result perform()
    {
        int filenum = 0;

        Bstring filename("tile0000.pcx");
        filename[4] = '0' + (tilenum_ / 1000) % 10;
        filename[5] = '0' + (tilenum_ / 100) % 10;
        filename[6] = '0' + (tilenum_ / 10) % 10;
        filename[7] = '0' + (tilenum_) % 10;

        // open art files until we find the one that encompasses the range we need
        // and when we find it, export it
        for (filenum = 0; filenum < 1000; filenum++) {
            ARTFile art(makefilename(filenum));

            if (art.getNumTiles() == 0) {
                // no file exists, so give up
                break;
            }

            if (tilenum_ >= art.getFirstTile() && tilenum_ <= art.getLastTile()) {
                int bytes, w, h;
                char * data = art.readTile(tilenum_, bytes);
                art.getTileSize(tilenum_, w, h);

                if (bytes == 0) {
                    return ERR_NO_ERROR;
                }

                switch (saveimage(filename, data, w, h)) {
                    case 0: break;  // win
                    default: return ERR_INVALID_IMAGE;
                }

                delete [] data;

                return ERR_NO_ERROR;
            }
        }

        return ERR_NO_ART_FILE;
    }
};

class TilePropOp : public Operation {
private:
    int xofs_, yofs_;
    int animframes_, animtype_, animspeed_;
    int tilenum_;

    int settings_;

    enum {
        SET_XOFS = 1,
        SET_YOFS = 2,
        SET_ANIMFRAMES = 4,
        SET_ANIMTYPE = 8,
        SET_ANIMSPEED = 16,
    };
public:
    TilePropOp()
    : xofs_(0), yofs_(0),
      animframes_(0), animtype_(0), animspeed_(0),
      tilenum_(-1), settings_(0)
    { }

    virtual Result setOption(const Bstring &opt, const Bstring &value)
    {
        if (opt == "x") {
            xofs_ = atoi(value());
            settings_ |= SET_XOFS;
        } else if (opt == "y") {
            yofs_ = atoi(value());
            settings_ |= SET_YOFS;
        } else if (opt == "ann") {
            animframes_ = atoi(value());
            settings_ |= SET_ANIMFRAMES;
            if (animframes_ < 0 || animframes_ > 63) {
                return ERR_BAD_VALUE;
            }
        } else if (opt == "ant") {
            animtype_ = atoi(value());
            settings_ |= SET_ANIMTYPE;
            if (animtype_ < 0 || animtype_ > 3) {
                return ERR_BAD_VALUE;
            }
        } else if (opt == "ans") {
            animspeed_ = atoi(value());
            settings_ |= SET_ANIMSPEED;
            if (animspeed_ < 0 || animspeed_ > 15) {
                return ERR_BAD_VALUE;
            }
        } else {
            return ERR_BAD_OPTION;
        }
        return ERR_NO_ERROR;
    }

    virtual Result setParameter(const int &number, const Bstring &value)
    {
        switch (number) {
            case 0:
                tilenum_ = atoi(value());
                return ERR_NO_ERROR;
            default:
                return ERR_TOO_MANY_PARAMS;
        }
    }

    virtual Result perform()
    {
        int filenum = 0;

        if (settings_ == 0) {
            return ERR_NO_ERROR;
        }

        // open art files until we find one that encompasses the range we need
        // and when we find it, make the change
        for (filenum = 0; filenum < 1000; filenum++) {
            ARTFile art(makefilename(filenum));

            if (art.getNumTiles() == 0) {
                // no file exists, so give up
                break;
            }

            if (tilenum_ >= art.getFirstTile() && tilenum_ <= art.getLastTile()) {
                if (settings_ & SET_XOFS) {
                    art.setXOfs(tilenum_, xofs_);
                }
                if (settings_ & SET_YOFS) {
                    art.setYOfs(tilenum_, yofs_);
                }
                if (settings_ & SET_ANIMFRAMES) {
                    art.setAnimFrames(tilenum_, animframes_);
                }
                if (settings_ & SET_ANIMSPEED) {
                    art.setAnimSpeed(tilenum_, animspeed_);
                }
                if (settings_ & SET_ANIMTYPE) {
                    art.setAnimType(tilenum_, animtype_);
                }
                art.write();
                return ERR_NO_ERROR;
            }
        }

        return ERR_NO_ART_FILE;
    }
};

int main(int argc, char ** argv)
{
    int showusage = 0;
    Operation * oper = 0;
    Operation::Result err = Operation::ERR_NO_ERROR;

    if (argc < 2) {
        showusage = 1;
    } else {
        Bstring opt(argv[1]);
        Bstring value;

        // create the option handler object according to the first param
        if (opt == "info") {
            oper = new InfoOp;
        } else if (opt == "create") {
            oper = new CreateOp;
        } else if (opt == "addtile") {
            oper = new AddTileOp;
        } else if (opt == "rmtile") {
            oper = new RmTileOp;
        } else if (opt == "exporttile") {
            oper = new ExportTileOp;
        } else if (opt == "tileprop") {
            oper = new TilePropOp;
        } else {
            showusage = 2;
        }

        // apply the command line options given
        if (oper) {
            int unnamedParm = 0;
            for (int i = 2; i < argc && !showusage; ++i) {
                if (argv[i][0] == '-') {
                    opt = argv[i] + 1;
                    if (i+1 >= argc) {
                        showusage = 2;
                        break;
                    }
                    value = argv[i+1];
                    ++i;

                    switch (err = oper->setOption(opt, value)) {
                        case Operation::ERR_NO_ERROR: break;
                        default:
                            Bfprintf(stderr, "error: %s\n", Operation::translateResult(err));
                            showusage = 2;
                            break;
                    }
                } else {
                    value = argv[i];
                    switch (oper->setParameter(unnamedParm, value)) {
                        case Operation::ERR_NO_ERROR: break;
                        default:
                            Bfprintf(stderr, "error: %s\n", Operation::translateResult(err));
                            showusage = 2;
                            break;
                    }
                    ++unnamedParm;
                }
            }
        }
    }

    if (showusage) {
        usage();
        if (oper) delete oper;
        return (showusage - 1);
    } else if (oper) {
        err = oper->perform();
        delete oper;

        switch (err) {
            case Operation::ERR_NO_ERROR: return 0;
            default:
                Bfprintf(stderr, "error: %s\n", Operation::translateResult(err));
                return 1;
        }
    }

    return 0;
}


code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.16'
Blender: 249
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos & Plagman"
__version__ = "0.16"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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.
#
# ***** END GPL LICENCE BLOCK *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene, NMesh, Key, Ipo, IpoCurve
#import meshtools

def read_main(filename):

    global counts
    counts = {'verts': 0, 'tris': 0}

    start = time.clock()
    file = open(filename, "r")

    print_boxed("----------------start-----------------")
    print 'Import Patch: ', filename

    editmode = Window.EditMode()    # are we in edit mode?  If so ...
    if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

    lines= file.readlines()
    read_file(file, lines)

    Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
    file.close()
    print "----------------end-----------------"
    end = time.clock()
    seconds = " in %.2f %s" % (end-start, "seconds")
    totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
    print_boxed(totals)
    message = "Successfully imported " + Blender.sys.basename(filename) + seconds
    #meshtools.print_boxed(message)
    print_boxed(message)

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
    lines = text.splitlines()
    maxlinelen = max(map(len, lines))
    if osSys.platform[:3] == "win":
        print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
        for line in lines:
            print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
        print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
    else:
        print '+-' + '-'*maxlinelen + '-+'
        for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
        print '+-' + '-'*maxlinelen + '-+'
    #print '\a\r', # beep when done

class ase_obj:

    def __init__(self):
        self.name = 'Name'
        self.objType = None
        self.row0x = None
        self.row0y = None
        self.row0z = None
        self.row1x = None
        self.row1y = None
        self.row1z = None
        self.row2x = None
        self.row2y = None
        self.row2z = None
        self.row3x = None
        self.row3y = None
        self.row3z = None
        self.parent = None
        self.obj = None
        self.objName = 'Name'

class ase_mesh:

    def __init__(self):
        self.name = ''
        self.vCount = 0
        self.fCount = 0
        self.frames = []
        self.verts = []
        self.faces = []
        self.animated = 0
        self.frameCount = -1

class mesh_vert:

    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0
        self.u = 0.0
        self.v = 0.0
        self.nx = 0.0
        self.ny = 0.0
        self.nz = 0.0
        self.origi = 0
    def make_tuple(self):
        return (self.x, self.y, self.z, self.u, self.v, self.nx, self.ny, self.nz)

class mesh_face:

    def __init__(self):
        self.v1 = mesh_vert()
        self.v2 = mesh_vert()
        self.v3 = mesh_vert()
        self.i1 = 0
        self.i2 = 0
        self.i3 = 0

def read_file(file, lines):

    objects = []
    objIdx = 0
    objCheck = -1 #needed to skip helper objects
    PBidx = 0.0
    lineCount = float(len(lines))
    processed_indices = []
    curFaceID = 0
    faceVertID = 0

    print 'Read file'
    Blender.Window.DrawProgressBar(0.0, "Read File...")

    for line in lines:
        words = string.split(line)

        if (PBidx % 10000) == 0.0:
            Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

        if not words:
            continue
        elif objIdx > 0 and me.animated == 1:
            # I don't know how to make empty statements, this is to skip everything else
            me.animated = me.animated
        elif words[0] == '*GEOMOBJECT':
            objCheck = 0
            newObj = ase_obj()
            objects.append(newObj)
            obj = objects[objIdx]
            objIdx += 1

            obj.objType = 'Mesh'
            obj.obj = ase_mesh()
            me = obj.obj
        elif words[0] == '*NODE_NAME' and objCheck != -1:
            if objCheck == 0:
                obj.name = words[1]
                objCheck = 1
            elif objCheck == 1:
                obj.objName = words[1]
        elif words[0] == '*TM_ROW0' and objCheck != -1:
            obj.row0x = float(words[1])
            obj.row0y = float(words[2])
            obj.row0z = float(words[3])
        elif words[0] == '*TM_ROW1' and objCheck != -1:
            obj.row1x = float(words[1])
            obj.row1y = float(words[2])
            obj.row1z = float(words[3])
        elif words[0] == '*TM_ROW2' and objCheck != -1:
            obj.row2x = float(words[1])
            obj.row2y = float(words[2])
            obj.row2z = float(words[3])
        elif words[0] == '*TM_ROW3' and objCheck != -1:
            obj.row3x = float(words[1])
            obj.row3y = float(words[2])
            obj.row3z = float(words[3])
            objCheck = -1
        elif words[0] == '*MESH_NUMVERTEX':
            me.vCount = int(words[1])
            for i in range(me.vCount):
                me.verts.append(mesh_vert())
        elif words[0] == '*MESH_NUMFACES':
            me.fCount = int(words[1])
            for i in range(me.fCount):
                me.faces.append(mesh_face())
        elif words[0] == '*MESH_VERTEX':
            i = int(words[1])
            me.verts[i].x = float(words[2]);
            me.verts[i].y = float(words[3]);
            me.verts[i].z = float(words[4]);
        elif words[0] == '*MESH_FACE':
            i = int(words[1].rstrip(":")) # looks like "13:"
            v1 = int(words[3]);
            v2 = int(words[5]);
            v3 = int(words[7]);
            me.faces[i].v1.x = me.verts[v1].x;
            me.faces[i].v1.y = me.verts[v1].y;
            me.faces[i].v1.z = me.verts[v1].z;
            me.faces[i].v1.origi = v1

            me.faces[i].v2.x = me.verts[v2].x;
            me.faces[i].v2.y = me.verts[v2].y;
            me.faces[i].v2.z = me.verts[v2].z;
            me.faces[i].v2.origi = v2

            me.faces[i].v3.x = me.verts[v3].x;
            me.faces[i].v3.y = me.verts[v3].y;
            me.faces[i].v3.z = me.verts[v3].z;
            me.faces[i].v3.origi = v3
        elif words[0] == '*MESH_NUMTVERTEX':
            del me.verts[:]
            uvCount = int(words[1])
            for i in range(uvCount):
                me.verts.append(mesh_vert())
        elif words[0] == '*MESH_TVERT':
            i = int(words[1])
            me.verts[i].u = float(words[2]);
            me.verts[i].v = float(words[3]);
        elif words[0] == '*MESH_TFACE':
            i = int(words[1])
            uv1 = int(words[2]);
            uv2 = int(words[3]);
            uv3 = int(words[4]);

            me.faces[i].v1.u = me.verts[uv1].u;
            me.faces[i].v1.v = me.verts[uv1].v;

            me.faces[i].v2.u = me.verts[uv2].u;
            me.faces[i].v2.v = me.verts[uv2].v;

            me.faces[i].v3.u = me.verts[uv3].u;
            me.faces[i].v3.v = me.verts[uv3].v;
        elif words[0] == '*MESH_FACENORMAL':
            curFaceID = int(words[1]) # global, vertexnormal needs this
            faceVertID = 0 # same
        elif words[0] == '*MESH_VERTEXNORMAL':
            nx = float(words[2])
            ny = float(words[3])
            nz = float(words[4])

            if (faceVertID == 0):
                me.faces[curFaceID].v1.nx = nx;
                me.faces[curFaceID].v1.ny = ny;
                me.faces[curFaceID].v1.nz = nz;
            elif (faceVertID == 1):
                me.faces[curFaceID].v2.nx = nx;
                me.faces[curFaceID].v2.ny = ny;
                me.faces[curFaceID].v2.nz = nz;
            elif (faceVertID == 2):
                me.faces[curFaceID].v3.nx = nx;
                me.faces[curFaceID].v3.ny = ny;
                me.faces[curFaceID].v3.nz = nz;

            faceVertID = faceVertID + 1;
        elif words[0] == '*MESH_ANIMATION':
            me.animated = 1

        # now the loop for animation frames
        if objIdx > 0 and me.animated == 1:
            if words[0] == '*MESH_VERTEX_LIST':
                me.frameCount += 1
                me.frames.append([])
            elif words[0] == '*MESH_VERTEX':
                me.frames[me.frameCount].append(mesh_vert())
                i = int(words[1])
                me.frames[me.frameCount][i].x = float(words[2]);
                me.frames[me.frameCount][i].y = float(words[3]);
                me.frames[me.frameCount][i].z = float(words[4]);

        PBidx += 1.0

    spawn_main(objects)

    Blender.Redraw()

def spawn_main(objects):

    PBidx = 0.0
    objCount = float(len(objects))

    print 'Import Objects'
    Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

    for obj in objects:

        Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

        if obj.objType == 'Mesh':
            spawn_mesh(obj)

        PBidx += 1.0

import random

def spawn_mesh(obj):

    objMe = obj.obj
    #normal_flag = 1

    row0 = obj.row0x, obj.row0y, obj.row0z
    row1 = obj.row1x, obj.row1y, obj.row1z
    row2 = obj.row2x, obj.row2y, obj.row2z
    row3 = obj.row3x, obj.row3y, obj.row3z

    newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
    newMatrix.resize4x4()

    newObj = Blender.Object.New(obj.objType, obj.name)
    newObj.setMatrix(newMatrix)
    Blender.Scene.getCurrent().link(newObj)

    newMesh = Blender.Mesh.New(obj.objName)
    newMesh.getFromObject(newObj.name)

    newMesh.vertexUV = 1
    newObj.link(newMesh)

    del objMe.verts[:]
    objMe.vCount = 0

    vertDict = {}

    #for face in objMe.faces:
        #objMe.verts.append(face.v1)
        #objMe.verts.append(face.v2)
        #objMe.verts.append(face.v3)
        #face.i1 = objMe.vCount
        #objMe.vCount = objMe.vCount + 1
        #face.i2 = objMe.vCount
        #objMe.vCount = objMe.vCount + 1
        #face.i3 = objMe.vCount
        #objMe.vCount = objMe.vCount + 1

    for face in objMe.faces:
        if not face.v1.make_tuple() in vertDict:
            vertDict[face.v1.make_tuple()] = objMe.vCount
            objMe.verts.append(face.v1)
            objMe.vCount = objMe.vCount + 1
        if not face.v2.make_tuple() in vertDict:
            vertDict[face.v2.make_tuple()] = objMe.vCount
            objMe.verts.append(face.v2)
            objMe.vCount = objMe.vCount + 1
        if not face.v3.make_tuple() in vertDict:
            vertDict[face.v3.make_tuple()] = objMe.vCount
            objMe.verts.append(face.v3)
            objMe.vCount = objMe.vCount + 1
        face.i1 = vertDict[face.v1.make_tuple()]
        face.i2 = vertDict[face.v2.make_tuple()]
        face.i3 = vertDict[face.v3.make_tuple()]

    # Verts
    for i in range(objMe.vCount):
        xyz = Blender.Mathutils.Vector(objMe.verts[i].x, objMe.verts[i].y, objMe.verts[i].z)
        newMesh.verts.extend(xyz)

    for i in range(objMe.vCount):
        xyz = Blender.Mathutils.Vector(objMe.verts[i].x, objMe.verts[i].y, objMe.verts[i].z)
        uv = Blender.Mathutils.Vector(objMe.verts[i].u, objMe.verts[i].v)
        norm = Blender.Mathutils.Vector(objMe.verts[i].nx, objMe.verts[i].ny, objMe.verts[i].nz)
        newMesh.verts[i].co  = xyz;
        newMesh.verts[i].uvco = uv;
        newMesh.verts[i].no = norm;

    if objMe.animated:
        objMe.frameCount -= 1 # do we always get an extra frame at the end?
        for frame in objMe.frames:
            for i in range(objMe.vCount):
                xyz = Blender.Mathutils.Vector(frame[objMe.verts[i].origi].x, frame[objMe.verts[i].origi].y, frame[objMe.verts[i].origi].z)

                newMesh.verts[i].co  = xyz;
            newObj.insertShapeKey()

        for key in Key.Get() :
            key.ipo = Ipo.New('Key', "bleh" + "_ipo")
        index = 1
        for curveName in key.ipo.curveConsts :
            # print curveName
            key.ipo.addCurve(curveName)
            key.ipo[curveName].interpolation = IpoCurve.InterpTypes.CONST
            key.ipo[curveName].addBezier((0, 0))
            key.ipo[curveName].addBezier((index, 1))
            key.ipo[curveName].addBezier((index + 1, 0))
            index+=1

    # Faces
    for i in range(objMe.fCount):
        face = [objMe.faces[i].i1, objMe.faces[i].i2, objMe.faces[i].i3]
        newMesh.faces.extend(face)

    # UV
    #if guiTable['UV'] == 1 and objMe.hasFUV == 1:
        #newMesh.faceUV = 1
        #for f in objMe.uvFaces:
            #uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
            #uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
            #uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
            #newMesh.faces[f.index].uv = [uv1, uv2, uv3]
    ## normals
    #vertices = [coords for n, coords in sorted(objMe.normals)]

    #random.seed()

    #i = 0
    #for v in newMesh.verts:
        #no = Blender.Mathutils.Vector(vertices[i][0], vertices[i][1], vertices[i][2])
        #v.no = no
        #print 'vertice ', i, 'normal : ', v.no
        ##v.no[0] = vertices[i][0]
        ##v.no[1] = vertices[i][1]
        ##v.no[2] = vertices[i][2]
        #i = i + 1

    newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)

    Blender.Set("curframe", objMe.frameCount + 1)

    counts['verts'] += objMe.vCount
    counts['tris'] += objMe.fCount
    print 'Imported Mesh-Object: ', obj.name

def read_ui(filename):
    Window.WaitCursor(1)

    read_main(filename)

    Window.WaitCursor(0)

Blender.Window.FileSelector(read_ui, "Import ASE")


code:
// BIN2C.CPP
// by Jonathon Fowler (jf@jonof.id.au)

// Converts a binary file to C source
// This is a DOS program originally written with Borland Turbo C++ for DOS 3.1

#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <dir.h>
#include <io.h>
#include <stdlib.h>

char defsrcext[] = ".DAT";
char defoutext[] = ".C";

char source[MAXPATH], output[MAXPATH], bytesize;

int PathAddExt(char *path, char *ext);

int main(int argc, char *argv[])
{
    printf("BIN2C - Binary to C data converter\n"
             "Copyright (c) 1999 Jonathon Fowler\n\n");

    if (argc < 4)
    {
        printf("Usage:\n"
                 "   BIN2C source<.DAT> output<.C> b|w\n\n"
                 "   source<.DAT>   Binary source file\n"
                 "   output<.C>     Output C code file\n"
                 "   b|w            Byte or word-sized data\n\n");
        exit(0);
    }

    int arg;
    FILE *in, *out;
    char datab1, datab2;
    int across=0, maxacross;
    int length, written=0;

    // get the source file
    strcpy(source, argv[1]);
    strupr(source);
    PathAddExt(source, defsrcext);
    printf("� Source file:  %s\n", source);

    // get the output file
    strcpy(output, argv[2]);
    strupr(output);
    PathAddExt(output, defoutext);
    printf("� Output file:  %s\n", output);

    // get byte/word data
    switch (tolower(argv[3][0]))
    {
        case 'b':
            printf("� Byte data.\n");
            bytesize=1;
            break;

        case 'w':
            printf("� Word data.\n");
            bytesize=0;
            break;

        default:
            printf("� Unknown data size specified. Defaulting to byte.\n");
            bytesize=1;
            break;
    }

    // open the input file
    in = fopen(source, "rb");
    if (!in)
    {
        printf("Error opening %s\n", source);
        exit(1);
    }

    // open the output file
    out = fopen(output, "w+t");
    if (!out)
    {
        printf("Error creating %s\n", output);
        exit(1);
    }

    length = filelength(fileno(in));

    // write a header out to the output file
    fprintf(out, "// %s\n\n// Generated by BIN2C.EXE\n// By Jonathon Fowler\n\n", output);

    // start a data block
    fprintf(out, "%s datablock[] = {\n // %ld bytes", (bytesize) ? "char" : "unsigned", length);

    if (bytesize)
        maxacross = 12;
    else
        maxacross = 9;
    across = maxacross;

    // convert the data
    for (written=0; written<length; written++) {
        if (across == maxacross)
        {
            fprintf(out, "\n  ");
            across = 0;
        }

        if (bytesize)
        {
            datab1 = fgetc(in);
            fprintf(out, " 0x%02X%c", datab1, ((length-written)>1) ? ',' : '\n');
        } else {
            datab1 = fgetc(in);
            datab2 = fgetc(in);
            fprintf(out, " 0x%02X%02X%c", datab2, datab1, ((length-written)>2) ? ',' : '\n');
        }

        across++;

        if (!bytesize) written++;
    }

    fprintf(out, "  };");

    fclose(out);
    fclose(in);

    return 0;
}

// Add an extention to a path if one doesn't exist
int PathAddExt(char *path, char *ext)
{
    char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], extn[MAXEXT];
    int flags;

    flags = fnsplit(path, drive, dir, name, extn);

    if (!(flags & EXTENSION))    // tack on an extension
        strcat(path, ext);

    return ((flags & EXTENSION) == 0);
}