SLUT.CPP 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdarg.h>
  5. #include <dos.h>
  6. #include <io.h>
  7. #include <fcntl.h>
  8. #include "getopt.h"
  9. #include "misc.h"
  10. #include "typedefs.h"
  11. #include "seq.h"
  12. #include "debug4g.h"
  13. #define kMaxFrames 1024
  14. struct SEQFRAME1
  15. {
  16. unsigned nTile : 16;
  17. signed shade : 8;
  18. unsigned translucent : 1;
  19. unsigned blocking : 1;
  20. unsigned hitscan : 1;
  21. unsigned pal : 4;
  22. };
  23. struct Seq1
  24. {
  25. char signature[4];
  26. short version;
  27. short nFrames; // sequence length
  28. short ticksPerFrame; // inverted play rate
  29. short keyFrame;
  30. uchar flags;
  31. char pad[3];
  32. SEQFRAME1 frame[1];
  33. };
  34. struct SEQFRAME2
  35. {
  36. unsigned nTile : 12;
  37. unsigned reserved1 : 3;
  38. unsigned translucentR : 1;
  39. signed shade : 8;
  40. unsigned translucent : 1;
  41. unsigned blocking : 1;
  42. unsigned hitscan : 1;
  43. unsigned pal : 5;
  44. unsigned xrepeat : 8;
  45. unsigned yrepeat : 8;
  46. unsigned reserved2 : 16;
  47. };
  48. struct Seq2
  49. {
  50. char signature[4];
  51. short version;
  52. short nFrames; // sequence length
  53. short ticksPerFrame; // inverted play rate
  54. short keyFrame;
  55. uchar flags;
  56. char pad[3];
  57. SEQFRAME2 frame[1];
  58. };
  59. struct FNODE
  60. {
  61. FNODE *next;
  62. char name[1];
  63. };
  64. FNODE head = { &head, "" };
  65. FNODE *tail = &head;
  66. BOOL bForcePal = FALSE;
  67. uchar nPal;
  68. BOOL bForceShade = FALSE;
  69. char nShade;
  70. BOOL bForceXRepeat = FALSE;
  71. uchar xrepeat;
  72. BOOL bForceYRepeat = FALSE;
  73. uchar yrepeat;
  74. BOOL bForceTranslucent = FALSE;
  75. BOOL bIsTranslucent;
  76. BOOL bIsTranslucentR;
  77. Seq *pSeq = NULL;
  78. /*******************************************************************************
  79. FUNCTION: ShowBanner()
  80. DESCRIPTION: Show application banner
  81. *******************************************************************************/
  82. void ShowBanner( void )
  83. {
  84. printf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n");
  85. printf("SEQ Loathing Update Tool Version 3.0 Copyright (c) 1995 Q Studios Corporation\n");
  86. printf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n");
  87. }
  88. /*******************************************************************************
  89. FUNCTION: ShowUsage()
  90. DESCRIPTION: Display command-line parameter usage, then exit
  91. *******************************************************************************/
  92. void ShowUsage(void)
  93. {
  94. printf("Syntax: SLUT [options] files[.seq]\n");
  95. printf("-pN force all palookups to N\n");
  96. printf("-sN force all shade values to N\n");
  97. printf("-t[0|1|2] force translucency level\n");
  98. printf("-xN force all x repeats to N\n");
  99. printf("-yN force all y repeats to N\n");
  100. printf("-? This help\n");
  101. exit(0);
  102. }
  103. /*******************************************************************************
  104. FUNCTION: QuitMessage()
  105. DESCRIPTION: Display a printf() style message, the exit with code 1
  106. *******************************************************************************/
  107. void QuitMessage(char * fmt, ...)
  108. {
  109. char msg[80];
  110. va_list argptr;
  111. va_start( argptr, fmt );
  112. vsprintf( msg, fmt, argptr );
  113. va_end(argptr);
  114. printf(msg);
  115. exit(1);
  116. }
  117. void ProcessFile(char *filename)
  118. {
  119. char bakname[_MAX_PATH], tempname[_MAX_PATH];
  120. int i, hFile, nSize;
  121. strcpy(bakname, filename);
  122. ChangeExtension(bakname, ".BAK");
  123. tmpnam(tempname);
  124. printf("%s: ", filename);
  125. hFile = open(filename, O_RDONLY | O_BINARY);
  126. if ( hFile == -1 )
  127. QuitMessage("Couldn't open file %s, errno=%d\n", filename, errno);
  128. nSize = filelength(hFile);
  129. Seq *pTempSeq = (Seq *)malloc(nSize);
  130. dassert(pTempSeq != NULL);
  131. if ( !FileRead(hFile, pTempSeq, nSize) )
  132. {
  133. close(hFile);
  134. QuitMessage("Error reading SEQ file");
  135. }
  136. close(hFile);
  137. memcpy(pSeq, pTempSeq, nSize);
  138. if (memcmp(pSeq->signature, kSEQSig, sizeof(pSeq->signature)) != 0)
  139. QuitMessage("SEQ file corrupted");
  140. switch ( pTempSeq->version >> 8 )
  141. {
  142. case 3:
  143. break; // current version
  144. case 2:
  145. {
  146. // convert old sequence format
  147. Seq2 *pSeq2 = (Seq2 *)pTempSeq;
  148. memset(pSeq, 0, sizeof(Seq));
  149. pSeq->nFrames = pSeq2->nFrames;
  150. pSeq->ticksPerFrame = pSeq2->ticksPerFrame;
  151. // check version 2 minor version
  152. switch ( pTempSeq->version & 0xFF )
  153. {
  154. case 2:
  155. pSeq->flags = pSeq2->flags;
  156. for (i = 0; i < pSeq2->nFrames; i++)
  157. {
  158. memset(&pSeq->frame[i], 0, sizeof(SEQFRAME));
  159. pSeq->frame[i].nTile = pSeq2->frame[i].nTile;
  160. pSeq->frame[i].translucent = pSeq2->frame[i].translucent;
  161. pSeq->frame[i].translucentR = pSeq2->frame[i].translucentR;
  162. pSeq->frame[i].blocking = pSeq2->frame[i].blocking;
  163. pSeq->frame[i].hitscan = pSeq2->frame[i].hitscan;
  164. pSeq->frame[i].xrepeat = pSeq2->frame[i].xrepeat;
  165. pSeq->frame[i].yrepeat = pSeq2->frame[i].yrepeat;;
  166. pSeq->frame[i].shade = pSeq2->frame[i].shade;
  167. pSeq->frame[i].pal = pSeq2->frame[i].pal;
  168. }
  169. break;
  170. case 1:
  171. pSeq->flags = pSeq2->flags;
  172. for (i = 0; i < pSeq2->nFrames; i++)
  173. {
  174. memset(&pSeq->frame[i], 0, sizeof(SEQFRAME));
  175. pSeq->frame[i].nTile = pSeq2->frame[i].nTile;
  176. pSeq->frame[i].translucent = pSeq2->frame[i].translucent;
  177. pSeq->frame[i].translucentR = 0;
  178. pSeq->frame[i].blocking = pSeq2->frame[i].blocking;
  179. pSeq->frame[i].hitscan = pSeq2->frame[i].hitscan;
  180. pSeq->frame[i].xrepeat = pSeq2->frame[i].xrepeat;
  181. pSeq->frame[i].yrepeat = pSeq2->frame[i].yrepeat;;
  182. pSeq->frame[i].shade = pSeq2->frame[i].shade;
  183. pSeq->frame[i].pal = pSeq2->frame[i].pal;
  184. }
  185. break;
  186. case 0:
  187. pSeq->flags = 0;
  188. for (i = 0; i < pSeq2->nFrames; i++)
  189. {
  190. memset(&pSeq->frame[i], 0, sizeof(SEQFRAME));
  191. pSeq->frame[i].nTile = pSeq2->frame[i].nTile;
  192. pSeq->frame[i].translucent = pSeq2->frame[i].translucent;
  193. pSeq->frame[i].translucentR = 0;
  194. pSeq->frame[i].blocking = pSeq2->frame[i].blocking;
  195. pSeq->frame[i].hitscan = pSeq2->frame[i].hitscan;
  196. pSeq->frame[i].xrepeat = pSeq2->frame[i].xrepeat;
  197. pSeq->frame[i].yrepeat = pSeq2->frame[i].yrepeat;;
  198. pSeq->frame[i].shade = pSeq2->frame[i].shade;
  199. pSeq->frame[i].pal = pSeq2->frame[i].pal;
  200. }
  201. break;
  202. }
  203. break;
  204. }
  205. case 1:
  206. {
  207. // convert old sequence format
  208. Seq1 *pSeq1 = (Seq1 *)pTempSeq;
  209. memset(pSeq, 0, sizeof(Seq));
  210. pSeq->nFrames = pSeq1->nFrames;
  211. pSeq->ticksPerFrame = pSeq1->ticksPerFrame;
  212. for (i = 0; i < pSeq1->nFrames; i++)
  213. {
  214. memset(&pSeq->frame[i], 0, sizeof(SEQFRAME));
  215. pSeq->frame[i].nTile = pSeq1->frame[i].nTile;
  216. pSeq->frame[i].translucent = pSeq1->frame[i].translucent;
  217. pSeq->frame[i].blocking = pSeq1->frame[i].blocking;
  218. pSeq->frame[i].hitscan = pSeq1->frame[i].hitscan;
  219. pSeq->frame[i].xrepeat = 64;
  220. pSeq->frame[i].yrepeat = 64;
  221. pSeq->frame[i].shade = pSeq1->frame[i].shade;
  222. pSeq->frame[i].pal = pSeq1->frame[i].pal;
  223. }
  224. break;
  225. }
  226. default:
  227. QuitMessage("Obsolete SEQ version");
  228. }
  229. free(pTempSeq);
  230. // set forced frame attributes
  231. for (i = 0; i < pSeq->nFrames; i++)
  232. {
  233. if ( bForcePal )
  234. pSeq->frame[i].pal = nPal;
  235. if ( bForceShade )
  236. pSeq->frame[i].shade = nShade;
  237. if ( bForceTranslucent )
  238. {
  239. if (bIsTranslucent)
  240. pSeq->frame[i].translucent = 1;
  241. else
  242. pSeq->frame[i].translucent = 0;
  243. if (bIsTranslucentR)
  244. pSeq->frame[i].translucentR = 1;
  245. else
  246. pSeq->frame[i].translucentR = 0;
  247. }
  248. if ( bForceXRepeat )
  249. pSeq->frame[i].xrepeat = xrepeat;
  250. if ( bForceYRepeat )
  251. pSeq->frame[i].yrepeat = yrepeat;
  252. }
  253. hFile = open(tempname, O_CREAT | O_WRONLY | O_BINARY | O_TRUNC, S_IWUSR);
  254. if ( hFile == -1 )
  255. QuitMessage("Error creating temporary file");
  256. memcpy(pSeq->signature, kSEQSig, sizeof(pSeq->signature));
  257. pSeq->version = kSEQVersion;
  258. if ( !FileWrite(hFile, pSeq, sizeof(Seq) + pSeq->nFrames * sizeof(SEQFRAME)) )
  259. {
  260. close(hFile);
  261. QuitMessage("Error writing temporary file");
  262. }
  263. close(hFile);
  264. // backup the existing sequence
  265. unlink(bakname);
  266. rename(filename, bakname);
  267. rename(tempname, filename);
  268. printf("done.\n");
  269. }
  270. void InsertFilename( char *fname )
  271. {
  272. FNODE *n = (FNODE *)malloc(sizeof(FNODE) + strlen(fname));
  273. strcpy(n->name, fname);
  274. // insert the node at the tail, so it stays in order
  275. n->next = tail->next;
  276. tail->next = n;
  277. tail = n;
  278. }
  279. void ProcessArgument(char *s)
  280. {
  281. char filespec[_MAX_PATH];
  282. char buffer[_MAX_PATH2];
  283. char path[_MAX_PATH];
  284. strcpy(filespec, s);
  285. AddExtension(filespec, ".SEQ");
  286. char *drive, *dir;
  287. // separate the path from the filespec
  288. _splitpath2(s, buffer, &drive, &dir, NULL, NULL);
  289. _makepath(path, drive, dir, NULL, NULL);
  290. struct find_t fileinfo;
  291. unsigned r = _dos_findfirst(s, _A_NORMAL, &fileinfo);
  292. if (r != 0)
  293. printf("%s not found\n", s);
  294. while ( r == 0 )
  295. {
  296. strcpy(filespec, path);
  297. strcat(filespec, fileinfo.name);
  298. InsertFilename(filespec);
  299. r = _dos_findnext( &fileinfo );
  300. }
  301. _dos_findclose(&fileinfo);
  302. }
  303. /***********************************************************************
  304. * Process command line arguments
  305. **********************************************************************/
  306. void ParseOptions( void )
  307. {
  308. enum {
  309. kSwitchHelp,
  310. kSwitchForcePal,
  311. kSwitchForceShade,
  312. kSwitchForceTrans,
  313. kSwitchXRepeat,
  314. kSwitchYRepeat,
  315. };
  316. static SWITCH switches[] = {
  317. { "?", kSwitchHelp, FALSE },
  318. { "P", kSwitchForcePal, TRUE },
  319. { "S", kSwitchForceShade, TRUE },
  320. { "T", kSwitchForceTrans, TRUE },
  321. { "X", kSwitchXRepeat, TRUE },
  322. { "Y", kSwitchYRepeat, TRUE },
  323. { NULL, 0, FALSE },
  324. };
  325. int value;
  326. int r;
  327. while ( (r = GetOptions(switches)) != GO_EOF )
  328. {
  329. switch (r)
  330. {
  331. case GO_INVALID:
  332. QuitMessage("Invalid argument: %s", OptArgument);
  333. case GO_FULL:
  334. ProcessArgument(OptArgument);
  335. break;
  336. case kSwitchForcePal:
  337. value = strtol(OptArgument, NULL, 0);
  338. bForcePal = TRUE;
  339. nPal = (uchar)value;
  340. break;
  341. case kSwitchForceShade:
  342. value = strtol(OptArgument, NULL, 0);
  343. bForceShade = TRUE;
  344. nShade = (char)value;
  345. break;
  346. case kSwitchForceTrans:
  347. value = strtol(OptArgument, NULL, 0);
  348. bForceTranslucent = TRUE;
  349. switch(value)
  350. {
  351. case 0:
  352. bIsTranslucent = bIsTranslucentR = FALSE;
  353. break;
  354. case 1:
  355. bIsTranslucent = TRUE;
  356. bIsTranslucentR = FALSE;
  357. break;
  358. case 2:
  359. bIsTranslucent = bIsTranslucentR = TRUE;
  360. break;
  361. default:
  362. QuitMessage("Invalid translucency argument: %s", OptArgument);
  363. break;
  364. }
  365. break;
  366. case kSwitchXRepeat:
  367. value = strtol(OptArgument, NULL, 0);
  368. bForceXRepeat = TRUE;
  369. xrepeat = (uchar)value;
  370. break;
  371. case kSwitchYRepeat:
  372. value = strtol(OptArgument, NULL, 0);
  373. bForceYRepeat = TRUE;
  374. yrepeat = (uchar)value;
  375. break;
  376. }
  377. }
  378. }
  379. void main( int argc )
  380. {
  381. ShowBanner();
  382. pSeq = (Seq *)malloc(sizeof(Seq) + kMaxFrames * sizeof(SEQFRAME));
  383. dassert(pSeq != NULL);
  384. if (argc < 2) ShowUsage();
  385. ParseOptions();
  386. // process the file list
  387. for (FNODE *n = head.next; n != &head; n = n->next)
  388. ProcessFile(n->name);
  389. }