In theory, we have tilemap support.

This commit is contained in:
Scott Duensing 2024-01-10 17:57:56 -06:00
parent a558f1a472
commit 22cca7c0ca
14 changed files with 328 additions and 113 deletions

3
.gitignore vendored
View file

@ -10,6 +10,9 @@ software/
*.pgx
*.bin
*.elf
*.lst
*.hex
*.o
# Crap for CrossOver
.windows-serial

View file

@ -183,9 +183,9 @@ int main(void) {
// Clear two graphics pages.
bitmapSetColor(0);
bitmapSetPage(0);
bitmapSetActive(0);
bitmapClear();
bitmapSetPage(1);
bitmapSetActive(1);
bitmapClear();
bitmapGetResolution(&widthOffset, &heightOffset);
@ -195,12 +195,14 @@ int main(void) {
while(1) {
if (p) {
p = 0;
bitmapSetPage(1);
bitmapShowPage(0);
bitmapSetActive(1);
bitmapSetVisible(0, true);
bitmapSetVisible(1, false);
} else {
p = 1;
bitmapSetPage(0);
bitmapShowPage(1);
bitmapSetActive(0);
bitmapSetVisible(0, false);
bitmapSetVisible(1, true);
}
bitmapSetColor(0);
for (i=0; i<12; i++) bitmapLine(past[i][p].x1, past[i][p].y1, past[i][p].x2, past[i][p].y2);

27
examples/pgztest/copy.sh Executable file
View file

@ -0,0 +1,27 @@
#!/bin/bash
#
# Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
python ../../FoenixMgr/FoenixMgr/fnxmgr.py --copy pgztest.pgz

26
examples/pgztest/dump.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
#
# Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
python ../../FoenixMgr/FoenixMgr/fnxmgr.py --dump 10000 --count 10

View file

@ -38,35 +38,24 @@ void bitmap(void) {
byte l;
byte c = 0;
textPrint("\n");
for (l=0; l<TEXTCOLORS_COUNT; l++) {
graphicsDefineColor(0, l, textColors[l].r, textColors[l].g, textColors[l].b);
textSetColor(l, 0);
textPrint("Color "); textPrintInt(l);
textPrint(" = R:"); textPrintInt(textColors[l].r);
textPrint(" G:"); textPrintInt(textColors[l].g);
textPrint(" B:"); textPrintInt(textColors[l].b);
textPrint("\n");
}
bitmapSetColor(0);
bitmapClear();
bitmapSetVisible(0, true);
bitmapGetResolution(&mx, &my);
for (l=0; l<TEXTCOLORS_COUNT; l++)
bitmapDefineColor(l, textColors[l].r, textColors[l].g, textColors[l].b);
l = 0;
while (1) {
// Abuse all three graphics pages.
switch (l) {
case 0:
bitmapSetPage(1);
bitmapShowPage(0);
l = 1;
break;
case 1:
bitmapSetPage(2);
bitmapShowPage(1);
l = 2;
break;
case 2:
bitmapSetPage(0);
bitmapShowPage(2);
l = 0;
break;
}
bitmapSetColor(0);
bitmapClear();
bitmapSetColor(c++);
if (c == TEXTCOLORS_COUNT) c = 0;

26
examples/pgztest/start.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
#
# Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
python ../../FoenixMgr/FoenixMgr/fnxmgr.py --start

26
examples/pgztest/stop.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
#
# Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
python ../../FoenixMgr/FoenixMgr/fnxmgr.py --stop

View file

@ -25,7 +25,7 @@
#include "dma.h"
#define EIGHTK 0x2000
#define EIGHTK 0x2000
static uint16_t _MAX_X;
@ -34,16 +34,15 @@ static uint32_t _PAGE_SIZE;
static uint32_t _BITMAP_BASE[3]; // Maximum of 3 pages possible.
static byte _BITMAP_CLUT[3];
static byte _color;
static byte _page; // Current drawing page.
static byte _pages; // Number of active pages.
static byte _active; // Current drawing page.
void bitmapClear(void) {
#ifdef BOOM
dmaFill(_BITMAP_BASE[_page], _PAGE_SIZE, _color);
//dma2dFill(_BITMAP_BASE[_page], _MAX_X, _MAX_Y, _MAX_X, _color);
dmaFill(_BITMAP_BASE[_active], _PAGE_SIZE, _color);
//dma2dFill(_BITMAP_BASE[_active], _MAX_X, _MAX_Y, _MAX_X, _color);
#else
byte block = _BITMAP_BASE[_page] / EIGHTK;
byte block = _BITMAP_BASE[_active] / EIGHTK;
byte x;
uint16_t c;
volatile byte *mem = (byte *)SWAP_ADDR;
@ -130,7 +129,7 @@ void bitmapPutPixel(uint16_t x, uint16_t y) {
uint32_t pixelRAM;
byte block;
pixelRAM = _BITMAP_BASE[_page] + mathUnsignedAddition(mathUnsignedMultiply(y, _MAX_X), (int32_t)x);
pixelRAM = _BITMAP_BASE[_active] + mathUnsignedAddition(mathUnsignedMultiply(y, _MAX_X), (int32_t)x);
block = pixelRAM / EIGHTK;
pixelRAM &= 0x1FFF; // Find offset into this block.
POKE(SWAP_SLOT, block);
@ -145,13 +144,12 @@ void bitmapReset(void) {
_MAX_X = 320;
_MAX_Y = 240;
_PAGE_SIZE = mathUnsignedMultiply(_MAX_X, _MAX_Y);
_pages = 1;
_page = 0;
_active = 0;
_color = 255;
// I could hardcode this, but this preserves the math so I don't forget later.
pageBlocks = _PAGE_SIZE / EIGHTK;
if ((pageBlocks * EIGHTK) != _PAGE_SIZE) {
if (mathUnsignedMultiply(pageBlocks, EIGHTK) != _PAGE_SIZE) {
// Fractional pageBlock. Round up.
pageBlocks++;
}
@ -176,7 +174,15 @@ void bitmapReset(void) {
POKEA(VKY_BM1_ADDR_L, _BITMAP_BASE[1]); // Location of bitmap data.
POKEA(VKY_BM2_ADDR_L, _BITMAP_BASE[2]); // Location of bitmap data.
bitmapShowNone();
// Hide everything.
bitmapSetVisible(0, false);
bitmapSetVisible(1, false);
bitmapSetVisible(2, false);
}
void bitmapSetActive(byte p) {
_active = p;
}
@ -196,31 +202,19 @@ void bitmapSetAddress(byte p, uint32_t a) {
}
void bitmapSetCLUT(uint16_t clut) {
void bitmapSetCLUT(byte clut) {
// Convert CLUT address to bits for bitmap control registers.
switch (clut) {
case GRAPHICS_CLUT_0:
_BITMAP_CLUT[_page] = 0;
break;
case GRAPHICS_CLUT_1:
_BITMAP_CLUT[_page] = 2;
break;
case GRAPHICS_CLUT_2:
_BITMAP_CLUT[_page] = 4;
break;
case GRAPHICS_CLUT_3:
_BITMAP_CLUT[_page] = 6;
break;
}
switch (_page) {
_BITMAP_CLUT[_active] = clut << 1;
switch (_active) {
case 0:
POKE(VKY_BM0_CTRL, (PEEK(VKY_BM0_CTRL) & 0xf9) | _BITMAP_CLUT[_page]);
POKE(VKY_BM0_CTRL, (PEEK(VKY_BM0_CTRL) & 0xf9) | _BITMAP_CLUT[_active]);
break;
case 1:
POKE(VKY_BM1_CTRL, (PEEK(VKY_BM1_CTRL) & 0xf9) | _BITMAP_CLUT[_page]);
POKE(VKY_BM1_CTRL, (PEEK(VKY_BM1_CTRL) & 0xf9) | _BITMAP_CLUT[_active]);
break;
case 2:
POKE(VKY_BM2_CTRL, (PEEK(VKY_BM2_CTRL) & 0xf9) | _BITMAP_CLUT[_page]);
POKE(VKY_BM2_CTRL, (PEEK(VKY_BM2_CTRL) & 0xf9) | _BITMAP_CLUT[_active]);
break;
}
}
@ -231,20 +225,16 @@ void bitmapSetColor(byte c) {
}
void bitmapSetPage(byte p) {
_page = p;
}
void bitmapShowNone(void) {
POKE(VKY_BM0_CTRL, 0);
POKE(VKY_BM1_CTRL, 0);
POKE(VKY_BM2_CTRL, 0);
}
void bitmapShowPage(byte p) {
POKE(VKY_BM0_CTRL, p == 0 ? 1 | _BITMAP_CLUT[_page] : 0); // Enable bitmap 0, GLUT 0.
POKE(VKY_BM1_CTRL, p == 1 ? 1 | _BITMAP_CLUT[_page] : 0);
POKE(VKY_BM2_CTRL, p == 2 ? 1 | _BITMAP_CLUT[_page] : 0);
void bitmapSetVisible(byte p, bool v) {
switch (p) {
case 0:
POKE(VKY_BM0_CTRL, v ? 1 | _BITMAP_CLUT[p] : 0); // Enable bitmap 0, GLUT 0.
break;
case 1:
POKE(VKY_BM1_CTRL, v ? 1 | _BITMAP_CLUT[p] : 0); // Enable bitmap 0, GLUT 0.
break;
case 2:
POKE(VKY_BM2_CTRL, v ? 1 | _BITMAP_CLUT[p] : 0); // Enable bitmap 0, GLUT 0.
break;
}
}

View file

@ -39,12 +39,11 @@ void bitmapGetResolution(uint16_t *x, uint16_t *y);
void bitmapLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void bitmapPutPixel(uint16_t x, uint16_t y);
void bitmapReset(void);
void bitmapSetCLUT(uint16_t clut);
void bitmapSetColor(byte c);
void bitmapSetPage(byte p);
void bitmapSetActive(byte p);
void bitmapSetAddress(byte p, uint32_t a);
void bitmapShowNone(void);
void bitmapShowPage(byte p);
void bitmapSetCLUT(byte clut);
void bitmapSetColor(byte c);
void bitmapSetVisible(byte p, bool v);
#ifdef __cplusplus

View file

@ -49,6 +49,11 @@ extern "C"
typedef unsigned char byte;
typedef unsigned char bool;
#define true 1
#define false 0
// Our stuff.
@ -58,9 +63,19 @@ typedef unsigned char byte;
// Things not in the Merlin defs.
#define TEXT_MATRIX 0xc000 // I/O Page 2
#define RAST_ROW_L 0xd01a
#define RAST_ROW_H 0xd01b
#define VKY_TS0_SQUARE (VKY_TS0_ADDR_H+1)
#define VKY_TS1_SQUARE (VKY_TS1_ADDR_H+1)
#define VKY_TS2_SQUARE (VKY_TS2_ADDR_H+1)
#define VKY_TS3_SQUARE (VKY_TS3_ADDR_H+1)
#define VKY_TS4_SQUARE (VKY_TS4_ADDR_H+1)
#define VKY_TS5_SQUARE (VKY_TS5_ADDR_H+1)
#define VKY_TS6_SQUARE (VKY_TS6_ADDR_H+1)
#define VKY_TS7_SQUARE (VKY_TS7_ADDR_H+1)
typedef struct colorS {
byte r;

View file

@ -24,14 +24,32 @@
#include "graphics.h"
void graphicsDefineColor(byte clut, byte slot, byte r, byte g, byte b) {
byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state.
byte *write;
uint16_t gclut;
void graphicsDefineColor(uint16_t clut, byte slot, byte r, byte g, byte b) {
byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state.
byte *write;
switch (clut) {
case 0:
gclut = VKY_GR_CLUT_0;
break;
case 1:
gclut = VKY_GR_CLUT_1;
break;
case 2:
gclut = VKY_GR_CLUT_2;
break;
case 3:
gclut = VKY_GR_CLUT_3;
break;
}
POKE(MMU_IO_CTRL, MMU_IO_PAGE_1); // Swap I/O page 1 into bank 6.
write = (byte *)mathUnsignedAddition(clut, mathUnsignedMultiply(slot, 4));
// This doesn't work for some reason.
//write = (byte *)mathUnsignedAddition((uint32_t)gclut, mathUnsignedMultiply((uint16_t)slot, (uint16_t)4));
write = (byte *)gclut + (slot * 4);
*write++ = b;
*write++ = g;
*write++ = r;
@ -44,36 +62,40 @@ void graphicsDefineColor(uint16_t clut, byte slot, byte r, byte g, byte b) {
void graphicsReset() {
int16_t x;
byte y;
uint16_t cluts[] = { GRAPHICS_CLUT_0, GRAPHICS_CLUT_1, GRAPHICS_CLUT_2, GRAPHICS_CLUT_3 };
// Set palettes to a gradient so there's at least *something*.
for (y=0; y<4; y++) {
for (x=0; x<256; x++) {
graphicsDefineColor(cluts[y], x, x, x, x);
graphicsDefineColor(y, x, x, x, x);
}
}
graphicsSetLayerType(0, GRAPHICS_BITMAP_0);
graphicsSetLayerType(1, GRAPHICS_BITMAP_1);
graphicsSetLayerType(2, GRAPHICS_BITMAP_2);
graphicsSetLayerBitmap(0, 0);
graphicsSetLayerBitmap(1, 1);
graphicsSetLayerBitmap(2, 2);
}
void graphicsSetLayerType(byte layer, byte what) {
void graphicsSetLayerBitmap(byte layer, byte which) {
switch (layer) {
case 0:
POKE(VKY_LAYER_CTRL_0, (PEEK(VKY_LAYER_CTRL_0) & 0xf0) | what);
POKE(VKY_LAYER_CTRL_0, (PEEK(VKY_LAYER_CTRL_0) & 0xf0) | which);
break;
case 1:
POKE(VKY_LAYER_CTRL_0, (PEEK(VKY_LAYER_CTRL_0) & 0x0f) | (what << 4));
POKE(VKY_LAYER_CTRL_0, (PEEK(VKY_LAYER_CTRL_0) & 0x0f) | (which << 4));
break;
case 2:
POKE(VKY_LAYER_CTRL_1, what);
POKE(VKY_LAYER_CTRL_1, which);
break;
}
}
void graphicsSetLayerTile(byte layer, byte which) {
graphicsSetLayerBitmap(layer, which + 4);
}
void graphicsWaitVerticalBlank(void) {
//***TODO*** This assumes we're 60hz with graphics enabled.
while (PEEKW(RAST_ROW_L) != 482)

View file

@ -34,24 +34,10 @@ extern "C"
#include "f256.h"
// Names to match the library.
#define GRAPHICS_CLUT_0 VKY_GR_CLUT_0
#define GRAPHICS_CLUT_1 VKY_GR_CLUT_1
#define GRAPHICS_CLUT_2 VKY_GR_CLUT_2
#define GRAPHICS_CLUT_3 VKY_GR_CLUT_3
#define GRAPHICS_BITMAP_0 0
#define GRAPHICS_BITMAP_1 1
#define GRAPHICS_BITMAP_2 2
#define GRAPHICS_TILE_0 4
#define GRAPHICS_TILE_1 5
#define GRAPHICS_TILE_2 6
void graphicsDefineColor(uint16_t clut, byte slot, byte r, byte g, byte b);
void graphicsDefineColor(byte clut, byte slot, byte r, byte g, byte b);
void graphicsReset();
void graphicsSetLayerType(byte layer, byte what);
void graphicsSetLayerBitmap(byte layer, byte which);
void graphicsSetLayerTile(byte layer, byte which);
void graphicsWaitVerticalBlank(void);

View file

@ -24,3 +24,102 @@
#include "tile.h"
void tileDefineTileMap(byte t, uint32_t address, byte tileSize, uint16_t mapSizeX, uint16_t mapSizeY) {
// Map size is 10 bits. Docs are wrong.
switch (t) {
case 0:
POKE(VKY_TM0_CTRL, tileSize << 4);
POKEA(VKY_TM0_ADDR_L, address);
POKEW(VKY_TM0_SIZE_X, mapSizeX);
POKEW(VKY_TM0_SIZE_Y, mapSizeY);
break;
case 1:
POKE(VKY_TM1_CTRL, tileSize << 4);
POKEA(VKY_TM1_ADDR_L, address);
POKEW(VKY_TM1_SIZE_X, mapSizeX);
POKEW(VKY_TM1_SIZE_Y, mapSizeY);
break;
case 2:
POKE(VKY_TM2_CTRL, tileSize << 4);
POKEA(VKY_TM2_ADDR_L, address);
POKEW(VKY_TM2_SIZE_X, mapSizeX);
POKEW(VKY_TM2_SIZE_Y, mapSizeY);
break;
}
tileSetScroll(t, 0, 0, 0, 0);
}
void tileDefineTileSet(byte t, uint32_t address, bool square) {
switch (t) {
case 0:
POKEA(VKY_TS0_ADDR_L, address);
POKE(VKY_TS0_SQUARE, square << 3);
break;
case 1:
POKEA(VKY_TS1_ADDR_L, address);
POKE(VKY_TS1_SQUARE, square << 3);
break;
case 2:
POKEA(VKY_TS2_ADDR_L, address);
POKE(VKY_TS2_SQUARE, square << 3);
break;
case 3:
POKEA(VKY_TS3_ADDR_L, address);
POKE(VKY_TS3_SQUARE, square << 3);
break;
case 4:
POKEA(VKY_TS4_ADDR_L, address);
POKE(VKY_TS4_SQUARE, square << 3);
break;
case 5:
POKEA(VKY_TS5_ADDR_L, address);
POKE(VKY_TS5_SQUARE, square << 3);
break;
case 6:
POKEA(VKY_TS6_ADDR_L, address);
POKE(VKY_TS6_SQUARE, square << 3);
break;
case 7:
POKEA(VKY_TS7_ADDR_L, address);
POKE(VKY_TS7_SQUARE, square << 3);
break;
}
}
void tileSetScroll(byte t, byte xPixels, uint16_t xTiles, byte yPixels, uint16_t yTiles) {
uint16_t scrollX = (xTiles << 4) + xPixels;
uint16_t scrollY = (yTiles << 4) + yPixels;
switch (t) {
case 0:
POKEW(VKY_TM0_POS_X_L, scrollX);
POKEW(VKY_TM0_POS_Y_L, scrollY);
break;
case 1:
POKEW(VKY_TM1_POS_X_L, scrollX);
POKEW(VKY_TM1_POS_Y_L, scrollY);
break;
case 2:
POKEW(VKY_TM2_POS_X_L, scrollX);
POKEW(VKY_TM2_POS_Y_L, scrollY);
break;
}
}
void tileSetVisible(byte t, bool v) {
switch (t) {
case 0:
POKE(VKY_TM0_CTRL, (PEEK(VKY_TM0_CTRL) & 0xfe) | v);
break;
case 1:
POKE(VKY_TM1_CTRL, (PEEK(VKY_TM1_CTRL) & 0xfe) | v);
break;
case 2:
POKE(VKY_TM2_CTRL, (PEEK(VKY_TM2_CTRL) & 0xfe) | v);
break;
}
}

View file

@ -34,6 +34,11 @@ extern "C"
#include "f256.h"
void tileDefineTileMap(byte t, uint32_t address, byte tileSize, uint16_t mapSizeX, uint16_t mapSizeY);
void tileDefineTileSet(byte t, uint32_t address, bool square);
void tileSetScroll(byte t, byte xPixels, uint16_t xTiles, byte yPixels, uint16_t yTiles);
void tileSetVisible(byte t, bool v);
#ifdef __cplusplus
}