/*! \note Still very unsafe, but I need to redo everything later anyway. */ void grs_run(GritShared *grs, GritRec *gr_base) { // Make sure we have shared data. if( grs->dib==NULL && grs->palRec.data==NULL) { lprintf(LOG_WARNING, "No shared data to run with!\n"); return; } // Make copy of gr_base for flags, etc GritRec *gr= grit_alloc(); grs_free(gr->shared); grit_copy_options(gr, gr_base); grit_copy_strings(gr, gr_base); // Attach shared data gr->shared= grs; strrepl(&gr->symName, grs->symName); strrepl(&gr->dstPath, grs->dstPath); if(grs->dib == NULL) { // Palette only. Create new dib. gr->srcDib= dib_alloc(16, 16, 8, NULL); memset(dib_get_pal(gr->srcDib), 0, PAL_MAX*RGB_SIZE); memcpy(dib_get_pal(gr->srcDib), grs->palRec.data, rec_size(&grs->palRec)); } else gr->srcDib= dib_clone(grs->dib); // NOTE: aliasing screws up deletion later; detach manually. gr->_dib= gr->srcDib; // Run for shared gr do { if(!grit_validate(gr)) break; bool grit_prep_gfx(GritRec *gr); bool grit_prep_shared_pal(GritRec *gr); if(gr->gfxProcMode != GRIT_EXCLUDE) grit_prep_gfx(gr); if(gr->palProcMode != GRIT_EXCLUDE) grit_prep_shared_pal(gr); if(gr->bExport) grit_export(gr); } while(0); gr->_dib= NULL; // Detach shared data and delete gr gr->shared= NULL; grit_free(gr); }
BOOL CxpGbaDlg::UpdateGritRec(BOOL b2gr) { DWORD dw; char str[MAXPATHLEN]; // TODO: al/gfx trans ; img modes ; tileset if(b2gr) // data -> gr { UpdateData(TRUE); SetDstPath(mDstPath); // clear previous gr data grit_clear(mgr); grs_clear(mgr->shared); mgr->bExport= true; // Yes, yes, very wasteful mgr->srcDib= dib_clone(mpDib); mgr->bHeader= mbHeader==TRUE; mgr->bAppend= mbAppend==TRUE; mgr->fileType= mFileType; // TODO check whether this is all OK!! if(mbSymChk) mgr->symName= strdup(mSymName); else mgr->symName= strdup(mDstTitle); // make sure it's a valid C varname str_fix_ident(mgr->symName, mgr->symName, strlen(mgr->symName)); sprintf(str, "%s/%s.%s", mDstDir, mDstTitle, c_fileTypes[mFileType]); mgr->dstPath= strdup(str); // --- palette --- if(mbPal) { mgr->palProcMode= GRIT_EXPORT; mgr->palStart= mPalStart; mgr->palEnd= mPalStart+mPalCount; if(mgr->palEnd > 256) mgr->palEnd= 256; if(mPalTrans != 0) { mgr->palHasAlpha= true; mgr->palAlphaId= mPalTrans; } } // --- image --- // NOTE: we should probably always process the image, // just not necessarily export if(1) { if(mbGfx) mgr->gfxProcMode= GRIT_EXPORT; switch(mGfxMode) { case GFX_MODE_TILE: mgr->gfxMode= GRIT_GFX_TILE; break; case GFX_MODE_BMP: mgr->gfxMode= GRIT_GFX_BMP; break; case GFX_MODE_BMP_A: mgr->gfxMode= GRIT_GFX_BMP_A; break; case GFX_MODE_BMP_T: mgr->gfxMode= GRIT_GFX_BMP; // Empty color && non-zero pal-trans -> use pal-trans // Empty color otherwise: use FF00FF // non-empty: use non-empty dw= strlen(mGfxTransStr); if( dw != 0 || !mgr->palHasAlpha ) { if(dw==0) mGfxTransStr= "FF00FF"; mgr->gfxAlphaColor= str2rgb(mGfxTransStr); mgr->gfxHasAlpha= true; } break; } mgr->gfxOffset= 0; mgr->gfxBpp= 1<<mGfxBpp; mgr->gfxCompression= mGfxCprs; } // --- map --- if(mbMap) { mgr->mapProcMode= GRIT_EXPORT; mgr->mapCompression= mMapCprs; if(mbMapRdx) { mgr->mapRedux |= GRIT_RDX_TILE; if(mbMapRdxFlip) mgr->mapRedux |= GRIT_RDX_FLIP; if(mbMapRdxPal) mgr->mapRedux |= GRIT_RDX_PBANK; } if(mbMetaPal) mgr->mapRedux |= GRIT_META_PAL; mgr->mapLayout= moMapFormat; if(mgr->mapLayout == GRIT_MAP_AFFINE) mgr->msFormat= c_mapselGbaAffine; else mgr->msFormat= c_mapselGbaText; mgr->msFormat.base= mMapOffset; // Add external tileset stuff if(mbTileset) { if(mTilesetPath.IsEmpty()) mTilesetPath= mDstDir + mDstTitle + "tiles.bmp"; mgr->shared->tilePath= strdup(mTilesetPath); mgr->gfxIsShared= true; } } if(mbObjCustom) { mgr->metaWidth= mObjHorz; mgr->metaHeight= mObjVert; } else { dw= moObjShape*4 + moObjSize; mgr->metaWidth= cObjSizes[dw][0]; mgr->metaHeight= cObjSizes[dw][1]; } // area dw= moAreaSize+IDC_AREA_CSM; if(dw == IDC_AREA_CSM) { mgr->areaLeft = mAreaLeft; mgr->areaTop = mAreaTop; mgr->areaRight = mAreaLeft+mAreaWidth; mgr->areaBottom= mAreaTop+mAreaHeight; } else { mgr->areaLeft = 0; mgr->areaTop = 0; mgr->areaRight = dib_get_width(mpDib); mgr->areaBottom= dib_get_height(mpDib); } mgr->gfxDataType= moVarChunk; mgr->mapDataType= moVarChunk; mgr->palDataType= moVarChunk; // RIFF overrides if(IsRiffed()) { mgr->bRiff= true; if(mgr->gfxCompression==GRIT_CPRS_OFF) mgr->gfxCompression= GRIT_CPRS_HEADER; if(mgr->mapCompression==GRIT_CPRS_OFF) mgr->mapCompression= GRIT_CPRS_HEADER; if(mgr->palCompression==GRIT_CPRS_OFF) mgr->palCompression= GRIT_CPRS_HEADER; } } else // gr -> data { // --- file --- mbHeader = mgr->bHeader; mbAppend = mgr->bAppend; // --- palette --- mPalStart= mgr->palStart; mPalCount= mgr->palEnd-mgr->palStart; mPalTrans= mgr->palAlphaId; // --- image --- if(mgr->gfxHasAlpha) { RGBQUAD *rgb= &mgr->gfxAlphaColor; mGfxMode= GFX_MODE_BMP_T; mGfxTransStr.Format("%02X%02X%02X", rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); } else if(mgr->gfxMode == GRIT_GFX_BMP_A) mGfxMode= GFX_MODE_BMP_T; else if(mgr->gfxMode == GRIT_GFX_BMP) mGfxMode= GFX_MODE_BMP; else mGfxMode= GFX_MODE_TILE; //mgr->gfx_ofs; //mgr->gfxBpp; // map if(mbMap) { moMapFormat= mgr->mapLayout; if(mgr->mapRedux & GRIT_RDX_TILE) { mbMapRdx= TRUE; mbMapRdxFlip= mbMapRdxPal= FALSE; if(mgr->mapRedux & GRIT_RDX_FLIP) mbMapRdxFlip= TRUE; if(mgr->mapRedux & GRIT_RDX_PBANK) mbMapRdxPal= TRUE; } mMapOffset= mgr->msFormat.base; } // meta if(mbObjCustom) { mObjHorz= mgr->metaWidth; mObjVert= mgr->metaHeight; } // area mAreaLeft= mgr->areaLeft; mAreaTop= mgr->areaTop; mAreaWidth= mgr->areaRight-mgr->areaLeft; mAreaHeight= mgr->areaBottom-mgr->areaTop; UpdateData(FALSE); } return TRUE; }
/*! Does map creation and layout, tileset reduction and map compression. Updates \a gr._dib with the new tileset, and fills in \a gr._mapRec and \a gr._metaRec. \note The work bitmap must be 8 bpp here, and already rearranged to a tile strip, which are the results of \c grit_prep_work_dib() and \c grit_prep_tiles(), respectively. */ bool grit_prep_map(GritRec *gr) { if(dib_get_bpp(gr->_dib) < 8) { lprintf(LOG_ERROR, " Can't map for bpp<8.\n"); return false; } CLDIB *workDib= gr->_dib; // --- if SBB-mode, tile to 256x256. --- if(gr->mapLayout == GRIT_MAP_REG) { lprintf(LOG_STATUS, " tiling to Screenblock size (256x256p).\n"); int blockW= 256, blockH= 256; if(gr->bColMajor) { blockW= dib_get_width(workDib); blockH= dib_get_height(workDib); dib_redim(workDib, 256, blockH, 0); } if(!dib_redim(workDib, blockW, blockH, 0)) { lprintf(LOG_ERROR, " SBB tiling failed.\n"); return false; } } ETmapFlags flags; Tilemap *metaMap= NULL, *map= NULL; RECORD metaRec= { 0, 0, NULL }, mapRec= { 0, 0, NULL }; MapselFormat mf; CLDIB *extDib= NULL; int tileN= 0; uint extW= 0, extH= 0, tileW= gr->tileWidth, tileH= gr->tileHeight; uint mtileW= gr->mtileWidth(), mtileH= gr->mtileHeight(); if(gr->gfxIsShared) { extDib= gr->shared->dib; extW= extDib ? dib_get_width(extDib) : 0; extH= extDib ? dib_get_height(extDib) : 0; } // --- If metatiled, convert to metatiles. --- if(gr->isMetaTiled()) { lprintf(LOG_STATUS, " Performing metatile reduction: tiles%s%s\n", (gr->mapRedux & GRIT_META_PAL ? ", palette" : "") ); flags = TMAP_DEFAULT; if(gr->mapRedux & GRIT_META_PAL) flags |= TMAP_PBANK; if(gr->bColMajor) flags |= TMAP_COLMAJOR; metaMap= tmap_alloc(); if(extW == mtileW) { lprintf(LOG_STATUS, " Using external metatileset.\n"); tmap_init_from_dib(metaMap, workDib, mtileW, mtileH, flags, extDib); } else tmap_init_from_dib(metaMap, workDib, mtileW, mtileH, flags, NULL); mf= c_mapselGbaText; tileN= tmap_get_tilecount(metaMap); if(tileN >= (1<<mf.idLen)) lprintf(LOG_WARNING, " Number of metatiles (%d) exceeds field limit (%d).\n", tileN, 1<<mf.idLen); tmap_pack(metaMap, &metaRec, &mf); if( BYTE_ORDER == BIG_ENDIAN && mf.bitDepth > 8 ) data_byte_rev(metaRec.data, metaRec.data, rec_size(&metaRec), mf.bitDepth/8); // Make temp copy for base-tiling and try to avoid aliasing pointers. // Gawd, I hate manual mem-mgt >_<. dib_free(workDib); if(gr->bColMajor) workDib= dib_redim_copy(metaMap->tiles, tileN*mtileW, mtileH, 0); else workDib= dib_clone(metaMap->tiles); } // ---Convert to base tiles. --- flags = 0; if(gr->mapRedux & GRIT_RDX_TILE) flags |= TMAP_TILE; if(gr->mapRedux & GRIT_RDX_FLIP) flags |= TMAP_FLIP; if(gr->mapRedux & GRIT_RDX_PBANK) flags |= TMAP_PBANK; if(gr->bColMajor) flags |= TMAP_COLMAJOR; lprintf(LOG_STATUS, " Performing tile reduction: %s%s%s\n", (flags & TMAP_TILE ? "unique tiles; " : ""), (flags & TMAP_FLIP ? "flip; " : ""), (flags & TMAP_PBANK ? "palswap; " : "")); map= tmap_alloc(); if(extW == tileW) { lprintf(LOG_STATUS, " Using external tileset.\n"); tmap_init_from_dib(map, workDib, tileW, tileH, flags, extDib); } else tmap_init_from_dib(map, workDib, tileW, tileH, flags, NULL); // --- Pack/Reformat and compress --- //# TODO: allow custom mapsel format. mf= gr->msFormat; tileN= tmap_get_tilecount(metaMap); if(tileN >= (1<<mf.idLen)) lprintf(LOG_WARNING, " Number of tiles (%d) exceeds field limit (%d).\n", tileN, 1<<mf.idLen); tmap_pack(map, &mapRec, &mf); if( BYTE_ORDER == BIG_ENDIAN && mf.bitDepth > 8 ) data_byte_rev(mapRec.data, mapRec.data, rec_size(&mapRec), mf.bitDepth/8); grit_compress(&mapRec, &mapRec, gr->mapCompression); // --- Cleanup --- // Make extra copy for external tile dib. if(gr->gfxIsShared) { dib_free(gr->shared->dib); // Use metatileset for external, unless the old external was a // base tileset. if(gr->isMetaTiled() && extW != tileW) gr->shared->dib= dib_clone(metaMap->tiles); else gr->shared->dib= dib_clone(map->tiles); } // Attach tileset for later processing. gr->_dib= tmap_detach_tiles(map); rec_alias(&gr->_mapRec, &mapRec); rec_alias(&gr->_metaRec, &metaRec); tmap_free(map); tmap_free(metaMap); lprintf(LOG_STATUS, "Map preparation complete.\n"); return true; }