本文主要是介绍GF文件解码程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
PC98游戏中D.O公司常用的格式,游戏相当多。之所以不叫格式分析是因为确实不好分析……原理似乎是哈夫曼编码+流程码的结合……程序相当复杂,压缩效率也不见得高,个人觉得还不如用LZ+HUFF呢(那不成了ZIP了?)
这里贴出解码程序。基本上是把汇编用C翻译了一下。在《DOR》《DOR2》《DOR3》《DOR Special》《星之砂物语2》上做了测试。
另外,如果有心就可以发现,早期某台湾公司出品的游戏《麻X情趣屋》中大量使用了DOR系列的图片。显然是抄袭了。当然一来这个不关偶们的事;二来该公司出品的很多其它游戏品质还是相当高的……扯远了。
在测试中发现《全日X美少女麻将XXX》这个游戏中也是GF格式,但是它是一个大的ARC包。作者没有做进一步的分析,但是这个ARC用肉眼看格式相当简单,有兴趣的DX可以验证。
代码在VS2003上编译通过。使用方式是GF *.GF(*.GF可省)。
// gf.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <io.h>
typedef struct _tag_gf {
unsigned char* buf;
unsigned char* org_buf;
int size;
} gf_rec, *pgf_rec;
void gf_init(pgf_rec rec)
{
rec->buf = NULL;
rec->org_buf = NULL;
rec->size = 0;
}
void gf_free(pgf_rec rec)
{
if (rec->org_buf) {
free(rec->org_buf);
}
rec->org_buf = NULL;
rec->buf = NULL;
rec->size = 0;
}
int gf_load(pgf_rec rec, const char* filename)
{
FILE* fp = fopen(filename, "rb");
if (!fp) {
printf("Cannot open %s for read/n", filename);
return 0;
}
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
rec->buf = (unsigned char*)malloc(size);
fread(rec->buf, 1, size, fp);
fclose(fp);
rec->org_buf = rec->buf;
rec->size = size;
return 1;
}
void gf_decode(pgf_rec rec, const char* target_file)
{
unsigned char palette_data[32];
#define READ_WORD(p) *(unsigned short*)p;
unsigned char* p = rec->buf;
p += 16;
memcpy(palette_data, p, 32);
p += 32;
p += 2;
unsigned short width = READ_WORD(p);
p+=2;
unsigned short height = READ_WORD(p);
p+=2;
p+=10;
unsigned char al = 0;
unsigned char ah = 0;
unsigned char* target_buf = (unsigned char*)malloc(width*height/2+512*4);
unsigned char* dest = target_buf;
unsigned char* col_start = dest;
int dx = 0;
#define STOSB() *dest++ = al;
#define STOSW() *dest++ = al; *dest++ = ah;
#define MOVSB() al = *p++; *dest++ = al;
#define MOVSW() al = *p++; ah = *p++; *dest++ = al; *dest++ = ah;
#define AX ((((unsigned short)ah) << 8)|((unsigned short)al))
unsigned short cnt = 1;
unsigned short bpl = width/8;
for ( unsigned short x = 0; x < bpl; ++x ) {
col_start = dest;
dx = 0;
while (dx < height) {
al = *p++;
if (al & 0x80) {
/// Ctrl
if ((al & 0x70) == 0) { /// loc_1953
al &= 0x7F;
STOSB();
MOVSB();
MOVSW();
++dx;
} else if ((al & 0x60) == 0) { /// loc_193e
cnt = (al & 0xF)+2;
} else if ((al & 0x40) == 0) { /// loc_1947
unsigned short n = (al & 0x1F) + 1;
for ( unsigned short i = 0; i < n; ++i ) {
MOVSW();
MOVSW();
++dx;
}
} else if ((al & 0x20) != 0) { /// loc_1a8f
dx += cnt;
unsigned short i = 0;
switch(al & 0x1F) {
case 0: /// 0f48 al=es:[di-4] stopsb movsw al=es:[di-4] stopsb loop 0f48
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); STOSB(); MOVSW(); al = *(dest-4); STOSB();
}
break;
case 1: /// 0f56 movsb ax=es:[di-4] stopsw movsb loop 0f56
for ( i = 0; i < cnt; ++i ) {
MOVSB(); al = *(dest-4); ah = *(dest-3); STOSW(); MOVSB();
}
break;
case 2: /// 0f60: al=es:[di-4] stopsb movsb al=es:[di-4] stopsb movsb loop 0f60
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); STOSB(); MOVSB(); al = *(dest-4); STOSB(); MOVSB();
}
break;
case 3: /// 0f6f: movsb al=es:[di-4] stopsb movsb al=es:[di-4] stopsb loop 0f6f
for ( i = 0; i < cnt; ++i ) {
MOVSB(); al = *(dest-4); STOSB(); MOVSB(); al = *(dest-4); STOSB();
}
break;
case 4: /// 0f7e: ax=es:[di-4] stopsw lodsb ah=al stopsw loop 0f7e
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); ah = *(dest-3); STOSW(); al=*p++; ah=al; STOSW();
}
break;
case 5: /// 0f8a: lodsb ah=al stopsw ax=es:[di-4] stosw loop 0f8a
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah=al; STOSW(); al = *(dest-4); ah = *(dest-3); STOSW();
}
break;
case 6: /// 0f96: al=es:[di-4] stosb lodsb ah=al stosw al=es:[di-4] stosb loop 0f96
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); STOSB(); al=*p++; ah=al; STOSW(); al = *(dest-4); STOSB();
}
break;
case 7: /// 0fa7: lodsb stosb bx=ax ax=es:[di-4] stosw ax=bx stosb loop 0fa7
for ( i = 0; i < cnt; ++i ) {
al = *p++; STOSB();
unsigned char bh = ah; unsigned char bl = al;
al = *(dest-4); ah = *(dest-3); STOSW();
ah = bh; al = bl; STOSB();
}
break;
case 8: /// 0fb6: al=es:[ei-4] stosb lodsb stosb bx=ax al=es:[di-4] stosb ax=bx stosb loop 0fb6
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); STOSB(); al = *p++; STOSB();
unsigned char bh = ah; unsigned char bl = al;
al = *(dest-4); STOSB(); ah = bh; al = bl; STOSB();
}
break;
case 9: /// 0fca: lodsb stosb bx=ax al=es:[di-4] stosb ax=bx stosb al=es:[di-4] stosb loop 0fca
for ( i = 0; i < cnt; ++i ) {
al = *p++; STOSB();
unsigned char bh = ah; unsigned char bl = al;
al = *(dest-4); STOSB(); ah = bh; al = bl; STOSB(); al = *(dest-4); STOSB();
}
break;
case 10: /// 0fde
case 11:
case 12:
case 13:
case 14:
case 15:
default:
break;
case 16: /// 0ea7: ax=0 stosw stosw
ah = 0;
al = 0;
STOSW(); STOSW();
break;
case 17: /// 0eac: ax=0xffff stosw stosw
ah = 0xFF;
al = 0xFF;
STOSW(); STOSW();
break;
case 18: /// 0eb2: lodsb ah=al stosw stosw loop 0eb2
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = al; STOSW(); STOSW();
}
break;
case 19: /// 0eba: lodsw bx=ax ah=al stosw ax=bx stosw loop 0eba
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = *p++;
unsigned char bl = al; unsigned char bh = ah; ah = al;
STOSW(); al = bl; ah = bh; STOSW();
}
break;
case 20: /// 0ec6: lodsw bx=ax ah=al stosw al=bh stosw loop 0ec6
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = *p++;
unsigned char bl = al; unsigned char bh = ah;
ah = al; STOSW(); al = bh; STOSW();
}
break;
case 21: /// 0ed2: lodsw stosw ah=al stosw loop 0ed2
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = *p++; STOSW(); ah = al; STOSW();
}
break;
case 22: /// 0eda: lodsw xchg ah,al stosw al=ah stosw loop 0eda
for ( i = 0; i < cnt; ++i ) {
ah = *p++; al = *p++; STOSW(); al = ah; STOSW();
}
break;
case 23: /// 0ee4: lodsw bx=ax xchg bl,ah stosw ax=bx stosw loop 0ee4
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = *p++;
unsigned char bl = al; unsigned char bh = ah;
unsigned char t = bl; bl = ah; ah = t;
STOSW(); ah = bh; al = bl; STOSW();
}
break;
case 24: /// 0ef0: lodsw stosw xchg ah,al stosw loop 0ef0
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = *p++; STOSW();
unsigned char t = ah; ah = al; al = t; STOSW();
}
break;
case 25: /// 0ef8: lodsw stosw stosw loop 0ef8
for ( i = 0; i < cnt; ++i ) {
al = *p++; ah = *p++; STOSW(); STOSW();
}
break;
case 26: /// 0efe: ax=es:[di-4] stosw al=es:[di-4] stosb movsb loop 0efe
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); ah = *(dest-3); STOSW(); al = *(dest-4); STOSB(); MOVSB();
}
break;
case 27: /// 0f0c: ax=es:[di-4] stosw movsb al=es:[di-4] stosb loop 0f0c
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); ah = *(dest-3); STOSW(); MOVSB(); al = *(dest-4); STOSB();
}
break;
case 28: /// 0f1a: al=es:[di-4] stosb movsb ax=es:[di-4] stosw loop 0f1a
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); STOSB(); MOVSB(); al = *(dest-4); ah = *(dest-3); STOSW();
}
break;
case 29: /// 0f28: movsb al=es:[di-4] stosb ax=es:[di-4] stosw loop 0f28
for ( i = 0; i < cnt; ++i ) {
MOVSB(); al = *(dest-4); STOSB(); al = *(dest-4); ah = *(dest-3); STOSW();
}
break;
case 30: /// 0f36: ax=es:[di-4] stosw movsw loop 0f36
for ( i = 0; i < cnt; ++i ) {
al = *(dest-4); ah = *(dest-3); STOSW(); MOVSW();
}
break;
case 31: /// 0f3f: movsw ax=es:[di-4] stosw loop 0f3f
for ( i = 0; i < cnt; ++i ) {
MOVSW(); al = *(dest-4); ah = *(dest-3); STOSW();
}
break;
}
cnt = 1;
} else if ((al & 0x10) != 0) {
if ((al & 0x8) != 0) { /// loc_1a68
unsigned short cx = 7 & al;
if (cx == 0) { /// loc_1a77
cx = *p++;
cx += 8;
}
for ( unsigned short i = 0; i < cx; ++i ) {
unsigned short n = 1;
al = (dx >> 8);
ah = (dx & 0xFF);
al |= 2;
unsigned short si = AX;
si >>= 1;
si &= 0x3F;
if (si == 0) {
/// loc_196e (sub_1ae0)
unsigned char t = al; al = ah; ah = t;
si = AX;
si*=4;
unsigned char* src = col_start + si;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
} else {
/// loc_1978: copy from left col
unsigned char* src = target_buf + (x-si)*height*4;
unsigned char t = ah; ah = al; al = t;
ah &= 1;
src += (AX)*4;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
}
/// loc_1971
cnt = 1;
}
} else { /// 1a50
unsigned short n = al & 7;
if (n == 0) {
n = *p++;
n+=8;
}
al = (dx >> 8);
ah = (dx & 0xFF);
al |= 2;
unsigned short si = AX;
si >>= 1;
si &= 0x3F;
if (si == 0) {
/// loc_196e (sub_1ae0)
unsigned char t = al; al = ah; ah = t;
si = AX;
si*=4;
unsigned char* src = col_start + si;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
} else {
/// loc_1978: copy from left col
unsigned char* src = target_buf + (x-si)*height*4;
unsigned char t = ah; ah = al; al = t;
ah &= 1;
src += (AX)*4;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
}
/// loc_1971
cnt = 1;
}
} else { /// 1a28
short bx = -4;
if ((al & 0x8) != 0) {
bx*=2;
}
/// loc_1a31
unsigned short n = al & 7;
if (n == 0) {
n = *p++;
n += 8;
}
unsigned char* src = dest + bx;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
}
} else {
/// ! al & 0x80
--p;
al = *p++;
ah = *p++;
unsigned short n = cnt;
/// sub_195f
unsigned short si = AX;
si >>= 1;
si &= 0x3F;
if (si == 0) {
/// loc_196e (sub_1a06)
unsigned char t = al; al = ah; ah = t;
si = AX;
si &= 0x1FF;
si*=4;
unsigned char* src = col_start + si;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
} else {
/// loc_1978: copy from left col
unsigned char* src = target_buf + (x-si)*height*4;
unsigned char t = ah; ah = al; al = t;
ah &= 1;
src += (AX)*4;
for ( unsigned short i = 0; i < n; ++i ) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
++dx;
}
}
/// loc_1971
cnt = 1;
}
}
}
unsigned char *bits_buffer = (unsigned char*)malloc(bpl*4*height);
memset(bits_buffer, 0, bpl*4*height);
for ( int j = 0; j < height; ++j ) {
dest = bits_buffer + (height - 1 - j)*bpl*4;
for ( int i = 0; i < bpl; ++i ) {
unsigned char* src0 = target_buf + i*height*4 + j*4 + 0;
unsigned char* src1 = target_buf + i*height*4 + j*4 + 1;
unsigned char* src2 = target_buf + i*height*4 + j*4 + 2;
unsigned char* src3 = target_buf + i*height*4 + j*4 + 3;
/// a0b0c0d0e0f0g0h0 (src0)
/// a1b1c1d1e1f1g1h1 (src1)
/// a2b2c2d2e2f2g2h2 (src2)
/// a3b3c3d3e3f3g3h3 (src3)
/// => a0123 b0123 | c0123 d0123 | e0123 f0123 | g0123 h0123
/// dest[0] dest[1] dest[2] dest[3]
if (*src0 & 0x80) dest[0] |= 0x10;
if (*src1 & 0x80) dest[0] |= 0x20;
if (*src2 & 0x80) dest[0] |= 0x40;
if (*src3 & 0x80) dest[0] |= 0x80;
if (*src0 & 0x40) dest[0] |= 0x01;
if (*src1 & 0x40) dest[0] |= 0x02;
if (*src2 & 0x40) dest[0] |= 0x04;
if (*src3 & 0x40) dest[0] |= 0x08;
if (*src0 & 0x20) dest[1] |= 0x10;
if (*src1 & 0x20) dest[1] |= 0x20;
if (*src2 & 0x20) dest[1] |= 0x40;
if (*src3 & 0x20) dest[1] |= 0x80;
if (*src0 & 0x10) dest[1] |= 0x01;
if (*src1 & 0x10) dest[1] |= 0x02;
if (*src2 & 0x10) dest[1] |= 0x04;
if (*src3 & 0x10) dest[1] |= 0x08;
if (*src0 & 0x08) dest[2] |= 0x10;
if (*src1 & 0x08) dest[2] |= 0x20;
if (*src2 & 0x08) dest[2] |= 0x40;
if (*src3 & 0x08) dest[2] |= 0x80;
if (*src0 & 0x04) dest[2] |= 0x01;
if (*src1 & 0x04) dest[2] |= 0x02;
if (*src2 & 0x04) dest[2] |= 0x04;
if (*src3 & 0x04) dest[2] |= 0x08;
if (*src0 & 0x02) dest[3] |= 0x10;
if (*src1 & 0x02) dest[3] |= 0x20;
if (*src2 & 0x02) dest[3] |= 0x40;
if (*src3 & 0x02) dest[3] |= 0x80;
if (*src0 & 0x01) dest[3] |= 0x01;
if (*src1 & 0x01) dest[3] |= 0x02;
if (*src2 & 0x01) dest[3] |= 0x04;
if (*src3 & 0x01) dest[3] |= 0x08;
dest+=4;
}
}
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bmi;
memset(&bfh, 0, sizeof(BITMAPFILEHEADER));
bfh.bfType = 'MB';
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 64;
memset(&bmi, 0, sizeof(BITMAPINFOHEADER));
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biSizeImage = bpl * 4 * height;
bmi.biWidth = bpl*8;
bmi.biHeight = height;
bmi.biPlanes = 1;
bmi.biBitCount = 4;
bmi.biClrUsed = 16;
bmi.biClrImportant = 16;
FILE *fp = fopen(target_file, "wb");
fwrite(&bfh, 1, sizeof bfh, fp);
fwrite(&bmi, 1, sizeof bmi, fp);
char palette[64];
for ( int i = 0; i < 16; ++i ) {
palette[i*4+0] = ((palette_data[i*2+0] >> 4)<<4)+0xf;
palette[i*4+2] = ((palette_data[i*2+0] & 0xF)<<4)+0xf;
palette[i*4+1] = ((palette_data[i*2+1] & 0xF)<<4)+0xf;
palette[i*4+3] = 0;
}
fwrite(palette, 4, 16, fp);
fwrite(bits_buffer, 1, bpl * height * 4, fp);
fclose(fp);
free(bits_buffer);
}
int _tmain(int argc, _TCHAR* argv[])
{
char *input_files = "*.GF";
if ( argc == 2 ) {
input_files = argv[1];
}
if ( argc > 2 ) {
printf("usage: gf [gf files(E.G: *.GF)]/n");
return -1;
}
gf_rec rec;
struct _finddata_t t;
long handle;
if ((handle = (long)_findfirst(input_files, &t)) != -1)
{
char target_file[260];
do
{
strcpy(target_file, t.name);
char *dot_pos = strrchr(target_file, '.');
if ( dot_pos ) *dot_pos = '/0';
strcat(target_file, ".BMP");
gf_init(&rec);
printf("Processing %s ...", t.name);
gf_load( &rec, t.name );
gf_decode( &rec, target_file );
gf_free( &rec );
printf("Done./n");
}while(_findnext(handle, &t) != -1);
}
return 0;
}
这篇关于GF文件解码程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!