327 lines
7.2 KiB
C++
327 lines
7.2 KiB
C++
|
#include <stdio.h>
|
||
|
#ifdef __linux__
|
||
|
#include <unistd.h>
|
||
|
#else
|
||
|
#include <fcntl.h>
|
||
|
#include <io.h>
|
||
|
#endif
|
||
|
#include "zlib.h"
|
||
|
#include "amx.h"
|
||
|
#include "amxxpc.h"
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
struct abl pl32;
|
||
|
struct abl pl64;
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
printf("debug clamp\n");
|
||
|
getchar();
|
||
|
#endif
|
||
|
|
||
|
#ifdef __linux__
|
||
|
HINSTANCE lib = dlmount("./amxxpc32.so");
|
||
|
#else
|
||
|
HINSTANCE lib = dlmount("amxxpc32.dll");
|
||
|
#endif
|
||
|
if (!lib)
|
||
|
{
|
||
|
#ifdef __linux__
|
||
|
printf("32bit compiler failed to instantiate: %s\n", dlerror());
|
||
|
#else
|
||
|
printf("32bit compiler failed to instantiate: %d\n", GetLastError());
|
||
|
#endif
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
COMPILER sc32 = (COMPILER)dlsym(lib, "Compile32");
|
||
|
|
||
|
if (!sc32)
|
||
|
{
|
||
|
#ifdef __linux__
|
||
|
printf("32bit compiler failed to link: %p|%p.\n",sc32, sc_printf);
|
||
|
#else
|
||
|
printf("32bit compiler failed to link: %d.\n", GetLastError());
|
||
|
#endif
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
AMX_HEADER hdr;
|
||
|
|
||
|
printf("Welcome to the AMX Mod X %s Compiler.\n", VERSION_STRING);
|
||
|
printf("Copyright (c) 1997-2005 ITB CompuPhase, AMX Mod X Team\n\n");
|
||
|
|
||
|
if (argc < 2)
|
||
|
{
|
||
|
printf("Usage: <file.sma> [options]\n");
|
||
|
printf("Use -? or --help to see full options\n\n");
|
||
|
getchar();
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
if (!strcmp(argv[1], "-?") || !strcmp(argv[1], "--help"))
|
||
|
{
|
||
|
show_help();
|
||
|
printf("Press any key to continue.\n");
|
||
|
getchar();
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
sc32(argc, argv);
|
||
|
|
||
|
char *file = FindFileName(argc, argv);
|
||
|
|
||
|
if (file == NULL)
|
||
|
{
|
||
|
printf("Could not locate the output file.\n");
|
||
|
exit(0);
|
||
|
} else if (strstr(file, ".asm")) {
|
||
|
printf("Assembler output succeeded.\n");
|
||
|
exit(0);
|
||
|
} else {
|
||
|
FILE *fp = fopen(file, "rb");
|
||
|
if (fp == NULL)
|
||
|
{
|
||
|
printf("Could not locate output file %s (compile failed).\n", file);
|
||
|
exit(0);
|
||
|
}
|
||
|
fread(&hdr, sizeof(hdr), 1, fp);
|
||
|
amx_Align32((uint32_t *)&hdr.stp);
|
||
|
amx_Align32((uint32_t *)&hdr.size);
|
||
|
pl32.stp = hdr.stp;
|
||
|
pl32.cellsize = 4;
|
||
|
int size = sizeof(hdr) + hdr.size;
|
||
|
pl32.size = size;
|
||
|
pl32.data = new char[size];
|
||
|
rewind(fp);
|
||
|
fread(pl32.data, 1, size, fp);
|
||
|
fclose(fp);
|
||
|
}
|
||
|
|
||
|
unlink(file);
|
||
|
|
||
|
HINSTANCE lib64 = 0;
|
||
|
#ifdef __linux__
|
||
|
lib64 = dlmount("./amxxpc64.so");
|
||
|
#else
|
||
|
lib64 = dlmount("amxxpc64.dll");
|
||
|
#endif
|
||
|
if (!lib64)
|
||
|
{
|
||
|
printf("64bit compiler failed to instantiate.\n");
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
COMPILER sc64 = (COMPILER)dlsym(lib64, "Compile64");
|
||
|
|
||
|
if (!sc64)
|
||
|
{
|
||
|
#ifdef __linux__
|
||
|
sc_printf("64bit compiler failed to link: %s.\n", dlerror());
|
||
|
#else
|
||
|
printf("64bit compiler failed to link: %d.\n", GetLastError());
|
||
|
#endif
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
sc64(argc, argv);
|
||
|
|
||
|
dlclose(lib64);
|
||
|
|
||
|
if (file == NULL)
|
||
|
{
|
||
|
printf("Could not locate the output file on second pass.\n");
|
||
|
exit(0);
|
||
|
} else {
|
||
|
FILE *fp = fopen(file, "rb");
|
||
|
if (fp == NULL)
|
||
|
{
|
||
|
printf("Could not locate output file on second pass (compile failed).\n");
|
||
|
exit(0);
|
||
|
}
|
||
|
fread(&hdr, sizeof(hdr), 1, fp);
|
||
|
amx_Align32((uint32_t *)&hdr.stp);
|
||
|
amx_Align32((uint32_t *)&hdr.size);
|
||
|
pl64.stp = hdr.stp;
|
||
|
pl64.cellsize = 8;
|
||
|
int size = sizeof(hdr) + hdr.size;
|
||
|
pl64.size = sizeof(hdr) + hdr.size;
|
||
|
pl64.data = new char[size];
|
||
|
rewind(fp);
|
||
|
fread(pl64.data, 1, size, fp);
|
||
|
fclose(fp);
|
||
|
}
|
||
|
|
||
|
/////////////
|
||
|
// COMPRSSION
|
||
|
/////////////
|
||
|
|
||
|
int err;
|
||
|
|
||
|
pl32.cmpsize = compressBound(pl32.size);
|
||
|
pl32.cmp = new char[pl32.cmpsize];
|
||
|
err = compress((Bytef *)pl32.cmp, (uLongf *)&(pl32.cmpsize), (const Bytef*)pl32.data, pl32.size);
|
||
|
|
||
|
if (err != Z_OK)
|
||
|
{
|
||
|
printf("internal error - compression failed on first pass: %d\n", err);
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
pl64.cmpsize = compressBound(pl64.size);
|
||
|
pl64.cmp = new char[pl64.cmpsize];
|
||
|
err = compress((Bytef *)pl64.cmp, (uLongf *)&(pl64.cmpsize), (const Bytef*)pl64.data, pl64.size);
|
||
|
|
||
|
if (err != Z_OK)
|
||
|
{
|
||
|
printf("internal error - compression failed on second pass: %d\n", err);
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
char *newfile = new char[strlen(file)+3];
|
||
|
strcpy(newfile, file);
|
||
|
if (!strstr(file, ".amxx") && !strstr(file, ".AMXX"))
|
||
|
strcat(newfile, "x");
|
||
|
|
||
|
FILE *fp = fopen(newfile, "wb");
|
||
|
if (!fp)
|
||
|
{
|
||
|
printf("Error trying to write file %s.\n", newfile);
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
//magic + archn
|
||
|
int hdrsize = sizeof(long) + sizeof(char);
|
||
|
int entry = sizeof(long) + sizeof(long) + sizeof(char);
|
||
|
int offset1 = hdrsize + (entry * 2);
|
||
|
int offset2 = offset1 + pl32.cmpsize;
|
||
|
|
||
|
int magic = MAGIC_HEADER;
|
||
|
fwrite((void *)&magic, sizeof(int), 1, fp);
|
||
|
char n = 2;
|
||
|
fwrite((void *)&n, sizeof(char), 1, fp);
|
||
|
|
||
|
fwrite((void *)&(pl32.cellsize), sizeof(char), 1, fp);
|
||
|
fwrite((void *)&(pl32.stp), sizeof(long), 1, fp);
|
||
|
fwrite((void *)&(offset1), sizeof(long), 1, fp);
|
||
|
fwrite((void *)&(pl64.cellsize), sizeof(char), 1, fp);
|
||
|
fwrite((void *)&(pl64.stp), sizeof(long), 1, fp);
|
||
|
fwrite((void *)&(offset2), sizeof(long), 1, fp);
|
||
|
fwrite(pl32.cmp, sizeof(char), pl32.cmpsize, fp);
|
||
|
fwrite(pl64.cmp, sizeof(char), pl64.cmpsize, fp);
|
||
|
|
||
|
fclose(fp);
|
||
|
|
||
|
unlink(file);
|
||
|
|
||
|
printf("Done.\n");
|
||
|
|
||
|
dlclose(lib);
|
||
|
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
//we get the full name of the file here
|
||
|
//our job is to a] switch the .sma extension to .amx
|
||
|
// and to b] strip everything but the trailing name
|
||
|
char *swiext(const char *file, const char *ext, int isO)
|
||
|
{
|
||
|
int i = 0, pos = -1, j = 0;
|
||
|
int fileLen = strlen(file);
|
||
|
int extLen = strlen(ext);
|
||
|
int max = 0, odirFlag = -1;
|
||
|
|
||
|
for (i=fileLen-1; i>=0; i--)
|
||
|
{
|
||
|
if (file[i] == '.' && pos == -1)
|
||
|
{
|
||
|
pos = i+1;
|
||
|
}
|
||
|
if ((file[i] == '/' || file[i] == '\\') && !isO)
|
||
|
{
|
||
|
odirFlag = i+1;
|
||
|
//realign pos - we've just stripped fileLen-i chars
|
||
|
pos -= i + 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *newbuffer = new char[fileLen+strlen(ext)+2];
|
||
|
fileLen += strlen(ext);
|
||
|
if (odirFlag == -1)
|
||
|
{
|
||
|
strcpy(newbuffer, file);
|
||
|
} else {
|
||
|
strcpy(newbuffer, &(file[odirFlag]));
|
||
|
}
|
||
|
|
||
|
if (pos > -1)
|
||
|
{
|
||
|
for (i=pos; i<fileLen; i++)
|
||
|
{
|
||
|
if (j < extLen)
|
||
|
newbuffer[i] = ext[j++];
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
newbuffer[i] = '\0';
|
||
|
} else {
|
||
|
strcat(newbuffer, ".");
|
||
|
strcat(newbuffer, ext);
|
||
|
}
|
||
|
|
||
|
return newbuffer;
|
||
|
}
|
||
|
|
||
|
char *FindFileName(int argc, char **argv)
|
||
|
{
|
||
|
int i = 0;
|
||
|
int save = -1;
|
||
|
for (i=1; i<argc; i++)
|
||
|
{
|
||
|
if (argv[i][0] == '-' && argv[i][1] == 'o')
|
||
|
{
|
||
|
if (argv[i][2] == ' ' || argv[i][2] == '\0')
|
||
|
{
|
||
|
if (i == argc-1)
|
||
|
return NULL;
|
||
|
return swiext(&argv[i+1][2], "amx", 1);
|
||
|
} else {
|
||
|
return swiext(&(argv[i][2]), "amx", 1);
|
||
|
}
|
||
|
}
|
||
|
if (argv[i][0] != '-')
|
||
|
{
|
||
|
save = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (save>0)
|
||
|
{
|
||
|
return swiext(argv[save], "amx", 0);
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void show_help()
|
||
|
{
|
||
|
printf("Options:\n");
|
||
|
printf("\t-A<num> alignment in bytes of the data segment and the stack\n");
|
||
|
printf("\t-a output assembler code\n");
|
||
|
printf("\t-C[+/-] compact encoding for output file (default=-)\n");
|
||
|
printf("\t-c<name> codepage name or number; e.g. 1252 for Windows Latin-1\n");
|
||
|
printf("\t-Dpath active directory path\n");
|
||
|
printf("\t-d0 no symbolic information, no run-time checks\n");
|
||
|
printf("\t-d1 [default] run-time checks, no symbolic information\n");
|
||
|
printf("\t-d2 full debug information and dynamic checking\n");
|
||
|
printf("\t-d3 full debug information, dynamic checking, no optimization\n");
|
||
|
printf("\t-e<name> set name of error file (quiet compile)\n");
|
||
|
printf("\t-H<hwnd> window handle to send a notification message on finish\n");
|
||
|
printf("\t-i<name> path for include files\n");
|
||
|
printf("\t-l create list file (preprocess only)\n");
|
||
|
printf("\t-o<name> set base name of output file\n");
|
||
|
printf("\t-p<name> set name of \"prefix\" file\n");
|
||
|
printf("\t-r[name] write cross reference report to console or to specified file\n");
|
||
|
}
|