attribute.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //////////////////////////////////////////////////////////////////////
  19. //
  20. // ATTRIBUTE.CPP
  21. //
  22. // Created on 10/03/96 BRH
  23. // Implemented 10/03/96 BRH
  24. //
  25. // 10/03/96 BRH Started this class for use in the Postal
  26. // demo to provide a way to load the attribute
  27. // map and to access the data
  28. //
  29. // 10/14/96 BRH Added scaling to the attribute map utility and
  30. // changed the Load to read in the scale from
  31. // the new version of the attribute map file, and
  32. // changed GetAttribute functions to scale the
  33. // real world coordinates to the scaled map size.
  34. // This allows maps to be smaller and take less
  35. // less memory.
  36. //
  37. // 10/15/96 BRH Expanded the attribute map to 16 bits. The
  38. // High 8 bits are for height rather than the
  39. // simple walk/no walk attribute. The lower 8
  40. // bits are for flags. Whenever an attribute
  41. // for a region is returned, it is the ORed
  42. // combination of the low 8 bits, and the max
  43. // height in the high 8 bits.
  44. //
  45. // 10/22/96 JMI Moved #include <stdlib.h> to before
  46. // #include "System.h".
  47. //
  48. // 10/28/96 MJR Switched from __min and __max to MIN and MAX for
  49. // compatibility with CodeWarrior.
  50. //
  51. // 10/31/96 BRH Changed CAttributeMap to RAttributeMap which is
  52. // the new RSPiX naming convention.
  53. //
  54. // 11/01/96 JMI Changed:
  55. // Old label: New label:
  56. // ========= =========
  57. // LITTLE_ENDIAN RFile::LittleEndian
  58. //
  59. // 11/20/96 BRH Changed the load function to load the new attribute
  60. // format which includes block maps and detail maps.
  61. // Also changed the GetAttriubte functions to
  62. // interpret the new format.
  63. //
  64. // 11/21/96 BRH Changed the GetAttribute rectangle version for the
  65. // new attribute format. It now loops through the
  66. // rectangle but skips to the next block if the
  67. // attribute from the block it just read contains
  68. // all of the same attributes. The height is now
  69. // height and depth in the low 8 bits. It can be
  70. // cast to a signed char to get the value of the height
  71. // or depth. The attribute flag bits are in the upper 7
  72. // bits of the attribute and the high bit is the
  73. // flag to mark the map entry as a lookup or complete
  74. // block with a single attribute.
  75. //
  76. // 11/22/96 BRH Fixed problem with casting the result of the
  77. // attribute height/depth for the GetAttribute
  78. // function.
  79. //
  80. // 01/14/97 BRH Fixed problem of checking an attribute right on the
  81. // right or bottom edge of the world. If you called
  82. // GetAttribute with a point one pixel past the edge
  83. // of the world it would crash, if it were inside or
  84. // further outside it was fine.
  85. //
  86. // 02/03/97 BRH Added a Load that takes an RFile* in addition to
  87. // the one that takes the filename as char*.
  88. //
  89. //////////////////////////////////////////////////////////////////////
  90. #include <stdlib.h>
  91. #include "System.h"
  92. #ifdef PATHS_IN_INCLUDES
  93. #include "ORANGE/Attribute/attribute.h"
  94. #include "ORANGE/File/file.h"
  95. #else
  96. #include "ATTRIBUTE.H"
  97. #include "FILE.H"
  98. #endif //PATHS_IN_INCLUDES
  99. //////////////////////////////////////////////////////////////////////
  100. //
  101. // Constructor
  102. //
  103. // Description:
  104. // Default contstuctor for the RAttributeMap class. Initializes
  105. // the map buffer pointer.
  106. //
  107. // Parameters:
  108. // none
  109. //
  110. // Returns:
  111. // none
  112. //
  113. //////////////////////////////////////////////////////////////////////
  114. RAttributeMap::RAttributeMap()
  115. {
  116. m_pusDetailMap = NULL;
  117. m_pusMap = NULL;
  118. m_lWidth = 0;
  119. m_lHeight = 0;
  120. m_ucFlags = 0;
  121. m_ucMaxHeight = 0;
  122. m_ucMinHeight = 0;
  123. m_usLastAttribute = 0;
  124. m_sBlockDataSize = 0;
  125. m_sNumDetailMaps = 0;
  126. m_lWorldWidth = 0;
  127. m_lWorldHeight = 0;
  128. }
  129. //////////////////////////////////////////////////////////////////////
  130. //
  131. // Constructor
  132. //
  133. // Description:
  134. // This constructor takes the filename of the map to load and
  135. // first initializes a RAttributeMap and then calls the load
  136. // function.
  137. //
  138. // Parameters:
  139. // char* pszFilename = filename of map file to load
  140. //
  141. // Returns:
  142. // none
  143. //
  144. //////////////////////////////////////////////////////////////////////
  145. RAttributeMap::RAttributeMap(char* pszFilename)
  146. {
  147. m_pusDetailMap = NULL;
  148. m_pusMap = NULL;
  149. m_lWidth = 0;
  150. m_lHeight = 0;
  151. m_ucFlags = 0;
  152. m_ucMaxHeight = 0;
  153. m_ucMinHeight = 0;
  154. m_usLastAttribute = 0;
  155. m_sBlockDataSize = 0;
  156. m_sNumDetailMaps = 0;
  157. m_lWorldWidth = 0;
  158. m_lWorldHeight = 0;
  159. Load(pszFilename);
  160. }
  161. //////////////////////////////////////////////////////////////////////
  162. //
  163. // Destructor
  164. //
  165. // Description:
  166. // General destructor for RAttributeMap class. Frees the map
  167. // pointer if one was allocated.
  168. //
  169. // Parameters:
  170. // none
  171. //
  172. // Returns:
  173. // none
  174. //
  175. //////////////////////////////////////////////////////////////////////
  176. RAttributeMap::~RAttributeMap()
  177. {
  178. FreeMap();
  179. }
  180. //////////////////////////////////////////////////////////////////////
  181. //
  182. // FreeMap
  183. //
  184. // Description:
  185. // Frees the map buffer if one was allocated
  186. //
  187. // Parameters:
  188. // none
  189. //
  190. // Returns:
  191. // none
  192. //
  193. //////////////////////////////////////////////////////////////////////
  194. void RAttributeMap::FreeMap()
  195. {
  196. if (m_pusMap)
  197. {
  198. delete []m_pusMap;
  199. m_pusMap = NULL;
  200. }
  201. if (m_pusDetailMap)
  202. {
  203. delete []m_pusDetailMap;
  204. m_pusDetailMap = NULL;
  205. }
  206. }
  207. //////////////////////////////////////////////////////////////////////
  208. //
  209. // AllocateMap
  210. //
  211. // Description:
  212. // Allocates memory for a map of the given size
  213. //
  214. // Parameters:
  215. // ULONG ulSize = size of buffer to allocate
  216. //
  217. // Returns:
  218. // SUCCESS if memory was allocated
  219. // FAILURE otherwise
  220. //
  221. //////////////////////////////////////////////////////////////////////
  222. short RAttributeMap::AllocateMap(ULONG ulSize, ULONG ulDetailMapSize)
  223. {
  224. short sReturn = SUCCESS;
  225. if (m_pusMap == NULL)
  226. m_pusMap = new USHORT[ulSize];
  227. if (m_pusDetailMap == NULL)
  228. m_pusDetailMap = new USHORT[ulDetailMapSize];
  229. if (m_pusMap == NULL || m_pusDetailMap == NULL)
  230. return FAILURE;
  231. else
  232. return SUCCESS;
  233. }
  234. //////////////////////////////////////////////////////////////////////
  235. //
  236. // GetAttribute
  237. //
  238. // Description:
  239. // This is the single point version which returns the attribute
  240. // at the given position on the map.
  241. //
  242. // Parameters:
  243. // ULONG ulX = x position of point
  244. // ULONG ulY = y position of point
  245. //
  246. // Returns:
  247. // USHORT = attribute at the specified point
  248. //
  249. //////////////////////////////////////////////////////////////////////
  250. /*
  251. USHORT RAttributeMap::GetAttribute(long lX, long lY)
  252. {
  253. if ((lX/m_sScaleX) > m_lWidth || (lY/m_sScaleY) > m_lHeight || lX < 0 || lY < 0)
  254. return ATTRIBUTE_NOT_WALKABLE;
  255. m_usLastAttribute = m_pusMap[(lY/m_sScaleY)*m_lWidth + (lX/m_sScaleX)];
  256. m_ucFlags = (UCHAR) (m_usLastAttribute & 0x00ff);
  257. m_ucMinHeight = m_ucMaxHeight = (UCHAR) ((m_usLastAttribute & 0xff00) >> 8);
  258. return m_usLastAttribute;
  259. }
  260. */
  261. USHORT RAttributeMap::GetAttribute(long lX, long lY)
  262. {
  263. USHORT usBlockData;
  264. if ((lX/m_sScaleX) >= m_lWidth || (lY/m_sScaleY) >= m_lHeight || lX < 0 || lY < 0)
  265. return ATTRIBUTE_NOT_WALKABLE;
  266. // See if the block being accessed is an attribute or
  267. // a detail map lookup
  268. usBlockData = m_pusMap[(lY/m_sScaleY)*m_lWidth + (lX/m_sScaleX)];
  269. if (usBlockData & 0x8000)
  270. // Lookup the value for this pixel
  271. {
  272. m_usLastAttribute = m_pusDetailMap[((usBlockData & 0x7fff) * m_sBlockDataSize) + (((lY % m_sScaleY)*m_sScaleY) + (lX % m_sScaleX))];
  273. m_ucFlags = (UCHAR) ((m_usLastAttribute & 0xff00) >> 8);
  274. m_ucMinHeight = m_ucMaxHeight = (UCHAR) (m_usLastAttribute & 0x00ff);
  275. }
  276. else
  277. {
  278. m_usLastAttribute = usBlockData;
  279. m_ucFlags = (UCHAR) ((usBlockData & 0xff00) >> 8);
  280. m_ucMinHeight = m_ucMaxHeight = (UCHAR) (usBlockData & 0x00ff);
  281. }
  282. return m_usLastAttribute;
  283. }
  284. //////////////////////////////////////////////////////////////////////
  285. //
  286. // GetAttribute
  287. //
  288. // Description:
  289. // This is the rectangle version which returns the ORed
  290. // combination of the attributes within the rectangle. The
  291. // attribute bits have been arranged so that an ORed combination
  292. // has a real meaning. If any point within the rectnagle is
  293. // non-walkable, then the non-walkable bit is set and the other
  294. // bits pertain to shadow behind different layers, so the ORed
  295. // combination will tell you each layer that the object is
  296. // behind. The coordinates given are scaled down to the map size.
  297. // It converts the real world coordinates to map coordinates
  298. // by dividing them by the scale for the Map. The maps may be
  299. // created such that a single map position refers to more than
  300. // one pixel location. This help saves memory by having smaller
  301. // maps, and it also results in faster checking of this version
  302. // of GetAttribute that takes the rectangular area to be checked.
  303. //
  304. // Note the rectangle is clipped to the map size if it happens
  305. // to exceed the boundries.
  306. //
  307. // Parameters:
  308. // ulTopCoord = top of box to check.
  309. // ulBottomCoord = bottom of box to check
  310. // ulLeftCoord = left size of box to check
  311. // ulRightCoord = right side of box to check
  312. //
  313. // Returns
  314. // USHORT = ORed combination of attribute bits within this rectangle
  315. //
  316. //////////////////////////////////////////////////////////////////////
  317. /*
  318. USHORT RAttributeMap::GetAttribute(long lTopCoord, long lBottomCoord,
  319. long lLeftCoord, long lRightCoord)
  320. {
  321. long lTop = lTopCoord / m_sScaleY;
  322. long lBottom = lBottomCoord / m_sScaleY;
  323. long lLeft = lLeftCoord / m_sScaleX;
  324. long lRight = lRightCoord / m_sScaleX;
  325. // Clip the box to the map size if necessary
  326. if (lTop >= m_lHeight)
  327. lTop = m_lHeight - 1;
  328. if (lTop < 0)
  329. lTop = 0;
  330. if (lBottom >= m_lHeight)
  331. lBottom = m_lHeight - 1;
  332. if (lBottom < 0)
  333. lBottom = 0;
  334. if (lLeft >= m_lWidth)
  335. lLeft = m_lWidth - 1;
  336. if (lLeft < 0)
  337. lLeft = 0;
  338. if (lRight >= m_lWidth)
  339. lRight = m_lWidth - 1;
  340. if (lRight < 0)
  341. lRight = 0;
  342. long lRow;
  343. long lCol;
  344. USHORT usResult = 0;
  345. USHORT usAttrib = 0;
  346. USHORT usMin = m_pusMap[lTop*m_lWidth + lLeft];
  347. USHORT usMax = m_pusMap[lTop*m_lWidth + lLeft];
  348. USHORT usFlags = 0;
  349. for (lRow = lTop; lRow <= lBottom; lRow++)
  350. for (lCol = lLeft; lCol <= lRight; lCol++)
  351. {
  352. usAttrib = m_pusMap[lRow*m_lWidth + lCol];
  353. usFlags |= usAttrib;
  354. usMin = MIN(usMin, usAttrib);
  355. usMax = MAX(usMax, usAttrib);
  356. }
  357. m_ucFlags = (UCHAR) (usFlags & 0x00ff);
  358. m_ucMinHeight = (UCHAR) (usMin >> 8);
  359. m_ucMaxHeight = (UCHAR) (usMax >> 8);
  360. usResult = (usMax & 0xff00) | (usFlags & 0x00ff);
  361. return usResult;
  362. }
  363. */
  364. USHORT RAttributeMap::GetAttribute(long lTopCoord, long lBottomCoord,
  365. long lLeftCoord, long lRightCoord)
  366. {
  367. long lTop = lTopCoord;// / m_sScaleY;
  368. long lBottom = lBottomCoord;// / m_sScaleY;
  369. long lLeft = lLeftCoord;// / m_sScaleX;
  370. long lRight = lRightCoord;// / m_sScaleX;
  371. // Clip the box to the map size if necessary
  372. if (lTop >= m_lWorldHeight)
  373. lTop = m_lWorldHeight - 1;
  374. if (lTop < 0)
  375. lTop = 0;
  376. if (lBottom >= m_lWorldHeight)
  377. lBottom = m_lWorldHeight - 1;
  378. if (lBottom < 0)
  379. lBottom = 0;
  380. if (lLeft >= m_lWorldWidth)
  381. lLeft = m_lWorldWidth - 1;
  382. if (lLeft < 0)
  383. lLeft = 0;
  384. if (lRight >= m_lWorldWidth)
  385. lRight = m_lWorldWidth - 1;
  386. if (lRight < 0)
  387. lRight = 0;
  388. long lRow;
  389. long lCol;
  390. USHORT usResult = 0;
  391. USHORT usAttrib = 0;
  392. USHORT usFlags = 0;
  393. char cMax = (char) 0x80;
  394. for (lRow = lTop; lRow <= lBottom; lRow++)
  395. for (lCol = lLeft; lCol <= lRight; lCol++)
  396. {
  397. usAttrib = m_pusMap[((lRow/m_sScaleY) * m_lWidth ) + (lCol / m_sScaleX)];
  398. if (usAttrib & 0x8000)
  399. // Lookup the value in the detail map
  400. {
  401. usAttrib = m_pusDetailMap[((usAttrib & 0x7fff) * m_sBlockDataSize) +
  402. (((lRow % m_sScaleY) * m_sScaleX) +
  403. (lCol % m_sScaleX))];
  404. usFlags |= usAttrib;
  405. cMax = MAX(cMax, (char) (usAttrib & 0x00ff));
  406. }
  407. else
  408. // Get the attribute for this whole block
  409. {
  410. usAttrib &= 0x7fff;
  411. usFlags |= usAttrib;
  412. cMax = MAX(cMax, (char) (usAttrib & 0x00ff));
  413. // Skip to next block since these are all the same
  414. lCol += m_sScaleX - (lCol % m_sScaleX);
  415. }
  416. }
  417. usResult = (usFlags & 0xff00) | (U8) cMax;
  418. return usResult;
  419. }
  420. //////////////////////////////////////////////////////////////////////
  421. //
  422. // Load
  423. //
  424. // Description:
  425. // Loads the map file into a buffer. Checks to make sure that
  426. // the file is the right type and version before loading.
  427. //
  428. // Parameters:
  429. // char* pszFilename = filename of map file to be loaded
  430. //
  431. // Returns:
  432. // SUCCESS if loaded correctly
  433. // -1 if file not found
  434. // -2 if wrong file type
  435. // -3 if wrong version
  436. // -4 if error reading width
  437. // -5 if error reading height
  438. // -6 if error reading X scale
  439. // -7 if error reading Y scale
  440. // -8 if error allocating memory for map buffer
  441. // -9 if error reading map data
  442. //
  443. //////////////////////////////////////////////////////////////////////
  444. short RAttributeMap::Load(char* pszFilename)
  445. {
  446. RFile cf;
  447. short sReturn = SUCCESS;
  448. if (cf.Open(pszFilename, "rb", RFile::LittleEndian) != SUCCESS)
  449. {
  450. TRACE("RAttributeMap::Load - could not open file %s\n", pszFilename);
  451. return FAILURE;
  452. }
  453. sReturn = Load(&cf);
  454. cf.Close();
  455. return sReturn;
  456. }
  457. short RAttributeMap::Load(RFile* prf)
  458. {
  459. short sReturn = SUCCESS;
  460. ULONG ulFileType;
  461. ULONG ulVersion;
  462. if (prf && prf->IsOpen())
  463. {
  464. if (prf->Read(&ulFileType) == 1)
  465. {
  466. if (ulFileType == ATTRIBUTE_MAP_COOKIE)
  467. {
  468. if (prf->Read(&ulVersion) == 1)
  469. {
  470. if (ulVersion == ATTRIBUTE_CURRENT_VERSION)
  471. {
  472. if (prf->Read(&m_lWidth) == 1)
  473. {
  474. if (prf->Read(&m_lHeight) == 1)
  475. {
  476. if (prf->Read(&m_sScaleX) == 1)
  477. {
  478. if (prf->Read(&m_sScaleY) == 1)
  479. {
  480. if (prf->Read(&m_sNumDetailMaps) == 1)
  481. {
  482. if (AllocateMap(m_lWidth * m_lHeight, m_sNumDetailMaps * m_sScaleX * m_sScaleY) == SUCCESS)
  483. {
  484. if (prf->Read(m_pusMap, m_lWidth*m_lHeight) == (long) (m_lWidth*m_lHeight))
  485. {
  486. if (prf->Read(m_pusDetailMap, m_sNumDetailMaps*m_sScaleX*m_sScaleY) == m_sNumDetailMaps*m_sScaleX*m_sScaleY)
  487. {
  488. sReturn = SUCCESS;
  489. m_sBlockDataSize = m_sScaleX * m_sScaleY;
  490. }
  491. else
  492. {
  493. TRACE("RAttributeMap::Load - Error reading detail maps\n");
  494. sReturn = -11;
  495. }
  496. }
  497. else
  498. {
  499. TRACE("RAttributeMap::Load - Error reading map data\n");
  500. sReturn = -9;
  501. }
  502. }
  503. else
  504. {
  505. TRACE("RAttributeMap::Load - Error allocating map buffer\n");
  506. sReturn = -8;
  507. }
  508. }
  509. else
  510. {
  511. TRACE("RAttributeMap::Load - Error reading number of detail maps\n");
  512. sReturn = -10;
  513. }
  514. }
  515. else
  516. {
  517. TRACE("RAttributeMap::Load - Error reading Y scaling value\n");
  518. sReturn = -7;
  519. }
  520. }
  521. else
  522. {
  523. TRACE("RAttributeMap::Load - Error reading X scaling value\n");
  524. sReturn = -6;
  525. }
  526. }
  527. else
  528. {
  529. TRACE("RAttributeMap::Load - Error reading height\n");
  530. sReturn = -5;
  531. }
  532. }
  533. else
  534. {
  535. TRACE("RAttributeMap::Load - Error reading width\n");
  536. sReturn = -4;
  537. }
  538. }
  539. else
  540. {
  541. TRACE("RAttributeMap::Load - Wrong version: This file %d current version %d\n", ulVersion, ATTRIBUTE_CURRENT_VERSION);
  542. sReturn = -3;
  543. }
  544. }
  545. else
  546. {
  547. TRACE("RAttributeMap::Load - Error reading version\n");
  548. sReturn = -3;
  549. }
  550. }
  551. else
  552. {
  553. TRACE("RAttributeMap::Load - Wrong file type, should be \"ATRM\"\n");
  554. sReturn = -2;
  555. }
  556. }
  557. else
  558. {
  559. TRACE("RAttributeMap::Load - Error reading file type\n");
  560. sReturn = -2;
  561. }
  562. }
  563. else
  564. {
  565. TRACE("RAttributeMap::Load - prf does not refer to an open RFile*\n");
  566. sReturn = -1;
  567. }
  568. m_lWorldWidth = m_lWidth * m_sScaleX;
  569. m_lWorldHeight = m_lHeight * m_sScaleY;
  570. return sReturn;
  571. }