SEQEDIT.CPP 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. /*******************************************************************************
  2. FILE: SEQEDIT.CPP
  3. DESCRIPTION: Allows editing of sprite sequences
  4. AUTHOR: Peter M. Freese
  5. CREATED: 06-15-95
  6. COPYRIGHT: Copyright (c) 1995 Q Studios Corporation
  7. *******************************************************************************/
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <helix.h>
  11. #include <string.h>
  12. #include <io.h>
  13. #include <fcntl.h>
  14. #include "typedefs.h"
  15. #include "engine.h"
  16. #include "key.h"
  17. #include "misc.h"
  18. #include "gameutil.h"
  19. #include "gfx.h"
  20. #include "bstub.h"
  21. #include "globals.h"
  22. #include "debug4g.h"
  23. #include "error.h"
  24. #include "gui.h"
  25. #include "tile.h"
  26. #include "screen.h"
  27. #include "textio.h"
  28. #include "inifile.h"
  29. #include "options.h"
  30. #include "timer.h"
  31. #include "seq.h"
  32. #include "trig.h"
  33. #include "mouse.h"
  34. #include <memcheck.h>
  35. #define kMaxFrames 1024
  36. #define kAttrTitle (kColorLightGray * 16 + kColorYellow)
  37. BOOL looping = TRUE;
  38. char buffer[256];
  39. static BOOL seqModified;
  40. static BOOL tilesModified;
  41. EHF prevErrorHandler;
  42. POINT origin = { 160, 100 };
  43. schar gShade = 20;
  44. char gSeqName[128];
  45. Seq *pSeq = NULL;
  46. int nOctant = 0;
  47. char *viewNames[] =
  48. {
  49. "SINGLE",
  50. "5 FULL",
  51. "8 FULL",
  52. "5 HALF",
  53. "3 FLAT",
  54. "4 FLAT",
  55. };
  56. char *animNames[] =
  57. {
  58. "NoAnm",
  59. "Oscil",
  60. "AnmFw",
  61. "AnmBk",
  62. };
  63. void faketimerhandler( void )
  64. { }
  65. /***********************************************************************
  66. * EditorErrorHandler()
  67. *
  68. * Terminate from error condition, displaying a message in text mode.
  69. *
  70. **********************************************************************/
  71. ErrorResult EditorErrorHandler( const Error& error )
  72. {
  73. uninitengine();
  74. keyRemove();
  75. setvmode(gOldDisplayMode);
  76. // chain to the default error handler
  77. return prevErrorHandler(error);
  78. };
  79. void SetOrigin( int x, int y )
  80. {
  81. origin.x = ClipRange(x, 0, 319);
  82. origin.y = ClipRange(y, 0, 199);
  83. }
  84. void DrawOrigin( int nColor )
  85. {
  86. Video.SetColor(nColor);
  87. gfxHLine(origin.y, origin.x - 6, origin.x - 1);
  88. gfxHLine(origin.y, origin.x + 1, origin.x + 6);
  89. gfxVLine(origin.x, origin.y - 5, origin.y - 1);
  90. gfxVLine(origin.x, origin.y + 1, origin.y + 5);
  91. }
  92. BOOL SaveSeq( void )
  93. {
  94. char filename[_MAX_PATH];
  95. int hFile;
  96. strcpy(filename, gSeqName);
  97. ChangeExtension(filename, ".SEQ");
  98. // see if file exists
  99. if ( access(filename, F_OK) == 0 )
  100. {
  101. // create the dialog
  102. Window dialog(59, 80, 202, 46, "Overwrite file?");
  103. dialog.Insert(new TextButton(4, 4, 60, 20, "&Yes", mrYes));
  104. dialog.Insert(new TextButton(68, 4, 60, 20, "&No", mrNo));
  105. dialog.Insert(new TextButton(132, 4, 60, 20, "&Cancel", mrCancel));
  106. ShowModal(&dialog);
  107. switch ( dialog.endState )
  108. {
  109. case mrCancel:
  110. return FALSE;
  111. case mrNo:
  112. return TRUE;
  113. }
  114. char bakname[_MAX_PATH];
  115. strcpy(bakname, filename);
  116. ChangeExtension(bakname, ".BAK");
  117. unlink(bakname);
  118. rename(filename, bakname);
  119. }
  120. hFile = open(filename, O_CREAT | O_WRONLY | O_BINARY | O_TRUNC, S_IWUSR);
  121. if ( hFile == -1 )
  122. ThrowError("Error creating SEQ file", ES_ERROR);
  123. memcpy(pSeq->signature, kSEQSig, sizeof(pSeq->signature));
  124. pSeq->version = kSEQVersion;
  125. if ( !FileWrite(hFile, pSeq, sizeof(Seq) + pSeq->nFrames * sizeof(SEQFRAME)) )
  126. {
  127. close(hFile);
  128. ThrowError("Error writing SEQ file", ES_ERROR);
  129. }
  130. close(hFile);
  131. seqModified = FALSE;
  132. scrSetMessage("Sequence saved.");
  133. return TRUE;
  134. }
  135. BOOL LoadSeq( void )
  136. {
  137. char filename[128];
  138. int hFile;
  139. int nSize;
  140. strcpy(filename, gSeqName);
  141. ChangeExtension(filename, ".SEQ");
  142. dprintf("Attempting to load %s\n", filename);
  143. hFile = open(filename, O_RDONLY | O_BINARY);
  144. if ( hFile == -1 )
  145. {
  146. dprintf("Couldn't open file, errno=%d\n", errno);
  147. return FALSE;
  148. }
  149. nSize = filelength(hFile);
  150. if ( !FileRead(hFile, pSeq, nSize) )
  151. {
  152. close(hFile);
  153. ThrowError("Error reading SEQ file", ES_ERROR);
  154. }
  155. close(hFile);
  156. // check signature
  157. if (memcmp(pSeq->signature, kSEQSig, sizeof(pSeq->signature)) != 0)
  158. ThrowError("SEQ file corrupted", ES_ERROR);
  159. // check version
  160. if ( (pSeq->version & 0xFF00) != (kSEQVersion & 0xFF00) )
  161. ThrowError("Obsolete SEQ version", ES_ERROR);
  162. seqModified = FALSE;
  163. return TRUE;
  164. }
  165. BOOL SaveAs( void )
  166. {
  167. if ( GetStringBox("Save As", gSeqName) )
  168. {
  169. // save it if it seems valid
  170. if (strlen(gSeqName) > 0)
  171. return SaveSeq();
  172. }
  173. return FALSE;
  174. }
  175. BOOL LoadAs( void )
  176. {
  177. if ( GetStringBox("Load Anim", gSeqName) )
  178. {
  179. // load it if it seems valid
  180. if (strlen(gSeqName) > 0)
  181. {
  182. LoadSeq();
  183. return TRUE;
  184. }
  185. }
  186. return FALSE;
  187. }
  188. /*******************************************************************************
  189. ** ChangeAcknowledge()
  190. **
  191. ** Returns TRUE if the YES/NO selected, or FALSE if aborted or escape pressed.
  192. *******************************************************************************/
  193. BOOL AcknowledgeSeqChange(void)
  194. {
  195. // create the dialog
  196. Window dialog(59, 80, 202, 46, "Save Sequence?");
  197. dialog.Insert(new TextButton(4, 4, 60, 20, "&Yes", mrYes));
  198. dialog.Insert(new TextButton(68, 4, 60, 20, "&No", mrNo));
  199. dialog.Insert(new TextButton(132, 4, 60, 20, "&Cancel", mrCancel));
  200. ShowModal(&dialog);
  201. switch ( dialog.endState )
  202. {
  203. case mrCancel:
  204. return FALSE;
  205. case mrOk:
  206. case mrYes:
  207. return SaveAs();
  208. }
  209. return TRUE;
  210. }
  211. BOOL AcknowledgeTileChange(void)
  212. {
  213. // create the dialog
  214. Window dialog(59, 80, 202, 46, "Save Tile Changes?");
  215. dialog.Insert(new TextButton(4, 4, 60, 20, "&Yes", mrYes));
  216. dialog.Insert(new TextButton(68, 4, 60, 20, "&No", mrNo));
  217. dialog.Insert(new TextButton(132, 4, 60, 20, "&Cancel", mrCancel));
  218. ShowModal(&dialog);
  219. switch ( dialog.endState )
  220. {
  221. case mrCancel:
  222. return FALSE;
  223. case mrOk:
  224. case mrYes:
  225. tileSaveArtInfo();
  226. }
  227. return TRUE;
  228. }
  229. int DrawTile( SEQFRAME *pFrame )
  230. {
  231. schar nShade = (schar)ClipRange(gShade + pFrame->shade, -128, 127);
  232. char flags = 0; // default position by origin
  233. short nTile = (short)pFrame->nTile;
  234. uchar nPal = (uchar)pFrame->pal;
  235. long zoom = pFrame->xrepeat << 10;
  236. short ang = 0;
  237. if ( keystatus[KEY_CAPSLOCK] )
  238. flags |= kRotateNoMask;
  239. if (pFrame->translucent)
  240. flags |= kRotateTranslucent;
  241. if (pFrame->translucentR)
  242. flags |= kRotateTranslucentR;
  243. switch ( picanm[nTile].view )
  244. {
  245. case kSpriteViewSingle:
  246. break;
  247. case kSpriteView5Full:
  248. if (nOctant <= 4)
  249. nTile += nOctant;
  250. else
  251. {
  252. nTile += 8 - nOctant;
  253. // rotate 180 degrees + y-flip is equivalent to x-flip
  254. ang += kAngle180;
  255. flags ^= kRotateYFlip;
  256. }
  257. break;
  258. case kSpriteView8Full:
  259. nTile += nOctant;
  260. break;
  261. case kSpriteView5Half:
  262. break;
  263. }
  264. origin.x = ClipLow(origin.x, tilesizx[nTile] / 2 + picanm[nTile].xcenter);
  265. origin.x = ClipHigh(origin.x, 319 - tilesizx[nTile] / 2 + picanm[nTile].xcenter);
  266. origin.y = ClipLow(origin.y, tilesizy[nTile] / 2 + picanm[nTile].ycenter);
  267. origin.y = ClipHigh(origin.y, 180 - tilesizy[nTile] / 2 + picanm[nTile].ycenter);
  268. rotatesprite(origin.x << 16, origin.y << 16, 0x10000, ang, nTile, nShade,
  269. nPal, flags, windowx1, windowy1, windowx2, windowy2);
  270. return nTile;
  271. }
  272. void EditLoop( void )
  273. {
  274. BYTE key, shift, alt, ctrl, pad5;
  275. int nbuttons;
  276. static int obuttons = 0;
  277. char buffer[256];
  278. int timeCounter = 0, frameIndex = 0;
  279. int nTile = 0, nTileView = 0;
  280. BOOL playing = FALSE;
  281. BOOL looping = FALSE;
  282. while (1)
  283. {
  284. gFrameTicks = gGameClock - gFrameClock;
  285. gFrameClock += gFrameTicks;
  286. UpdateBlinkClock(gFrameTicks);
  287. clearview(0);
  288. if (playing)
  289. {
  290. timeCounter -= gFrameTicks;
  291. while (timeCounter < 0)
  292. {
  293. timeCounter += pSeq->ticksPerFrame;
  294. if (++frameIndex == pSeq->nFrames)
  295. {
  296. if ( looping )
  297. frameIndex = 0;
  298. else
  299. {
  300. frameIndex--;
  301. playing = FALSE;
  302. }
  303. }
  304. }
  305. }
  306. if (frameIndex < 0)
  307. frameIndex = 0;
  308. if (frameIndex < pSeq->nFrames)
  309. {
  310. SEQFRAME *pFrame = &pSeq->frame[frameIndex];
  311. nTileView = DrawTile(pFrame);
  312. sprintf(buffer,"TILE=%4d VIEW=%6s SH=%+3d PAL=%2d XR=%3d YR=%3d",
  313. nTile,
  314. viewNames[picanm[nTile].view],
  315. pFrame->shade,
  316. pFrame->pal,
  317. pFrame->xrepeat,
  318. pFrame->yrepeat
  319. );
  320. printext256(0, 180, gStdColor[14], -1, buffer, 1);
  321. if ( pFrame->trigger )
  322. printext256(275, 180, gStdColor[11], gStdColor[8], "F", 1);
  323. if ( pFrame->smoke )
  324. printext256(280, 180, gStdColor[11], gStdColor[8], "S", 1);
  325. if ( pFrame->translucent )
  326. printext256(285, 180, gStdColor[11], gStdColor[8], "T", 1);
  327. if ( pFrame->translucentR )
  328. printext256(285, 180, gStdColor[11], gStdColor[8], "t", 1);
  329. if ( pFrame->blocking )
  330. printext256(290, 180, gStdColor[11], gStdColor[8], "B", 1);
  331. if ( pFrame->hitscan )
  332. printext256(295, 180, gStdColor[11], gStdColor[8], "H", 1);
  333. if ( pSeq->flags & kSeqRemove )
  334. printext256(300, 180, gStdColor[12], gStdColor[8], "R", 1);
  335. if ( pSeq->flags & kSeqLoop )
  336. printext256(300, 180, gStdColor[12], gStdColor[8], "L", 1);
  337. nTile = pFrame->nTile;
  338. }
  339. sprintf(buffer,"GLOBAL SH=%4d ANGLE=%3d FRAME %2d/%2d TPF=%3d",
  340. gShade, nOctant * 45, frameIndex + 1, pSeq->nFrames, pSeq->ticksPerFrame);
  341. printext256(0, 190, gStdColor[7], -1, buffer, 1);
  342. if ( !playing )
  343. DrawOrigin(gStdColor[keystatus[KEY_O] ? 15 : 8]);
  344. scrDisplayMessage(gStdColor[kColorWhite]);
  345. if (vidoption != 1)
  346. WaitVSync();
  347. scrNextPage();
  348. key = keyGet();
  349. shift = keystatus[KEY_LSHIFT] | keystatus[KEY_RSHIFT];
  350. ctrl = keystatus[KEY_LCTRL] | keystatus[KEY_RCTRL];
  351. alt = keystatus[KEY_LALT] | keystatus[KEY_RALT];
  352. pad5 = keystatus[KEY_PAD5];
  353. switch (key)
  354. {
  355. case KEY_ESC:
  356. if ( playing )
  357. {
  358. playing = FALSE;
  359. break;
  360. }
  361. if (!seqModified || AcknowledgeSeqChange())
  362. return;
  363. break;
  364. case KEY_COMMA: // "<"
  365. nOctant = DecRotate(nOctant, 8);
  366. break;
  367. case KEY_PERIOD: // ">"
  368. nOctant = IncRotate(nOctant, 8);
  369. break;
  370. case KEY_SLASH:
  371. nOctant = 0;
  372. break;
  373. case KEY_PLUS:
  374. pSeq->ticksPerFrame++;
  375. seqModified = TRUE;
  376. break;
  377. case KEY_MINUS:
  378. pSeq->ticksPerFrame = (short)ClipLow(pSeq->ticksPerFrame - 1, 1);
  379. seqModified = TRUE;
  380. break;
  381. }
  382. if ( !playing )
  383. {
  384. switch ( key )
  385. {
  386. case KEY_F2:
  387. if (keystatus[KEY_LCTRL] || keystatus[KEY_RCTRL] || strlen(gSeqName) == 0)
  388. SaveAs();
  389. else
  390. SaveSeq();
  391. break;
  392. case KEY_F3:
  393. if (!seqModified || AcknowledgeSeqChange())
  394. {
  395. LoadAs();
  396. frameIndex = 0;
  397. }
  398. break;
  399. case KEY_ENTER:
  400. if (pSeq->nFrames > 0)
  401. {
  402. playing = TRUE;
  403. looping = TRUE;
  404. frameIndex = 0;
  405. timeCounter = pSeq->ticksPerFrame;
  406. }
  407. break;
  408. case KEY_SPACE:
  409. if (pSeq->nFrames > 0)
  410. {
  411. playing = TRUE;
  412. looping = FALSE;
  413. frameIndex = 0;
  414. timeCounter = pSeq->ticksPerFrame;
  415. }
  416. break;
  417. case KEY_1:
  418. if (frameIndex > 0)
  419. frameIndex--;
  420. break;
  421. case KEY_2:
  422. if (frameIndex < pSeq->nFrames - 1)
  423. frameIndex++;
  424. break;
  425. case KEY_HOME:
  426. frameIndex = 0;
  427. break;
  428. case KEY_END:
  429. frameIndex = pSeq->nFrames - 1;
  430. break;
  431. case KEY_INSERT:
  432. frameIndex++;
  433. if (ctrl)
  434. frameIndex--;
  435. if (frameIndex > pSeq->nFrames)
  436. frameIndex = pSeq->nFrames;
  437. if (ctrl)
  438. memmove(&pSeq->frame[frameIndex + 1], &pSeq->frame[frameIndex],
  439. sizeof(SEQFRAME) * (pSeq->nFrames - frameIndex));
  440. else
  441. memmove(&pSeq->frame[frameIndex], &pSeq->frame[frameIndex - 1],
  442. sizeof(SEQFRAME) * (pSeq->nFrames - frameIndex + 1));
  443. if (pSeq->nFrames == 0)
  444. {
  445. pSeq->frame[frameIndex].shade = -4;
  446. pSeq->frame[frameIndex].translucentR = 0;
  447. pSeq->frame[frameIndex].translucent = 0;
  448. pSeq->frame[frameIndex].blocking = 1;
  449. pSeq->frame[frameIndex].hitscan = 1;
  450. pSeq->frame[frameIndex].pal = 0;
  451. }
  452. pSeq->frame[frameIndex].nTile = tilePick(nTile, -1, SS_ALL);
  453. pSeq->nFrames++;
  454. seqModified = TRUE;
  455. break;
  456. case KEY_DELETE:
  457. if (pSeq->nFrames > 0)
  458. {
  459. memmove(&pSeq->frame[frameIndex], &pSeq->frame[frameIndex + 1],
  460. sizeof(SEQFRAME) * (pSeq->nFrames - frameIndex - 1));
  461. pSeq->nFrames--;
  462. if (frameIndex == pSeq->nFrames)
  463. frameIndex--;
  464. }
  465. seqModified = TRUE;
  466. break;
  467. case KEY_B:
  468. if (frameIndex < pSeq->nFrames)
  469. pSeq->frame[frameIndex].blocking = !pSeq->frame[frameIndex].blocking;
  470. seqModified = TRUE;
  471. break;
  472. case KEY_F:
  473. if (frameIndex < pSeq->nFrames)
  474. pSeq->frame[frameIndex].trigger = !pSeq->frame[frameIndex].trigger;
  475. seqModified = TRUE;
  476. break;
  477. case KEY_H:
  478. if (frameIndex < pSeq->nFrames)
  479. pSeq->frame[frameIndex].hitscan = !pSeq->frame[frameIndex].hitscan;
  480. seqModified = TRUE;
  481. break;
  482. case KEY_L:
  483. if (frameIndex < pSeq->nFrames)
  484. {
  485. pSeq->flags ^= kSeqLoop;
  486. pSeq->flags &= ~kSeqRemove;
  487. seqModified = TRUE;
  488. }
  489. break;
  490. case KEY_S:
  491. if (frameIndex < pSeq->nFrames)
  492. pSeq->frame[frameIndex].smoke = !pSeq->frame[frameIndex].smoke;
  493. seqModified = TRUE;
  494. break;
  495. case KEY_T:
  496. if (frameIndex < pSeq->nFrames)
  497. {
  498. if ( pSeq->frame[frameIndex].translucent )
  499. {
  500. if ( pSeq->frame[frameIndex].translucentR )
  501. {
  502. pSeq->frame[frameIndex].translucent = 0;
  503. pSeq->frame[frameIndex].translucentR = 0;
  504. }
  505. else
  506. pSeq->frame[frameIndex].translucentR = 1;
  507. }
  508. else
  509. pSeq->frame[frameIndex].translucent = 1;
  510. }
  511. seqModified = TRUE;
  512. break;
  513. case KEY_P:
  514. if (frameIndex < pSeq->nFrames)
  515. {
  516. if ( alt )
  517. pSeq->frame[frameIndex].pal = GetNumberBox("Palookup", pSeq->frame[frameIndex].pal, pSeq->frame[frameIndex].pal );
  518. else
  519. pSeq->frame[frameIndex].pal = IncRotate(pSeq->frame[frameIndex].pal, kMaxPLU);
  520. seqModified = TRUE;
  521. }
  522. break;
  523. case KEY_R:
  524. if (frameIndex < pSeq->nFrames)
  525. {
  526. pSeq->flags ^= kSeqRemove;
  527. pSeq->flags &= ~kSeqLoop;
  528. seqModified = TRUE;
  529. }
  530. break;
  531. case KEY_V:
  532. if (frameIndex < pSeq->nFrames)
  533. pSeq->frame[frameIndex].nTile = tilePick(nTile, nTile, SS_ALL);
  534. seqModified = TRUE;
  535. break;
  536. case KEY_W:
  537. if (frameIndex < pSeq->nFrames)
  538. {
  539. picanm[nTile].view = IncRotate(picanm[nTile].view, LENGTH(viewNames));
  540. tileMarkDirty(nTile);
  541. tilesModified = TRUE;
  542. }
  543. break;
  544. case KEY_PADPLUS:
  545. if ( alt )
  546. gShade = (schar)ClipLow(gShade - 1, 0);
  547. else if (frameIndex < pSeq->nFrames)
  548. {
  549. if ( ctrl )
  550. pSeq->frame[frameIndex].shade = -128;
  551. else
  552. pSeq->frame[frameIndex].shade = ClipLow(pSeq->frame[frameIndex].shade - 1, -128);
  553. seqModified = TRUE;
  554. }
  555. break;
  556. case KEY_PADMINUS:
  557. if ( alt )
  558. gShade = (schar)ClipHigh(gShade + 1, 127);
  559. else if (frameIndex < pSeq->nFrames)
  560. {
  561. if ( ctrl )
  562. pSeq->frame[frameIndex].shade = 127;
  563. else
  564. pSeq->frame[frameIndex].shade = ClipHigh(pSeq->frame[frameIndex].shade + 1, 127);
  565. seqModified = TRUE;
  566. }
  567. break;
  568. case KEY_PAD0:
  569. if (frameIndex < pSeq->nFrames)
  570. {
  571. pSeq->frame[frameIndex].shade = 0;
  572. seqModified = TRUE;
  573. }
  574. break;
  575. case KEY_PAGEUP:
  576. while (pSeq->frame[frameIndex].nTile > 0)
  577. {
  578. pSeq->frame[frameIndex].nTile--;
  579. if (tilesizx[pSeq->frame[frameIndex].nTile] && tilesizx[pSeq->frame[frameIndex].nTile])
  580. break;
  581. }
  582. seqModified = TRUE;
  583. break;
  584. case KEY_PAGEDN:
  585. while (pSeq->frame[frameIndex].nTile < kMaxTiles - 1)
  586. {
  587. pSeq->frame[frameIndex].nTile++;
  588. if (tilesizx[pSeq->frame[frameIndex].nTile] && tilesizx[pSeq->frame[frameIndex].nTile])
  589. break;
  590. }
  591. seqModified = TRUE;
  592. break;
  593. case KEY_UP:
  594. if ( keystatus[KEY_O] )
  595. {
  596. SetOrigin(origin.x, origin.y - 1);
  597. break;
  598. }
  599. else if (frameIndex < pSeq->nFrames)
  600. {
  601. if (shift)
  602. picanm[nTileView].ycenter = -tilesizy[nTileView] / 2;
  603. else
  604. picanm[nTileView].ycenter++;
  605. tileMarkDirty(nTileView);
  606. tilesModified = TRUE;
  607. }
  608. break;
  609. case KEY_LEFT:
  610. if ( keystatus[KEY_O] )
  611. {
  612. SetOrigin(origin.x - 1, origin.y);
  613. break;
  614. }
  615. else if (frameIndex < pSeq->nFrames)
  616. {
  617. if (shift)
  618. picanm[nTileView].xcenter = -tilesizx[nTileView] / 2;
  619. else
  620. picanm[nTileView].xcenter++;
  621. tileMarkDirty(nTileView);
  622. tilesModified = TRUE;
  623. }
  624. break;
  625. case KEY_PAD5:
  626. if ( frameIndex < pSeq->nFrames && shift )
  627. {
  628. picanm[nTileView].xcenter = 0;
  629. picanm[nTileView].ycenter = 0;
  630. tileMarkDirty(nTileView);
  631. tilesModified = TRUE;
  632. }
  633. break;
  634. case KEY_RIGHT:
  635. if ( keystatus[KEY_O] )
  636. {
  637. SetOrigin(origin.x + 1, origin.y);
  638. break;
  639. }
  640. else if (frameIndex < pSeq->nFrames)
  641. {
  642. if (shift)
  643. picanm[nTileView].xcenter = tilesizx[nTileView] - tilesizx[nTileView] / 2;
  644. else
  645. picanm[nTileView].xcenter--;
  646. tileMarkDirty(nTileView);
  647. tilesModified = TRUE;
  648. }
  649. break;
  650. case KEY_DOWN:
  651. if ( keystatus[KEY_O] )
  652. {
  653. SetOrigin(origin.x, origin.y + 1);
  654. break;
  655. }
  656. else if (frameIndex < pSeq->nFrames)
  657. {
  658. if (shift)
  659. picanm[nTileView].ycenter = tilesizy[nTileView] - tilesizy[nTileView] / 2;
  660. else
  661. picanm[nTileView].ycenter--;
  662. tileMarkDirty(nTileView);
  663. tilesModified = TRUE;
  664. }
  665. break;
  666. case KEY_PADUP:
  667. if (frameIndex < pSeq->nFrames)
  668. pSeq->frame[frameIndex].yrepeat = IncNext(pSeq->frame[frameIndex].yrepeat,
  669. pad5 ? 8 : 1);
  670. seqModified = TRUE;
  671. break;
  672. case KEY_PADDOWN:
  673. if (frameIndex < pSeq->nFrames)
  674. pSeq->frame[frameIndex].yrepeat = DecNext(pSeq->frame[frameIndex].yrepeat,
  675. pad5 ? 8 : 1);
  676. seqModified = TRUE;
  677. break;
  678. case KEY_PADLEFT:
  679. if (frameIndex < pSeq->nFrames)
  680. pSeq->frame[frameIndex].xrepeat = DecNext(pSeq->frame[frameIndex].xrepeat,
  681. pad5 ? 8 : 1);
  682. seqModified = TRUE;
  683. break;
  684. case KEY_PADRIGHT:
  685. if (frameIndex < pSeq->nFrames)
  686. pSeq->frame[frameIndex].xrepeat = IncNext(pSeq->frame[frameIndex].xrepeat,
  687. pad5 ? 8 : 1);
  688. seqModified = TRUE;
  689. break;
  690. }
  691. }
  692. Mouse::Read(gFrameTicks);
  693. // which buttons just got pressed
  694. nbuttons = (short)(~obuttons & Mouse::buttons);
  695. obuttons = Mouse::buttons;
  696. if ( Mouse::buttons & 1 )
  697. {
  698. if ( keystatus[KEY_O] )
  699. SetOrigin(origin.x + Mouse::dX2, origin.y + Mouse::dY2);
  700. }
  701. }
  702. }
  703. void main( int argc, char *argv[] )
  704. {
  705. char title[256];
  706. gOldDisplayMode = getvmode();
  707. sprintf(title, "Sequence Editor [%s] -- DO NOT DISTRIBUTE", gBuildDate);
  708. tioInit();
  709. tioCenterString(0, 0, tioScreenCols - 1, title, kAttrTitle);
  710. tioCenterString(tioScreenRows - 1, 0, tioScreenCols - 1,
  711. "Copyright (c) 1994, 1995 Q Studios Corporation", kAttrTitle);
  712. tioWindow(1, 0, tioScreenRows - 2, tioScreenCols);
  713. if ( _grow_handles(kRequiredFiles) < kRequiredFiles )
  714. ThrowError("Not enough file handles available", ES_ERROR);
  715. gGamma = BloodINI.GetKeyInt("View", "Gamma", 0);
  716. tioPrint("Initializing heap and resource system");
  717. Resource::heap = new QHeap(dpmiDetermineMaxRealAlloc());
  718. tioPrint("Initializing resource archive");
  719. gSysRes.Init("BLOOD.RFF", "*.*");
  720. gGuiRes.Init("GUI.RFF", NULL);
  721. tioPrint("Initializing mouse");
  722. if ( !initmouse() )
  723. tioPrint("Mouse not detected");
  724. // install our error handler
  725. prevErrorHandler = errSetHandler(EditorErrorHandler);
  726. InitEngine();
  727. Mouse::SetRange(xdim, ydim);
  728. tioPrint("Loading tiles");
  729. if (tileInit() == 0)
  730. ThrowError("ART files not found", ES_ERROR);
  731. tioPrint("Initializing screen");
  732. scrInit();
  733. tioPrint("Installing keyboard handler");
  734. keyInstall();
  735. scrCreateStdColors();
  736. tioPrint("Installing timer");
  737. timerRegisterClient(ClockStrobe, kTimerRate);
  738. timerInstall();
  739. tioPrint("Engaging graphics subsystem...");
  740. scrSetGameMode();
  741. scrSetGamma(gGamma);
  742. scrSetDac(0);
  743. strcpy(gSeqName, "");
  744. pSeq = (Seq *)Resource::Alloc(sizeof(Seq) + kMaxFrames * sizeof(SEQFRAME));
  745. memset(pSeq, 0, sizeof(Seq) + kMaxFrames * sizeof(SEQFRAME));
  746. pSeq->nFrames = 0;
  747. pSeq->ticksPerFrame = 12;
  748. seqModified = FALSE;
  749. tilesModified = FALSE;
  750. if ( argc > 1 )
  751. {
  752. strcpy(gSeqName, argv[1]);
  753. LoadSeq();
  754. }
  755. do {
  756. EditLoop();
  757. } while (tilesModified && !AcknowledgeTileChange());
  758. setvmode(gOldDisplayMode);
  759. dprintf("Removing timer\n");
  760. timerRemove();
  761. dprintf("uninitengine()\n");
  762. uninitengine();
  763. dprintf("All subsystems shut down. Processing exit functions\n");
  764. errSetHandler(prevErrorHandler);
  765. }