v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
tilebuffer.h
1 /* -*- mode: C; c-basic-offset: 4; intent-tabs-mode: nil -*-
2  *
3  * This file is part of the public interface to the Sifteo SDK.
4  * Copyright <c> 2012 Sifteo, Inc. All rights reserved.
5  */
6 
7 #pragma once
8 #ifdef NOT_USERSPACE
9 # error This is a userspace-only header, not allowed by the current build.
10 #endif
11 
12 #include <sifteo/abi.h>
13 #include <sifteo/macros.h>
14 #include <sifteo/math.h>
15 #include <sifteo/asset.h>
16 #include <sifteo/memory.h>
17 #include <sifteo/cube.h>
18 
19 namespace Sifteo {
20 
50 template <unsigned tW, unsigned tH, unsigned tF = 1>
51 struct TileBuffer {
52  struct {
53  _SYSAssetImage image;
54  _SYSCubeID cube;
55  } sys;
56  uint16_t tiles[tW * tH * tF];
57 
58  // Implicit conversion to AssetImage base class
59  operator const AssetImage& () const { return *reinterpret_cast<const AssetImage*>(&sys.image); }
60  operator AssetImage& () { return *reinterpret_cast<AssetImage*>(&sys.image); }
61  operator const AssetImage* () const { return reinterpret_cast<const AssetImage*>(&sys.image); }
62  operator AssetImage* () { return reinterpret_cast<AssetImage*>(&sys.image); }
63 
64  // Implicit conversion to FlatAssetImage
65  operator const FlatAssetImage& () const { return *reinterpret_cast<const FlatAssetImage*>(&sys.image); }
66  operator FlatAssetImage& () { return *reinterpret_cast<FlatAssetImage*>(&sys.image); }
67  operator const FlatAssetImage* () const { return reinterpret_cast<const FlatAssetImage*>(&sys.image); }
68  operator FlatAssetImage* () { return reinterpret_cast<FlatAssetImage*>(&sys.image); }
69 
70  // Implicit conversion to system object
71  operator const _SYSAssetImage& () const { return sys.image; }
72  operator _SYSAssetImage& () { return sys.image; }
73  operator const _SYSAssetImage* () const { return sys.image; }
74  operator _SYSAssetImage* () { return sys.image; }
75 
79  CubeID cube() const {
80  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
81  return sys.cube;
82  }
83 
94  sys.cube = cube;
95  }
96 
100  void init() {
101  sys.cube = _SYS_CUBE_ID_INVALID;
102  bzero(sys.image);
103  sys.image.width = tW;
104  sys.image.height = tH;
105  sys.image.frames = tF;
106  sys.image.format = _SYS_AIF_FLAT;
107  sys.image.pData = reinterpret_cast<uint32_t>(&tiles[0]);
108  }
109 
117  init();
118  }
119 
132  init();
133 
134  sys.cube = cube;
135  }
136 
140  static unsigned tileWidth() {
141  return tW;
142  }
143 
147  static unsigned tileHeight() {
148  return tH;
149  }
150 
154  static UInt2 tileSize() {
155  return vec(tileWidth(), tileHeight());
156  }
157 
161  static unsigned pixelWidth() {
162  return tileWidth() * 8;
163  }
164 
168  static unsigned pixelHeight() {
169  return tileHeight() * 8;
170  }
171 
175  static UInt2 pixelSize() {
176  return vec(pixelWidth(), pixelHeight());
177  }
178 
182  static int numFrames() {
183  return tF;
184  }
185 
189  static int numTilesPerFrame() {
190  return tileWidth() * tileHeight();
191  }
192 
196  static int numTiles() {
197  return numFrames() * numTilesPerFrame();
198  }
199 
203  static unsigned sizeInBytes() {
204  return numTiles() * 2;
205  }
206 
210  static unsigned sizeInWords() {
211  return numTiles();
212  }
213 
218  void erase(uint16_t index = 0) {
219  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
220  memset16(&tiles[0], index, sizeInWords());
221  }
222 
227  void erase(const PinnedAssetImage &image) {
228  erase(image.tile(sys.cube, 0));
229  }
230 
236  uint16_t tileAddr(UInt2 pos, unsigned frame = 0) const {
237  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
238  return pos.x + (pos.y + frame * tileHeight()) * tileWidth();
239  }
240 
247  void plot(unsigned i, uint16_t tileIndex) {
248  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
249  ASSERT(i < numTiles());
250  tiles[i] = tileIndex;
251  }
252 
259  void plot(UInt2 pos, uint16_t tileIndex, unsigned frame = 0) {
260  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
261  ASSERT(pos.x < tileWidth() && pos.y < tileHeight() && frame < numFrames());
262  tiles[tileAddr(pos, frame)] = tileIndex;
263  }
264 
268  uint16_t tile(unsigned i) const {
269  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
270  ASSERT(i < numTiles());
271  return tiles[i];
272  }
273 
278  uint16_t tile(UInt2 pos, unsigned frame = 0) const {
279  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
280  ASSERT(pos.x < tileWidth() && pos.y < tileHeight() && frame < numFrames());
281  return tiles[tileAddr(pos, frame)];
282  }
283 
290  void span(UInt2 pos, unsigned width, unsigned tileIndex, unsigned frame = 0)
291  {
292  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
293  ASSERT(pos.x <= tileWidth() && width <= tileWidth() &&
294  (pos.x + width) <= tileWidth() && pos.y < tileHeight());
295  memset16(&tiles[tileAddr(pos, frame)], tileIndex, width);
296  }
297 
303  void span(UInt2 pos, unsigned width, const PinnedAssetImage &image, unsigned frame = 0)
304  {
305  span(pos, width, image.tile(sys.cube, 0), frame);
306  }
307 
314  void fill(UInt2 topLeft, UInt2 size, unsigned tileIndex, unsigned frame = 0)
315  {
316  while (size.y) {
317  span(topLeft, size.x, tileIndex, frame);
318  size.y--;
319  topLeft.y++;
320  }
321  }
322 
329  void fill(UInt2 topLeft, UInt2 size, const PinnedAssetImage &image, unsigned frame = 0)
330  {
331  fill(topLeft, size, image.tile(sys.cube, 0), frame);
332  }
333 
343  void image(UInt2 pos, const AssetImage &image, unsigned srcFrame = 0, unsigned destFrame = 0)
344  {
345  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
346  ASSERT(pos.x < tileWidth() && pos.x + image.tileWidth() <= tileWidth() &&
347  pos.y < tileHeight() && pos.y + image.tileHeight() <= tileHeight() &&
348  destFrame < numFrames());
349  _SYS_image_memDraw(&tiles[tileAddr(pos, destFrame)], sys.cube, image, tileWidth(), srcFrame);
350  }
351 
361  void image(UInt2 destXY, UInt2 size, const AssetImage &image, UInt2 srcXY,
362  unsigned srcFrame = 0, unsigned destFrame = 0)
363  {
364  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
365  ASSERT(destXY.x < tileWidth() && destXY.x + size.x <= tileWidth() &&
366  destXY.y < tileHeight() && destXY.y + size.y <= tileHeight() &&
367  destFrame < numFrames());
368  _SYS_image_memDrawRect(&tiles[tileAddr(destXY, destFrame)], sys.cube,
369  image, tileWidth(), srcFrame, (_SYSInt2*) &srcXY, (_SYSInt2*) &size);
370  }
371 
378  void text(Int2 topLeft, const AssetImage &font, const char *str,
379  unsigned destFrame = 0, char firstChar = ' ')
380  {
381  ASSERT(sys.cube != _SYS_CUBE_ID_INVALID);
382  uint16_t *addr = &tiles[tileAddr(topLeft, destFrame)];
383  uint16_t *lineAddr = addr;
384  char c;
385 
386  while ((c = *str)) {
387  if (c == '\n') {
388  addr = (lineAddr += tileWidth());
389  } else {
390  ASSERT(font.tileWidth() + (font.tileHeight() - 1) * tileWidth() + addr
391  <= numTiles() + tiles);
392  _SYS_image_memDraw(addr, sys.cube, font, tileWidth(), c - firstChar);
393  addr += font.tileWidth();
394  }
395  str++;
396  }
397  }
398 };
399 
400 
428 template <unsigned tW, unsigned tH, unsigned tF = 1>
430  _SYSAssetImage sys;
431  uint16_t tiles[tW * tH * tF];
432 
434  operator const AssetImage& () const { return *reinterpret_cast<const AssetImage*>(&sys); }
435  operator AssetImage& () { return *reinterpret_cast<AssetImage*>(&sys); }
436  operator const AssetImage* () const { return reinterpret_cast<const AssetImage*>(&sys); }
437  operator AssetImage* () { return reinterpret_cast<AssetImage*>(&sys); }
438 
440  operator const FlatAssetImage& () const { return *reinterpret_cast<const FlatAssetImage*>(&sys); }
441  operator FlatAssetImage& () { return *reinterpret_cast<FlatAssetImage*>(&sys); }
442  operator const FlatAssetImage* () const { return reinterpret_cast<const FlatAssetImage*>(&sys); }
443  operator FlatAssetImage* () { return reinterpret_cast<FlatAssetImage*>(&sys); }
444 
446  operator const _SYSAssetImage& () const { return sys; }
447  operator _SYSAssetImage& () { return sys; }
448  operator const _SYSAssetImage* () const { return sys; }
449  operator _SYSAssetImage* () { return sys; }
450 
457  void init() {
458  bzero(sys);
459  sys.width = tW;
460  sys.height = tH;
461  sys.frames = tF;
462  sys.format = _SYS_AIF_FLAT;
463  sys.pData = reinterpret_cast<uint32_t>(&tiles[0]);
464  }
465 
470  init();
471  }
472 
476  static unsigned tileWidth() {
477  return tW;
478  }
479 
483  static unsigned tileHeight() {
484  return tH;
485  }
486 
490  static UInt2 tileSize() {
491  return vec(tileWidth(), tileHeight());
492  }
493 
497  static unsigned pixelWidth() {
498  return tileWidth() * 8;
499  }
500 
504  static unsigned pixelHeight() {
505  return tileHeight() * 8;
506  }
507 
511  static UInt2 pixelSize() {
512  return vec(pixelWidth(), pixelHeight());
513  }
514 
518  static int numFrames() {
519  return tF;
520  }
521 
525  static int numTilesPerFrame() {
526  return tileWidth() * tileHeight();
527  }
528 
532  static int numTiles() {
533  return numFrames() * numTilesPerFrame();
534  }
535 
539  static unsigned sizeInBytes() {
540  return numTiles() * 2;
541  }
542 
546  static unsigned sizeInWords() {
547  return numTiles();
548  }
549 
555  void setAssetGroup(AssetGroup &group) {
556  uint32_t pAssetGroup = reinterpret_cast<uint32_t>(&group.sys);
557  ASSERT(sys.pAssetGroup == 0 || sys.pAssetGroup == pAssetGroup);
558  sys.pAssetGroup = pAssetGroup;
559  }
560 
565  void erase(uint16_t index = 0) {
566  memset16(&tiles[0], index, sizeInWords());
567  }
568 
573  void erase(const PinnedAssetImage &image) {
574  setAssetGroup(image.assetGroup());
575  erase(image.tile(0));
576  }
577 
583  uint16_t tileAddr(UInt2 pos, unsigned frame = 0) {
584  return pos.x + (pos.y + frame * tileHeight()) * tileWidth();
585  }
586 
593  void plot(unsigned i, uint16_t tileIndex) {
594  ASSERT(i < numTiles());
595  tiles[i] = tileIndex;
596  }
597 
604  void plot(UInt2 pos, uint16_t tileIndex, unsigned frame = 0) {
605  ASSERT(pos.x < tileWidth() && pos.y < tileHeight() && frame < numFrames());
606  tiles[tileAddr(pos, frame)] = tileIndex;
607  }
608 
612  uint16_t tile(unsigned i) const {
613  ASSERT(i < numTiles());
614  return tiles[i];
615  }
616 
621  uint16_t tile(UInt2 pos, unsigned frame = 0) const {
622  ASSERT(pos.x < tileWidth() && pos.y < tileHeight() && frame < numFrames());
623  return tiles[tileAddr(pos, frame)];
624  }
625 
632  void span(UInt2 pos, unsigned width, unsigned tileIndex, unsigned frame = 0)
633  {
634  ASSERT(pos.x <= tileWidth() && width <= tileWidth() &&
635  (pos.x + width) <= tileWidth() && pos.y < tileHeight());
636  memset16(&tiles[tileAddr(pos, frame)], tileIndex, width);
637  }
638 
644  void span(UInt2 pos, unsigned width, const PinnedAssetImage &image, unsigned frame = 0)
645  {
646  setAssetGroup(image.assetGroup());
647  span(pos, width, image.tile(0), frame);
648  }
649 
656  void fill(UInt2 topLeft, UInt2 size, unsigned tileIndex, unsigned frame = 0)
657  {
658  while (size.y) {
659  span(topLeft, size.x, tileIndex, frame);
660  size.y--;
661  topLeft.y++;
662  }
663  }
664 
671  void fill(UInt2 topLeft, UInt2 size, const PinnedAssetImage &image, unsigned frame = 0)
672  {
673  setAssetGroup(image.assetGroup());
674  fill(topLeft, size, image.tile(0), frame);
675  }
676 
686  void image(UInt2 pos, const AssetImage &image, unsigned srcFrame = 0, unsigned destFrame = 0)
687  {
688  setAssetGroup(image.assetGroup());
689  ASSERT(pos.x < tileWidth() && pos.x + image.tileWidth() <= tileWidth() &&
690  pos.y < tileHeight() && pos.y + image.tileHeight() <= tileHeight() &&
691  destFrame < numFrames());
692  _SYS_image_memDraw(&tiles[tileAddr(pos, destFrame)],
693  _SYS_CUBE_ID_INVALID, image, tileWidth(), srcFrame);
694  }
695 
705  void image(UInt2 destXY, UInt2 size, const AssetImage &image, UInt2 srcXY,
706  unsigned srcFrame = 0, unsigned destFrame = 0)
707  {
708  setAssetGroup(image.assetGroup());
709  ASSERT(destXY.x < tileWidth() && destXY.x + size.x <= tileWidth() &&
710  destXY.y < tileHeight() && destXY.y + size.y <= tileHeight() &&
711  destFrame < numFrames());
712  _SYS_image_memDrawRect(&tiles[tileAddr(destXY, destFrame)],
713  _SYS_CUBE_ID_INVALID, image, tileWidth(), srcFrame,
714  (_SYSInt2*) &srcXY, (_SYSInt2*) &size);
715  }
716 
723  void text(Int2 topLeft, const AssetImage &font, const char *str,
724  unsigned destFrame = 0, char firstChar = ' ')
725  {
726  setAssetGroup(font.assetGroup());
727  uint16_t *addr = &tiles[tileAddr(topLeft, destFrame)];
728  uint16_t *lineAddr = addr;
729  char c;
730 
731  while ((c = *str)) {
732  if (c == '\n') {
733  addr = (lineAddr += tileWidth());
734  } else {
735  ASSERT(font.tileWidth() + (font.tileHeight() - 1) * tileWidth() + addr
736  <= numTiles() + tiles);
737  _SYS_image_memDraw(addr, _SYS_CUBE_ID_INVALID, font, tileWidth(), c - firstChar);
738  addr += font.tileWidth();
739  }
740  str++;
741  }
742  }
743 };
744 
745 
750 }; // namespace Sifteo