v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
bg1.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 
17 namespace Sifteo {
18 
36 struct BG1Mask {
37  // Matches the memory layout of BG1, but uses faster 32-bit arithmetic.
38  uint32_t row10;
39  uint32_t row32;
40  uint32_t row54;
41  uint32_t row76;
42  uint32_t row98;
43  uint32_t rowBA;
44  uint32_t rowDC;
45  uint32_t rowFE;
46 
50  static BG1Mask empty() {
51  BG1Mask result = { 0, 0, 0, 0, 0, 0, 0, 0 };
52  return result;
53  }
54 
64  static BG1Mask filled(UInt2 topLeft, UInt2 size) {
65  unsigned xBits = ((1 << size.x) - 1) << topLeft.x;
66  unsigned yBits = ((1 << size.y) - 1) << topLeft.y;
67 
68  unsigned row0 = yBits & 0x0001 ? xBits : 0;
69  unsigned row1 = yBits & 0x0002 ? xBits : 0;
70  unsigned row2 = yBits & 0x0004 ? xBits : 0;
71  unsigned row3 = yBits & 0x0008 ? xBits : 0;
72  unsigned row4 = yBits & 0x0010 ? xBits : 0;
73  unsigned row5 = yBits & 0x0020 ? xBits : 0;
74  unsigned row6 = yBits & 0x0040 ? xBits : 0;
75  unsigned row7 = yBits & 0x0080 ? xBits : 0;
76  unsigned row8 = yBits & 0x0100 ? xBits : 0;
77  unsigned row9 = yBits & 0x0200 ? xBits : 0;
78  unsigned rowA = yBits & 0x0400 ? xBits : 0;
79  unsigned rowB = yBits & 0x0800 ? xBits : 0;
80  unsigned rowC = yBits & 0x1000 ? xBits : 0;
81  unsigned rowD = yBits & 0x2000 ? xBits : 0;
82  unsigned rowE = yBits & 0x4000 ? xBits : 0;
83  unsigned rowF = yBits & 0x8000 ? xBits : 0;
84 
85  BG1Mask result = {
86  (row1 << 16) | row0,
87  (row3 << 16) | row2,
88  (row5 << 16) | row4,
89  (row7 << 16) | row6,
90  (row9 << 16) | row8,
91  (rowB << 16) | rowA,
92  (rowD << 16) | rowC,
93  (rowF << 16) | rowE,
94  };
95  return result;
96  }
97 
101  void clear() {
102  _SYS_memset32(&row10, 0, 8);
103  }
104 
108  uint16_t *rows() {
109  return (uint16_t*) this;
110  }
111  const uint16_t *rows() const {
112  return (const uint16_t*) this;
113  }
114 
120  void plot(unsigned x, unsigned y) {
121  ASSERT(x < 16 && y < 16);
122  rows()[y] |= 1 << x;
123  }
124 
130  void plot(UInt2 pos) {
131  plot(pos.x, pos.y);
132  }
133 
139  void fill(UInt2 topLeft, UInt2 size) {
140  for (unsigned y = 0; y < size.y; y++)
141  for (unsigned x = 0; x < size.x; x++)
142  plot(topLeft.x + x, topLeft.y + y);
143  }
144 
147  row10 |= other.row10;
148  row32 |= other.row32;
149  row54 |= other.row54;
150  row76 |= other.row76;
151  row98 |= other.row98;
152  rowBA |= other.rowBA;
153  rowDC |= other.rowDC;
154  rowFE |= other.rowFE;
155  return *this;
156  }
157 
160  row10 &= other.row10;
161  row32 &= other.row32;
162  row54 &= other.row54;
163  row76 &= other.row76;
164  row98 &= other.row98;
165  rowBA &= other.rowBA;
166  rowDC &= other.rowDC;
167  rowFE &= other.rowFE;
168  return *this;
169  }
170 
173  row10 ^= other.row10;
174  row32 ^= other.row32;
175  row54 ^= other.row54;
176  row76 ^= other.row76;
177  row98 ^= other.row98;
178  rowBA ^= other.rowBA;
179  rowDC ^= other.rowDC;
180  rowFE ^= other.rowFE;
181  return *this;
182  }
183 
185  BG1Mask operator| (BG1Mask other) const {
186  BG1Mask result = {
187  row10 | other.row10,
188  row32 | other.row32,
189  row54 | other.row54,
190  row76 | other.row76,
191  row98 | other.row98,
192  rowBA | other.rowBA,
193  rowDC | other.rowDC,
194  rowFE | other.rowFE,
195  };
196  return result;
197  }
198 
200  BG1Mask operator& (BG1Mask other) const {
201  BG1Mask result = {
202  row10 & other.row10,
203  row32 & other.row32,
204  row54 & other.row54,
205  row76 & other.row76,
206  row98 & other.row98,
207  rowBA & other.rowBA,
208  rowDC & other.rowDC,
209  rowFE & other.rowFE,
210  };
211  return result;
212  }
213 
215  BG1Mask operator^ (BG1Mask other) const {
216  BG1Mask result = {
217  row10 ^ other.row10,
218  row32 ^ other.row32,
219  row54 ^ other.row54,
220  row76 ^ other.row76,
221  row98 ^ other.row98,
222  rowBA ^ other.rowBA,
223  rowDC ^ other.rowDC,
224  rowFE ^ other.rowFE,
225  };
226  return result;
227  }
228 
230  BG1Mask operator~ () const {
231  BG1Mask result = {
232  ~row10,
233  ~row32,
234  ~row54,
235  ~row76,
236  ~row98,
237  ~rowBA,
238  ~rowDC,
239  ~rowFE,
240  };
241  return result;
242  }
243 };
244 
245 
266 struct BG1Drawable {
267  _SYSAttachedVideoBuffer sys;
268 
272  static unsigned tileWidth() {
273  return _SYS_VRAM_BG1_WIDTH;
274  }
275 
279  static unsigned tileHeight() {
280  return _SYS_VRAM_BG1_WIDTH;
281  }
282 
286  static UInt2 tileSize() {
287  return vec(tileWidth(), tileHeight());
288  }
289 
293  static unsigned pixelWidth() {
294  return tileWidth() * 8;
295  }
296 
300  static unsigned pixelHeight() {
301  return tileHeight() * 8;
302  }
303 
307  static UInt2 pixelSize() {
308  return vec(pixelWidth(), pixelHeight());
309  }
310 
314  static unsigned numTiles() {
315  return _SYS_VRAM_BG1_TILES;
316  }
317 
323  void erase(uint16_t index = 0) {
324  eraseMask();
325  _SYS_vbuf_fill(&sys.vbuf, _SYS_VA_BG1_TILES / 2,
326  _SYS_TILE77(index), numTiles());
327  setPanning(vec(0,0));
328  }
329 
335  void erase(const PinnedAssetImage &image) {
336  erase(image.tile(sys.cube, 0));
337  }
338 
343  void fill(uint16_t index = 0) {
344  _SYS_vbuf_fill(&sys.vbuf, _SYS_VA_BG1_TILES / 2,
345  _SYS_TILE77(index), numTiles());
346  }
347 
352  void fill(const PinnedAssetImage &image) {
353  fill(image.tile(sys.cube, 0));
354  }
355 
369  void eraseMask() {
370  _SYS_finish();
371  _SYS_vbuf_fill(&sys.vbuf, _SYS_VA_BG1_BITMAP/2, 0, _SYS_VRAM_BG1_WIDTH);
372  }
373 
386  void setMask(const BG1Mask &mask) {
387  _SYS_finish();
388  _SYS_vbuf_write(&sys.vbuf, offsetof(_SYSVideoRAM, bg1_bitmap)/2,
389  mask.rows(), 16);
390  }
391 
413  void fillMask(UInt2 topLeft, UInt2 size) {
414  _SYS_finish();
415  _SYS_vbuf_fill(&sys.vbuf,
416  offsetof(_SYSVideoRAM, bg1_bitmap)/2 + topLeft.y,
417  ((1 << size.x) - 1) << topLeft.x, size.y);
418  }
419 
430  void setPanning(Int2 pixels) {
431  unsigned x = pixels.x & 0xFF;
432  unsigned y = pixels.y & 0xFF;
433  _SYS_vbuf_poke(&sys.vbuf, offsetof(_SYSVideoRAM, bg1_x) / 2, x | (y << 8));
434  }
435 
439  Int2 getPanning() const {
440  unsigned word = _SYS_vbuf_peek(&sys.vbuf, offsetof(_SYSVideoRAM, bg0_x) / 2);
441  return vec<int>((int8_t)(word & 0xFF), (int8_t)(word >> 8));
442  }
443 
448  void plot(unsigned locationIndex, uint16_t tileIndex) {
449  ASSERT(locationIndex < numTiles());
450  _SYS_vbuf_poke(&sys.vbuf, _SYS_VA_BG1_TILES / 2 + locationIndex,
451  _SYS_TILE77(tileIndex));
452  }
453 
460  void span(unsigned locationIndex, unsigned count, unsigned tileIndex)
461  {
462  ASSERT(locationIndex <= numTiles() && count <= numTiles() &&
463  (locationIndex + count) < numTiles());
464  _SYS_vbuf_fill(&sys.vbuf, _SYS_VA_BG1_TILES / 2 + locationIndex,
465  _SYS_TILE77(tileIndex), count);
466  }
467 
479  void image(UInt2 pos, const AssetImage &image, unsigned frame = 0)
480  {
481  _SYS_image_BG1Draw(&sys, image, (_SYSInt2*) &pos, frame);
482  }
483 
495  void image(UInt2 destXY, UInt2 size, const AssetImage &image, UInt2 srcXY, unsigned frame = 0)
496  {
497  _SYS_image_BG1DrawRect(&sys, image, (_SYSInt2*) &destXY,
498  frame, (_SYSInt2*) &srcXY, (_SYSInt2*) &size);
499  }
500 
513  void maskedImage(const AssetImage &image, const PinnedAssetImage &key,
514  unsigned frame = 0)
515  {
516  _SYS_finish();
517  _SYS_image_BG1MaskedDraw(&sys, image, key.tile(sys.cube, 0), frame);
518  }
519 
533  void maskedImage(UInt2 size, const AssetImage &image,
534  const PinnedAssetImage &key, UInt2 srcXY,
535  unsigned frame = 0)
536  {
537  _SYS_finish();
538  _SYS_image_BG1MaskedDrawRect(&sys, image, key.tile(sys.cube, 0), frame,
539  (_SYSInt2*) &srcXY, (_SYSInt2*) &size);
540  }
541 
548  void text(Int2 topLeft, const AssetImage &font, const char *str, char firstChar = ' ')
549  {
550  Int2 pos = topLeft;
551  char c;
552 
553  while ((c = *str)) {
554  if (c == '\n') {
555  pos.x = topLeft.x;
556  pos.y += font.tileHeight();
557  } else {
558  _SYS_image_BG1Draw(&sys, font, (_SYSInt2*) &pos, c - firstChar);
559  pos.x += font.tileWidth();
560  }
561  str++;
562  }
563  }
564 
568  _SYSVideoBuffer &videoBuffer() {
569  return sys.vbuf;
570  }
571 
575  CubeID cube() const {
576  return sys.cube;
577  }
578 };
579 
584 }; // namespace Sifteo