void writeUncompressedData(QDataStream& stream, const ImageContainer& images, int pixelFormat) { // Mipmap offset if (images.hasMipmaps()) { writeZeroes(stream, MIPMAP_OFFSET_16BPP); } // Texture data, from smallest to largest mipmap for (int i=0; i<images.imageCount(); i++) { const QImage& img = images.getByIndex(i); // The 1x1 mipmap level is a bit special for YUV textures. Since there's only // one pixel, it can't be saved as YUV422, so save it as RGB565 instead. if (img.width() == 1 && img.height() == 1 && pixelFormat == PIXELFORMAT_YUV422) { convertAndWriteTexel(stream, img.pixel(0, 0), PIXELFORMAT_RGB565, true); continue; } const Twiddler twiddler(img.width(), img.height()); const int pixels = img.width() * img.height(); // Write all texels for this mipmap level in twiddled order for (int j=0; j<pixels; j++) { const int index = twiddler.index(j); const int x = index % img.width(); const int y = index / img.width(); convertAndWriteTexel(stream, img.pixel(x, y), pixelFormat, true); } } }
void writeCompressedData(QDataStream& stream, const ImageContainer& images, int pixelFormat) { QVector<QImage> indexedImages; QVector<quint64> codebook; const int numQuads = encodeLossless(images, pixelFormat, indexedImages, codebook, 256); qDebug() << "Source images contain" << numQuads << "unique quads"; if (numQuads > 256) { if ((pixelFormat != PIXELFORMAT_ARGB1555) && (pixelFormat != PIXELFORMAT_ARGB4444)) { QVector<Vec<12>> vectors; VectorQuantizer<12> vq; vectorizeRGB(images, vectors); vq.compress(vectors, 256); devectorizeRGB(images, vectors, vq, pixelFormat, indexedImages, codebook); } else { QVector<Vec<16>> vectors; VectorQuantizer<16> vq; vectorizeARGB(images, vectors); vq.compress(vectors, 256); devectorizeARGB(images, vectors, vq, pixelFormat, indexedImages, codebook); } } // Build the codebook quint16 codes[256 * 4]; memset(codes, 0, 2048); for (int i=0; i<codebook.size(); i++) { const quint64& quad = codebook[i]; codes[i * 4 + 0] = (quint16)((quad >> 48) & 0xFFFF); codes[i * 4 + 1] = (quint16)((quad >> 16) & 0xFFFF); codes[i * 4 + 2] = (quint16)((quad >> 32) & 0xFFFF); codes[i * 4 + 3] = (quint16)((quad >> 0) & 0xFFFF); } // Write the codebook for (int i=0; i<1024; i++) stream << codes[i]; // Write the 1x1 mipmap level if (images.imageCount() > 1) writeZeroes(stream, 1); // Write all mipmap levels for (int i=0; i<indexedImages.size(); i++) { const QImage& img = indexedImages[i]; const Twiddler twiddler(img.width(), img.height()); const int pixels = img.width() * img.height(); for (int j=0; j<pixels; j++) { const int index = twiddler.index(j); const int x = index % img.width(); const int y = index / img.width(); stream << (quint8)img.pixelIndex(x, y); } } }
int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "%s <device>\n", argv[0]); fprintf(stderr, " Create a Glidix File System on the specified device.\n"); return 1; }; int fd = open(argv[1], O_RDWR); if (fd < 0) { fprintf(stderr, "%s: error: could not open %s\n", argv[0], argv[1]); return 1; }; SDParams pars; if (ioctl(fd, IOCTL_SDI_IDENTITY, &pars) != 0) { close(fd); fprintf(stderr, "%s: error: could not get information about %s\n", argv[0], argv[1]); return 1; }; diskBlockSize = pars.blockSize; diskTotalSize = pars.totalSize; lseek(fd, 0x10, SEEK_SET); uint64_t f = 0x400; write(fd, &f, 8); uint64_t sectionsToMake = 2; uint64_t bytesPerInode = 0x4000; // 16KB uint64_t fsBlockSize = pars.blockSize; uint64_t sectionPlacement = 0x400 + sizeof(gxfsCIS) + sectionsToMake * sizeof(gxfsSD); uint64_t inodesPerSection = (diskTotalSize - sectionPlacement) / bytesPerInode / sectionsToMake; uint64_t inodeBitmapSize = inodesPerSection / 8; if (inodesPerSection % 8) inodeBitmapSize++; uint64_t blocksPerSection, blockBitmapSize; calculateBlocksToMake((diskTotalSize - sectionPlacement - inodesPerSection * sectionsToMake * sizeof(gxfsInode) - inodeBitmapSize)/sectionsToMake, fsBlockSize, &blocksPerSection, &blockBitmapSize); printf("GXFS Details (consistency check):\n"); printf("\tSize of CIS: %d\n", sizeof(gxfsCIS)); printf("\tSize of SD: %d\n", sizeof(gxfsSD)); printf("\tSize of inode: %d\n", sizeof(gxfsInode)); printf("\tSize of dirent: %d\n", sizeof(struct dirent)); printf("Filesystem plan:\n"); printf("\tSections: %d\n", sectionsToMake); printf("\tData per inode: %dKB\n", bytesPerInode/1024); printf("\tBlock size: %d bytes\n", fsBlockSize); printf("\tInodes per section: %d\n", inodesPerSection); printf("\tInode bitmap size: %d bytes\n", inodeBitmapSize); printf("\tBlocks per section: %d\n", blocksPerSection); printf("\tBlock bitmap size: %d bytes\n", blockBitmapSize); lseek(fd, 0x400, SEEK_SET); gxfsCIS cis; memcpy(cis.cisMagic, "GXFS", 4); cis.cisTotalIno = inodesPerSection * sectionsToMake; cis.cisInoPerSection = inodesPerSection; cis.cisTotalBlocks = blocksPerSection * sectionsToMake; cis.cisBlocksPerSection = blocksPerSection; cis.cisBlockSize = fsBlockSize; cis.cisCreateTime = time(NULL); cis.cisFirstDataIno = 8; cis.cisOffSections = 0x440; // straight after the CIS cis.cisZero = 0; write(fd, &cis, 64); uint64_t imap0, bmap0, itab0, btab0; uint64_t i; gxfsSD sect; for (i=0; i<sectionsToMake; i++) { sect.sdOffMapIno = sectionPlacement; if (i == 0) imap0 = sectionPlacement; sectionPlacement += inodeBitmapSize; sect.sdOffMapBlocks = sectionPlacement; if (i == 0) bmap0 = sectionPlacement; sectionPlacement += blockBitmapSize; sect.sdOffTabIno = sectionPlacement; if (i == 0) itab0 = sectionPlacement; sectionPlacement += inodesPerSection * sizeof(gxfsInode); sect.sdOffTabBlocks = sectionPlacement; if (i == 0) btab0 = sectionPlacement; sectionPlacement += blocksPerSection * fsBlockSize; write(fd, §, 32); printf("Section %d: imap=%p; bmap=%p; itab=%p; btab=%p\n", i, (void*)sect.sdOffMapIno, (void*)sect.sdOffMapBlocks, (void*)sect.sdOffTabIno, (void*)sect.sdOffTabBlocks); }; // we need to clear the inode and block bitmaps for (i=0; i<sectionsToMake; i++) { writeZeroes(fd, inodeBitmapSize); writeZeroes(fd, blockBitmapSize); lseek(fd, inodesPerSection * sizeof(gxfsInode) + blocksPerSection * fsBlockSize, SEEK_CUR); }; // mark inode 2 (index 1) and inode 3 (index 2) as used, and fill in the structure. // This effectively creates the root and lost+found directory. printf("Creating root directory (inode 2) imap0=%p...\n", (void*)imap0); lseek(fd, imap0, SEEK_SET); uint8_t b = (1 << 1) | (1 << 2); write(fd, &b, 1); lseek(fd, itab0 + sizeof(gxfsInode), SEEK_SET); gxfsInode inode; inode.inoMode = 011755; inode.inoSize = /*sizeof(struct dirent);*/ 25; // for the lost+found directory. inode.inoLinks = 2; // number of entries + 1 inode.inoCTime = cis.cisCreateTime; inode.inoATime = cis.cisCreateTime; inode.inoMTime = cis.cisCreateTime; inode.inoOwner = 0; inode.inoGroup = 0; memset(inode.inoFrags, 0, 16*sizeof(gxfsFragment)); // assign block 7 to the root inode. inode.inoFrags[0].fOff = 0; inode.inoFrags[0].fBlock = 7; inode.inoFrags[0].fExtent = 1; write(fd, &inode, sizeof(gxfsInode)); printf("Creating the lost+found directory (inode 3)...\n"); lseek(fd, itab0 + 2 * sizeof(gxfsInode), SEEK_SET); inode.inoMode = 011700; inode.inoSize = 15; inode.inoLinks = 1; inode.inoCTime = cis.cisCreateTime; inode.inoATime = cis.cisCreateTime; inode.inoMTime = cis.cisCreateTime; inode.inoOwner = 0; inode.inoGroup = 0; memset(inode.inoFrags, 0, 16*sizeof(gxfsFragment)); // assign the first 7 blocks to the lost+found directory. inode.inoFrags[0].fOff = 0; inode.inoFrags[0].fBlock = 0; inode.inoFrags[0].fExtent = 7; write(fd, &inode, sizeof(gxfsInode)); // create the directory entry for lost+found in the root directory. lseek(fd, btab0 + 7 * fsBlockSize, SEEK_SET); //struct dirent ent; //ent.d_ino = 3; //strcpy(ent.d_name, "lost+found"); //write(fd, &ent, sizeof(struct dirent)); char direntdata[26]; gxfsDirHeader *dhead = (gxfsDirHeader*) &direntdata[0]; gxfsDirent *lfent = (gxfsDirent*) &direntdata[5]; dhead->dhCount = 1; dhead->dhFirstSz = 20; lfent->deInode = 3; lfent->deNextSz = 0; lfent->deNameLen = 10; // strlen("lost+found") strcpy(lfent->deName, "lost+found"); write(fd, direntdata, 25); // create the null entry in lost+found lseek(fd, btab0 + fsBlockSize, SEEK_SET); dhead->dhCount = 1; dhead->dhFirstSz = 0; lfent->deInode = 0; lfent->deNextSz = 0; lfent->deNameLen = 0; write(fd, direntdata, 15); printf("Marking the first 8 blocks as used...\n"); lseek(fd, bmap0, SEEK_SET); b = 0xFF; write(fd, &b, 1); close(fd); printf("Filesystem created, you may mount now.\n"); return 0; };