1 /* 2 * Copyright (C) 2015-2020, by Laszlo Szeremi under the Boost license. 3 * 4 * Pixel Perfect Engine, graphics.layers.trnstilelayer module 5 */ 6 7 module pixelperfectengine.graphics.layers.trnstilelayer; 8 9 public import pixelperfectengine.graphics.layers.base; 10 import pixelperfectengine.system.etc; 11 import pixelperfectengine.system.exc; 12 import collections.treemap; 13 import inteli.emmintrin; 14 15 /** 16 * Implements a modified TileLayer with transformability with capabilities similar to MODE7. 17 * <br/> 18 * Transform function: 19 * [x',y'] = ([A,B,C,D] * ([x,y] + [sX,sY] - [x_0,y_0])>>>8 + [x_0,y_0] 20 * <br/> 21 * All basic transform values are integer based, 256 equals with 1.0 22 * <br/> 23 * Restrictions compared to standard TileLayer: 24 * <ul> 25 * <li>Tiles must have any of the following sizes: 8, 16, 32, 64; since this layer needs to do modulo computations for each pixel.</li> 26 * <li>In future versions, map sizes for this layer will be restricted to power of two sizes to make things faster</li> 27 * <li>Maximum layer size in pixels are restricted to 65536*65536 due to architectural limitations. Accelerated versions might raise 28 * this limitation.</li> 29 * </ul> 30 * HDMA emulation supported through delegate hBlankInterrupt. 31 */ 32 public class TransformableTileLayer(BMPType = Bitmap16Bit, int TileX = 8, int TileY = 8) : Layer, ITileLayer, ITTL{ 33 /*if(isPowerOf2(TileX) && isPowerOf2(TileY))*/ 34 protected struct DisplayListItem { 35 BMPType tile; ///For reference counting 36 void* pixelSrc; ///Used for quicker access to the Data 37 wchar ID; ///ID, mainly used as a padding and secondary identification 38 /** 39 * Sets the maximum accessable color amount by the bitmap. 40 * By default, for 4 bit bitmaps, it's 4, and it enables 256 * 16 color palettes. 41 * This limitation is due to the way how the MappingElement struct works. 42 * 8 bit bitmaps can assess the full 256 * 256 palette space. 43 * Lower values can be described to avoid wasting palettes space in cases when the 44 * bitmaps wouldn't use their full capability. 45 * Not used with 16 bit indexed and 32 bit direct color bitmaps. 46 */ 47 ubyte palShift; 48 ubyte reserved; ///Padding for 32 bit 49 this (wchar ID, BMPType tile, ubyte paletteSh = 0) pure @trusted @nogc nothrow { 50 void _systemWrapper() pure @system @nogc nothrow { 51 pixelSrc = cast(void*)tile.getPtr(); 52 } 53 this.ID = ID; 54 this.tile = tile; 55 static if (is(BMPType == Bitmap4Bit)) this.palShift = paletteSh ? paletteSh : 4; 56 else static if (is(BMPType == Bitmap8Bit)) this.palShift = paletteSh ? paletteSh : 8; 57 _systemWrapper; 58 } 59 string toString() const { 60 import std.conv : to; 61 string result = to!string(cast(ushort)ID) ~ " ; " ~ to!string(pixelSrc); 62 return result; 63 } 64 } 65 alias DisplayList = TreeMap!(wchar, DisplayListItem, true); 66 protected DisplayList displayList; 67 protected short[4] transformPoints; /** Defines how the layer is being transformed */ 68 protected short[2] tpOrigin; /** Transform point */ 69 protected Bitmap32Bit backbuffer; ///used to store current screen output 70 /*static if(BMPType.mangleof == Bitmap8Bit.mangleof){ 71 protected ubyte[] src; 72 protected Color* palettePtr; ///Shared palette 73 }else static if(BMPType.mangleof == Bitmap16Bit.mangleof){ 74 protected ushort[] src;*/ 75 static if(is(BMPType == Bitmap4Bit) || is(BMPType == Bitmap8Bit) || is(BMPType == Bitmap16Bit)){ 76 protected ushort[] src; 77 }else static if(is(BMPType == Bitmap32Bit)){ 78 79 }else static assert(false,"Template parameter " ~ BMPType.mangleof ~ " not supported by TransformableTileLayer!"); 80 //TO DO: Replace these with a single 32 bit value 81 protected bool needsUpdate; ///Set to true if backbuffer needs an update (might be replaced with flags) 82 public WarpMode warpMode; ///Repeats the whole layer if set to true 83 public ubyte masterVal; ///Sets the master alpha value for the layer 84 public ushort paletteOffset; ///Offsets the palette by the given amount 85 protected int mX, mY; ///"Inherited" from TileLayer 86 static if(TileX == 8) 87 protected immutable int shiftX = 3; 88 else static if(TileX == 16) 89 protected immutable int shiftX = 4; 90 else static if(TileX == 32) 91 protected immutable int shiftX = 5; 92 else static if(TileX == 64) 93 protected immutable int shiftX = 6; 94 else static assert(false,"Unsupported horizontal tile size!"); 95 static if(TileY == 8) 96 protected immutable int shiftY = 3; 97 else static if(TileY == 16) 98 protected immutable int shiftY = 4; 99 else static if(TileY == 32) 100 protected immutable int shiftY = 5; 101 else static if(TileY == 64) 102 protected immutable int shiftY = 6; 103 else static assert(false,"Unsupported vertical tile size!"); 104 protected int totalX, totalY; 105 protected MappingElement[] mapping; 106 107 protected int4 _tileAmpersand; ///Used for quick modulo by power of two to calculate tile positions. 108 protected short8 _increment; 109 protected __m128i _mapAmpersand; ///Used for quick modulo by power of two to read maps 110 //protected __m128i _mapShift; ///Used for quick divide by power of two to read maps 111 112 alias HBIDelegate = 113 @nogc nothrow void delegate(ref short[4] localABCD, ref short[2] localsXsY, ref short[2] localx0y0, short y); 114 /** 115 * Called before each line being redrawn. Can modify global values for each lines. 116 */ 117 public HBIDelegate hBlankInterrupt; 118 119 this (RenderingMode renderMode = RenderingMode.AlphaBlend) { 120 A = 256; 121 B = 0; 122 C = 0; 123 D = 256; 124 x_0 = 0; 125 y_0 = 0; 126 _tileAmpersand = [TileX - 1, TileY - 1, TileX - 1, TileY - 1]; 127 //_mapShift = [shiftX, shiftY, shiftX, shiftY]; 128 masterVal = ubyte.max; 129 setRenderingMode(renderMode); 130 needsUpdate = true; 131 //static if (BMPType.mangleof == Bitmap4Bit.mangleof) _paletteOffset = 4; 132 //else static if (BMPType.mangleof == Bitmap8Bit.mangleof) _paletteOffset = 8; 133 for(int i ; i < 8 ; i+=2) 134 _increment[i] = 2; 135 } 136 137 138 139 override public void setRasterizer(int rX,int rY) { 140 super.setRasterizer(rX,rY); 141 backbuffer = new Bitmap32Bit(rX, rY); 142 static if(BMPType.mangleof == Bitmap8Bit.mangleof || BMPType.mangleof == Bitmap16Bit.mangleof){ 143 src.length = rX; 144 } 145 } 146 public override LayerType getLayerType() @nogc @safe pure nothrow const { 147 return LayerType.TransformableTile; 148 } 149 override public @nogc void updateRaster(void* workpad,int pitch,Color* palette) { 150 //import core.stdc.stdio; 151 if(needsUpdate){ 152 needsUpdate = false; 153 //clear buffer 154 //backbuffer.clear(); 155 Color* dest = backbuffer.getPtr(); 156 short[2] sXsY = [cast(short)sX,cast(short)sY]; 157 short[4] localTP = transformPoints; 158 short[2] localTPO = tpOrigin; 159 //write new data into it 160 for(short y; y < rasterY; y++){ 161 if(hBlankInterrupt !is null){ 162 hBlankInterrupt(localTP, sXsY, localTPO, y); 163 } 164 short8 _sXsY, _localTP, _localTPO; 165 for(int i; i < 8; i++){ 166 _sXsY[i] = sXsY[i & 1]; 167 _localTP[i] = localTP[i & 3]; 168 _localTPO[i] = localTPO[i & 1]; 169 } 170 short8 xy_in; 171 for(int i = 1; i < 8; i += 2){ 172 xy_in[i] = y; 173 } 174 xy_in[4] = 1; 175 xy_in[6] = 1; 176 int4 _localTPO_0; 177 for(int i; i < 4; i++){ 178 _localTPO_0[i] = localTPO[i & 1]; 179 } 180 for(short x; x < rasterX; x++){ 181 int4 xy = _mm_srai_epi32(_mm_madd_epi16(cast(int4)_localTP, cast(int4)(xy_in + _sXsY - _localTPO)),8) 182 + _localTPO_0; 183 /+MappingElement currentTile0 = tileByPixelWithoutTransform(xy[0],xy[1]), 184 currentTile[1] = tileByPixelWithoutTransform(xy[2],xy[3]);+/ 185 MappingElement[2] currentTile = tileByPixelWithoutTransform(xy); 186 xy &= _tileAmpersand; 187 if(currentTile[0].tileID != 0xFFFF){ 188 const DisplayListItem d = displayList[currentTile[0].tileID]; 189 static if(is(BMPType == Bitmap4Bit)){ 190 ubyte* tsrc = cast(ubyte*)d.pixelSrc; 191 }else static if(is(BMPType == Bitmap8Bit)){ 192 ubyte* tsrc = cast(ubyte*)d.pixelSrc; 193 }else static if(is(BMPType == Bitmap16Bit)){ 194 ushort* tsrc = cast(ushort*)d.pixelSrc; 195 }else static if(is(BMPType == Bitmap32Bit)){ 196 Color* tsrc = cast(Color*)d.pixelSrc; 197 } 198 xy[0] = xy[0] & (TileX - 1); 199 xy[1] = xy[1] & (TileY - 1); 200 const int totalOffset = xy[0] + xy[1] * TileX; 201 static if(BMPType.mangleof == Bitmap4Bit.mangleof){ 202 src[x] = cast(ushort)((totalOffset & 1 ? tsrc[totalOffset>>1]>>4 : tsrc[totalOffset>>1] & 0x0F) | 203 currentTile[0].paletteSel<<d.palShift); 204 }else static if(BMPType.mangleof == Bitmap8Bit.mangleof ){ 205 src[x] = cast(ushort)(tsrc[totalOffset] | currentTile[0].paletteSel<<d.palShift); 206 }else static if(BMPType.mangleof == Bitmap16Bit.mangleof){ 207 src[x] = tsrc[totalOffset]; 208 }else{ 209 *dest = *tsrc; 210 dest++; 211 } 212 }else{ 213 static if(BMPType.mangleof == Bitmap8Bit.mangleof || BMPType.mangleof == Bitmap16Bit.mangleof || 214 BMPType.mangleof == Bitmap4Bit.mangleof){ 215 src[x] = 0; 216 }else{ 217 (*dest).raw = 0; 218 } 219 } 220 x++; 221 if(currentTile[1].tileID != 0xFFFF){ 222 const DisplayListItem d = displayList[currentTile[1].tileID]; 223 static if(is(BMPType == Bitmap4Bit)){ 224 ubyte* tsrc = cast(ubyte*)d.pixelSrc; 225 }else static if(is(BMPType == Bitmap8Bit)){ 226 ubyte* tsrc = cast(ubyte*)d.pixelSrc; 227 }else static if(is(BMPType == Bitmap16Bit)){ 228 ushort* tsrc = cast(ushort*)d.pixelSrc; 229 }else static if(is(BMPType == Bitmap32Bit)){ 230 Color* tsrc = cast(Color*)d.pixelSrc; 231 } 232 xy[2] = xy[2] & (TileX - 1); 233 xy[3] = xy[3] & (TileY - 1); 234 const int totalOffset = xy[2] + xy[3] * TileX; 235 static if(BMPType.mangleof == Bitmap4Bit.mangleof){ 236 src[x] = cast(ushort)((totalOffset & 1 ? tsrc[totalOffset>>1]>>4 : tsrc[totalOffset>>1] & 0x0F) | 237 currentTile[1].paletteSel<<d.palShift); 238 } else static if(BMPType.mangleof == Bitmap8Bit.mangleof ) { 239 src[x] = cast(ushort)(tsrc[totalOffset] | currentTile[1].paletteSel<<d.palShift); 240 } else static if(BMPType.mangleof == Bitmap16Bit.mangleof) { 241 src[x] = tsrc[totalOffset]; 242 } else { 243 *dest = *tsrc; 244 dest++; 245 } 246 } else { 247 static if(BMPType.mangleof == Bitmap8Bit.mangleof || BMPType.mangleof == Bitmap16Bit.mangleof || 248 BMPType.mangleof == Bitmap4Bit.mangleof){ 249 src[x] = 0; 250 } else { 251 (*dest).raw = 0; 252 } 253 } 254 xy_in += _increment; 255 256 } 257 /+else { 258 for(short x; x < rasterX; x++){ 259 int[2] xy = transformFunctionInt([x,y], localTP, localTPO, sXsY); 260 //printf("[%i,%i]",xy[0],xy[1]); 261 MappingElement currentTile = tileByPixelWithoutTransform(xy[0],xy[1]); 262 if(currentTile.tileID != 0xFFFF){ 263 const DisplayListItem d = displayList[currentTile.tileID]; 264 static if(BMPType.mangleof == Bitmap4Bit.mangleof){ 265 ubyte* tsrc = cast(ubyte*)d.pixelSrc; 266 }else static if(BMPType.mangleof == Bitmap8Bit.mangleof){ 267 ubyte* tsrc = cast(ubyte*)d.pixelSrc; 268 }else static if(BMPType.mangleof == Bitmap16Bit.mangleof){ 269 ushort* tsrc = cast(ushort*)d.pixelSrc; 270 }else static if(BMPType.mangleof == Bitmap32Bit.mangleof){ 271 Color* tsrc = cast(Color*)d.pixelSrc; 272 } 273 xy[0] = xy[0] & (TileX - 1); 274 xy[1] = xy[1] & (TileY - 1); 275 const int totalOffset = xy[0] + xy[1] * TileX; 276 static if(BMPType.mangleof == Bitmap4Bit.mangleof){ 277 src[x] = (totalOffset & 1 ? tsrc[totalOffset>>1]>>4 : tsrc[totalOffset>>1] & 0x0F) | currentTile.paletteSel<<_paletteOffset; 278 }else static if(BMPType.mangleof == Bitmap8Bit.mangleof ){ 279 src[x] = tsrc[totalOffset] | currentTile.paletteSel<<_paletteOffset; 280 }else static if(BMPType.mangleof == Bitmap16Bit.mangleof){ 281 src[x] = tsrc[totalOffset]; 282 }else{ 283 *dest = *tsrc; 284 dest++; 285 } 286 }else{ 287 static if(BMPType.mangleof == Bitmap8Bit.mangleof || BMPType.mangleof == Bitmap16Bit.mangleof || 288 BMPType.mangleof == Bitmap4Bit.mangleof){ 289 src[x] = 0; 290 }else{ 291 (*dest).raw = 0; 292 } 293 } 294 } 295 }+/ 296 static if(BMPType.mangleof == Bitmap4Bit.mangleof || BMPType.mangleof == Bitmap8Bit.mangleof || 297 BMPType.mangleof == Bitmap16Bit.mangleof){ 298 mainColorLookupFunction(src.ptr, cast(uint*)dest, cast(uint*)palette + paletteOffset, rasterX); 299 dest += rasterX; 300 } 301 } 302 } 303 //render surface onto the raster 304 void* p0 = workpad; 305 Color* c = backbuffer.getPtr(); 306 for(int y; y < rasterY; y++){ 307 mainRenderingFunction(cast(uint*)c, cast(uint*)p0, rasterX, masterVal); 308 c += rasterX; 309 p0 += pitch; 310 } 311 312 } 313 ///Returns which tile is at the given pixel 314 public MappingElement tileByPixel(int x, int y) @nogc @safe pure nothrow const { 315 //static if (USE_INTEL_INTRINSICS) { 316 // return MappingElement.init; 317 //} else { 318 int[2] xy = transformFunctionInt([cast(short)x,cast(short)y],transformPoints,tpOrigin,[cast(short)sX,cast(short)sY]); 319 return tileByPixelWithoutTransform(xy[0],xy[1]); 320 //} 321 322 } 323 ///Returns which tile is at the given pixel. 324 final protected MappingElement tileByPixelWithoutTransform(int x, int y) @nogc @safe pure nothrow const { 325 x >>>= shiftX; 326 y >>>= shiftY; 327 final switch (warpMode) with (WarpMode) { 328 case Off: 329 if (x >= mX || y >= mY || x < 0 || y < 0) return MappingElement(0xFFFF); 330 break; 331 case MapRepeat: 332 x &= _mapAmpersand[0]; 333 y &= _mapAmpersand[1]; 334 break; 335 case TileRepeat: 336 if (x >= mX || y >= mY || x < 0 || y < 0) return MappingElement(0x0000); 337 break; 338 } 339 return mapping[x + y * mX]; 340 } 341 ///Returns two tiles to speed up rendering. 342 final protected MappingElement[2] tileByPixelWithoutTransform(__m128i params) @nogc @safe pure nothrow const { 343 //params >>>= mapShift; 344 params[0] >>= shiftX; 345 params[2] >>= shiftX; 346 params[1] >>= shiftY; 347 params[3] >>= shiftY; 348 MappingElement[2] result; 349 final switch (warpMode) with (WarpMode) { 350 case Off: 351 if (params[0] >= mX || params[1] >= mY || params[0] < 0 || params[1] < 0) result[0] = MappingElement(0xFFFF); 352 else result[0] = mapping[params[0] + params[1] * mX]; 353 if (params[2] >= mX || params[3] >= mY || params[2] < 0 || params[3] < 0) result[1] = MappingElement(0xFFFF); 354 else result[1] = mapping[params[2] + params[3] * mX]; 355 return result; 356 case MapRepeat: 357 params &= _mapAmpersand; 358 result[0] = mapping[params[0] + params[1] * mX]; 359 result[1] = mapping[params[2] + params[3] * mX]; 360 return result; 361 case TileRepeat: 362 if (params[0] >= mX || params[1] >= mY || params[0] < 0 || params[1] < 0) result[0] = MappingElement(0x0000); 363 else result[0] = mapping[params[0] + params[1] * mX]; 364 if (params[2] >= mX || params[3] >= mY || params[2] < 0 || params[3] < 0) result[1] = MappingElement(0x0000); 365 else result[1] = mapping[params[2] + params[3] * mX]; 366 return result; 367 } 368 } 369 /** 370 * Horizontal scaling. Greater than 256 means zooming in, less than 256 means zooming out. 371 */ 372 public @property short A() @nogc @safe nothrow pure const { 373 return transformPoints[0]; 374 } 375 /** 376 * Horizontal shearing. 377 */ 378 public @property short B() @nogc @safe nothrow pure const { 379 return transformPoints[1]; 380 } 381 /** 382 * Vertical shearing. 383 */ 384 public @property short C() @nogc @safe nothrow pure const { 385 return transformPoints[2]; 386 } 387 /** 388 * Vertical scaling. Greater than 256 means zooming in, less than 256 means zooming out. 389 */ 390 public @property short D() @nogc @safe nothrow pure const { 391 return transformPoints[3]; 392 } 393 /** 394 * Horizontal transformation offset. 395 */ 396 public @property short x_0() @nogc @safe nothrow pure const { 397 return tpOrigin[0]; 398 } 399 /** 400 * Vertical transformation offset. 401 */ 402 public @property short y_0() @nogc @safe nothrow pure const { 403 return tpOrigin[1]; 404 } 405 /** 406 * Horizontal scaling. Greater than 256 means zooming in, less than 256 means zooming out. 407 */ 408 public @property short A(short newval) @nogc @safe nothrow pure { 409 transformPoints[0] = newval; 410 needsUpdate = true; 411 return transformPoints[0]; 412 } 413 /** 414 * Horizontal shearing. 415 */ 416 public @property short B(short newval) @nogc @safe nothrow pure { 417 transformPoints[1] = newval; 418 needsUpdate = true; 419 return transformPoints[1]; 420 } 421 /** 422 * Vertical shearing. 423 */ 424 public @property short C(short newval) @nogc @safe nothrow pure { 425 transformPoints[2] = newval; 426 needsUpdate = true; 427 return transformPoints[2]; 428 } 429 /** 430 * Vertical scaling. Greater than 256 means zooming in, less than 256 means zooming out. 431 */ 432 public @property short D(short newval) @nogc @safe nothrow pure { 433 transformPoints[3] = newval; 434 needsUpdate = true; 435 return transformPoints[3]; 436 } 437 /** 438 * Horizontal transformation offset. 439 */ 440 public @property short x_0(short newval) @nogc @safe nothrow pure { 441 tpOrigin[0] = newval; 442 //tpOrigin[2] = newval; 443 needsUpdate = true; 444 return tpOrigin[0]; 445 } 446 /** 447 * Vertical transformation offset. 448 */ 449 public @property short y_0(short newval) @nogc @safe nothrow pure { 450 tpOrigin[1] = newval; 451 //tpOrigin[3] = newval; 452 needsUpdate = true; 453 return tpOrigin[1]; 454 } 455 override public void scroll(int x,int y) { 456 super.scroll(x,y); 457 needsUpdate = true; 458 } 459 override public void relScroll(int x,int y) { 460 super.relScroll(x,y); 461 needsUpdate = true; 462 } 463 public MappingElement[] getMapping() @nogc @safe pure nothrow { 464 return mapping; 465 } 466 /+public MappingElement readMapping(int x, int y) @nogc @safe pure nothrow const { 467 return mapping[(y * mX) + x]; 468 }+/ 469 public int getTileWidth() @nogc @safe pure nothrow const { 470 return TileX; 471 } 472 public int getTileHeight() @nogc @safe pure nothrow const { 473 return TileY; 474 } 475 public int getMX() @nogc @safe pure nothrow const { 476 return mX; 477 } 478 public int getMY() @nogc @safe pure nothrow const { 479 return mY; 480 } 481 public size_t getTX() @nogc @safe pure nothrow const { 482 return totalX; 483 } 484 public size_t getTY() @nogc @safe pure nothrow const { 485 return totalY; 486 } 487 /// Sets the warp mode. 488 /// Returns the new warp mode that is being used. 489 public WarpMode setWarpMode(WarpMode mode) @nogc @safe pure nothrow { 490 return warpMode = mode; 491 } 492 /// Returns the currently used warp mode. 493 public WarpMode getWarpMode() @nogc @safe pure nothrow const { 494 return warpMode; 495 } 496 ///Gets the the ID of the given element from the mapping. x , y : Position. 497 public MappingElement readMapping(int x, int y) @nogc @safe pure nothrow const { 498 if(!warpMode){ 499 if(x < 0 || y < 0 || x >= mX || y >= mY){ 500 return MappingElement(0xFFFF); 501 } 502 }else{ 503 x = x % mX; 504 y = y % mY; 505 } 506 return mapping[x+(mX*y)]; 507 } 508 ///Writes to the map. x , y : Position. w : ID of the tile. 509 @nogc public void writeMapping(int x, int y, MappingElement w) { 510 mapping[x+(mX*y)]=w; 511 } 512 public void addTile(ABitmap tile, wchar id, ubyte paletteSh = 0) { 513 if(typeid(tile) !is typeid(BMPType)){ 514 throw new TileFormatException("Incorrect type of tile!"); 515 } 516 if(tile.width == TileX && tile.height == TileY){ 517 displayList[id] = DisplayListItem(id, cast(BMPType)tile, paletteSh); 518 }else{ 519 throw new TileFormatException("Incorrect tile size!", __FILE__, __LINE__, null); 520 } 521 } 522 ///Returns a tile from the displaylist 523 public ABitmap getTile(wchar id) { 524 return displayList[id].tile; 525 } 526 ///Removes the tile with the ID from the set. 527 public void removeTile(wchar id){ 528 displayList.remove(id); 529 } 530 ///Loads a mapping from an array. x , y : Sizes of the mapping. map : an array representing the elements of the map. 531 ///x*y=map.length 532 public void loadMapping(int x, int y, MappingElement[] mapping) { 533 if (!isPowerOf2(x) || !isPowerOf2(y)) 534 throw new MapFormatException("Map sizes are not power of two!"); 535 if (x * y != mapping.length) 536 throw new MapFormatException("Incorrect map sizes!"); 537 mX=x; 538 mY=y; 539 _mapAmpersand[0] = x - 1; 540 _mapAmpersand[1] = y - 1; 541 _mapAmpersand[2] = x - 1; 542 _mapAmpersand[3] = y - 1; 543 this.mapping = mapping; 544 totalX=mX*TileX; 545 totalY=mY*TileY; 546 } 547 public void clearTilemap() @nogc @safe pure nothrow { 548 for (size_t i ; i < mapping.length ; i++) { 549 mapping[i] = MappingElement.init; 550 } 551 } 552 }