--- deliantra/Deliantra-Client/Client.xs 2018/11/18 12:01:50 1.327 +++ deliantra/Deliantra-Client/Client.xs 2018/11/19 01:37:28 1.334 @@ -78,14 +78,8 @@ # include #endif -#if __GNUC__ >= 4 -# define expect(expr,value) __builtin_expect ((expr),(value)) -#else -# define expect(expr,value) (expr) -#endif - -#define expect_false(expr) expect ((expr) != 0, 0) -#define expect_true(expr) expect ((expr) != 0, 1) +#include "ecb.h" +#include "salloc.h" #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ @@ -113,7 +107,7 @@ STRLEN len = SvLEN (sv); STRLEN want = SvCUR (sv) + need; - if (expect_false (len < want)) + if (ecb_expect_false (len < want)) { do len *= 2; @@ -258,6 +252,8 @@ *h = rect.height; } +///////////////////////////////////////////////////////////////////////////// + typedef uint16_t tileid; typedef uint16_t faceid; @@ -289,46 +285,56 @@ struct mapgrid { int x, y, w, h; int ox, oy; /* offset to virtual global coordinate system */ - std::vector tile; - std::vector tex; + int faces; tileid *face2tile; // [faceid] + int texs; maptex *tex; // [tileid] int32_t rows; maprow *row; - - ~mapgrid () - { - clear_cells (); - } - - void clear_cells (); }; typedef mapgrid *DC__Map; -static char * -prepend (char *ptr, int sze, int inc) +template +static void +prepend (T *&ptr, int sze, int inc) { - char *p; + T *p; - New (0, p, sze + inc, char); - Zero (p, inc, char); - Move (ptr, p + inc, sze, char); + Newx (p, inc + sze, T); + Zero (p, inc, T); + Move (ptr, p + inc, sze, T); Safefree (ptr); - return p; + ptr = p; } -static char * -append (char *ptr, int sze, int inc) +template +static void +append (T *&ptr, int sze, int inc) { - Renew (ptr, sze + inc, char); - Zero (ptr + sze, inc, char); + Renew (ptr, sze + inc, T); + Zero (ptr + sze, inc, T); +} - return ptr; +static void +need_facenum (struct mapgrid *self, faceid face) +{ + while (self->faces <= face) + { + append (self->face2tile, self->faces, self->faces); + self->faces *= 2; + } } -#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) -#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) +static void +need_texid (struct mapgrid *self, int texid) +{ + while (self->texs <= texid) + { + append (self->tex, self->texs, self->texs); + self->texs *= 2; + } +} static maprow * map_get_row (mapgrid *self, int y) @@ -336,7 +342,7 @@ if (0 > y) { int extend = - y + MAP_EXTEND_Y; - Prepend (maprow, self->row, self->rows, extend); + prepend (self->row, self->rows, extend); self->rows += extend; self->y += extend; @@ -345,7 +351,7 @@ else if (y >= self->rows) { int extend = y - self->rows + MAP_EXTEND_Y; - Append (maprow, self->row, self->rows, extend); + append (self->row, self->rows, extend); self->rows += extend; } @@ -365,13 +371,13 @@ if (row->c0 > x) { int extend = row->c0 - x + MAP_EXTEND_X; - Prepend (mapcell, row->col, row->c1 - row->c0, extend); + prepend (row->col, row->c1 - row->c0, extend); row->c0 -= extend; } else if (x >= row->c1) { int extend = x - row->c1 + MAP_EXTEND_X; - Append (mapcell, row->col, row->c1 - row->c0, extend); + append (row->col, row->c1 - row->c0, extend); row->c1 += extend; } @@ -384,21 +390,22 @@ return row_get_cell (map_get_row (self, y), x); } -void mapgrid::clear_cells () +static void +map_clear (mapgrid *self) { int r; - for (r = 0; r < rows; r++) - Safefree (row[r].col); + for (r = 0; r < self->rows; r++) + Safefree (self->row[r].col); - Safefree (row); + Safefree (self->row); - x = 0; - y = 0; - ox = 0; - oy = 0; - row = 0; - rows = 0; + self->x = 0; + self->y = 0; + self->ox = 0; + self->oy = 0; + self->row = 0; + self->rows = 0; } #define CELL_CLEAR(cell) \ @@ -450,7 +457,7 @@ } }; -typedef ska::flat_hash_map smooth_hash; +typedef ska::flat_hash_map, std::equal_to, slice_allocator> smooth_hash; namespace std { template <> @@ -524,17 +531,6 @@ return n + 1; } -static unsigned int -popcount (unsigned int n) -{ - n -= (n >> 1) & 0x55555555U; - n = ((n >> 2) & 0x33333333U) + (n & 0x33333333U); - n = ((n >> 4) + n) & 0x0f0f0f0fU; - n *= 0x01010101U; - - return n >> 24; -} - /* SDL should provide this, really. */ #define SDLK_MODIFIER_MIN 300 #define SDLK_MODIFIER_MAX 314 @@ -873,7 +869,17 @@ IV minpot (UV n) +UV ld32 (UV n) + CODE: + RETVAL = ecb_ld32 (n); + OUTPUT: + RETVAL + IV popcount (UV n) + CODE: + RETVAL = ecb_popcount32 (n); + OUTPUT: + RETVAL NV distance (NV dx, NV dy) CODE: @@ -1888,13 +1894,15 @@ DC::Map new (SV *klass) CODE: - RETVAL = new mapgrid; + New (0, RETVAL, 1, mapgrid); RETVAL->x = 0; RETVAL->y = 0; RETVAL->w = 0; RETVAL->h = 0; RETVAL->ox = 0; RETVAL->oy = 0; + RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid); + RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex); RETVAL->rows = 0; RETVAL->row = 0; OUTPUT: @@ -1904,7 +1912,10 @@ DESTROY (DC::Map self) CODE: { - delete self; + map_clear (self); + Safefree (self->face2tile); + Safefree (self->tex); + Safefree (self); } void @@ -1916,55 +1927,57 @@ void clear (DC::Map self) CODE: - self->clear_cells (); + map_clear (self); void set_tileid (DC::Map self, int face, int tile) CODE: { - if (self->tile.size () <= face) self->tile.resize (face + 1); - self->tile[face] = tile; - if (self->tex.size () <= tile) self->tex .resize (tile + 1); + need_facenum (self, face); self->face2tile [face] = tile; + need_texid (self, tile); } void set_smooth (DC::Map self, int face, int smooth, int level) CODE: { - if (face < 0 || face >= self->tile.size ()) + tileid texid; + maptex *tex; + + if (face < 0 || face >= self->faces) return; - if (smooth < 0 || smooth >= self->tile.size ()) + if (smooth < 0 || smooth >= self->faces) return; - tileid texid = self->tile[face]; + texid = self->face2tile [face]; if (!texid) return; - maptex &tex = self->tex[texid]; - tex.smoothtile = self->tile[smooth]; - tex.smoothlevel = level; + tex = self->tex + texid; + tex->smoothtile = self->face2tile [smooth]; + tex->smoothlevel = level; } void set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) CODE: { - if (self->tex.size () < texid) self->tex.resize (texid + 1); + need_texid (self, texid); { - maptex &tex = self->tex[texid]; + maptex *tex = self->tex + texid; - tex.name = name; - tex.w = w; - tex.h = h; - tex.s = s; - tex.t = t; - tex.r = r; - tex.g = g; - tex.b = b; - tex.a = a; + tex->name = name; + tex->w = w; + tex->h = h; + tex->s = s; + tex->t = t; + tex->r = r; + tex->g = g; + tex->b = b; + tex->a = a; } // somewhat hackish, but for textures that require it, it really @@ -1980,20 +1993,20 @@ void expire_textures (DC::Map self, int texid, int count) PPCODE: - for (; texid < self->tex.size () && count; ++texid, --count) + for (; texid < self->texs && count; ++texid, --count) { - maptex &tex = self->tex[texid]; + maptex *tex = self->tex + texid; - if (tex.name) + if (tex->name) { - if (tex.unused) + if (tex->unused) { - tex.name = 0; - tex.unused = 0; + tex->name = 0; + tex->unused = 0; XPUSHs (sv_2mortal (newSViv (texid))); } else - tex.unused = 1; + tex->unused = 1; } } @@ -2037,7 +2050,7 @@ while (self->y < 0) { - Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y); + prepend (self->row, self->rows, MAP_EXTEND_Y); self->rows += MAP_EXTEND_Y; self->y += MAP_EXTEND_Y; @@ -2114,23 +2127,23 @@ for (z = 0; z <= 2; ++z) if (flags & (4 >> z)) { - faceid face = (data[0] << 8) + data[1]; data += 2; - if (self->tile.size () <= face) self->tile.resize (face + 1); - cell->tile[z] = self->tile[face]; + faceid face = (data [0] << 8) + data [1]; data += 2; + need_facenum (self, face); + cell->tile [z] = self->face2tile [face]; - if (cell->tile[z]) + if (cell->tile [z]) { - maptex &tex = self->tex[cell->tile[z]]; - tex.unused = 0; - if (!tex.name) + maptex *tex = self->tex + cell->tile [z]; + tex->unused = 0; + if (!tex->name) av_push (missing, newSViv (cell->tile [z])); - if (tex.smoothtile) + if (tex->smoothtile) { - maptex &smooth = self->tex[tex.smoothtile]; - smooth.unused = 0; - if (!smooth.name) - av_push (missing, newSViv (tex.smoothtile)); + maptex *smooth = self->tex + tex->smoothtile; + smooth->unused = 0; + if (!smooth->name) + av_push (missing, newSViv (tex->smoothtile)); } } } @@ -2291,7 +2304,7 @@ px = (x + 1) * Th - tex.w; py = (y + 1) * Tw - tex.h; - if (expect_false (cell->player == player) && expect_false (z == 2)) + if (ecb_expect_false (cell->player == player) && ecb_expect_false (z == 2)) { pl_x = px; pl_y = py; @@ -2344,7 +2357,7 @@ } } - if (expect_false (z == 2) && expect_false (cell->flags)) + if (ecb_expect_false (z == 2) && ecb_expect_false (cell->flags)) { // overlays such as the speech bubble, probably more to come if (cell->flags & 1) @@ -2473,7 +2486,7 @@ int px = x * Tw; int py = y * Th; - if (expect_false (cell->player == player)) + if (ecb_expect_false (cell->player == player)) { px += sdx; py += sdy; @@ -2789,13 +2802,13 @@ { tileid t = tile [z]; - if (t >= self->tex.size () || (t && !self->tex[t].name)) + if (t >= self->texs || (t && !self->tex [t].name)) { PUSHs (sv_2mortal (newSViv (t))); - if (self->tex.size () <= t) self->tex.resize (t + 1); + need_texid (self, t); } - cell->tile[z] = t; + cell->tile [z] = t; } } }