From d82008dac020b1216b708e11d2c2471c60e5db02 Mon Sep 17 00:00:00 2001 From: enne2 Date: Mon, 22 Jun 2026 19:21:19 +0200 Subject: [PATCH] Optimize map rendering and implement dynamic fog of war --- engine.c | 63 ++++++++++++++++++----- generate_assets.py | 110 ++++++++++++++++++++++++++-------------- hello_iso_gb.png | Bin 1490 -> 1335 bytes opencv_analyze_tiles.py | 2 +- test_movement.py | 34 +++++++++---- tiles.c | 102 +++++++++++++++++++++++++++++++++++-- tiles.h | 8 +-- tiles.png | Bin 1553 -> 2184 bytes 8 files changed, 252 insertions(+), 67 deletions(-) diff --git a/engine.c b/engine.c index 87698be..cf664a3 100644 --- a/engine.c +++ b/engine.c @@ -8,7 +8,7 @@ #include "tiles.h" #include "player.h" -#define MAP_SIZE 7 +#define MAP_SIZE 15 uint8_t maze[MAP_SIZE][MAP_SIZE]; static uint8_t map_buffer[32 * 32]; @@ -37,9 +37,9 @@ static void generate_maze(void) { // Clear maze (all 0/walls) memset(maze, 0, sizeof(maze)); - // Stack for backtracking (3x3 grid has 9 odd cells max) - uint8_t stack_x[9]; - uint8_t stack_y[9]; + // Stack for backtracking (7x7 grid of odd cells has 49 cells max) + uint8_t stack_x[49]; + uint8_t stack_y[49]; uint8_t stack_ptr = 0; // Start at (1, 1) @@ -59,7 +59,7 @@ static void generate_maze(void) { nx[count] = cx; ny[count] = cy - 2; count++; } // Down - if (cy <= 3 && maze[cy + 2][cx] == 0) { + if (cy <= MAP_SIZE - 4 && maze[cy + 2][cx] == 0) { nx[count] = cx; ny[count] = cy + 2; count++; } // Left @@ -67,7 +67,7 @@ static void generate_maze(void) { nx[count] = cx - 2; ny[count] = cy; count++; } // Right - if (cx <= 3 && maze[cy][cx + 2] == 0) { + if (cx <= MAP_SIZE - 4 && maze[cy][cx + 2] == 0) { nx[count] = cx + 2; ny[count] = cy; count++; } @@ -98,15 +98,35 @@ static void generate_maze(void) { } } -static void draw_map(void) { +static void draw_map(uint8_t center_x, uint8_t center_y) { // Fill entire map with tile index 0 (completely black empty tile) memset(map_buffer, 0, sizeof(map_buffer)); - // Draw logical map path tiles - for (int8_t ly = 0; ly < MAP_SIZE; ly++) { - for (int8_t lx = 0; lx < MAP_SIZE; lx++) { + int8_t start_x = center_x - 3; + if (start_x < 0) start_x = 0; + int8_t end_x = center_x + 3; + if (end_x >= MAP_SIZE) end_x = MAP_SIZE - 1; + + int8_t start_y = center_y - 3; + if (start_y < 0) start_y = 0; + int8_t end_y = center_y + 3; + if (end_y >= MAP_SIZE) end_y = MAP_SIZE - 1; + + // Draw logical map path tiles in the visible 7x7 window + for (int8_t ly = start_y; ly <= end_y; ly++) { + for (int8_t lx = start_x; lx <= end_x; lx++) { if (maze[ly][lx] == 1) { - // Centering math for 7x7 map on 32x32 background map + // Calculate Chebyshev distance to center + int8_t dx = lx - center_x; + int8_t dy = ly - center_y; + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + int8_t dist = (dx > dy) ? dx : dy; + + // Hide tiles at distance > 3 (Fog of War) + if (dist > 3) continue; + + // Centering math for 15x15 map on 32x32 background map int8_t iso_x = (lx - ly) * 2 + 12; int8_t iso_y = (lx + ly) * 1 + 2; @@ -120,7 +140,16 @@ static void draw_map(void) { uint8_t has_br = (lx < MAP_SIZE - 1 && maze[ly][lx + 1] == 1); uint8_t mask = (has_tl ? 1 : 0) | (has_tr ? 2 : 0) | (has_bl ? 4 : 0) | (has_br ? 8 : 0); - uint8_t v = is_alt ? (16 + mask) : mask; + + // Determine variation style based on lighting distance + uint8_t v; + if (dist == 3) { + // Darker variants (Tile 1 Dark starting at 32, Tile 2 Dark starting at 48) + v = is_alt ? (48 + mask) : (32 + mask); + } else { + // Normal variants + v = is_alt ? (16 + mask) : mask; + } for (uint8_t y = 0; y < 2; y++) { for (uint8_t x = 0; x < 4; x++) { @@ -175,7 +204,7 @@ void engine_init(void) { set_bkg_data(0, tiles_TILE_COUNT, tiles_tiles); set_sprite_data(0, player_TILE_COUNT, player_tiles); - draw_map(); + draw_map(player_lx, player_ly); update_camera(); update_player_sprite(); } @@ -212,6 +241,11 @@ void engine_update(uint8_t keys, uint8_t prev_keys) { // Update walk animation frame (alternate frame every 4 ticks) update_player_sprite(); + // Update visible tiles (fog of war center) mid-way through movement + if (move_progress == 8) { + draw_map(target_lx, target_ly); + } + if (move_progress == 16) { is_moving = 0; player_lx = target_lx; @@ -224,6 +258,9 @@ void engine_update(uint8_t keys, uint8_t prev_keys) { scroll_y = final_py - 72; move_bkg(scroll_x, scroll_y); + // Draw map at final coordinates + draw_map(player_lx, player_ly); + // Set player to idle stand frame update_player_sprite(); } diff --git a/generate_assets.py b/generate_assets.py index b2bb766..f807ec7 100644 --- a/generate_assets.py +++ b/generate_assets.py @@ -10,58 +10,94 @@ PALETTE = [ 0, 0, 0 # 3 ] + [0] * (256 * 3 - 12) -def draw_autotile(draw, y_offset, is_alt, mask): +def draw_autotile(draw, y_offset, is_alt, mask, is_dark=False): # Determine the neighbor fill color # Tile 1 (Normal, is_alt=False) neighbors should match Tile 2 (Alt) body color: 1 (Light Gray) # Tile 2 (Alt, is_alt=True) neighbors should match Tile 1 (Normal) body color: 0 (White) - neighbor_color = 0 if is_alt else 1 - - # 4 corners - # Bit 0 (1): Top-Left - # Bit 1 (2): Top-Right - # Bit 2 (4): Bottom-Left - # Bit 3 (8): Bottom-Right - - tl_color = neighbor_color if (mask & 1) else 3 - tr_color = neighbor_color if (mask & 2) else 3 - dl_color = neighbor_color if (mask & 4) else 3 - dr_color = neighbor_color if (mask & 8) else 3 - - # Draw corners - draw.polygon([(0, y_offset), (15, y_offset), (0, y_offset + 7)], fill=tl_color) - draw.polygon([(16, y_offset), (31, y_offset), (31, y_offset + 7)], fill=tr_color) - draw.polygon([(0, y_offset + 8), (0, y_offset + 15), (15, y_offset + 15)], fill=dl_color) - draw.polygon([(31, y_offset + 8), (31, y_offset + 15), (16, y_offset + 15)], fill=dr_color) - - # Draw the main diamond shape on top - points = [(15, y_offset), (31, y_offset + 7), (16, y_offset + 15), (0, y_offset + 8)] - inner = [(15, y_offset + 4), (27, y_offset + 7), (16, y_offset + 11), (4, y_offset + 8)] - - if not is_alt: - # Tile 1: Normal floor (body is White, inner is Light Gray) - draw.polygon(points, fill=0, outline=2) - draw.polygon(inner, fill=1, outline=2) + if not is_dark: + neighbor_color = 0 if is_alt else 1 + + tl_color = neighbor_color if (mask & 1) else 3 + tr_color = neighbor_color if (mask & 2) else 3 + dl_color = neighbor_color if (mask & 4) else 3 + dr_color = neighbor_color if (mask & 8) else 3 + + # Draw corners + draw.polygon([(0, y_offset), (15, y_offset), (0, y_offset + 7)], fill=tl_color) + draw.polygon([(16, y_offset), (31, y_offset), (31, y_offset + 7)], fill=tr_color) + draw.polygon([(0, y_offset + 8), (0, y_offset + 15), (15, y_offset + 15)], fill=dl_color) + draw.polygon([(31, y_offset + 8), (31, y_offset + 15), (16, y_offset + 15)], fill=dr_color) + + # Draw the main diamond shape on top + points = [(15, y_offset), (31, y_offset + 7), (16, y_offset + 15), (0, y_offset + 8)] + inner = [(15, y_offset + 4), (27, y_offset + 7), (16, y_offset + 11), (4, y_offset + 8)] + + if not is_alt: + # Tile 1: Normal floor (body is White, inner is Light Gray) + draw.polygon(points, fill=0, outline=2) + draw.polygon(inner, fill=1, outline=2) + else: + # Tile 2: Alt floor (body is Light Gray, inner is White) + draw.polygon(points, fill=1, outline=2) + draw.polygon(inner, fill=0, outline=2) else: - # Tile 2: Alt floor (body is Light Gray, inner is White) - draw.polygon(points, fill=1, outline=2) - draw.polygon(inner, fill=0, outline=2) + # Darker version: Shift colors down + # White (0) -> Light Gray (1) + # Light Gray (1) -> Dark Gray (2) + # Dark Gray (2) -> Black (3) + # Black (3) -> Black (3) + neighbor_color = 1 if is_alt else 2 + + tl_color = neighbor_color if (mask & 1) else 3 + tr_color = neighbor_color if (mask & 2) else 3 + dl_color = neighbor_color if (mask & 4) else 3 + dr_color = neighbor_color if (mask & 8) else 3 + + # Draw corners + draw.polygon([(0, y_offset), (15, y_offset), (0, y_offset + 7)], fill=tl_color) + draw.polygon([(16, y_offset), (31, y_offset), (31, y_offset + 7)], fill=tr_color) + draw.polygon([(0, y_offset + 8), (0, y_offset + 15), (15, y_offset + 15)], fill=dl_color) + draw.polygon([(31, y_offset + 8), (31, y_offset + 15), (16, y_offset + 15)], fill=dr_color) + + # Draw the main diamond shape on top + points = [(15, y_offset), (31, y_offset + 7), (16, y_offset + 15), (0, y_offset + 8)] + inner = [(15, y_offset + 4), (27, y_offset + 7), (16, y_offset + 11), (4, y_offset + 8)] + + if not is_alt: + # Tile 1 Dark: body is Light Gray (1), inner is Dark Gray (2), outline is Black (3) + draw.polygon(points, fill=1, outline=3) + draw.polygon(inner, fill=2, outline=3) + else: + # Tile 2 Dark: body is Dark Gray (2), inner is Light Gray (1), outline is Black (3) + draw.polygon(points, fill=2, outline=3) + draw.polygon(inner, fill=1, outline=3) def generate_tiles(): - # 32 variants total: + # 64 variants total: # 0..15: Tile 1 (Normal Floor) with masks 0..15 # 16..31: Tile 2 (Alt Floor) with masks 0..15 - # Height is 8 pixels (black spacer) + 32 variants * 16 pixels = 520 pixels - img = Image.new("P", (32, 520), 3) + # 32..47: Tile 1 Dark (Normal Floor Dark) with masks 0..15 + # 48..63: Tile 2 Dark (Alt Floor Dark) with masks 0..15 + # Height is 8 pixels (black spacer) + 64 variants * 16 pixels = 1032 pixels + img = Image.new("P", (32, 1032), 3) img.putpalette(PALETTE) draw = ImageDraw.Draw(img) # Draw Tile 1 variants (start at y=8) for mask in range(16): - draw_autotile(draw, 8 + mask * 16, False, mask) + draw_autotile(draw, 8 + mask * 16, False, mask, False) - # Draw Tile 2 variants (start at y=8 + 256 = 264) + # Draw Tile 2 variants (start at y=264) for mask in range(16): - draw_autotile(draw, 264 + mask * 16, True, mask) + draw_autotile(draw, 264 + mask * 16, True, mask, False) + + # Draw Tile 1 Dark variants (start at y=520) + for mask in range(16): + draw_autotile(draw, 520 + mask * 16, False, mask, True) + + # Draw Tile 2 Dark variants (start at y=776) + for mask in range(16): + draw_autotile(draw, 776 + mask * 16, True, mask, True) img.save("tiles.png") diff --git a/hello_iso_gb.png b/hello_iso_gb.png index a652d87f374c9e3bc04f79bb4afa524a0c7cc8cb..1cf90e17bece3755de07b67df62434ac111a014e 100644 GIT binary patch literal 1335 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62OE&=-ld+SLu;jrt6Yid9TphAvl1}8Y^(nUBJ?k&A<;**Atfs*5m<^A@r)B$?C8Qah zx)>B)8zv|@cnB&i;SdO7;m~Ai5gF{lSLDCSzPS3ftoqmI=g*hF+4rSKw1C-u-;Mi; zvW#IHR?DrvUnZV>#<^C#>WE^6JkU?`T5?Q$FJGSj{`+o_>f!^u6+)Zjfj)iS!1^Zf zd)Yd_CrlE(z<=I6se?u0VO$2^(Tsm=qQ7VTfA4dU%POdY zWrpHbtz}CN74yH()?Q>;*uxT`V16W`VqyAWwZdA%FZJielo<0S6z{!|`uJq5W3b~q zT^FV`2ELPb#;rg2A!+qpv4!5w>6{y1Gepm@+xYz;|KXIj?;k&I{JHJCK;rc4jLGc| zN0}4zFCP<#WCcjd|tRk!|4QDZ(c^SHL{^{m9u z6TF6Eaqn--UkYhhdi{D*)coV!tvkf-MQ*!))umzaxyQbjQ=V1wwV5CKHv1aWokhffO~Xci!5czJC%JAM zwuyUb17t{4f1kIM!!>Pzvpv^t|t-tNJJ~EYF z;9aXYrEQ?)a-3C}7GI+ZBxvXm|jTQQmTTxpvrEL;BqnVK{oNs?dKfLezc|Y&xd7tBEDR6` zgi&x1J{peIuodg+!X9iPF%Sry@?gAQ47E~TIdT4u7kWRG{?~{|3ujx8!#zG@%Uc1Y z4xs`+8`NjZ;ESD7sNfhW$yZ$HoVetQz^vD&BcAFa{S36SH=$5CJ-ui&y4J=f$j`Sp zn_;8#Z55_K`i8?(N~Ll}27)GUI+_iwnzCa$M9U;Al*sQRJ*|@tZyh<0FHF(*(S_GF z^miz)o0*YmR-MPoZoJ1fY3bTRSqz)pi+rP;{<+mlRXh~L2{0FFZ$@`NByu{fN2BIN zTg@=S8g1v|-+$0sU|YGAe$r?(%c%*K`Nn$!!ntuf-0zRe6B855`ln`8ZG<`-v3nYy zxm$6jb)0i5F%g7@YeGAhmzI_mH407cvVXTV+SQ&YlKbDjvvsrEDQ!%q8Id2;(IC#q z$T&!`)NkMLWm*ayb>&^3ljmf8F2Pcg@R+i&RqAdMfxy^h(3=Nl^U%E~KC zossRrk*fPfR%u%>m?j3hv8}s=s+h`Xus;mB*-h$(>>DWX^t5=8yVBGCP9BCw-K|dO zaNX8R81pO3`47%Tk3GUJ@Q6u0{pTN9e5lK#W9}s*y=x<$_|zVctD(-%&%YX<^Lw&w z8kt(=+f$%7Zs;a`SZ(!Oe{@+DxlXK@Wsol;Od>XqTs3pwF1=ygcEM$)X05@)c2bax zHrZ~+3OrJgh%2|eYt`Ls^EVk8S`~8lJSx>rA_$~~id$mVO`Uai_DN3jgbUBV|2nOZ zzM9%*nj-sh*m$1Ctz?qLs_4us8GgA3@{3P%>TQ46^6@q{7$!SV}V>4n>K)jLtSQojxe`_t~=?NHc`265vSD6`oW< zAF^lJO^$h7miKnaR|+ZKpzs7%5s7RaqD<}R>vEc~SFs=&4x};}sbZdkiRU>iCm#?y zBgs`~pYALY3$Wfjj?qOG5Sh33FO9!w>ROgN-ZjSF;!Irxh%yyrmcgcRo$T_A+ZIuz z{`j$vG_GLQ#kA=suyw2K!eTEOmN}|i45$fMO6Va#{r2P{z?xPk=>YCvYZ`i}qu$yZ zoW8fV9T{H^5r!IySdcPiy=MUX3}ER;JpD)mOjPl8$@BqUiXd;W?{Vwp1!m~2pxJoN z`mi~zxg~aPieFV4Si82MUN_GbKy80&h<_Iu0GTeM_l5n!b z^JV;@_4@B#uuQ&`)9|xA)D7+D$`o32;BK=t@^0`o)GLVh^cynPI(C&CrQ;)T35L~tbBlFvEnhnlu2mM zB=vu!^RKgnkn$!(kc9JnBVcw&Qh(Nwbl{Fm(ozf&MspZhu>y#U18>*iklI8cMBW9% zU>L&e&oE3z4)&?3PSc8)z0=5L@v#i<4JGwt1$<&y0Yqp7Ut3J*n|*5XA#S7ryC)3H zB*!uU4h#eIzOt-VfK^e0GNi^?bA(ay*t|`yld!-thRcuN_DX#ss`nRP_*Wx>_l4sd I{YlyX11U= 3 and parts[0] == 'DEF' and parts[1] == symbol_name: + return int(parts[2], 16) + except FileNotFoundError: + pass + raise ValueError(f"Symbol {symbol_name} not found in hello_iso.noi") + def main(): pyboy = PyBoy('hello_iso.gb', window='null', cgb=False) # Let the game boot and generate the maze for _ in range(60 * 2): pyboy.tick() + # Dynamically look up addresses + player_lx_addr = get_symbol_address('_player_lx') + player_ly_addr = get_symbol_address('_player_ly') + maze_addr = get_symbol_address('_maze') + # Read player position from RAM - # player_lx at 0xC4F4, player_ly at 0xC4F5 - lx = pyboy.memory[0xC4F4] - ly = pyboy.memory[0xC4F5] + lx = pyboy.memory[player_lx_addr] + ly = pyboy.memory[player_ly_addr] print(f"Initial player coordinates in RAM: lx={lx}, ly={ly}") - # Read maze array from RAM (7x7 starting at 0xC0B1) + # Read maze array from RAM (15x15 starting at maze_addr) + map_size = 15 maze = [] - for y in range(7): + for y in range(map_size): row = [] - for x in range(7): - val = pyboy.memory[0xC0B1 + y * 7 + x] + for x in range(map_size): + val = pyboy.memory[maze_addr + y * map_size + x] row.append(val) maze.append(row) @@ -42,7 +58,7 @@ def main(): pyboy.send_input(WindowEvent.RELEASE_ARROW_DOWN) for _ in range(30): pyboy.tick() - print(f"Player coordinates after DOWN: lx={pyboy.memory[0xC4F4]}, ly={pyboy.memory[0xC4F5]}") + print(f"Player coordinates after DOWN: lx={pyboy.memory[player_lx_addr]}, ly={pyboy.memory[player_ly_addr]}") # Try pressing Right (Down-Right) print("\nSimulating pressing RIGHT...") @@ -51,7 +67,7 @@ def main(): pyboy.send_input(WindowEvent.RELEASE_ARROW_RIGHT) for _ in range(30): pyboy.tick() - print(f"Player coordinates after RIGHT: lx={pyboy.memory[0xC4F4]}, ly={pyboy.memory[0xC4F5]}") + print(f"Player coordinates after RIGHT: lx={pyboy.memory[player_lx_addr]}, ly={pyboy.memory[player_ly_addr]}") pyboy.stop() diff --git a/tiles.c b/tiles.c index f065d66..1b423fe 100644 --- a/tiles.c +++ b/tiles.c @@ -18,7 +18,7 @@ const palette_color_t tiles_palettes[32] = { RGB8( 0, 0, 0), RGB8( 0, 0, 0), RGB8( 0, 0, 0), RGB8( 0, 0, 0) }; -const uint8_t tiles_tiles[528] = { +const uint8_t tiles_tiles[1040] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xf8,0xfe,0xe0,0xf8,0x80,0xe3, 0xfe,0xff,0xf8,0xfe,0xe0,0xf8,0x80,0xe0,0x00,0x83,0x03,0x1c,0x1f,0x60,0x7f,0x80, @@ -51,11 +51,43 @@ const uint8_t tiles_tiles[528] = { 0x30,0xce,0x0e,0x31,0x03,0x0c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xe0,0xe0,0x1e,0x7e,0x81,0x1f,0x60,0x07,0x18,0x01,0x06,0x00,0x01, 0x00,0x01,0x01,0x06,0x07,0x38,0x3e,0xc1,0xf8,0x06,0xe0,0x18,0x80,0x60,0x00,0x80, - 0x38,0xc6,0xe0,0x18,0x80,0x60,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + 0x38,0xc6,0xe0,0x18,0x80,0x60,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xf8,0xff,0xe3, + 0xff,0xff,0xff,0xfe,0xff,0xf8,0xff,0xe0,0xff,0x83,0xfc,0x1f,0xe0,0x7f,0x80,0xff, + 0xff,0xff,0xff,0x7f,0xff,0x1f,0xff,0x07,0xff,0x81,0x7f,0xf8,0x07,0xff,0x00,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0x8f,0x7f,0xf3, + 0xfe,0xcf,0xff,0xf1,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x00,0xff,0xe0,0xff,0xfe,0x1f,0xff,0x81,0xff,0xe0,0xff,0xf8,0xff,0xfe,0xff,0xff, + 0x01,0xff,0x07,0xfe,0x3f,0xf8,0xff,0xc1,0xff,0x07,0xff,0x1f,0xff,0x7f,0xff,0xff, + 0xff,0xc7,0xff,0x1f,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x01,0xff,0x07,0xfe,0x1f,0xf8,0x7f,0xe3, + 0x01,0xff,0x07,0xfe,0x1f,0xf8,0x7f,0xe0,0xff,0x83,0xfc,0x1f,0xe0,0x7f,0x80,0xff, + 0x80,0xff,0xe0,0x7f,0xf8,0x1f,0xfe,0x07,0xff,0x81,0x7f,0xf8,0x07,0xff,0x00,0xff, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xc0,0xff,0xf0,0x3f,0xfc,0x8f,0x7f,0xf3, + 0xfe,0xcf,0x3f,0xf1,0x0f,0xfc,0x03,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0x00,0xff,0xe0,0xff,0xfe,0x1f,0xff,0x81,0x7f,0xe0,0x1f,0xf8,0x07,0xfe,0x01,0xff, + 0x01,0xff,0x07,0xfe,0x3f,0xf8,0xff,0xc1,0xfe,0x07,0xf8,0x1f,0xe0,0x7f,0x80,0xff, + 0xfe,0xc7,0xf8,0x1f,0xe0,0x7f,0x80,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xf8,0xff,0xe3,0xff, + 0xff,0xff,0xfe,0xff,0xf8,0xff,0xe0,0xff,0x83,0xff,0x1f,0xfc,0x7f,0xe0,0xff,0x80, + 0xff,0xff,0x7f,0xff,0x1f,0xff,0x07,0xff,0x81,0xff,0xf8,0x7f,0xff,0x07,0xff,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0x8f,0xff,0xf3,0x7f, + 0xcf,0xfe,0xf1,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x00,0xff,0xe0,0x1f,0xfe,0x81,0xff,0xe0,0xff,0xf8,0xff,0xfe,0xff,0xff,0xff, + 0xff,0x01,0xfe,0x07,0xf8,0x3f,0xc1,0xff,0x07,0xff,0x1f,0xff,0x7f,0xff,0xff,0xff, + 0xc7,0xff,0x1f,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x01,0xfe,0x07,0xf8,0x1f,0xe3,0x7f, + 0xff,0x01,0xfe,0x07,0xf8,0x1f,0xe0,0x7f,0x83,0xff,0x1f,0xfc,0x7f,0xe0,0xff,0x80, + 0xff,0x80,0x7f,0xe0,0x1f,0xf8,0x07,0xfe,0x81,0xff,0xf8,0x7f,0xff,0x07,0xff,0x00, + 0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xc0,0x3f,0xf0,0x8f,0xfc,0xf3,0x7f, + 0xcf,0xfe,0xf1,0x3f,0xfc,0x0f,0xff,0x03,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, + 0xff,0x00,0xff,0xe0,0x1f,0xfe,0x81,0xff,0xe0,0x7f,0xf8,0x1f,0xfe,0x07,0xff,0x01, + 0xff,0x01,0xfe,0x07,0xf8,0x3f,0xc1,0xff,0x07,0xfe,0x1f,0xf8,0x7f,0xe0,0xff,0x80, + 0xc7,0xfe,0x1f,0xf8,0x7f,0xe0,0xff,0x80,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00 }; -const unsigned char tiles_map[260] = { +const unsigned char tiles_map[516] = { 0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04, 0x05,0x06,0x07,0x08, @@ -121,4 +153,68 @@ const unsigned char tiles_map[260] = { 0x1d,0x1e,0x1f,0x20, 0x19,0x1a,0x1b,0x1c, 0x1d,0x1e,0x1f,0x20, + 0x21,0x22,0x23,0x24, + 0x25,0x26,0x27,0x28, + 0x29,0x2a,0x23,0x24, + 0x25,0x26,0x27,0x28, + 0x21,0x22,0x2b,0x2c, + 0x25,0x26,0x27,0x28, + 0x29,0x2a,0x2b,0x2c, + 0x25,0x26,0x27,0x28, + 0x21,0x22,0x23,0x24, + 0x2d,0x2e,0x27,0x28, + 0x29,0x2a,0x23,0x24, + 0x2d,0x2e,0x27,0x28, + 0x21,0x22,0x2b,0x2c, + 0x2d,0x2e,0x27,0x28, + 0x29,0x2a,0x2b,0x2c, + 0x2d,0x2e,0x27,0x28, + 0x21,0x22,0x23,0x24, + 0x25,0x26,0x2f,0x30, + 0x29,0x2a,0x23,0x24, + 0x25,0x26,0x2f,0x30, + 0x21,0x22,0x2b,0x2c, + 0x25,0x26,0x2f,0x30, + 0x29,0x2a,0x2b,0x2c, + 0x25,0x26,0x2f,0x30, + 0x21,0x22,0x23,0x24, + 0x2d,0x2e,0x2f,0x30, + 0x29,0x2a,0x23,0x24, + 0x2d,0x2e,0x2f,0x30, + 0x21,0x22,0x2b,0x2c, + 0x2d,0x2e,0x2f,0x30, + 0x29,0x2a,0x2b,0x2c, + 0x2d,0x2e,0x2f,0x30, + 0x31,0x32,0x33,0x34, + 0x35,0x36,0x37,0x38, + 0x39,0x3a,0x33,0x34, + 0x35,0x36,0x37,0x38, + 0x31,0x32,0x3b,0x3c, + 0x35,0x36,0x37,0x38, + 0x39,0x3a,0x3b,0x3c, + 0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34, + 0x3d,0x3e,0x37,0x38, + 0x39,0x3a,0x33,0x34, + 0x3d,0x3e,0x37,0x38, + 0x31,0x32,0x3b,0x3c, + 0x3d,0x3e,0x37,0x38, + 0x39,0x3a,0x3b,0x3c, + 0x3d,0x3e,0x37,0x38, + 0x31,0x32,0x33,0x34, + 0x35,0x36,0x3f,0x40, + 0x39,0x3a,0x33,0x34, + 0x35,0x36,0x3f,0x40, + 0x31,0x32,0x3b,0x3c, + 0x35,0x36,0x3f,0x40, + 0x39,0x3a,0x3b,0x3c, + 0x35,0x36,0x3f,0x40, + 0x31,0x32,0x33,0x34, + 0x3d,0x3e,0x3f,0x40, + 0x39,0x3a,0x33,0x34, + 0x3d,0x3e,0x3f,0x40, + 0x31,0x32,0x3b,0x3c, + 0x3d,0x3e,0x3f,0x40, + 0x39,0x3a,0x3b,0x3c, + 0x3d,0x3e,0x3f,0x40, }; diff --git a/tiles.h b/tiles.h index 798a40c..40d2b5d 100644 --- a/tiles.h +++ b/tiles.h @@ -12,18 +12,18 @@ #define tiles_TILE_W 8 #define tiles_TILE_H 8 #define tiles_WIDTH 32 -#define tiles_HEIGHT 520 -#define tiles_TILE_COUNT 33 +#define tiles_HEIGHT 1032 +#define tiles_TILE_COUNT 65 #define tiles_PALETTE_COUNT 8 #define tiles_COLORS_PER_PALETTE 4 #define tiles_TOTAL_COLORS 32 #define tiles_MAP_ATTRIBUTES 0 -extern const unsigned char tiles_map[260]; +extern const unsigned char tiles_map[516]; #define tiles_map_attributes tiles_map BANKREF_EXTERN(tiles) extern const palette_color_t tiles_palettes[32]; -extern const uint8_t tiles_tiles[528]; +extern const uint8_t tiles_tiles[1040]; #endif diff --git a/tiles.png b/tiles.png index 859604aede98470cb303ff69e1b0f8bf5dcc77ed..9f5d607d6887fc1b8712a79587bd3e39e9b0eaef 100644 GIT binary patch literal 2184 zcmeAS@N?(olHy`uVBq!ia0vp^3JeS^930F*R;M1%SFKtV8X5`| z9|fZ!Fw#Q6US{$J1_oAVPZ!6KiaBrRTwHfYfybrs&wu;yOs0*t&Ahd%u02`0w?b@# zrG@g^El;`TO$xp+OFLt&h_a?yjlEZpLXL`S`)zaY$xZ1ywuWWr=638}(Ehq2?xL>d z_22P=a*L|>*!=(S!Pa%>F_Em!jh%~vGaetdy?SZ$pG%jgM(AB}S}D%=deL#-pSzj1 zxomy9adyiF-{5vm{#D<4*ae^2TseGLieJHiHPPFL^}gClhvl41hnhuvDqb+Pw?`LL zL_B8vwB2Tg!KZ{nCzxAw`K^2^0=A~x{P_D&Oh)cn#SLMVZ~R-?Y%-Q`@)xWfu zPxZqGzioFs*6$FFFErl&;hErY`|e4S!;RIwrKS3(RPIEFUKqV}EmD zY2^gtAh|PJE_Vk%ULF4UboArb^?#Uo(;qSZYS#96BR}cG26ZsS@b}<8{ROo<{w>sZ zX5BSOq2ln{*++k{S2{S?@cwU@TI2upBmXCzDKFkHpI2Y8Y6 z!*2B|o0s1s^A?JE?JbB9x6M0oUvz`2kA(Tjfbh&$1`i#t&iklvXij?(D4bZfDW!C- zd~jPuG+}utW*{o7^?<^W;bCXWx#m^2j}N}*SFWkxs00V0e2}o5$)y%{OXa7DMTPsE z9zLD9ch>10dwy+Du&usR-E`!iA}9Z|_mAa0EQI+LHYlfXn)lfFT$lD`3YwVk^lP^5`!-tOQX$PF==LW6Fw~Wf#8Cw)#C2x^8yMW^iU(x>8@|QqC1ELsy zvOiq%PmvcG{mjSh8Gugca+>u)A$^I>jLhlp!V0Vp|9;!nU%%j?kBvip0c+=9XCb+7 zEMRKggN;p5u?IJwT=~FzGFR0Rk1h`TKA*1k2S0cBK9_yn^fB@49?hxd#!~BQJIl=^ zm%tOs{CVn#5Y2hNUZ`SP{d-@c%uphTy@|@A_jCx=FiKEOMXAXSi-&xTx z(P6?Bdz1VAb-q2HJ_Pi-UNTQ!Jn>ZIkv#L+KV9S46%DLU{9RY?arp2$g_S^x`N?~( zOTXGpY#I*O9Jk+Nv!ia4^XpHLa9b|E{Al?4qtmw^z5f3PyVSWO%nSk?K*cIHZ#ad1 z11X344eOaRuDy*-4EW}fiv zi>>|f(PXw?;`#vYrTZQoR_gzIaDu~uX)CtbluhRO>c&zG3$ztTf%c(POY6c}9+m^m zVgYiiel)J+a`12nO6*^niO!DBwcw`>&d>?Jg&`YNN-mv>cNl%kCR*(~S3@ zK+egcDrhHr=4CLJkEYL4OE4Ay85}Sb4q9e0If5Z4FCWD delta 766 zcmeAWoX9gljGKvrgPDPW!QzO_mW_&h%=JuXJY5_^D(1YM>0NY0fyd?No&V=FkF%+i zDkn_un&E4-f_*~8iP)zh;`2p<1G=;|R8^Hd)&A5>QE|NCF^O-wq4&h5@*Ptq73(eS zp1q*8_{nEKKON#ZSCpiITJr6ESnoQXV1Q>%G%1$zkbF4cQ`z;qT$~IE~ek@3N~{% z!IVS&hV$I@8S?AuGfoFIu2bRIS0K4r;=cm_itg<1{1GSLhs6C?IPcV1SO4|j!-se7 zrF#k;%{=ivGWR)?eZ~B#q4U1fPK#dA8Qu*M+s{7>f4z1~HaJsVdlb9BgS+O=LRRU+}L} m*ig@L2pB0F>N^e|=AU^ic46%S_p`uc&fw|l=d#Wzp$PyG?`4z#