diff --git a/sys/msdos/vidvesa.c b/sys/msdos/vidvesa.c index bb66379ad..147e21da3 100644 --- a/sys/msdos/vidvesa.c +++ b/sys/msdos/vidvesa.c @@ -60,6 +60,8 @@ static unsigned long vesa_DoublePixels(unsigned long); static unsigned long vesa_TriplePixels(unsigned long); static void vesa_WriteStr(const char *, int, int, int, int); static unsigned char __far *vesa_FontPtrs(void); +static unsigned char *vesa_tile(unsigned); +static unsigned char *vesa_oview_tile(unsigned); /* static void vesa_process_tile(struct TileImage *tile); */ #ifdef POSITIONBAR @@ -849,7 +851,7 @@ vesa_redrawmap(void) for (cy = 0; cy < ROWNO; ++cy) { for (py = 0; py < vesa_oview_height; ++py) { for (cx = 0; cx < COLNO; ++cx) { - tile = vesa_oview_tiles[map[cy][cx].tileidx]; + tile = vesa_oview_tile(map[cy][cx].tileidx); vesa_WritePixelRow(offset + p_row_width * cx, tile + p_row_width * py, p_row_width); } x = COLNO * vesa_oview_width; @@ -869,7 +871,7 @@ vesa_redrawmap(void) for (cy = clipy; cy <= (unsigned) clipymax && cy < ROWNO; ++cy) { for (py = 0; py < (unsigned) iflags.wc_tile_height; ++py) { for (cx = clipx; cx <= (unsigned) clipxmax && cx < COLNO; ++cx) { - tile = vesa_tiles[map[cy][cx].tileidx]; + tile = vesa_tile(map[cy][cx].tileidx); vesa_WritePixelRow(offset + p_row_width * (cx - clipx), tile + p_row_width * py, p_row_width); } x = (cx - clipx) * iflags.wc_tile_width; @@ -1053,8 +1055,6 @@ vesa_Init(void) { static boolean inited = FALSE; const struct Pixel *paletteptr; - unsigned i; - unsigned num_pixels, num_oview_pixels; const char *tile_file; const char *font_name; int tilefailure = 0; @@ -1186,31 +1186,33 @@ vesa_Init(void) /* Process tiles for the current video mode */ vesa_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *)); + memset(vesa_tiles, 0, total_tiles_used * sizeof(void *)); vesa_oview_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *)); - num_pixels = iflags.wc_tile_width * iflags.wc_tile_height; - num_oview_pixels = vesa_oview_width * vesa_oview_height; + memset(vesa_oview_tiles, 0, total_tiles_used * sizeof(void *)); set_tile_type(vesa_pixel_size > 8); - for (i = 0; i < (unsigned) total_tiles_used; ++i) { - const struct TileImage *tile = get_tile(i); - struct TileImage *ov_tile = stretch_tile(tile, vesa_oview_width, vesa_oview_height); +} + +RESTORE_WARNING_FORMAT_NONLITERAL + +/* Return processed pixels for a normal tile */ +static unsigned char * +vesa_tile(unsigned index) +{ + if (vesa_tiles[index] == NULL) { + unsigned num_pixels = iflags.wc_tile_width * iflags.wc_tile_height; + const struct TileImage *tile = get_tile(index); unsigned j; unsigned char *t_img = (unsigned char *) alloc(num_pixels * vesa_pixel_bytes); - unsigned char *ot_img = (unsigned char *) alloc(num_oview_pixels * vesa_pixel_bytes); - vesa_tiles[i] = t_img; - vesa_oview_tiles[i] = ot_img; + vesa_tiles[index] = t_img; switch (vesa_pixel_bytes) { case 1: memcpy(t_img, tile->indexes, num_pixels); - memcpy(ot_img, ov_tile->indexes, num_oview_pixels); break; case 2: for (j = 0; j < num_pixels; ++j) { ((uint16_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]); } - for (j = 0; j < num_oview_pixels; ++j) { - ((uint16_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]); - } break; case 3: @@ -1220,6 +1222,42 @@ vesa_Init(void) t_img[3*j + 1] = (color >> 8) & 0xFF; t_img[3*j + 2] = (color >> 16) & 0xFF; } + break; + + case 4: + for (j = 0; j < num_pixels; ++j) { + ((uint32_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]); + } + break; + } + } + + return vesa_tiles[index]; +} + +/* Return processed pixels for an overview tile */ +static unsigned char * +vesa_oview_tile(unsigned index) +{ + if (vesa_oview_tiles[index] == NULL) { + unsigned num_oview_pixels = vesa_oview_width * vesa_oview_height; + const struct TileImage *tile = get_tile(index); + struct TileImage *ov_tile = stretch_tile(tile, vesa_oview_width, vesa_oview_height); + unsigned j; + unsigned char *ot_img = (unsigned char *) alloc(num_oview_pixels * vesa_pixel_bytes); + vesa_oview_tiles[index] = ot_img; + switch (vesa_pixel_bytes) { + case 1: + memcpy(ot_img, ov_tile->indexes, num_oview_pixels); + break; + + case 2: + for (j = 0; j < num_oview_pixels; ++j) { + ((uint16_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]); + } + break; + + case 3: for (j = 0; j < num_oview_pixels; ++j) { unsigned long color = vesa_MakeColor(ov_tile->pixels[j]); ot_img[3*j + 0] = color & 0xFF; @@ -1229,9 +1267,6 @@ vesa_Init(void) break; case 4: - for (j = 0; j < num_pixels; ++j) { - ((uint32_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]); - } for (j = 0; j < num_oview_pixels; ++j) { ((uint32_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]); } @@ -1239,10 +1274,9 @@ vesa_Init(void) } free_tile(ov_tile); } - free_tiles(); -} -RESTORE_WARNING_FORMAT_NONLITERAL + return vesa_oview_tiles[index]; +} /* Set the size of the map viewport */ static void @@ -1314,6 +1348,7 @@ vesa_Finish(void) } free(vesa_tiles); free(vesa_oview_tiles); + free_tiles(); vesa_SwitchMode(MODETEXT); windowprocs.win_cliparound = tty_cliparound; g_attribute = attrib_text_normal; @@ -1873,11 +1908,11 @@ vesa_DisplayCell(int tilenum, int col, int row) unsigned p_row_width; if (iflags.over_view) { - tile = vesa_oview_tiles[tilenum]; + tile = vesa_oview_tile(tilenum); t_width = vesa_oview_width; t_height = vesa_oview_height; } else { - tile = vesa_tiles[tilenum]; + tile = vesa_tile(tilenum); t_width = iflags.wc_tile_width; t_height = iflags.wc_tile_height; } diff --git a/sys/msdos/vidvga.c b/sys/msdos/vidvga.c index 792a32e2b..a546d67c1 100644 --- a/sys/msdos/vidvga.c +++ b/sys/msdos/vidvga.c @@ -213,8 +213,8 @@ int vp[SCREENPLANES] = { 8, 4, 2, 1 }; #endif int vp2[SCREENPLANES] = { 1, 2, 4, 8 }; -static struct planar_cell_struct planecell; -static struct overview_planar_cell_struct planecell_O; +static struct planar_cell_struct **cell_cache; +static struct overview_planar_cell_struct **cell_cache_O; /* static int g_attribute; */ /* Current attribute to use */ @@ -410,6 +410,7 @@ vga_xputg(const glyph_info *glyphinfo, vga_WriteChar(ch, col, row, attr); } else if (!iflags.over_view) { if ((col >= clipx) && (col <= clipxmax)) { + struct planar_cell_struct planecell; read_planar_tile(glyphnum, &planecell); if (map[ry][col].special) decal_planar(&planecell, special); @@ -426,6 +427,7 @@ vga_xputg(const glyph_info *glyphinfo, } } } else { + struct overview_planar_cell_struct planecell_O; read_planar_tile_O(glyphnum, &planecell_O); vga_DisplayCell_O(&planecell_O, col, row); } @@ -512,11 +514,13 @@ vga_redrawmap(boolean clearfirst) } else { t = map[y][x].glyph; if (!iflags.over_view) { + struct planar_cell_struct planecell; read_planar_tile(t, &planecell); if (map[y][x].special) decal_planar(&planecell, map[y][x].special); vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW); } else { + struct overview_planar_cell_struct planecell_O; read_planar_tile_O(t, &planecell_O); vga_DisplayCell_O(&planecell_O, x, y + TOP_MAP_ROW); } @@ -643,6 +647,7 @@ boolean left; } for (y = 0; y < ROWNO; ++y) { for (x = i; x < j; x += 2) { + struct planar_cell_struct planecell; t = map[y][x].glyph; read_planar_tile(t, &planecell); if (map[y][x].special) @@ -656,47 +661,69 @@ boolean left; static void read_planar_tile(unsigned glyph, struct planar_cell_struct *cell) { + struct planar_cell_struct *pcell; unsigned char indexes[TILE_Y][TILE_X]; unsigned plane, y, byte, bit; + int tilenum = glyphmap[glyph].tileidx; - read_tile_indexes(glyph, indexes); - /* cell->plane[0..3].image[0..15][0..1] */ - for (plane = 0; plane < SCREENPLANES; ++plane) { - for (y = 0; y < TILE_Y; ++y) { - for (byte = 0; byte < MAX_BYTES_PER_CELL; ++byte) { - unsigned char b = 0; - for (bit = 0; bit < 8; ++bit) { - unsigned char x = byte * 8 + bit; - unsigned char i = indexes[y][x]; - b <<= 1; - if (i & (0x8 >> plane)) b |= 1; + /* Get the processed tile from the cache if we can */ + pcell = cell_cache[tilenum]; + if (pcell == NULL) { + /* Process the tile */ + pcell = (struct planar_cell_struct *) alloc(sizeof(*pcell)); + cell_cache[tilenum] = pcell; + read_tile_indexes(glyph, indexes); + /* pcell->plane[0..3].image[0..15][0..1] */ + for (plane = 0; plane < SCREENPLANES; ++plane) { + for (y = 0; y < TILE_Y; ++y) { + for (byte = 0; byte < MAX_BYTES_PER_CELL; ++byte) { + unsigned char b = 0; + for (bit = 0; bit < 8; ++bit) { + unsigned char x = byte * 8 + bit; + unsigned char i = indexes[y][x]; + b <<= 1; + if (i & (0x8 >> plane)) b |= 1; + } + pcell->plane[plane].image[y][byte] = b; } - cell->plane[plane].image[y][byte] = b; } } } + + *cell = *pcell; } static void read_planar_tile_O(unsigned glyph, struct overview_planar_cell_struct *cell) { + struct overview_planar_cell_struct *pcell; unsigned char indexes[TILE_Y][TILE_X]; unsigned plane, y, bit; + int tilenum = glyphmap[glyph].tileidx; - read_tile_indexes(glyph, indexes); - /* cell->plane[0..3].image[0..15][0..0] */ - for (plane = 0; plane < SCREENPLANES; ++plane) { - for (y = 0; y < TILE_Y; ++y) { - unsigned char b = 0; - for (bit = 0; bit < 8; ++bit) { - unsigned char x = bit * 2; - unsigned char i = indexes[y][x]; - b <<= 1; - if (i & (0x8 >> plane)) b |= 1; + /* Get the processed tile from the cache if we can */ + pcell = cell_cache_O[tilenum]; + if (pcell == NULL) { + /* Process the tile */ + pcell = (struct overview_planar_cell_struct *) alloc(sizeof(*pcell)); + cell_cache_O[tilenum] = pcell; + read_tile_indexes(glyph, indexes); + /* pcell->plane[0..3].image[0..15][0..0] */ + for (plane = 0; plane < SCREENPLANES; ++plane) { + for (y = 0; y < TILE_Y; ++y) { + unsigned char b = 0; + for (bit = 0; bit < 8; ++bit) { + unsigned char x = bit * 2; + unsigned char i = indexes[y][x]; + b <<= 1; + if (i & (0x8 >> plane)) b |= 1; + } + pcell->plane[plane].image[y][0] = b; } - cell->plane[plane].image[y][0] = b; } } + + *cell = *pcell; } static void @@ -782,6 +809,15 @@ vga_Init(void) /* term_clear_screen() */ /* not vga_clear_screen() */ return; } + + if (cell_cache == NULL) { + cell_cache = (struct planar_cell_struct **) alloc( + total_tiles_used * sizeof(cell_cache[0])); + memset(cell_cache, 0, total_tiles_used * sizeof(cell_cache[0])); + cell_cache_O = (struct overview_planar_cell_struct **) alloc( + total_tiles_used * sizeof(cell_cache_O[0])); + memset(cell_cache_O, 0, total_tiles_used * sizeof(cell_cache_O[0])); + } #endif if (iflags.usevga) { @@ -860,7 +896,17 @@ vga_SwitchMode(unsigned int mode) void vga_Finish(void) { + int i; + free_tiles(); + for (i = 0; i < total_tiles_used; ++i) { + free(cell_cache[i]); + free(cell_cache_O[i]); + } + free(cell_cache); + cell_cache = NULL; + free(cell_cache_O); + cell_cache_O = NULL; vga_SwitchMode(MODETEXT); windowprocs.win_cliparound = tty_cliparound; g_attribute = attrib_text_normal; diff --git a/win/share/tileset.c b/win/share/tileset.c index 2fff3affa..c3fbb209a 100644 --- a/win/share/tileset.c +++ b/win/share/tileset.c @@ -30,6 +30,9 @@ read_tiles(const char *filename, boolean true_color) char header[16]; boolean ok; + if (tiles != NULL) + return TRUE; + /* Fill the image structure with known values */ image.width = 0; image.height = 0; @@ -283,7 +286,7 @@ split_tiles(const struct TileSetImage *image) { unsigned tile_rows, tile_cols; size_t tile_size, i, j; - unsigned x1, y1, x2, y2; + unsigned x1, y1, y2; /* Get the number of tiles */ tile_rows = image->height / iflags.wc_tile_height; @@ -308,16 +311,15 @@ split_tiles(const struct TileSetImage *image) tile->indexes = (unsigned char *) alloc(tile_size); } for (y2 = 0; y2 < (unsigned) iflags.wc_tile_height; ++y2) { - for (x2 = 0; x2 < (unsigned) iflags.wc_tile_width; ++x2) { - unsigned x = x1 * iflags.wc_tile_width + x2; - unsigned y = y1 * iflags.wc_tile_height + y2; - - i = y * image->width + x; - j = y2 * tile->width + x2; - tile->pixels[j] = image->pixels[i]; - if (image->indexes != NULL) { - tile->indexes[j] = image->indexes[i]; - } + unsigned y = y1 * iflags.wc_tile_height + y2; + unsigned x = x1 * iflags.wc_tile_width; + i = y * image->width; + j = y2 * tile->width; + memcpy(tile->pixels + j, image->pixels + i + x, + sizeof(tile->pixels[0]) * iflags.wc_tile_width); + if (image->indexes != NULL) { + memcpy(tile->indexes + j, image->indexes + i + x, + iflags.wc_tile_width); } } }