/* Default implementation of tile_rectangle */ int gx_default_tile_rectangle(gx_device *dev, register gx_bitmap *tile, int x, int y, int w, int h, gx_color_index color0, gx_color_index color1) { /* Fill the rectangle in chunks */ int width = tile->width; int height = tile->height; int raster = tile->raster; int ex = x + w, ey = y + h; int fex = ex - width, fey = ey - height; int irx = ((width & (width - 1)) == 0 ? /* power of 2 */ x & (width - 1) : x % width); int ry = y % height; int icw = width - irx; int ch = height - ry; byte *row = tile->data + ry * raster; int (*proc_mono)(P10(gx_device *, byte *, int, int, int, int, int, int, gx_color_index, gx_color_index)); int (*proc_color)(P8(gx_device *, byte *, int, int, int, int, int, int)); int color_halftone = (color0 == gx_no_color_index && color1 == gx_no_color_index); int cx, cy; if ( color_halftone ) proc_color = dev->procs->copy_color; else proc_mono = dev->procs->copy_mono; #ifdef DEBUG if ( gs_debug['t'] ) { int ptx, pty; byte *ptp = tile->data; printf("[t]tile w=%d h=%d raster=%d; x=%d y=%d w=%d h=%d\n", tile->width, tile->height, tile->raster, x, y, w, h); for ( pty = 0; pty < tile->height; pty++ ) { printf(" "); for ( ptx = 0; ptx < tile->raster; ptx++ ) printf("%3x", *ptp++); } printf("\n"); } #endif if ( icw > w ) icw = w; if ( ch > h ) ch = h; #define real_copy_tile(sourcex, tx, tw)\ (color_halftone ?\ (*proc_color)(dev, row, sourcex, raster, tx, cy, tw, ch) :\ (*proc_mono)(dev, row, sourcex, raster, tx, cy, tw, ch, color0, color1)) #ifdef DEBUG #define copy_tile(sx, tx, tw)\ if ( gs_debug['t'] )\ printf(" copy sx=%d x=%d y=%d w=%d h=%d\n",\ sx, tx, cy, tw, ch);\ real_copy_tile(sx, tx, tw) #else #define copy_tile(sx, tx, tw)\ real_copy_tile(sx, tx, tw) #endif for ( cy = y; cy < ey; ) { copy_tile(irx, x, icw); cx = x + icw; while ( cx <= fex ) { copy_tile(0, cx, width); cx += width; } if ( cx < ex ) { copy_tile(0, cx, ex - cx); } cy += ch; ch = (cy > fey ? ey - cy : height); row = tile->data; } #undef copy_tile #undef real_copy_tile return 0; }
// Find the block boundary for each discard level in the input image. // We parse the input blocks and copy them in a temporary output stream. // For the moment, we do nothing more that parsing the raw list of blocks and outputing result. void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base) { // We need the number of levels in that image before starting. getMetadata(base); for (int discard_level = 0; discard_level < mLevels; discard_level++) { //std::cout << "Parsing discard level = " << discard_level << std::endl; // Create the input codestream object. setupCodeStream(base, TRUE, MODE_FAST); mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL); mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true); siz_params *siz_in = mCodeStreamp->access_siz(); // Create the output codestream object. siz_params siz; siz.copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false); siz.set(Scomponents,0,0,mCodeStreamp->get_num_components()); U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents(); max_output_size = (max_output_size < 1000 ? 1000 : max_output_size); U8 *output_buffer = new U8[max_output_size]; U32 output_size = 0; // Address updated by LLKDUMemTarget to give the final compressed buffer size LLKDUMemTarget output(output_buffer, output_size, max_output_size); kdu_codestream codestream_out; codestream_out.create(&siz,&output); //codestream_out.share_buffering(*mCodeStreamp); siz_params *siz_out = codestream_out.access_siz(); siz_out->copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false); codestream_out.access_siz()->finalize_all(-1); // Set up rate control variables kdu_long max_bytes = KDU_LONG_MAX; kdu_params *cod = siz_out->access_cluster(COD_params); int total_layers; cod->get(Clayers,0,0,total_layers); kdu_long *layer_bytes = new kdu_long[total_layers]; int nel, non_empty_layers = 0; // Now ready to perform the transfer of compressed data between streams int flush_counter = INT_MAX; kdu_dims tile_indices_in; mCodeStreamp->get_valid_tiles(tile_indices_in); kdu_dims tile_indices_out; codestream_out.get_valid_tiles(tile_indices_out); assert((tile_indices_in.size.x == tile_indices_out.size.x) && (tile_indices_in.size.y == tile_indices_out.size.y)); int num_blocks=0; kdu_coords idx; //std::cout << "Parsing tiles : x = " << tile_indices_out.size.x << " to y = " << tile_indices_out.size.y << std::endl; for (idx.y=0; idx.y < tile_indices_out.size.y; idx.y++) { for (idx.x=0; idx.x < tile_indices_out.size.x; idx.x++) { kdu_tile tile_in = mCodeStreamp->open_tile(idx+tile_indices_in.pos); int tnum_in = tile_in.get_tnum(); int tnum_out = idx.x + idx.y*tile_indices_out.size.x; siz_out->copy_from(siz_in,tnum_in,tnum_out,0,0,discard_level,false,false,false); siz_out->finalize_all(tnum_out); // Note: do not open the output tile without first copying any tile-specific code-stream parameters kdu_tile tile_out = codestream_out.open_tile(idx+tile_indices_out.pos); assert(tnum_out == tile_out.get_tnum()); copy_tile(tile_in,tile_out,tnum_in,tnum_out,siz_in,siz_out,0,num_blocks); tile_in.close(); tile_out.close(); flush_counter--; if ((flush_counter <= 0) && codestream_out.ready_for_flush()) { flush_counter = INT_MAX; nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers); non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers; } } } // Generate the output code-stream if (codestream_out.ready_for_flush()) { nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers); non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers; } if (non_empty_layers > total_layers) non_empty_layers = total_layers; // Can happen if a tile has more layers // Print out stats std::cout << "Code stream parsing for discard level = " << discard_level << std::endl; std::cout << " Total compressed memory in = " << mCodeStreamp->get_compressed_data_memory() << " bytes" << std::endl; std::cout << " Total compressed memory out = " << codestream_out.get_compressed_data_memory() << " bytes" << std::endl; //std::cout << " Output contains " << total_layers << " quality layers" << std::endl; std::cout << " Transferred " << num_blocks << " code-blocks from in to out" << std::endl; //std::cout << " Read " << mCodeStreamp->get_num_tparts() << " tile-part(s) from a total of " << (int) tile_indices_in.area() << " tile(s)" << std::endl; std::cout << " Total bytes read = " << mCodeStreamp->get_total_bytes() << std::endl; //std::cout << " Wrote " << codestream_out.get_num_tparts() << " tile-part(s) in a total of " << (int) tile_indices_out.area() << " tile(s)" << std::endl; std::cout << " Total bytes written = " << codestream_out.get_total_bytes() << std::endl; std::cout << "-------------" << std::endl; // Clean-up cleanupCodeStream(); codestream_out.destroy(); delete[] output_buffer; } return; }
/* Note that this also does the right thing for colored tiles. */ static int win_ddb_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile, int x, int y, int w, int h, gx_color_index czero, gx_color_index cone, int px, int py) { fit_fill(dev, x, y, w, h); if (czero != gx_no_color_index && cone != gx_no_color_index) { fill_rect(x, y, w, h, czero); czero = gx_no_color_index; } if (tile->raster == bmWidthBytes && tile->size.y <= bmHeight && (px | py) == 0 && cone != gx_no_color_index ) { /* We can do this much more efficiently */ /* by using the internal algorithms of copy_mono */ /* and gx_default_tile_rectangle. */ int width = tile->size.x; int height = tile->size.y; int rwidth = tile->rep_width; int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ x & (rwidth - 1) : x % rwidth); int ry = y % tile->rep_height; int icw = width - irx; int ch = height - ry; int ex = x + w, ey = y + h; int fex = ex - width, fey = ey - height; int cx, cy; select_brush((int)cone); if (tile->id != wdev->bm_id || tile->id == gx_no_bitmap_id) { wdev->bm_id = tile->id; SetBitmapBits(wdev->hbmmono, (DWORD) (bmWidthBytes * tile->size.y), (BYTE *) tile->data); } #define copy_tile(srcx, srcy, tx, ty, tw, th)\ BitBlt(wdev->hdcbit, tx, ty, tw, th, wdev->hdcmono, srcx, srcy, rop_write_at_1s) if (ch > h) ch = h; for (cy = y;;) { if (w <= icw) copy_tile(irx, ry, x, cy, w, ch); else { copy_tile(irx, ry, x, cy, icw, ch); cx = x + icw; while (cx <= fex) { copy_tile(0, ry, cx, cy, width, ch); cx += width; } if (cx < ex) { copy_tile(0, ry, cx, cy, ex - cx, ch); } } if ((cy += ch) >= ey) break; ch = (cy > fey ? ey - cy : height); ry = 0; } win_update((gx_device_win *) dev); return 0; } return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py); }
static void loadsty(char* filename, char* exprt, char* setname_tex, char* setname_spr, char* setname_font, char* etiles, char* esprites) { sty = fopen(filename,"rb"); fseek(sty,0,2); int filesize = ftell(sty); fseek(sty,0,0); printf("Reading %s...\n",filename); FREAD(&chunkheader, 1, 4, sty, filename, printf); FREAD(&chunkdata, 2, 1, sty, filename, printf); if (chunkheader != 0x54534247) { //GBST printf("Not a GTA2 style file!\n"); return; } if ((chunkdata & 0xFFFF) != 700) { printf("Bad GTA2 style file version (must be 700)\n"); return; } sprite_count = 0; bool TilesPresent = false; bool SpritesPresent = false; //read map chunks while (ftell(sty) < filesize) { FREAD(&chunkheader, 1, 4, sty, filename, printf); FREAD(&chunkdata, 1, 4, sty, filename, printf); printf("\n"); /* PALX palette index PPAL physical palettes PALB palette base TILE tiles SPRG sprite graphics SPRX sprite index SPRB sprites bases DELS delta store DELX delta index FONB font base CARI car info OBJI map object info PSXT PSX tiles RECY car recycling info*/ switch (chunkheader) { case 0x584C4150: //PALX printf("PALX: Found PALX chunk [size: %d]\n",chunkdata); printf("PALX: Reading %d pallete entries\n",chunkdata/2); FREAD(&pallete_index,1,32768,sty, filename, printf); break; case 0x4C415050: //PPAL printf("PPAL: Found PPAL chunk [size: %d]\n",chunkdata); printf("PPAL: Reading %d pallete pages (%d palletes)\n",chunkdata/(64*1024),chunkdata/(1024)); FREAD(&pallete,4,chunkdata/4,sty, filename, printf); break; case 0x424C4150: //PALB printf("PALB: Found PALB chunk [size: %d]\n",chunkdata); printf("PALB: Reading pallete bases...\n"); FREAD(&palletebase.tile,2,1,sty, filename, printf); FREAD(&palletebase.sprite,2,1,sty, filename, printf); FREAD(&palletebase.car_remap,2,1,sty, filename, printf); FREAD(&palletebase.ped_remap,2,1,sty, filename, printf); FREAD(&palletebase.code_obj_remap,2,1,sty, filename, printf); FREAD(&palletebase.map_obj_remap,2,1,sty, filename, printf); FREAD(&palletebase.user_remap,2,1,sty, filename, printf); FREAD(&palletebase.font_remap,2,1,sty, filename, printf); printf("PALB: tile base: %d\n",palletebase.tile); printf("PALB: sprite base: %d\n",palletebase.sprite); printf("PALB: car_remap base: %d\n",palletebase.car_remap); printf("PALB: ped_remap base: %d\n",palletebase.ped_remap); printf("PALB: code_obj_remap base: %d\n",palletebase.code_obj_remap); printf("PALB: map_obj_remap base: %d\n",palletebase.map_obj_remap); printf("PALB: user_remap base: %d\n",palletebase.user_remap); printf("PALB: font_remap base: %d\n",palletebase.font_remap); break; case 0x454C4954: //TILE printf("TILE: Found TILE chunk [size: %d]\n",chunkdata); printf("TILE: Reading %d tiles...\n",chunkdata/(64*64)); FREAD(&tile_data,1,chunkdata,sty, filename, printf); TilesPresent = true; break; case 0x47525053: //SPRG printf("SPRG: Found SPRG chunk [size: %d]\n",chunkdata); printf("SPRG: Reading sprite graphics\n"); FREAD(&spritedata[0],1,chunkdata,sty, filename, printf); SpritesPresent = true; break; case 0x58525053: //SPRX printf("SPRX: Found SPRX chunk [size: %d]\n",chunkdata); printf("SPRX: Reading %d sprites...\n",chunkdata/8); FREAD(&sprite_entries[0],1,chunkdata,sty, filename, printf); sprite_count = chunkdata/8; break; case 0x42525053: //SPRB unsigned short temp; printf("SPRB: Found SPRB chunk [size: %d]\n",chunkdata); printf("SPRB: Reading sprite bases...\n"); spritebase.car = 0; FREAD(&temp,2,1,sty, filename, printf); spritebase.ped = spritebase.car + temp; FREAD(&temp,2,1,sty, filename, printf); spritebase.code_obj = spritebase.ped + temp; FREAD(&temp,2,1,sty, filename, printf); spritebase.map_obj = spritebase.code_obj + temp; FREAD(&temp,2,1,sty, filename, printf); spritebase.user = spritebase.map_obj + temp; FREAD(&temp,2,1,sty, filename, printf); spritebase.font = spritebase.user + temp; FREAD(&temp,2,1,sty, filename, printf); /*spritebase.ped = spritebase.car; spritebase.car = 0; spritebase.code_obj += spritebase.ped; spritebase.map_obj += spritebase.code_obj; spritebase.user += spritebase.map_obj; spritebase.font += spritebase.user;*/ printf("SPRB: car base: %d\n",spritebase.car); printf("SPRB: ped base: %d\n",spritebase.ped); printf("SPRB: code_obj base: %d\n",spritebase.code_obj); printf("SPRB: map_obj base: %d\n",spritebase.map_obj); printf("SPRB: user base: %d\n",spritebase.user); printf("SPRB: font base: %d\n",spritebase.font); break; case 0x534C4544: //DELS printf("DELS: Found DELS chunk [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; case 0x584C4544: //DELX printf("DELX: Found DELX chunk [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; case 0x424E4F46: //FONB printf("FONB: Found FONB chunk [size: %d]\n",chunkdata); //fseek(sty,chunkdata,1); FREAD(&fontbase.font_count,2,1,sty, filename, printf); printf("FONB: Found %d fonts...\n",fontbase.font_count); fontbase.sprbase[0] = spritebase.font; for (int i=0;i<fontbase.font_count;i++) { FREAD(&fontbase.base[i],2,1,sty, filename, printf); if (i > 0) fontbase.sprbase[i] = fontbase.sprbase[i-1] + fontbase.base[i]; printf("FONB: Font %d [%d characters, sprbase %d]\n",i,fontbase.base[i],fontbase.sprbase[i]); } break; case 0x49524143: //CARI printf("CARI: Found CARI chunk [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; case 0x494A424F: //OBJI printf("OBJI: Found OBJI chunk [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; case 0x54585350: //PSXT printf("PSXT: Found PSXT chunk, skipping (dont need PSX tiles) [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; case 0x59434552: //RECY printf("RECY: Found RECY chunk [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; case 0x43455053: //SPEC printf("SPEC: Undocumented SPEC chunk, skipping [size: %d]\n",chunkdata); fseek(sty,chunkdata,1); break; default: printf("UNKN: Unknown/unsupported chunk, skipping [size: %d]\n",chunkdata); fseek(sty,chunkdata,SEEK_CUR); break; } } if (strcmp(exprt,"true") == 0) { if (strcmp(etiles,"true") != 0) { printf("\nExporting tiles...\n"); for (int i=0;i<992;i++) { char tilename[256]; sprintf(&tilename[0],"tile_%d.bmp",i); save_tile(&tilename[0],i); printf("..writing tile bitmaps %d\r",i); } } if (strcmp(esprites,"true") == 0) { printf("\n\nExporting sprites...\n"); for (int i=0;i<sprite_count;i++) { char tilename[256]; sprintf(&tilename[0],"sprite_%d.bmp",i); save_sprite(&tilename[0],i); printf("..writing sprite %d\r",i); } } } printf("\nSaving graphics (opengta.tex)\n"); bmp = fopen("opengta.tex","wb+"); char header[5] = "ZTEX"; int chunksize = 4; int texversion = 130; fwrite(&header[0],1,4,bmp); //"ZTEX" fwrite(&chunksize,4,1,bmp); fwrite(&texversion,4,1,bmp); printf("\tchunk %s (%d bytes)\n",header,chunksize); if (strcmp(etiles,"true") != 0) { TilesPresent = false; } if (strcmp(esprites,"true") != 0) { SpritesPresent = false; } //Write tile data int cpos; if (TilesPresent) { sprintf(header,"%s","TILE"); chunksize = 0; fwrite(&header[0],1,4,bmp); //"TILE" cpos = ftell(bmp); chunksize += fwrite(&chunksize,4,1,bmp); texversion = strlen(setname_tex); chunksize += fwrite(&texversion,1,1,bmp); //TILEID: 0 chunksize += fwrite(&setname_tex[0],1,texversion,bmp); printf("\t\tGenerating texture atlas for tiles\n"); Texture_Atlas tileAtlas; tileAtlas.createEmpty(2048,2048); tileAtlas.atlasStart(1024); for (int i=0;i<992;i++) { copy_tile(i); printf("\t\tTile: %d out of %d\r",i,992); tileAtlas.atlasAdd(0x1,0x0,4,64,64,(unsigned char*)&sprite_buffer[0]); //write_tile_tex(i); } printf("\nEffective atlas size: %d bytes (%d KB)\n",tileAtlas.effectiveSize(),tileAtlas.effectiveSize() / 1024); tileAtlas.atlasStop(); tileAtlas.dumpBMP("tiles.bmp"); //Write atlas chunksize += fwrite(tileAtlas.textureData,1,tileAtlas.effectiveSize(),bmp); //for (int y = 0; y < tileAtlas.atlasHeight; y++) //for (int x = 0; x < tileAtlas.atlasWidth; x++) //fwrite(&tileAtlas.textureData[x+y*tileAtlas.atlasWidth],4,1,bmp); tileAtlas.releaseTexture(); printf("\tchunk %s (%d bytes)\n",header,chunksize); fseek(bmp,cpos,0); fwrite(&chunksize,4,1,bmp); fseek(bmp,chunksize,1); } //Write sprite data if (SpritesPresent) { sprintf(header,"%s","SPR0"); chunksize = 0; fwrite(&header[0],1,4,bmp); //"SPR0" (sprite data) cpos = ftell(bmp); fwrite(&chunksize,4,1,bmp); texversion = strlen(setname_spr); chunksize += fwrite(&texversion,1,1,bmp); //TILEID: 0 chunksize += fwrite(&setname_spr[0],1,texversion,bmp); //Prepare tiles for (int i = 0; i < sprite_count; i++) sprite_entries[i].pad = i; sort_tiles(); printf("\t\tGenerating texture atlas for sprites (takes a while)\n"); Texture_Atlas spriteAtlas; spriteAtlas.createEmpty(2048,2048); spriteAtlas.atlasStart(8192); //sprite_count = 64; int atlasid[8192]; for (int i=0;i<sprite_count;i++) { copy_sprite(i); printf("\t\tSprite: %d out of %d\r",i,sprite_count); atlasid[sprite_entries[i].pad] = spriteAtlas.atlasAdd(0x1,0x0,4,sprite_entries[i].w,sprite_entries[i].h,(unsigned char*)&sprite_buffer[0]); } printf("\nEffective atlas size: %d bytes (%d KB)\n",spriteAtlas.effectiveSize(),spriteAtlas.effectiveSize() / 1024); printf("\t\tWriting sprites\n"); //Unsort sprites (from previous sort request) bool all_sort; do { all_sort = true; for (int i = 0; i < sprite_count; i++) if (sprite_entries[i].pad != i) { int j = sprite_entries[i].pad; sprite_entry tmp = sprite_entries[i]; sprite_entries[i] = sprite_entries[j]; sprite_entries[j] = tmp; all_sort = false; } } while (all_sort == false); //Write sprite information chunksize += 4*fwrite(&sprite_count,4,1,bmp); for (int i=0;i<sprite_count;i++) { char spritename[256]; sprintf(&spritename[0],"%s_%d",setname_spr,i); unsigned char namelen = strlen(&spritename[0]); chunksize += fwrite(&namelen,1,1,bmp); chunksize += fwrite(&spritename[0],1,namelen,bmp); //chunksize += fwrite(&sprite_entries[i].w,1,1,bmp); //chunksize += fwrite(&sprite_entries[i].h,1,1,bmp); //chunksize += fwrite(&sprite_entries[i].,1,1,bmp); chunksize += 4*fwrite(&spriteAtlas.atlasTextures[atlasid[i]].Left,4,1,bmp); chunksize += 4*fwrite(&spriteAtlas.atlasTextures[atlasid[i]].Right,4,1,bmp); chunksize += 4*fwrite(&spriteAtlas.atlasTextures[atlasid[i]].Top,4,1,bmp); chunksize += 4*fwrite(&spriteAtlas.atlasTextures[atlasid[i]].Bottom,4,1,bmp); } spriteAtlas.atlasStop(); spriteAtlas.dumpBMP("sprites.bmp"); //Write atlas chunksize += fwrite(spriteAtlas.textureData,1,spriteAtlas.effectiveSize(),bmp); //for (int y = 0; y < spriteAtlas.atlasHeight; y++) //for (int x = 0; x < spriteAtlas.atlasWidth; x++) //fwrite(&spriteAtlas.textureData[x+y*spriteAtlas.atlasWidth],4,1,bmp); spriteAtlas.releaseTexture(); printf(" chunk %s (%d bytes)\n",header,chunksize); fseek(bmp,cpos,0); fwrite(&chunksize,4,1,bmp); fseek(bmp,chunksize,1); sprintf(header,"%s","FNT0"); chunksize = 0; fwrite(&header[0],1,4,bmp); //"FNT0" (sprite data) cpos = ftell(bmp); fwrite(&chunksize,4,1,bmp); chunksize += 2*fwrite(&fontbase.font_count,2,1,bmp); //Font count //texversion = strlen(setname_spr); //chunksize += fwrite(&texversion,1,1,bmp); //TILEID: 0 //chunksize += fwrite(&setname_spr[0],1,texversion,bmp); printf("\t\tWriting fonts\n"); for (int i=0;i<fontbase.font_count;i++) { char fontname[256]; sprintf(&fontname[0],"%s_%d",setname_font,i); unsigned char namelen = strlen(&fontname[0]); unsigned short numchars = fontbase.base[i] + '!'; chunksize += fwrite(&namelen,1,1,bmp); chunksize += fwrite(&fontname[0],1,namelen,bmp); chunksize += 2*fwrite(&numchars,2,1,bmp); for (int k = 0; k < numchars; k++) { char charname[256]; if ((k >= '!') && (k <= numchars)) { sprintf(charname,"%s_%d",setname_spr,k-'!'+fontbase.sprbase[i]); namelen = strlen(charname); } else { namelen = 0; } chunksize += fwrite(&namelen,1,1,bmp); chunksize += fwrite(&charname[0],1,namelen,bmp); } } printf(" chunk %s (%d bytes)\n",header,chunksize); fseek(bmp,cpos,0); fwrite(&chunksize,4,1,bmp); fseek(bmp,chunksize,1); } fclose(bmp); /* ZTEX Texture file header SPR0 GTA2-exported sprites (2048x2048 atlas) SPR1 GTA2-exported sprites (1024x1024 atlas) SPR2 GTA2-exported sprites (256x256 atlas) SPR3 OpenGTA2 sprites (variable atlas size) TILE GTA2-exported tiles (2048x2048 atlas by 64x64 tiles) TIL1 GTA2-exported tiles (1024x1024 atlas) TIL2 GTA2-exported tiles (256x256 atlas) TIL3 OpenGTA2 tiles (variable tile size, variable atlas size) FNT0 GTA2-exported fonts FNT1 OpenGTA2 fonts (sprite based) FNT2 OpenGTA2 fonts (with font graphics) PACK Packed information (unpacked into different chunk) */ printf("\nDone!\n"); fclose(sty); }
/* Default implementation of tile_rectangle */ int gx_default_tile_rectangle(gx_device *dev, register const gx_bitmap *tile, int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, int px, int py) { /* Fill the rectangle in chunks */ int width = tile->size.x; int height = tile->size.y; int raster = tile->raster; int rwidth = tile->rep_width; int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ (x + px) & (rwidth - 1) : (x + px) % rwidth); int ry = (y + py) % tile->rep_height; int icw = width - irx; int ch = height - ry; byte *row = tile->data + ry * raster; #define d_proc_mono (dev->procs->copy_mono) dev_proc_copy_mono((*proc_mono)); #define d_proc_color (dev->procs->copy_color) dev_proc_copy_color((*proc_color)); #define d_color_halftone\ (color0 == gx_no_color_index && color1 == gx_no_color_index) int color_halftone; #define get_color_info()\ if ( (color_halftone = d_color_halftone) ) proc_color = d_proc_color;\ else proc_mono = d_proc_mono int code; #ifdef DEBUG if ( gs_debug['t'] ) { int ptx, pty; const byte *ptp = tile->data; dprintf3("[t]tile %dx%d raster=%d;", tile->size.x, tile->size.y, tile->raster); dprintf6(" x,y=%d,%d w,h=%d,%d p=%d,%d\n", x, y, w, h, px, py); for ( pty = 0; pty < tile->size.y; pty++ ) { dprintf(" "); for ( ptx = 0; ptx < tile->raster; ptx++ ) dprintf1("%3x", *ptp++); } dputc('\n'); } #endif #define real_copy_tile(srcx, tx, ty, tw, th)\ code =\ (color_halftone ?\ (*proc_color)(dev, row, srcx, raster, gx_no_bitmap_id, tx, ty, tw, th) :\ (*proc_mono)(dev, row, srcx, raster, gx_no_bitmap_id, tx, ty, tw, th, color0, color1));\ gp_check_interrupts();\ if ( code < 0 ) return_error(code) #ifdef DEBUG #define copy_tile(sx, tx, ty, tw, th)\ if ( gs_debug['t'] )\ dprintf5(" copy sx=%d x=%d y=%d w=%d h=%d\n",\ sx, tx, ty, tw, th);\ real_copy_tile(sx, tx, ty, tw, th) #else #define copy_tile(sx, tx, ty, tw, th)\ real_copy_tile(sx, tx, ty, tw, th) #endif if ( icw >= w ) { /* Narrow operation */ int ey, fey, cy; if ( ch >= h ) { /* Just one (partial) tile to transfer. */ #define color_halftone d_color_halftone #define proc_color d_proc_color #define proc_mono d_proc_mono copy_tile(irx, x, y, w, h); #undef proc_mono #undef proc_color #undef color_halftone return 0; } get_color_info(); ey = y + h; fey = ey - height; copy_tile(irx, x, y, w, ch); cy = y + ch; row = tile->data; do { ch = (cy > fey ? ey - cy : height); copy_tile(irx, x, cy, w, ch); } while ( (cy += ch) < ey ); return 0; } get_color_info(); if ( ch >= h ) { /* Shallow operation */ int ex = x + w; int fex = ex - width; int cx = x + icw; copy_tile(irx, x, y, icw, h); while ( cx <= fex ) { copy_tile(0, cx, y, width, h); cx += width; } if ( cx < ex ) { copy_tile(0, cx, y, ex - cx, h); } } else { /* Full operation */ int ex = x + w, ey = y + h; int fex = ex - width, fey = ey - height; int cx, cy; for ( cy = y; ; ) { copy_tile(irx, x, cy, icw, ch); cx = x + icw; while ( cx <= fex ) { copy_tile(0, cx, cy, width, ch); cx += width; } if ( cx < ex ) { copy_tile(0, cx, cy, ex - cx, ch); } if ( (cy += ch) >= ey ) break; ch = (cy > fey ? ey - cy : height); row = tile->data; } } #undef copy_tile #undef real_copy_tile return 0; }