From 3069f428816867e0a0a03093ca14042521b75d47 Mon Sep 17 00:00:00 2001
From: revvv <8734113+revvv@users.noreply.github.com>
Date: Sun, 21 Jul 2024 14:12:22 +0200
Subject: [PATCH 1/6] add DynamicMap example
---
.settings/language.settings.xml | 25 +
snes-examples/maps/DynamicMap/DynamicMap.c | 518 ++++++++++++++++++
snes-examples/maps/DynamicMap/Makefile | 35 ++
snes-examples/maps/DynamicMap/c64_sprite.asm | 44 ++
snes-examples/maps/DynamicMap/data.asm | 25 +
snes-examples/maps/DynamicMap/hdr.asm | 45 ++
snes-examples/maps/DynamicMap/map32x32.c | 151 +++++
snes-examples/maps/DynamicMap/map32x32.h | 22 +
snes-examples/maps/DynamicMap/map64x64.c | 162 ++++++
snes-examples/maps/DynamicMap/map64x64.h | 21 +
snes-examples/maps/DynamicMap/maputil.c | 45 ++
snes-examples/maps/DynamicMap/maputil.h | 7 +
.../maps/DynamicMap/pvsneslibfont.bmp | Bin 0 -> 7222 bytes
snes-examples/maps/DynamicMap/ram.asm | 8 +
snes-examples/maps/DynamicMap/sprite16.bmp | Bin 0 -> 368 bytes
.../maps/DynamicMap/sprite16_64x64.bmp | Bin 0 -> 368 bytes
16 files changed, 1108 insertions(+)
create mode 100644 .settings/language.settings.xml
create mode 100644 snes-examples/maps/DynamicMap/DynamicMap.c
create mode 100644 snes-examples/maps/DynamicMap/Makefile
create mode 100644 snes-examples/maps/DynamicMap/c64_sprite.asm
create mode 100644 snes-examples/maps/DynamicMap/data.asm
create mode 100644 snes-examples/maps/DynamicMap/hdr.asm
create mode 100644 snes-examples/maps/DynamicMap/map32x32.c
create mode 100644 snes-examples/maps/DynamicMap/map32x32.h
create mode 100644 snes-examples/maps/DynamicMap/map64x64.c
create mode 100644 snes-examples/maps/DynamicMap/map64x64.h
create mode 100644 snes-examples/maps/DynamicMap/maputil.c
create mode 100644 snes-examples/maps/DynamicMap/maputil.h
create mode 100644 snes-examples/maps/DynamicMap/pvsneslibfont.bmp
create mode 100644 snes-examples/maps/DynamicMap/ram.asm
create mode 100644 snes-examples/maps/DynamicMap/sprite16.bmp
create mode 100644 snes-examples/maps/DynamicMap/sprite16_64x64.bmp
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
new file mode 100644
index 000000000..d52ba7087
--- /dev/null
+++ b/.settings/language.settings.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/snes-examples/maps/DynamicMap/DynamicMap.c b/snes-examples/maps/DynamicMap/DynamicMap.c
new file mode 100644
index 000000000..14f22a1bd
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/DynamicMap.c
@@ -0,0 +1,518 @@
+/*---------------------------------------------------------------------------------
+
+
+ DynamicMap
+
+ Create and update 16x16 sprites in RAM on a 32x32 or 64x64 map.
+
+---------------------------------------------------------------------------------*/
+#include
+#include
+
+#include "maputil.h"
+#include "map32x32.h"
+#include "map64x64.h"
+
+#define SPRITE_EMPTY 0
+#define SPRITE_GARGOYLE 1
+#define SPRITE_ROCKFORD 2
+
+extern char snesfont, snespal;
+extern char sprite16, sprite16_end, palsprite16, palsprite16_end;
+extern char sprite16_64x64, sprite16_64x64_end, palsprite16_64x64, palsprite16_64x64_end;
+extern char c64_sprite;
+
+// map32x32 or map64x64 (visible: 16x14)
+u16 spritemap_len = 0x2000;
+u16 spritemap[0x2000];
+
+int number_of_sprites = 0x40; // keep in sync with ram.asm
+
+//char sprites_ram[0x40 * 256]; // this will collide with 0x7E8000 RAM, so using ramsection 0x7F (ram.asm)
+extern char sprites_ram;
+
+// no endless scrolling
+bool scroll_lock = true;
+
+// 32x32 or 64x64 map
+bool map32x32 = true;
+
+u16 max_scroll_width = MAX_SCROLL_WIDTH_32x32;
+u16 max_scroll_height = MAX_SCROLL_HEIGHT_32x32;
+
+void refresh()
+{
+ screenRefresh(spritemap, 0x1000);
+}
+
+void copySpriteToRAM_32x32(u8 *from, u16 index)
+{
+ // 16x16 sprite, 256 colors, 256 bytes
+ u16 i;
+ for (i = 0; i < 256; i++)
+ {
+ *(&sprites_ram + index + i) = *(from + i);
+ }
+}
+void copySpriteToRAM64x64(u8 *from, u16 index)
+{
+ // 16x16 sprite, 256 colors, 256 bytes
+ // top = 128 bytes
+ // bottom = 128 bytes
+ // between top and bottom is a 1024 bytes gap!
+ // => sprites can be interleaved!
+
+ u16 i;
+
+ // copy top
+ for (i = 0; i < 128; i++)
+ {
+ *(&sprites_ram + index + i) = *(from + i);
+ }
+
+ // copy bottom
+ for (i = 1024; i < 1024 + 128; i++)
+ {
+ *(&sprites_ram + index + i) = *(from + i);
+ }
+}
+
+/**
+ * Just to convert the 256 bytes sprite16 to RAM.
+ * This makes the 2048 bytes sprite16_64x64 superfluous!
+ */
+void copySpriteToRAM64x64_alt(u8 *from, u16 index)
+{
+ // 16x16 sprite, 256 colors, 256 bytes
+ // top = 128 bytes
+ // bottom = 128 bytes
+ // between top and bottom is a 1024 bytes gap!
+ // => sprites can be interleaved!
+
+ u16 i;
+
+ // copy top
+ for (i = 0; i < 128; i++)
+ {
+ *(&sprites_ram + index + i) = *(from + i);
+ }
+
+ // copy bottom
+ for (i = 1024; i < 1024 + 128; i++)
+ {
+ *(&sprites_ram + index + i) = *(from + i - 1024 + 128);
+ }
+}
+
+void resetRAM32x32(u16 index)
+{
+ // 16x16 sprite, 256 colors, 256 bytes
+ u16 i;
+ for (i = 0; i < 256; i++)
+ {
+ *(&sprites_ram + index + i) = 0;
+ }
+}
+
+void resetRAM64x64(u16 index)
+{
+ u16 i;
+
+ // reset top
+ for (i = 0; i < 128; i++)
+ {
+ *(&sprites_ram + index + i) = 0;
+ }
+
+ // reset bottom
+ for (i = 1024; i < 1024 + 128; i++)
+ {
+ *(&sprites_ram + index + i) = 0;
+ }
+}
+
+bool isBitSet(u8 b, u8 index)
+{
+ return ((b >> index) & 1) == 1;
+}
+
+/**
+ * Get pixel from a C64 sprite.
+ *
+ * C64 sprite spec:
+ * 8x16 pixels (32 bytes), NOTE: will be stretched to 16x16 on screen
+ * quarter tile: 4x8 pixels (8 bytes)
+ * quarter order: top left, top right, bottom left, bottom right
+ * 16 colors (4 colors effectively)
+ * colors:
+ * 00 = black
+ * 01 = orange
+ * 10 = grey
+ * 11 = white
+ *
+ * @param chr_no c64 sprite
+ * @param tile 0 - 3
+ * @param x 0 - 7
+ * @param y 0 - 7
+ * @return color
+ */
+u8 getPixel(u8 chr_no, u8 tile, u8 x, u8 y)
+{
+ vuint32 c64_sprite_base = (vuint32) &c64_sprite;
+
+ // stretch by resetting to even number
+ int x_even = x & 0b11111110;
+ if (tile >= 2)
+ {
+ tile -= 2;
+ chr_no += 0x10; // bottom half of C64 sprites are shifted
+ }
+
+ u8 row = *((u8*)(c64_sprite_base + chr_no*8 + 8*tile + y));
+
+ // C64 sprite has 2-bit color depth
+ bool bit0 = isBitSet(row, 7 - x_even);
+ bool bit1 = isBitSet(row, 7 - x_even - 1);
+ u8 color = (bit1 << 1) | bit0;
+
+ return color;
+}
+
+/**
+ * Convert C64 sprite to SNES format.
+ *
+ * @param chr_no c64 sprite to convert
+ * @param index index of address area to copy sprite to
+ * @param map32x32 32x32 or 64x64 map
+ */
+void convertC64Sprite(u8 chr_no, u16 index, bool map32x32)
+{
+ consoleNocashMessage("sprite: 0x%x, index=0x%x\n", (int) chr_no, index);
+
+ // 2^8 = 256 colors, 8 bitplanes
+ // 8x8 tile size
+ // 8 rows * 8 bitplanes = 64 bytes * 4 tiles = 256 bytes
+
+ // Convert2PicLZ77 from https://github.com/alekmaul/pvsneslib/blob/master/tools/gfx2snes/imgtools.c
+ u8 num_tiles = 4;
+ u8 bitplanes = 8;
+ u8 mask;
+ u8 t;
+ u8 b;
+ u16 x;
+ u16 y;
+ unsigned char data;
+
+ for (t = 0; t < num_tiles; t++) // loop through tiles
+ {
+ // added for map32x32: sprite top and bottom have a distance of 1024 bytes
+ if (!map32x32 && t == 2)
+ index += 1024 - 128; // sprite top length is 128 bytes
+
+ for (b = 0; b < bitplanes; b += 2) // loop through bitplane pairs
+ {
+ for (y = 0; y < 8; y++)
+ {
+ // get bit-mask
+ mask = 1 << b;
+ data = 0;
+
+ // get row of bit-plane and save row
+ for (x = 0; x < 8; x++)
+ {
+ data = data << 1;
+ if (getPixel(chr_no, t, x, y) & mask)
+ data = data + 1;
+ }
+ *(&sprites_ram + index++) = data;
+
+ // adjust bit-mask
+ mask = mask << 1;
+ data = 0;
+
+ // get row of next bit-plane and save row
+ for (x = 0; x < 8; x++)
+ {
+ data = data << 1;
+ if (getPixel(chr_no, t, x, y) & mask)
+ data = data + 1;
+ }
+ *(&sprites_ram + index++) = data;
+ }
+ }
+ }
+}
+
+void initDemoMap32x32()
+{
+ map32x32 = true;
+ max_scroll_width = MAX_SCROLL_WIDTH_32x32;
+ max_scroll_height = MAX_SCROLL_HEIGHT_32x32;
+
+ setMode(BG_MODE3, BG1_TSIZE8x8);
+
+ setSpriteMap32x32(spritemap, spritemap_len);
+ initSpriteMap32x32();
+
+ u16 sprites_len = calculateSpritesLength32x32(number_of_sprites);
+ consoleNocashMessage("sprites.addr: 0x%x\n", &sprites_ram);
+ consoleNocashMessage("sprites_len=0x%x\n", sprites_len);
+
+ // init empty sprite (required if emulator does not clear RAM)
+ resetRAM32x32(calculateSpriteIndex32x32(0));
+
+ u16 i;
+ // copy sprites to RAM, for this example just use the same graphics for sprites 1-9
+ for (i = 1; i < 10; i++)
+ {
+ u16 index = calculateSpriteIndex32x32(i);
+ copySpriteToRAM_32x32(&sprite16, index); // Gargoyle sprite: 16x16, 256 colors, 256 bytes
+ consoleNocashMessage("element: 0x%x, sprite: 0x%x, index: 0x%x\n", (int) i, element2sprite32x32(i), index);
+ /* output:
+ element: 0x1, sprite: 0x4, index: 0x100
+ element: 0x2, sprite: 0x8, index: 0x200
+ element: 0x3, sprite: 0xc, index: 0x300
+ element: 0x4, sprite: 0x10, index: 0x400
+ element: 0x5, sprite: 0x14, index: 0x500
+ element: 0x6, sprite: 0x18, index: 0x600
+ element: 0x7, sprite: 0x1c, index: 0x700
+ element: 0x8, sprite: 0x20, index: 0x800
+ element: 0x9, sprite: 0x24, index: 0x900
+ */
+ }
+
+ //bgInitTileSet(0, &sprite16, &palsprite16, 0, (&sprite16_end - &sprite16), 16 * 2, BG_256COLORS, 0x4000); // Gargoyle from ROM
+ bgInitTileSet(0, (u8*) &sprites_ram, &palsprite16, 0, sprites_len, 16 * 2, BG_256COLORS, 0x4000);
+ bgInitMapSet(0, (u8*) spritemap, spritemap_len, SC_64x64, 0x1000);
+}
+
+void initDemoMap64x64()
+{
+ map32x32 = false;
+ max_scroll_width = MAX_SCROLL_WIDTH_64x64;
+ max_scroll_height = MAX_SCROLL_HEIGHT_64x64;
+
+ setMode(BG_MODE3, BG1_TSIZE16x16);
+
+ setSpriteMap64x64(spritemap, spritemap_len);
+ initSpriteMap64x64();
+
+ u16 sprites_len = calculateSpritesLength64x64(number_of_sprites); // keep in sync with ram.asm
+ consoleNocashMessage("sprites.addr: 0x%x\n", &sprites_ram);
+ consoleNocashMessage("sprites_len=0x%x\n", sprites_len);
+
+ // init empty sprite (required if emulator does not clear RAM)
+ resetRAM64x64(calculateSpriteIndex64x64(0));
+
+ u16 i;
+ // copy sprites to RAM, for this example just use the same graphics for sprites 1-9
+ for (i = 1; i < 9; i++)
+ {
+ u16 index = calculateSpriteIndex64x64(i);
+ copySpriteToRAM64x64(&sprite16_64x64, index); // Gargoyle sprite: 16x16, 256 colors, 2048 bytes
+ //copySpriteToRAM64x64_alt(&sprite16, index); // alternative: reuse the 256 bytes sprite
+ consoleNocashMessage("element: 0x%x, sprite: 0x%x, index: 0x%x\n", (int) i, element2sprite64x64(i), index);
+ /* output:
+ element: 0x1, sprite: 0x2, index: 0x80
+ element: 0x2, sprite: 0x4, index: 0x100
+ element: 0x3, sprite: 0x6, index: 0x180
+ element: 0x4, sprite: 0x8, index: 0x200
+ element: 0x5, sprite: 0xa, index: 0x280
+ element: 0x6, sprite: 0xc, index: 0x300
+ element: 0x7, sprite: 0xe, index: 0x380
+ element: 0x8, sprite: 0x20, index: 0x800
+ element: 0x9, sprite: 0x22, index: 0x880
+ */
+ }
+
+ //bgInitTileSet(0, &sprite16_64x64, &palsprite16_64x64, 0, (&sprite16_64x64_end - &sprite16_64x64), 16 * 2, BG_256COLORS, 0x4000); // Gargoyle from ROM
+ bgInitTileSet(0, (u8*) &sprites_ram, &palsprite16_64x64, 0, sprites_len, 16 * 2, BG_256COLORS, 0x4000);
+ bgInitMapSet(0, (u8*) spritemap, spritemap_len, SC_64x64, 0x1000);
+}
+
+void drawSpriteFrame32x32(u16 sprite)
+{
+ u8 x;
+ u8 y;
+ for (x = 0; x < 32; x++)
+ for (y = 0; y < 32; y++)
+ if (x == 0 || y == 0 || x == 31 || y == 31)
+ drawSprite32x32(x, y, element2sprite32x32(sprite));
+}
+
+void drawSpriteFrame64x64(u16 sprite)
+{
+ u8 x;
+ u8 y;
+ for (x = 0; x < 64; x++)
+ for (y = 0; y < 64; y++)
+ if (x == 0 || y == 0 || x == 63 || y == 63)
+ drawSprite64x64(x, y, element2sprite64x64(sprite));
+}
+
+void testGetSprite32x32()
+{
+ u8 x = rand() % 31;
+ u8 y = rand() % 31;
+ //consoleNocashMessage("%u,%u\n", (int) x, (int) y);
+ u16 sprite = element2sprite32x32(SPRITE_GARGOYLE);
+ drawSprite32x32(x, y, sprite);
+ WaitForVBlank();
+ screenRefreshPos32x32(x, y, 0x1000);
+
+ u16 sprite2 = getSprite32x32(x, y);
+ if (sprite == sprite2)
+ consoleNocashMessage("TEST OK: testGetSprite32x32(): 0x%x == 0x%x\n", sprite, sprite2);
+ else
+ consoleNocashMessage("TEST FAILED: testGetSprite32x32(): 0x%x != 0x%x\n", sprite, sprite2);
+}
+
+void testGetSprite64x64()
+{
+ u8 x = rand() % 63;
+ u8 y = rand() % 63;
+ //consoleNocashMessage("%u,%u\n", (int) x, (int) y);
+ u16 sprite = element2sprite64x64(SPRITE_GARGOYLE);
+ drawSprite64x64(x, y, sprite);
+ WaitForVBlank();
+ screenRefreshPos64x64(x, y, 0x1000);
+
+ u16 sprite2 = getSprite64x64(x, y);
+ if (sprite == sprite2)
+ consoleNocashMessage("TEST OK: testGetSprite64x64(): 0x%x == 0x%x\n", sprite, sprite2);
+ else
+ consoleNocashMessage("TEST FAILED: testGetSprite64x64(): 0x%x != 0x%x\n", sprite, sprite2);
+}
+
+//---------------------------------------------------------------------------------
+int main()
+{
+ // Initialize text console with our font
+ consoleSetTextVramBGAdr(0x6800);
+ consoleSetTextVramAdr(0x3000);
+
+ consoleSetTextOffset(0x0100);
+ consoleInitText(0, 16 * 2, &snesfont, &snespal);
+
+ // Init background
+ bgSetGfxPtr(1, 0x2000);
+ bgSetMapPtr(1, 0x6800, SC_32x32);
+
+ consoleDrawText(6, 10, "DynamicMap");
+ consoleDrawText(6, 12, "A = Map size 32x32");
+ consoleDrawText(6, 14, "B = Scroll lock ON ");
+ consoleDrawText(6, 16, "X = Random sprite");
+ consoleDrawText(6, 18, "Y = Convert C64 sprite");
+ consoleDrawText(6, 20, "DPAD = Scroll map");
+
+ initDemoMap32x32();
+ setScreenOn();
+ drawSpriteFrame32x32(SPRITE_GARGOYLE);
+ refresh();
+
+ short sxbg0 = 0;
+ short sybg0 = 0;
+
+ u16 pad0;
+ u16 pad0_up;
+
+ consoleNocashMessage("c64_sprite.addr=0x%x\n", &c64_sprite);
+
+ while (true)
+ {
+ //consoleNocashMessage("x=%d y=%d\n", sxbg0, sybg0);
+ pad0 = padsCurrent(0);
+ pad0_up = padsUp(0);
+ if (pad0 & KEY_RIGHT)
+ {
+ if (!scroll_lock)
+ sxbg0 += 4;
+ else if (sxbg0 < max_scroll_width)
+ sxbg0 += 4;
+ }
+ else if (pad0 & KEY_LEFT)
+ {
+ if (!scroll_lock)
+ sxbg0 -= 4;
+ else if (sxbg0 > 0)
+ sxbg0 -= 4;
+ }
+ if (pad0 & KEY_UP)
+ {
+ if (!scroll_lock)
+ sybg0 -= 4;
+ else if (sybg0 > 0)
+ sybg0 -= 4;
+ }
+ else if (pad0 & KEY_DOWN)
+ {
+ if (!scroll_lock)
+ sybg0 += 4;
+ else if (sybg0 < max_scroll_height)
+ sybg0 += 4;
+ }
+ if (pad0_up & KEY_A)
+ {
+ map32x32 = !map32x32;
+ if (map32x32)
+ {
+ consoleDrawText(6, 12, "A = Map size 32x32");
+ setScreenOff();
+ initDemoMap32x32();
+ setScreenOn();
+ drawSpriteFrame32x32(SPRITE_GARGOYLE);
+ refresh();
+ }
+ else
+ {
+ consoleDrawText(6, 12, "A = Map size 64x64");
+ setScreenOff();
+ initDemoMap64x64();
+ setScreenOn();
+ drawSpriteFrame64x64(SPRITE_GARGOYLE);
+ refresh();
+ }
+ sxbg0 = 0;
+ sybg0 = 0;
+ }
+ if (pad0_up & KEY_B)
+ {
+ scroll_lock = !scroll_lock;
+ if (scroll_lock)
+ consoleDrawText(6, 14, "B = Scroll lock ON ");
+ else
+ consoleDrawText(6, 14, "B = Scroll lock OFF");
+ }
+ if (pad0 & KEY_X)
+ {
+ if (map32x32)
+ testGetSprite32x32();
+ else
+ testGetSprite64x64();
+ }
+ if (pad0 & KEY_Y)
+ {
+ if (map32x32)
+ {
+ convertC64Sprite(0, calculateSpriteIndex32x32(SPRITE_ROCKFORD), true);
+ WaitForVBlank();
+ updateSprite32x32(&sprites_ram, 0x4000, SPRITE_ROCKFORD);
+ drawSpriteFrame32x32(SPRITE_ROCKFORD);
+ refresh();
+ }
+ else
+ {
+ convertC64Sprite(0, calculateSpriteIndex64x64(SPRITE_ROCKFORD), false);
+ WaitForVBlank();
+ updateSprite64x64(&sprites_ram, 0x4000, SPRITE_ROCKFORD);
+ drawSpriteFrame64x64(SPRITE_ROCKFORD);
+ refresh();
+ }
+ }
+
+ bgSetScroll(0, sxbg0, sybg0);
+ WaitForVBlank();
+ }
+
+ return 0;
+}
diff --git a/snes-examples/maps/DynamicMap/Makefile b/snes-examples/maps/DynamicMap/Makefile
new file mode 100644
index 000000000..6b385d7f0
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/Makefile
@@ -0,0 +1,35 @@
+ifeq ($(strip $(PVSNESLIB_HOME)),)
+$(error "Please create an environment variable PVSNESLIB_HOME with path to its folder and restart application. (you can do it on windows with )")
+endif
+
+include ${PVSNESLIB_HOME}/devkitsnes/snes_rules
+
+.PHONY: bitmaps all
+
+#---------------------------------------------------------------------------------
+# ROMNAME is used in snes_rules file
+export ROMNAME := DynamicMap
+
+all: bitmaps $(ROMNAME).sfc
+
+clean: cleanBuildRes cleanRom cleanGfx
+
+#---------------------------------------------------------------------------------
+
+# Creates 256 bytes .pic file
+# NOTE: With "-s 8" there will be no 1024 bytes gap between top and bottom of the sprite
+# and with "-m" there will be no trailing space
+sprite16.pic: sprite16.bmp
+ @echo convert bitmap ... $(notdir $@)
+ $(GFXCONV) -s 8 -o 256 -u 256 -t bmp -m -i $<
+
+# Creates 2048 bytes .pic file
+sprite16_64x64.pic: sprite16_64x64.bmp
+ @echo convert bitmap ... $(notdir $@)
+ $(GFXCONV) -s 16 -o 256 -u 256 -t bmp -i $<
+
+pvsneslibfont.pic: pvsneslibfont.bmp
+ @echo convert font with no tile reduction ... $(notdir $@)
+ $(GFXCONV) -s 8 -o 2 -u 16 -e 1 -t bmp -i $<
+
+bitmaps : pvsneslibfont.pic sprite16.pic sprite16_64x64.pic
diff --git a/snes-examples/maps/DynamicMap/c64_sprite.asm b/snes-examples/maps/DynamicMap/c64_sprite.asm
new file mode 100644
index 000000000..d83e79f98
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/c64_sprite.asm
@@ -0,0 +1,44 @@
+; Sample C64 sprite from the game "Boulder Dash"
+; Source reverse engineered by DrHonz
+; https://csdb.dk/release/?id=145094
+
+.include "hdr.asm"
+
+c64_sprite:
+ .byte $00 ; ........ -> $3210 = Gfx_42 - BD_TileRockFord top left
+ .byte $08 ; ....#...
+ .byte $0a ; ....#.#.
+ .byte $22 ; ..#...#.
+ .byte $22 ; ..#...#.
+ .byte $0a ; ....#.#.
+ .byte $02 ; ......#.
+ .byte $0a ; ....#.#.
+
+ .byte $00 ; ........ -> $3218 = Gfx_43 - BD_TileRockFord top right
+ .byte $20 ; ..#.....
+ .byte $a0 ; #.#.....
+ .byte $88 ; #...#...
+ .byte $88 ; #...#...
+ .byte $a0 ; #.#.#...
+ .byte $80 ; #.......
+ .byte $a0 ; #.#.....
+
+.dsb 112, $00 ; 112 zero bytes (gap between sprite top and bottom)
+
+ .byte $23 ; ..#...## -> $3290 = Gfx_52 - BD_TileRockFord bottom left
+ .byte $32 ; ..##..#.
+ .byte $03 ; ......##
+ .byte $02 ; ......#.
+ .byte $07 ; .....###
+ .byte $04 ; .....#..
+ .byte $04 ; .....#..
+ .byte $3c ; ..####..
+
+ .byte $c8 ; ##..#... -> $3298 = Gfx_53 - BD_TileRockFord bottom right
+ .byte $8c ; #...##..
+ .byte $c0 ; ##......
+ .byte $80 ; #.......
+ .byte $d0 ; ##.#....
+ .byte $10 ; ...#....
+ .byte $10 ; ...#....
+ .byte $3c ; ..####..
diff --git a/snes-examples/maps/DynamicMap/data.asm b/snes-examples/maps/DynamicMap/data.asm
new file mode 100644
index 000000000..2bc671d45
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/data.asm
@@ -0,0 +1,25 @@
+.include "hdr.asm"
+
+.section ".rodata1" superfree
+
+sprite16:
+.incbin "sprite16.pic"
+sprite16_end:
+
+palsprite16:
+.incbin "sprite16.pal"
+
+sprite16_64x64:
+.incbin "sprite16_64x64.pic"
+sprite16_64x64_end:
+
+palsprite16_64x64:
+.incbin "sprite16_64x64.pal"
+
+snesfont:
+.incbin "pvsneslibfont.pic"
+
+snespal:
+.incbin "pvsneslibfont.pal"
+
+.ends
\ No newline at end of file
diff --git a/snes-examples/maps/DynamicMap/hdr.asm b/snes-examples/maps/DynamicMap/hdr.asm
new file mode 100644
index 000000000..318026f81
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/hdr.asm
@@ -0,0 +1,45 @@
+
+.MEMORYMAP ; Begin describing the system architecture.
+ SLOTSIZE $8000 ; The slot is $8000 bytes in size. More details on slots later.
+ DEFAULTSLOT 0 ; There's only 1 slot in SNES, there are more in other consoles.
+ SLOT 0 $8000 ; Defines Slot 0's starting address.
+ SLOT 1 $0 $2000
+ SLOT 2 $2000 $E000
+ SLOT 3 $0 $10000
+.ENDME ; End MemoryMap definition
+
+.ROMBANKSIZE $8000 ; Every ROM bank is 32 KBytes in size
+.ROMBANKS 8 ; 2 Mbits - Tell WLA we want to use 8 ROM Banks
+
+.SNESHEADER
+ ID "SNES" ; 1-4 letter string, just leave it as "SNES"
+
+ NAME "DYNAMIC MAP EXAMPLE " ; Program Title - can't be over 21 bytes,
+ ; "123456789012345678901" ; use spaces for unused bytes of the name.
+
+ SLOWROM
+ LOROM
+
+ CARTRIDGETYPE $00 ; $00 = ROM only $02 = ROM+SRAM, see WLA documentation for others
+ ROMSIZE $08 ; $08 = 2 Mbits, see WLA doc for more..
+ SRAMSIZE $00 ; $00 = No Sram, $01 = 16 kbits, see WLA doc for more..
+ COUNTRY $01 ; $01 = U.S. $00 = Japan, that's all I know
+ LICENSEECODE $00 ; Just use $00
+ VERSION $00 ; $00 = 1.00, $01 = 1.01, etc.
+.ENDSNES
+
+.SNESNATIVEVECTOR ; Define Native Mode interrupt vector table
+ COP EmptyHandler
+ BRK EmptyHandler
+ ABORT EmptyHandler
+ NMI VBlank
+ IRQ EmptyHandler
+.ENDNATIVEVECTOR
+
+.SNESEMUVECTOR ; Define Emulation Mode interrupt vector table
+ COP EmptyHandler
+ ABORT EmptyHandler
+ NMI EmptyHandler
+ RESET tcc__start ; where execution starts
+ IRQBRK EmptyHandler
+.ENDEMUVECTOR
diff --git a/snes-examples/maps/DynamicMap/map32x32.c b/snes-examples/maps/DynamicMap/map32x32.c
new file mode 100644
index 000000000..8079fb5a2
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/map32x32.c
@@ -0,0 +1,151 @@
+#include
+#include
+
+u16 spritemap32x32_len = 0;
+u16* spritemap32x32;
+
+void setSpriteMap32x32(u16* spritemap, u16 spritemap_len)
+{
+ spritemap32x32 = spritemap;
+ spritemap32x32_len = spritemap_len;
+}
+
+u16* getSpriteMap32x32(u16* spritemap)
+{
+ return spritemap32x32;
+}
+
+u16 getSpriteMap32x32_length()
+{
+ return spritemap32x32_len;
+}
+
+void initSpriteMap32x32()
+{
+ u16 i;
+ for (i = 0; i < spritemap32x32_len; i++)
+ {
+ spritemap32x32[i] = 0;
+ }
+}
+
+/**
+ * Draw a sprite on a 32 x 32 map. The map consists of four 16 x 16 maps, which are ordered this way:
+ * Top left, top right, bottom left, bottom right.
+ * The top left 16 x 16 map begins with y = 0.
+ * The top right 16 x 16 map begins with y = 16.
+ * The bottom left 16 x 16 map begins with y = 32.
+ * The bottom right 16 x 16 map begins with y = 48.
+ *
+ * @param x 0 - 15
+ * @param y 0 - 63
+ */
+void drawSpriteRaw32x32(u8 x, u8 y, u16 sprite)
+{
+ // i = colsMax * row + col; // for 1 tile, but we have 4 tiles per sprite
+ u16 i = 64 * y + x * 2;
+
+ // four tiles
+ spritemap32x32[i] = sprite;
+ spritemap32x32[i + 1] = sprite + 1;
+ spritemap32x32[i + 32] = sprite + 2;
+ spritemap32x32[i + 33] = sprite + 3;
+}
+
+getSpriteRaw32x32(u8 x, u8 y)
+{
+ // i = colsMax * row + col; // for 1 tile, but we have 4 tiles per sprite
+ u16 i = 64 * y + x * 2;
+ return spritemap32x32[i];
+}
+
+/**
+ * Draw a sprite on a 32 x 32 map.
+ *
+ * @param x column 0 - 31
+ * @param y row 0 - 31
+ */
+void drawSprite32x32(u8 x, u8 y, u16 sprite)
+{
+ if (x < 16 && y < 16)
+ drawSpriteRaw32x32(x, y, sprite); // top left
+ else if (x < 32 && y < 16)
+ drawSpriteRaw32x32(x - 16, y + 16, sprite); // top right
+ else if (x < 16 && y < 32)
+ drawSpriteRaw32x32(x, y + 16, sprite); // bottom left
+ else if (x < 32 && y < 32)
+ drawSpriteRaw32x32(x - 16, y + 32, sprite); // bottom right
+ else
+ consoleNocashMessage("drawSprite32x32: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+}
+
+u16 getSprite32x32(u8 x, u8 y)
+{
+ if (x < 16 && y < 16)
+ return getSpriteRaw32x32(x, y); // top left
+ else if (x < 32 && y < 16)
+ return getSpriteRaw32x32(x - 16, y + 16); // top right
+ else if (x < 16 && y < 32)
+ return getSpriteRaw32x32(x, y + 16); // bottom left
+ else if (x < 32 && y < 32)
+ return getSpriteRaw32x32(x - 16, y + 32); // bottom right
+ else
+ consoleNocashMessage("drawSprite32x32: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+}
+
+/**
+ * Convert element to its sprite index.
+ *
+ * @param elem gfx tile no 0 - (number_of_sprites - 1)
+ * @return sprite index
+ */
+u16 element2sprite32x32(u8 elem)
+{
+ return elem * 4; // BG1_TSIZE8x8
+}
+
+u16 calculateSpriteIndex32x32(u8 elem)
+{
+ return elem * 256; // BG1_TSIZE8x8
+}
+
+u16 calculateSpritesLength32x32(u16 number_of_sprites)
+{
+ return 256 * number_of_sprites;
+}
+
+/**
+ * Refresh one sprite position. Might require to call WaitForVBlank() previously.
+ * @param x column
+ * @param y row
+ * @param address base vram address to copy to
+ */
+void screenRefreshPos32x32(u8 x, u8 y, u16 address)
+{
+ u16 offset = 0;
+ if (x < 16 && y < 16)
+ offset = x + y*64;
+ else if (x < 32 && y < 16)
+ offset = 32*32 + (x-16) + y*64;
+ else if (x < 16 && y < 32)
+ offset = 32*32*2 + x + (y-16)*64;
+ else if (x < 32 && y < 32)
+ offset = 32*32*3 + (x-16) + (y-16)*64;
+ else
+ consoleNocashMessage("screenRefreshPos32x32: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+
+ dmaCopyVram((u8 *) (spritemap32x32 + offset), address + offset, 256);
+}
+
+/**
+ * Update sprite after updating its graphics. Might require to call WaitForVBlank() previously.
+ * Intended for a 16x16 sprite on a 32x32 map.
+ *
+ * @param source the source base to copy from
+ * @param address base vram address to copy to
+ */
+void updateSprite32x32(u8 *source, u16 address, u16 sprite)
+{
+ //dmaCopyVram((u8*) source, address, 256 * number_of_sprites); // update all sprites
+ dmaCopyVram((u8*) (source + calculateSpriteIndex32x32(sprite)), address + element2sprite32x32(sprite)*32, 256); // update one sprite
+}
diff --git a/snes-examples/maps/DynamicMap/map32x32.h b/snes-examples/maps/DynamicMap/map32x32.h
new file mode 100644
index 000000000..7a6d51c81
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/map32x32.h
@@ -0,0 +1,22 @@
+#ifndef _MAP32X32_H
+#define _MAP32X32_H
+
+// max scroll area (visible area is 16 x 14)
+#define MAX_SCROLL_WIDTH_32x32 32*16 - 16*16 // 256
+#define MAX_SCROLL_HEIGHT_32x32 32*16 - 14*16 // 288
+
+void setSpriteMap32x32(u16* spritemap, u16 spritemap_len);
+u16* getSpriteMap32x32();
+u16 getSpriteMap32x32_length();
+void initSpriteMap32x32();
+void drawSpriteRaw32x32(u8 x, u8 y, u16 sprite);
+u16 getSpriteRaw32x32(u8 x, u8 y);
+void drawSprite32x32(u8 x, u8 y, u16 sprite);
+u16 getSprite32x32(u8 x, u8 y);
+u16 element2sprite32x32(u8 elem);
+u16 calculateSpriteIndex32x32(u8 elem);
+u16 calculateSpritesLength32x32(u16 number_of_sprites);
+void screenRefreshPos32x32(u8 x, u8 y, u16 address);
+void updateSprite32x32(u8 *source, u16 address, u16 sprite);
+
+#endif
diff --git a/snes-examples/maps/DynamicMap/map64x64.c b/snes-examples/maps/DynamicMap/map64x64.c
new file mode 100644
index 000000000..936cfa143
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/map64x64.c
@@ -0,0 +1,162 @@
+#include
+#include
+
+u16 spritemap64x64_len = 0;
+u16* spritemap64x64;
+
+void setSpriteMap64x64(u16* spritemap, u16 spritemap_len)
+{
+ spritemap64x64 = spritemap;
+ spritemap64x64_len = spritemap_len;
+}
+
+u16* getSpriteMap64x64(u16* spritemap)
+{
+ return spritemap64x64;
+}
+
+u16 getSpriteMap64x64_length()
+{
+ return spritemap64x64_len;
+}
+
+void initSpriteMap64x64()
+{
+ u16 i;
+ for (i = 0; i < spritemap64x64_len; i++)
+ {
+ spritemap64x64[i] = 0;
+ }
+}
+
+/**
+ * Draw a sprite on a 64 x 64 map. The map consists of four 32 x 32 maps, which are ordered this way:
+ * Top left, top right, bottom left, bottom right.
+ * The top left 32 x 32 map begins with y = 0.
+ * The top right 32 x 32 map begins with y = 32.
+ * The bottom left 32 x 32 map begins with y = 64.
+ * The bottom right 32 x 32 map begins with y = 96.
+ *
+ * @param x 0 - 32
+ * @param y 0 - 96
+ */
+void drawSpriteRaw64x64(u8 x, u8 y, u16 sprite)
+{
+ // i = colsMax * row + col;
+ u16 i = 32 * y + x;
+ spritemap64x64[i] = sprite;
+}
+
+u16 getSpriteRaw64x64(u8 x, u8 y)
+{
+ // i = colsMax * row + col;
+ u16 i = 32 * y + x;
+ return spritemap64x64[i];
+}
+
+/**
+ * Draw a sprite on a 64 x 64 map.
+ *
+ * @param x column 0 - 63
+ * @param y row 0 - 63
+ */
+void drawSprite64x64(u8 x, u8 y, u16 sprite)
+{
+ if (x < 32 && y < 32)
+ drawSpriteRaw64x64(x, y, sprite); // top left
+ else if (x < 64 && y < 32)
+ drawSpriteRaw64x64(x - 32, y + 32, sprite); // top right
+ else if (x < 32 && y < 64)
+ drawSpriteRaw64x64(x, y + 32, sprite); // bottom left
+ else if (x < 64 && y < 64)
+ drawSpriteRaw64x64(x - 32, y + 64, sprite); // bottom right
+ else
+ consoleNocashMessage("drawSprite64x64: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+}
+
+u16 getSprite64x64(u8 x, u8 y)
+{
+ if (x < 32 && y < 32)
+ return getSpriteRaw64x64(x, y); // top left
+ else if (x < 64 && y < 32)
+ return getSpriteRaw64x64(x - 32, y + 32); // top right
+ else if (x < 32 && y < 64)
+ return getSpriteRaw64x64(x, y + 32); // bottom left
+ else if (x < 64 && y < 64)
+ return getSpriteRaw64x64(x - 32, y + 64); // bottom right
+ else
+ consoleNocashMessage("getSprite64x64: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+}
+
+/**
+ * Convert element to its sprite index.
+ *
+ * @param elem gfx tile no 0 - (number_of_sprites - 1)
+ * @return sprite index
+ */
+u16 element2sprite64x64(u8 elem)
+{
+ // for BG1_TSIZE16x16
+ u8 mult = elem / 8;
+ return (elem * 2) + (mult * 16);
+
+ // alternative: maybe easier to understand
+ //return calculateSpriteIndex64x64(elem) * 2 / 128;
+}
+
+u16 calculateSpriteIndex64x64(u8 elem)
+{
+ // BG1_TSIZE16x16: Sprite top and bottom have a distance of 1024 bytes.
+ // To prevent that a sprite top overwrites an already existing sprite bottom,
+ // this correction is required:
+ u16 index = elem * 128;
+ u8 mult = index / 1024;
+ index += 1024 * mult;
+
+ return index;
+}
+
+u16 calculateSpritesLength64x64(u16 number_of_sprites)
+{
+ // sprite bottom is shifted by 1024, sprite bottom length is 128
+ return calculateSpriteIndex64x64(number_of_sprites - 1) + 1024 + 128;
+
+ // NOTE: Sometimes identical with (256 * number_of_sprites), but not always!
+}
+
+/**
+ * Refresh one sprite position. Might require to call WaitForVBlank() previously.
+ * @param x column
+ * @param y row
+ * @param address vram base address to copy to
+ */
+void screenRefreshPos64x64(u8 x, u8 y, u16 address)
+{
+ u16 offset = 0;
+ if (x < 32 && y < 32)
+ offset = x + y*32;
+ else if (x < 64 && y < 32)
+ offset = 32*32 + (x-32) + y*32;
+ else if (x < 32 && y < 64)
+ offset = 32*32*2 + x + (y-32)*32;
+ else if (x < 64 && y < 64)
+ offset = 32*32*3 + (x-32) + (y-32)*32;
+ else
+ consoleNocashMessage("screenRefreshPos64x64: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+
+ dmaCopyVram((u8 *) (spritemap64x64 + offset), address + offset, 256);
+}
+
+/**
+ * Update sprite after updating its graphics. Might require to call WaitForVBlank() previously.
+ * Intended for a 16x16 sprite on a 64x64 map.
+ *
+ * @param source the source base to copy from
+ * @param address base vram address to copy to
+ */
+void updateSprite64x64(u8 *source, u16 address, u16 sprite)
+{
+ //dmaCopyVram((u8*) source, address, 256 * number_of_sprites); // update all sprites
+ dmaCopyVram((u8*) (source + calculateSpriteIndex64x64(sprite)), address + element2sprite64x64(sprite)*32, 128); // update sprite top
+ dmaCopyVram((u8*) (source + calculateSpriteIndex64x64(sprite) + 1024), address + element2sprite64x64(sprite)*32 + 1024/2, 128); // update sprite bottom
+}
diff --git a/snes-examples/maps/DynamicMap/map64x64.h b/snes-examples/maps/DynamicMap/map64x64.h
new file mode 100644
index 000000000..f7a07e134
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/map64x64.h
@@ -0,0 +1,21 @@
+#ifndef _MAP64X64_H
+#define _MAP64X64_H
+
+#define MAX_SCROLL_WIDTH_64x64 64*16 - 16*16 // 768
+#define MAX_SCROLL_HEIGHT_64x64 64*16 - 14*16 // 800
+
+void setSpriteMap64x64(u16* spritemap, u16 spritemap_len);
+u16* getSpriteMap64x64(u16* spritemap);
+u16 getSpriteMap64x64_length();
+void initSpriteMap64x64();
+void drawSpriteRaw64x64(u8 x, u8 y, u16 sprite);
+u16 getSpriteRaw64x64(u8 x, u8 y);
+void drawSprite64x64(u8 x, u8 y, u16 sprite);
+u16 getSprite64x64(u8 x, u8 y);
+u16 element2sprite64x64(u8 elem);
+u16 calculateSpriteIndex64x64(u8 elem);
+u16 calculateSpritesLength64x64(u16 number_of_sprites);
+void screenRefreshPos64x64(u8 x, u8 y, u16 address);
+void updateSprite64x64(u8 *source, u16 address, u16 sprite);
+
+#endif
diff --git a/snes-examples/maps/DynamicMap/maputil.c b/snes-examples/maps/DynamicMap/maputil.c
new file mode 100644
index 000000000..dc7774ba1
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/maputil.c
@@ -0,0 +1,45 @@
+#include
+
+/**
+ * Refresh tile of a spritemap. Might require to call WaitForVBlank() previously.
+ *
+ * @param u16* spritemap 32x32 or 64x64 sprite map
+ * @param tile 0-3
+ * @param address vram base address to copy to
+ */
+void screenRefreshTile(u16* spritemap, u8 tile, u16 address)
+{
+ switch(tile)
+ {
+ case 0:
+ dmaCopyVram((u8 *) (spritemap), address, 2048); // top left map
+ break;
+ case 1:
+ dmaCopyVram((u8 *) (spritemap + 1024), address + 1024, 2048); // top right map
+ break;
+ case 2:
+ dmaCopyVram((u8 *) (spritemap + 1024*2), address + 1024*2, 2048); // bottom left map
+ break;
+ case 3:
+ dmaCopyVram((u8 *) (spritemap + 1024*3), address + 1024*3, 2048); // bottom right map
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Refresh spritemap.
+ *
+ * @param u16* spritemap 32x32 or 64x64 sprite map
+ * @param address vram base address to copy to
+ */
+void screenRefresh(u16* spritemap, u16 address)
+{
+ WaitForVBlank();
+ screenRefreshTile(spritemap, 0, address);
+ screenRefreshTile(spritemap, 1, address);
+ WaitForVBlank(); // required, otherwise screen not updated completely
+ screenRefreshTile(spritemap, 2, address);
+ screenRefreshTile(spritemap, 3, address);
+}
diff --git a/snes-examples/maps/DynamicMap/maputil.h b/snes-examples/maps/DynamicMap/maputil.h
new file mode 100644
index 000000000..d8c312cb2
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/maputil.h
@@ -0,0 +1,7 @@
+#ifndef _MAPUTIL_H
+#define _MAPUTIL_H
+
+void screenRefreshTile(u16* spritemap, u8 tile, u16 address);
+void screenRefresh(u16* spritemap, u16 address);
+
+#endif
diff --git a/snes-examples/maps/DynamicMap/pvsneslibfont.bmp b/snes-examples/maps/DynamicMap/pvsneslibfont.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..6fba7488608d5d0d02e9b49dceb749c6ac246807
GIT binary patch
literal 7222
zcmeHIL6Q?e44V`jcmf9=zzg;P-1+}=7E7|+cJEA2t7xQudmZm|fFNpC_bglCtRYse5q
z;rjsZpYS5pSer!L{T4|{S>~&We9U9|#YBjDO}k`nxE8r|!c!>^Z<#Mr?F)ZAonjDITw=
zN)UY$(DgK_4M&;_6tOJ0$7-wW8x<2tvGZ~QEYiPkwTNMrNR(@@gk+_K#{?DW$Ucz*
zP|=cyix!oxxvm|Xu0iH=4v*GEjTh*q*WPR2ze(wtohN6
z!sLNNn2mu8%Z?~fxMoCMzHVMcFKDI5qFx$aAHet>)YwYcw?$d=1?x!6Je42j$d4~w
zOpLAf;S~LNxE3Qxk_u$=zpAAI-Ey1cyVV*Z_?*-ny9}xgD7yOTbAk}>9}xcP0Vob@2(^_wSf?B<
zq9!<2e@{U0XBlG7+Wr|NIuHqTo5}&@Y3k}<7CurUg1GZBPLO-ntZ-!
z+kJ=zC~9KgW8ms*LUP^5jhI((SrHWd#2Hu;;{NFec6#bQ;0hxQ3*Fac*5WL`vOh^6
ztYOu%LKf<$fqnLv3kc?kBR&~EjWD3DC9DNjYxfi#bM)E!5T1RYi-*2G
z_Sn6|^p0d2Dj#(9z0rH(`E{^g-wTp#Bs+H?p4~EYA_=RcM}FeJ^vZZ*0VI$M);$8T
z*>y|-l+bTcD*$B+had6d9Nx)nZfV;PI(VGz9*&;hF20Q0t+Y7--KKy?MxGglzQgc!
zt#SPQB2|ZH9wJ0Rjb2Xh{8my@IE}>>Wx0-;yg+vSbMq$zb
d%ZJ_8suW2TxPX10iqFeaxd&_)o8Ubi#~)~B4uAjv
literal 0
HcmV?d00001
diff --git a/snes-examples/maps/DynamicMap/ram.asm b/snes-examples/maps/DynamicMap/ram.asm
new file mode 100644
index 000000000..2f03ee1d2
--- /dev/null
+++ b/snes-examples/maps/DynamicMap/ram.asm
@@ -0,0 +1,8 @@
+.include "hdr.asm"
+
+; need ramsection to prevent array colliding with 0x7E8000 RAM!
+
+.base 0
+.ramsection "asm_vars" BANK $7f SLOT 2 ; 0x2000
+ sprites_ram: dsb 0x4000 ; 0x40 * 256
+.ends
diff --git a/snes-examples/maps/DynamicMap/sprite16.bmp b/snes-examples/maps/DynamicMap/sprite16.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..632932b859abb779f148817899d948f789db2487
GIT binary patch
literal 368
zcmX|*F>V4e5JhLkHrVV6MQN!cA(1x4HWXB8(j?*p>CslX0B7I|NI4ZpG0%g=?0)b3
zzkj~x@HMM=ojAAPr9&mVZv1~89$2F^R36#U{D3RCiTqvurPeCbG|A@eUB2ft#wz3f
zS3W+Em|AJ8=Z7YQ*mw-#v4@VSsFpN3ZSImNH0Bhu<~$5JD2LJ#7
literal 0
HcmV?d00001
diff --git a/snes-examples/maps/DynamicMap/sprite16_64x64.bmp b/snes-examples/maps/DynamicMap/sprite16_64x64.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..632932b859abb779f148817899d948f789db2487
GIT binary patch
literal 368
zcmX|*F>V4e5JhLkHrVV6MQN!cA(1x4HWXB8(j?*p>CslX0B7I|NI4ZpG0%g=?0)b3
zzkj~x@HMM=ojAAPr9&mVZv1~89$2F^R36#U{D3RCiTqvurPeCbG|A@eUB2ft#wz3f
zS3W+Em|AJ8=Z7YQ*mw-#v4@VSsFpN3ZSImNH0Bhu<~$5JD2LJ#7
literal 0
HcmV?d00001
From 901006fe6b213d3c5774c3a5abbcadd629ec2de3 Mon Sep 17 00:00:00 2001
From: revvv <8734113+revvv@users.noreply.github.com>
Date: Sun, 21 Jul 2024 17:31:49 +0200
Subject: [PATCH 2/6] Delete .settings directory
---
.settings/language.settings.xml | 25 -------------------------
1 file changed, 25 deletions(-)
delete mode 100644 .settings/language.settings.xml
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
deleted file mode 100644
index d52ba7087..000000000
--- a/.settings/language.settings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
From 1e2ff73ffb241a691e880bc00497f86f7bac6976 Mon Sep 17 00:00:00 2001
From: revvv <8734113+revvv@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:05:18 +0200
Subject: [PATCH 3/6] rename param, update comments
---
snes-examples/maps/DynamicMap/map32x32.c | 6 ++++--
snes-examples/maps/DynamicMap/map64x64.c | 8 +++++---
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/snes-examples/maps/DynamicMap/map32x32.c b/snes-examples/maps/DynamicMap/map32x32.c
index 8079fb5a2..132473186 100644
--- a/snes-examples/maps/DynamicMap/map32x32.c
+++ b/snes-examples/maps/DynamicMap/map32x32.c
@@ -64,6 +64,7 @@ getSpriteRaw32x32(u8 x, u8 y)
*
* @param x column 0 - 31
* @param y row 0 - 31
+ * @param sprite sprite
*/
void drawSprite32x32(u8 x, u8 y, u16 sprite)
{
@@ -143,9 +144,10 @@ void screenRefreshPos32x32(u8 x, u8 y, u16 address)
*
* @param source the source base to copy from
* @param address base vram address to copy to
+ * @param elem gfx tile no 0 - (number_of_sprites - 1)
*/
-void updateSprite32x32(u8 *source, u16 address, u16 sprite)
+void updateSprite32x32(u8 *source, u16 address, u16 elem)
{
//dmaCopyVram((u8*) source, address, 256 * number_of_sprites); // update all sprites
- dmaCopyVram((u8*) (source + calculateSpriteIndex32x32(sprite)), address + element2sprite32x32(sprite)*32, 256); // update one sprite
+ dmaCopyVram((u8*) (source + calculateSpriteIndex32x32(elem)), address + element2sprite32x32(elem)*32, 256); // update one sprite
}
diff --git a/snes-examples/maps/DynamicMap/map64x64.c b/snes-examples/maps/DynamicMap/map64x64.c
index 936cfa143..d318bec55 100644
--- a/snes-examples/maps/DynamicMap/map64x64.c
+++ b/snes-examples/maps/DynamicMap/map64x64.c
@@ -59,6 +59,7 @@ u16 getSpriteRaw64x64(u8 x, u8 y)
*
* @param x column 0 - 63
* @param y row 0 - 63
+ * @param sprite sprite
*/
void drawSprite64x64(u8 x, u8 y, u16 sprite)
{
@@ -153,10 +154,11 @@ void screenRefreshPos64x64(u8 x, u8 y, u16 address)
*
* @param source the source base to copy from
* @param address base vram address to copy to
+ * @param elem gfx tile no 0 - (number_of_sprites - 1)
*/
-void updateSprite64x64(u8 *source, u16 address, u16 sprite)
+void updateSprite64x64(u8 *source, u16 address, u16 elem)
{
//dmaCopyVram((u8*) source, address, 256 * number_of_sprites); // update all sprites
- dmaCopyVram((u8*) (source + calculateSpriteIndex64x64(sprite)), address + element2sprite64x64(sprite)*32, 128); // update sprite top
- dmaCopyVram((u8*) (source + calculateSpriteIndex64x64(sprite) + 1024), address + element2sprite64x64(sprite)*32 + 1024/2, 128); // update sprite bottom
+ dmaCopyVram((u8*) (source + calculateSpriteIndex64x64(elem)), address + element2sprite64x64(elem)*32, 128); // update sprite top
+ dmaCopyVram((u8*) (source + calculateSpriteIndex64x64(elem) + 1024), address + element2sprite64x64(elem)*32 + 1024/2, 128); // update sprite bottom
}
From 435f35e914f954b23b2c5243ea28e6a692fd7712 Mon Sep 17 00:00:00 2001
From: revvv <8734113+revvv@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:09:47 +0200
Subject: [PATCH 4/6] add comment
---
snes-examples/maps/DynamicMap/map64x64.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/snes-examples/maps/DynamicMap/map64x64.h b/snes-examples/maps/DynamicMap/map64x64.h
index f7a07e134..8ae933e80 100644
--- a/snes-examples/maps/DynamicMap/map64x64.h
+++ b/snes-examples/maps/DynamicMap/map64x64.h
@@ -1,6 +1,7 @@
#ifndef _MAP64X64_H
#define _MAP64X64_H
+// max scroll area (visible area is 16 x 14)
#define MAX_SCROLL_WIDTH_64x64 64*16 - 16*16 // 768
#define MAX_SCROLL_HEIGHT_64x64 64*16 - 14*16 // 800
From 66900441df1f31df9ccf1f99ba8242d2257c6ffc Mon Sep 17 00:00:00 2001
From: revvv <8734113+revvv@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:11:30 +0200
Subject: [PATCH 5/6] rename param
---
snes-examples/maps/DynamicMap/map32x32.h | 2 +-
snes-examples/maps/DynamicMap/map64x64.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/snes-examples/maps/DynamicMap/map32x32.h b/snes-examples/maps/DynamicMap/map32x32.h
index 7a6d51c81..1e8cc03bb 100644
--- a/snes-examples/maps/DynamicMap/map32x32.h
+++ b/snes-examples/maps/DynamicMap/map32x32.h
@@ -17,6 +17,6 @@ u16 element2sprite32x32(u8 elem);
u16 calculateSpriteIndex32x32(u8 elem);
u16 calculateSpritesLength32x32(u16 number_of_sprites);
void screenRefreshPos32x32(u8 x, u8 y, u16 address);
-void updateSprite32x32(u8 *source, u16 address, u16 sprite);
+void updateSprite32x32(u8 *source, u16 address, u16 elem);
#endif
diff --git a/snes-examples/maps/DynamicMap/map64x64.h b/snes-examples/maps/DynamicMap/map64x64.h
index 8ae933e80..5ae703f86 100644
--- a/snes-examples/maps/DynamicMap/map64x64.h
+++ b/snes-examples/maps/DynamicMap/map64x64.h
@@ -17,6 +17,6 @@ u16 element2sprite64x64(u8 elem);
u16 calculateSpriteIndex64x64(u8 elem);
u16 calculateSpritesLength64x64(u16 number_of_sprites);
void screenRefreshPos64x64(u8 x, u8 y, u16 address);
-void updateSprite64x64(u8 *source, u16 address, u16 sprite);
+void updateSprite64x64(u8 *source, u16 address, u16 elem);
#endif
From 86e43b65198bcb30e821dafdc2b9b81ad271f981 Mon Sep 17 00:00:00 2001
From: revvv <8734113+revvv@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:18:18 +0200
Subject: [PATCH 6/6] add return in error case
---
snes-examples/maps/DynamicMap/map32x32.c | 3 +++
snes-examples/maps/DynamicMap/map64x64.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/snes-examples/maps/DynamicMap/map32x32.c b/snes-examples/maps/DynamicMap/map32x32.c
index 132473186..172684b98 100644
--- a/snes-examples/maps/DynamicMap/map32x32.c
+++ b/snes-examples/maps/DynamicMap/map32x32.c
@@ -91,7 +91,10 @@ u16 getSprite32x32(u8 x, u8 y)
else if (x < 32 && y < 32)
return getSpriteRaw32x32(x - 16, y + 32); // bottom right
else
+ {
consoleNocashMessage("drawSprite32x32: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+ return 0;
+ }
}
/**
diff --git a/snes-examples/maps/DynamicMap/map64x64.c b/snes-examples/maps/DynamicMap/map64x64.c
index d318bec55..4662ed0a2 100644
--- a/snes-examples/maps/DynamicMap/map64x64.c
+++ b/snes-examples/maps/DynamicMap/map64x64.c
@@ -86,7 +86,10 @@ u16 getSprite64x64(u8 x, u8 y)
else if (x < 64 && y < 64)
return getSpriteRaw64x64(x - 32, y + 64); // bottom right
else
+ {
consoleNocashMessage("getSprite64x64: out of bounds: x=%u,y=%u\n", (int) x, (int) y);
+ return 0;
+ }
}
/**