/* p2.c p2 loader enfle plugin This file is part of Enfle. $Id: p2.c,v 1.1 2000/05/25 15:35:10 sian Exp $ Base plugin system by Hiroshi Takekawa (c) Hiroshi Takekawa Original p2 decode system by Akira Yanagisawa (c) Akira Yanagisawa X680*0/MS-DOS/GO32 modified by Noboru Abe (c) Noboru Abe Enfle plugin modified by Masaru Nakagawa (c) Masaru Nakagawa This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "enfle.h" #include "p2.h" #include "archive.h" #include "bitio.h" #include "utils.h" #include "plugin.h" static int CheckHeaderID(Info*); static int ReadHeader(Info*,Image*,P2INFO*); static int ReadData(Info*,Image*,P2INFO*); static void DecodeScreen(P2INFO*); static DWORD GetBit(P2INFO*,int); static short P2ssBitDecode(P2INFO*,int); static short P2ssNnDecode(P2INFO*,int); static void P2ssExpandChain(P2INFO*,int,DWORD); static WORD P2ssGetnum15(P2INFO*,int,int); static long P2ssGetnum24(P2INFO*,int,long); static BYTE P2ssReadColor8(P2INFO*); static DWORD P2ssReadColor16(P2INFO*,WORD); static DWORD P2ssReadColor15(P2INFO*,WORD); static DWORD P2ssReadColor24(P2INFO*,WORD); static void P2ssParaOut(P2INFO*); static void P2ssParaIn(P2INFO*); static void P2ssLineExpand(P2INFO*); static long P2sfReadLen(P2INFO*); static void P2sfExpandChain(P2INFO*,int,DWORD); static BYTE P2sfReadColor8(P2INFO*); static DWORD P2sfReadColor16(P2INFO*,DWORD); static DWORD P2sfReadColor15(P2INFO*,DWORD); static DWORD P2sfReadColor24(P2INFO*,DWORD); static void P2sfParaOut(P2INFO*); static void P2sfParaIn(P2INFO*); static void P2sfLineExpand(P2INFO*); static void BetaLineExpand(P2INFO*); static int LoadP2ssScreen(P2INFO*); static int LoadP2sfScreen(P2INFO*); static int LoadBetaScreen(P2INFO*); int #ifdef PIC get_plugininfo(PluginInfo *p) #else loader_p2_get_plugininfo(PluginInfo *p) #endif { p->version = 1; p->type = _Loader; p->pluginname = "P2 Format Loader Plugin version 0.1"; p->pluginshortname = FORMAT_NAME; p->author = "Masaru Nakagawa"; p->dlhandle = NULL; /* set by plugin_load */ p->functions.loader.load_image = p2_load_image; return 1; } int p2_load_image(info,pInfo) Info *info; Image *pInfo; { int ret; P2INFO mInfo; if (CheckHeaderID(info) == False) { return PROC_NOT; } if (ReadHeader(info,pInfo,&mInfo) == False) { return PROC_NOT; } if ((ret = ReadData(info,pInfo,&mInfo)) != PROC_OK) { return ret; } info->npics = 1; /* set handler */ info->handler.destroy = NULL; info->handler.alarmset = NULL; info->handler.alarm = NULL; info->handler.alarmoff = NULL; return PROC_OK; } static int CheckHeaderID(info) Info *info; { Archive *ar = info->ar; int len; char buf[10]; static char magic[] = "P2DT"; len = strlen(magic); if (archive_read(ar,buf,len) != len) { return False; } if (strncmp(buf,magic,len) != 0) { if (archive_seek(ar,128,SEEK_SET) != 0 ||\ archive_read(ar,buf,len) != len ||\ strncmp(buf,magic,len) != 0) { return False; } } return True; } static int ReadHeader(info,pInfo,mInfo) Info *info; Image *pInfo; P2INFO *mInfo; { Archive *ar = info->ar; int ret = True; int i,ncolor; BYTE buf[32]; long tell; info->format = FORMAT_NAME; mInfo->ar = ar; mInfo->bitcnts = 0; tell = archive_tell(ar) - 4; if ((info->comment = (char*)malloc(sizeof(char) * 93)) == NULL) { ret = False; goto err; } if (archive_read(ar,info->comment,92) != 92) { ret = False; goto err; } info->comment[92] = '\0'; if (archive_read(ar,buf,28) != 28) { ret = False; goto err; } mInfo->p2_head.eof = buf[0]; mInfo->p2_head.reserve0 = buf[1]; mInfo->p2_head.flag = (buf[2] << 8) + buf[3]; mInfo->p2_head.no = (buf[4] << 8) + buf[5]; mInfo->p2_head.time = (buf[6] << 24) + \ (buf[7] << 16) + (buf[8] << 8) + buf[9]; mInfo->p2_head.size = (buf[10] << 24) + \ (buf[11] << 16) + (buf[12] << 8) + buf[13]; mInfo->p2_head.depth = (buf[14] << 8) + buf[15]; mInfo->p2_head.x_aspect = (buf[16] << 8) + buf[17]; mInfo->p2_head.y_aspect = (buf[18] << 8) + buf[19]; mInfo->p2_head.x_max = (buf[20] << 8) + buf[21]; mInfo->p2_head.y_max = (buf[22] << 8) + buf[23]; mInfo->p2_head.reserve1 = (buf[24] << 24) + \ (buf[25] << 16) + (buf[26] << 8) + buf[27]; if (mInfo->p2_head.flag & 1) { if (archive_read(ar,buf,3) != 3) { ret = False; goto err; } mInfo->depth = buf[0]; ncolor = (buf[1] << 8) + buf[2]; ncolor = (ncolor > 256) ? (256) : (ncolor); for (i = 0;i < ncolor;i++) { if (archive_read(ar,buf,3) != 3) { ret = False; goto err; } pInfo->colormap[i][0] = buf[0]; pInfo->colormap[i][1] = buf[1]; pInfo->colormap[i][2] = buf[2]; } } else { for (i = 0;i < 256;i++) { pInfo->colormap[i][0] = ((i >> 2) & 7) * (256 / 7); pInfo->colormap[i][1] = ((i >> 5) & 7) * (256 / 7); pInfo->colormap[i][2] = ( i & 3) * (256 / 3); } } mInfo->size = mInfo->p2_head.size + tell; pInfo->left = 0; pInfo->top = 0; pInfo->width = mInfo->p2_head.x_max; pInfo->height = mInfo->p2_head.y_max; /* pInfo->x_density = mInfo->p2_head.x_aspect; pInfo->y_density = mInfo->p2_head.y_aspect; */ pInfo->ncolors = 1 << mInfo->p2_head.depth; switch (mInfo->p2_head.depth) { case 8: pInfo->type = _INDEX; break; case 15: pInfo->type = _RGB16; break; case 24: pInfo->type = _RGB24; break; default: ret = False; goto err; } #ifdef DEBUG fprintf(stderr,"pInfo->width = %d\n",pInfo->width); fprintf(stderr,"pInfo->height = %d\n",pInfo->height); fprintf(stderr,"pInfo->ncolors = %d\n",pInfo->ncolors); #endif return ret; err: { if (info->comment != NULL) { free(info->comment); info->comment = NULL; } return ret; } } static int ReadData(info,pInfo,mInfo) Info *info; Image *pInfo; P2INFO *mInfo; { int ret = PROC_OK; int biWidth,biHeight; BYTE buf[32],*pHBm; pHBm = NULL; switch (pInfo->type) { case _INDEX: biWidth = pInfo->width; biHeight = pInfo->height; break; case _RGB16: biWidth = pInfo->width * 2; biHeight = pInfo->height; break; case _RGB24: biWidth = pInfo->width * 3; biHeight = pInfo->height; break; default: ret = PROC_ERROR; goto err; } pHBm = (BYTE*)calloc(1,biWidth * biHeight * sizeof(BYTE)); if (pHBm == NULL) { ret = PROC_ERROR; goto err; } mInfo->biWidth = biWidth; mInfo->biHeight = biHeight; mInfo->pHBm = pHBm; pInfo->image = pHBm; pInfo->bytes_per_line = biWidth; pInfo->image_size = biWidth * biHeight * sizeof(BYTE); for (;;) { archive_seek(mInfo->ar,mInfo->size,SEEK_SET); archive_read(mInfo->ar,mInfo->p2_block.id,4); if (mInfo->p2_block.id[0] == '\0' && \ mInfo->p2_block.id[1] == '\0' && \ mInfo->p2_block.id[2] == '\0' && \ mInfo->p2_block.id[3] == '\0') { goto done; } archive_read(mInfo->ar,buf,22); mInfo->p2_block.size = (buf[0] << 24) + \ (buf[1] << 16) + (buf[2] << 8) + buf[3]; mInfo->p2_block.flag = (buf[4] << 8) + buf[5]; mInfo->p2_block.x_wid = (buf[6] << 8) + buf[7]; mInfo->p2_block.y_wid = (buf[8] << 8) + buf[9]; mInfo->p2_block.x_offset = (buf[10] << 8) + buf[11]; mInfo->p2_block.y_offset = (buf[12] << 8) + buf[13]; mInfo->p2_block.opaque = (buf[14] << 24) + \ (buf[15] << 16) + (buf[16] << 8) + buf[17]; mInfo->p2_block.reserve = (buf[18] << 24) + \ (buf[19] << 16) + (buf[20] << 8) + buf[21]; mInfo->size += mInfo->p2_block.size; mInfo->bitcnts = 0; #ifdef DEBUG fprintf(stderr,"mInfo->p2_block.x_wid = %d\n",mInfo->p2_block.x_wid); fprintf(stderr,"mInfo->p2_block.y_wid = %d\n",mInfo->p2_block.y_wid); fprintf(stderr,"mInfo->p2_block.x_offset = %d\n",mInfo->p2_block.x_offset); fprintf(stderr,"mInfo->p2_block.y_offset = %d\n",mInfo->p2_block.y_offset); #endif if (strncmp(mInfo->p2_block.id,"P2SS",4) == 0) { if ((ret = LoadP2ssScreen(mInfo)) != PROC_OK) { goto err; } } else if (strncmp(mInfo->p2_block.id,"P2SF",4) == 0) { if ((ret = LoadP2sfScreen(mInfo)) != PROC_OK) { goto err; } } else if (strncmp(mInfo->p2_block.id,"P2BM",4) == 0) { if ((ret = LoadBetaScreen(mInfo)) != PROC_OK) { goto err; } } else if (strncmp(mInfo->p2_block.id,"P2BI",4) == 0) { if ((ret = LoadBetaScreen(mInfo)) != PROC_OK) { goto err; } } } done: #ifdef DEBUG fprintf(stderr,"loaded\n"); #endif return ret; err: { if (pHBm != NULL) { free(pHBm); pInfo->image = NULL; } if (info->comment != NULL) { free(info->comment); info->comment = NULL; } return ret; } } static void DecodeScreen(mInfo) P2INFO *mInfo; { int x,y,left,top,width,height; DWORD *SrcPtr; BYTE *DstPtr; left = mInfo->p2_block.x_offset; top = mInfo->p2_block.y_offset; width = mInfo->p2_block.x_wid; height = mInfo->p2_block.y_wid; switch (mInfo->p2_head.depth) { case 8: for (y = 0;y < height;y++) { #ifdef DEBUG fprintf(stderr,"lines = %d\n",y); #endif (*mInfo->line_expand)(mInfo); SrcPtr = mInfo->vram_prev; DstPtr = mInfo->pHBm + (y + top) * mInfo->biWidth + left; for (x = (width + 1) / 2;x > 0;x--) { *DstPtr++ = (*SrcPtr >> 8) & 255; *DstPtr++ = (*SrcPtr ) & 255; SrcPtr++; } } break; case 15: for (y = 0;y < height;y++) { #ifdef DEBUG fprintf(stderr,"lines = %d\n",y); #endif (*mInfo->line_expand)(mInfo); SrcPtr = mInfo->vram_prev; DstPtr = mInfo->pHBm + (y + top) * mInfo->biWidth + left * 2; for (x = width;x > 0;x--) { /* GGGGGRRR:RRBBBBB0 -> GGGBBBBB */ *DstPtr++ = ((*SrcPtr >> 5) & 0xc0) | ((*SrcPtr >> 1) & 0x1f); /* GGGGGRRR:RRBBBBB0 -> RRRRRGGG */ *DstPtr++ = ((*SrcPtr >> 3) & 0xf8) | ((*SrcPtr >> 13) & 0x07); SrcPtr++; } } break; case 24: for (y = 0;y < height;y++) { #ifdef DEBUG fprintf(stderr,"lines = %d\n",y); #endif (*mInfo->line_expand)(mInfo); SrcPtr = mInfo->vram_prev; DstPtr = mInfo->pHBm + (y + top) * mInfo->biWidth + left * 3; for (x = width;x > 0;x--) { *DstPtr++ = (*SrcPtr >> 16) & 255; *DstPtr++ = (*SrcPtr >> 8) & 255; *DstPtr++ = (*SrcPtr ) & 255; SrcPtr++; } } break; default: break; } } static DWORD GetBit(mInfo,n) P2INFO *mInfo; int n; { int i; DWORD l; BYTE c,b; b = mInfo->bitcnts; c = mInfo->c; for (l = 0,i = n;i > 0;i--) { if (b == 0) { c = archive_getc(mInfo->ar); b = 0x80; } l = c & b ? (l << 1) + 1 : l << 1; b >>= 1; } mInfo->bitcnts = b; mInfo->c = c; return l; } static short P2ssBitDecode(mInfo,n) P2INFO *mInfo; int n; { WORD pp = mInfo->mulu_tab[(mInfo->aa & 0x7f00) / 2 + n]; long aa = mInfo->aa; long dd = mInfo->dd; BYTE bb = mInfo->bitcnts; BYTE cc = mInfo->c; if (dd >= (int)pp) { dd -= pp; aa -= pp; while ((short)aa >= 0) { if (bb == 0) { cc = archive_getc(mInfo->ar); bb = 0x80; } dd = cc & bb ? (dd << 1) + 1 : dd << 1; aa <<= 1; bb >>= 1; } mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return 1; } else { aa = pp; while ((short)aa >= 0) { if (bb == 0) { cc = archive_getc(mInfo->ar); bb = 0x80; } dd = cc & bb ? (dd << 1) + 1 : dd << 1; aa <<= 1; bb >>= 1; } mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return 0; } } #define _P2ssBitDecode(aa,bb,cc,dd,ar,nn,jp_0)\ pp = mInfo->mulu_tab[(aa & 0x7f00) / 2 + nn];\ if (dd < (int)pp) {\ aa = pp;\ while ((short)aa >= 0) {\ if (bb == 0) {\ cc = archive_getc(ar);\ bb = 0x80;\ }\ dd = cc & bb ? (dd << 1) + 1 : dd << 1;\ aa <<= 1;\ bb >>= 1;\ }\ goto jp_0;\ } else {\ dd -= pp;\ aa -= pp;\ while ((short)aa >= 0) {\ if (bb == 0) {\ cc = archive_getc(ar);\ bb = 0x80;\ }\ dd = cc & bb ? (dd << 1) + 1 : dd << 1;\ aa <<= 1;\ bb >>= 1;\ }\ }\ static short P2ssNnDecode(mInfo,c) P2INFO *mInfo; int c; { Archive *ar = mInfo->ar; long aa = mInfo->aa; long dd = mInfo->dd; BYTE bb = mInfo->bitcnts; BYTE cc = mInfo->c; WORD pp; int n; _P2ssBitDecode(aa,bb,cc,dd,ar,c,jp_10) /* n < 1 */ mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return 0; jp_10: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 1,jp_20) /* n < 1 + 2 */ n = 1; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_21) n += 1; jp_21: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_20: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 2,jp_30) /* n < 1 + 2 + 4 */ n = 1 + 2; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_31) n += 1; jp_31: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 9,jp_32) n += 2; jp_32: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_30: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 3,jp_40) /* n < 1 + 2 + 4 + 8*/ n = 1 + 2 + 4; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_41) n += 1; jp_41: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 9,jp_42) n += 2; jp_42: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 10,jp_43) n += 4; jp_43: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_40: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 4,jp_50) /* n < 1 + 2 + 4 + 8 + 16*/ n = 1 + 2 + 4 + 8; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_51) n += 1; jp_51: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 9,jp_52) n += 2; jp_52: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 10,jp_53) n += 4; jp_53: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 11,jp_54) n += 8; jp_54: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_50: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 5,jp_60) /* n < 1 + 2 + 4 + 8 + 16 + 32*/ n = 1 + 2 + 4 + 8 + 16; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_61) n += 1; jp_61: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 9,jp_62) n += 2; jp_62: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 10,jp_63) n += 4; jp_63: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 11,jp_64) n += 8; jp_64: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 12,jp_65) n += 16; jp_65: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_60: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 6,jp_70) /* n < 1 + 2 + 4 + 8 + 16 + 32 + 64*/ n = 1 + 2 + 4 + 8 + 16 + 32; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_71) n += 1; jp_71: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 9,jp_72) n += 2; jp_72: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 10,jp_73) n += 4; jp_73: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 11,jp_74) n += 8; jp_74: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 12,jp_75) n += 16; jp_75: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 13,jp_76) n += 32; jp_76: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_70: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 7,jp_80) /* n < 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128*/ n = 1 + 2 + 4 + 8 + 16 + 32 + 64; _P2ssBitDecode(aa,bb,cc,dd,ar,c + 8,jp_81) n += 1; jp_81: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 9,jp_82) n += 2; jp_82: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 10,jp_83) n += 4; jp_83: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 11,jp_84) n += 8; jp_84: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 12,jp_85) n += 16; jp_85: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 13,jp_86) n += 32; jp_86: _P2ssBitDecode(aa,bb,cc,dd,ar,c + 14,jp_87) n += 64; jp_87: mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; jp_80: n = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128; mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return n; } static void P2ssExpandChain(mInfo,x,c) P2INFO *mInfo; int x; DWORD c; { static const WORD c_tab[] = { 80 + 6 * 5, /* -5 */ 80 + 6 * 4, 80 + 6 * 3, 80 + 6 * 2, 80 + 6 * 1, 80 + 6 * 0, /* 0 */ 80 + 6 * 0, /* 1 */ }; WORD b = c_tab[mInfo->flag_now[x] + 5]; Archive *ar = mInfo->ar; long aa = mInfo->aa; long dd = mInfo->dd; BYTE bb = mInfo->bitcnts; BYTE cc = mInfo->c; WORD pp; _P2ssBitDecode(aa,bb,cc,dd,ar,b++,jp_0) /* thru */ mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return; jp_0: _P2ssBitDecode(aa,bb,cc,dd,ar,b++,jp_1) /* down */ mInfo->vram_next[x ] = c; mInfo->flag_next[x ] = -1; mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return; jp_1: _P2ssBitDecode(aa,bb,cc,dd,ar,b++,jp_2) /* left */ mInfo->vram_next[x - 1] = c; mInfo->flag_next[x - 1] = -2; mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return; jp_2: _P2ssBitDecode(aa,bb,cc,dd,ar,b++,jp_3) /* right */ mInfo->vram_next[x + 1] = c; mInfo->flag_next[x + 1] = -3; mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return; jp_3: _P2ssBitDecode(aa,bb,cc,dd,ar,b++,jp_4) /* left2 */ mInfo->vram_next[x - 2] = c; mInfo->flag_next[x - 2] = -4; mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; return; jp_4: /* right2 */ mInfo->vram_next[x + 2] = c; mInfo->flag_next[x + 2] = -5; mInfo->aa = aa; mInfo->dd = dd; mInfo->bitcnts = bb; mInfo->c = cc; } static WORD P2ssGetnum15(mInfo,c,bef) P2INFO *mInfo; int c; int bef; { WORD n; n = P2ssNnDecode(mInfo,c); if (bef >= 16) { if (n > (31 - bef) * 2) n = 31 - n; else if (n & 1) n = n / 2 + bef + 1; else n = bef - n / 2; } else { if (n > bef * 2) n = n; else if (n & 1) n = n / 2 + bef + 1; else n = bef - n / 2; } return n; } static long P2ssGetnum24(mInfo,c,bef) P2INFO *mInfo; int c; long bef; { WORD n; n = P2ssNnDecode(mInfo,c); if (bef >= 128) { if (n > (255 - bef) * 2) n = 255 - n; else if (n & 1) n = n / 2 + bef + 1; else n = bef - n / 2; } else { if (n > bef * 2) n = n; else if (n & 1) n = n / 2 + bef + 1; else n = bef - n / 2; } return (long)n; } static BYTE P2ssReadColor8(mInfo) P2INFO *mInfo; { BYTE *cache8 = (BYTE*)mInfo->cache_pos; int i,n; BYTE cc; n = P2ssNnDecode(mInfo,32); cc = cache8[n]; for (i = n;i > 0;i--) { cache8[i] = cache8[i - 1]; } cache8[0] = cc; return cc; } #define N_CACHE8_S 5 #define N_CACHE8 (1 << N_CACHE8_S) static DWORD P2ssReadColor16(mInfo,x) P2INFO *mInfo; WORD x; { DWORD cc; int i,k,n,n2; k = mInfo->vram_now[x - 1] & 255; if (P2ssBitDecode(mInfo,mInfo->cache_hit_c)) { mInfo->cache_hit_c = 16; cc = P2ssReadColor8(mInfo); cc = (cc << 8) + P2ssReadColor8(mInfo); for (i = N_CACHE8 - 1;i > 0;i--) { mInfo->cache[(k << 5) + i] = mInfo->cache[(k << 5) + i - 1]; } mInfo->cache[k << 5] = cc; n = 32; } else { mInfo->cache_hit_c = 15; n = P2ssNnDecode(mInfo,17); n2 = n >> 1; cc = mInfo->cache[(k << 5) + n]; mInfo->cache[(k << 5) + n] = mInfo->cache[(k << 5) + n2]; mInfo->cache[(k << 5) + n2] = mInfo->cache[k << 5]; mInfo->cache[k << 5] = cc; } return cc; } static DWORD P2ssReadColor15(mInfo,x) P2INFO *mInfo; WORD x; { DWORD c1,c2,cc; WORD i,j,k,m; short r,g,b; short r0,g0,b0; c1 = mInfo->vram_prev[x]; k = ((c1 / 128) & 0x1c0) + ((c1 / 32) & 0x38) + ((c1 / 8) & 7); if (P2ssBitDecode(mInfo,mInfo->cache_hit_c)) { mInfo->cache_hit_c = 16; c2 = mInfo->vram_now[x - 1]; g = ((c1 & 0xf800) + (c2 & 0xf800)) >> 12; r = ((c1 & 0x07c0) + (c2 & 0x07c0)) >> 7; b = ((c1 & 0x003e) + (c2 & 0x003e)) >> 2; g0 = P2ssGetnum15(mInfo,32,g); r = r + g0 - g; if (r > 31) r = 31; else if (r < 0) r = 0; b = b + g0 - g; if (b > 31) b = 31; else if (b < 0) b = 0; r0 = P2ssGetnum15(mInfo,48,r); b0 = P2ssGetnum15(mInfo,64,b); mInfo->cache_pos[k] = j = (mInfo->cache_pos[k] - 1) & 31; mInfo->cache[(k << 5) + j] = cc = (g0 << 11) + (r0 << 6) + (b0 << 1); } else { mInfo->cache_hit_c = 15; j = P2ssNnDecode(mInfo,17); m = mInfo->cache_pos[k]; i = (m + j / 2) & 31; j = (m + j) & 31; cc = mInfo->cache[(k << 5) + j]; mInfo->cache[(k << 5) + j] = mInfo->cache[(k << 5) + i]; mInfo->cache[(k << 5) + i] = mInfo->cache[(k << 5) + m]; mInfo->cache[(k << 5) + m] = cc; } return cc; } static DWORD P2ssReadColor24(mInfo,x) P2INFO *mInfo; WORD x; { DWORD c1,c2,cc; WORD i,j,k,m; long r,g,b,g0; c1 = mInfo->vram_prev[x]; k = ((c1 >> 15) & 0x1c0) + ((c1 >> 10) & 0x38) + ((c1 >> 5) & 7); if (P2ssBitDecode(mInfo,mInfo->cache_hit_c)) { mInfo->cache_hit_c = 16; c2 = mInfo->vram_now[x - 1]; g = ((c1 & 0x00ff00) + (c2 & 0x00ff00)) >> 9; g0 = P2ssGetnum24(mInfo,32,g); r = (((c1 & 0xff0000) + (c2 & 0xff0000)) >> 17) + g0 - g; if (r > 255) r = 255; else if (r < 0) r = 0; r = P2ssGetnum24(mInfo,48,r); b = (((c1 & 0x0000ff) + (c2 & 0x0000ff)) >> 1) + g0 - g; if (b > 255) b = 255; else if (b < 0) b = 0; b = P2ssGetnum24(mInfo,64,b); mInfo->cache_pos[k] = j = (mInfo->cache_pos[k] - 1) & 31; mInfo->cache[(k << 5) + j] = cc = (r << 16) + (g0 << 8) + b; } else { mInfo->cache_hit_c = 15; j = P2ssNnDecode(mInfo,17); m = mInfo->cache_pos[k]; i = (m + j / 2) & 31; j = (m + j) & 31; cc = mInfo->cache[(k << 5) + j]; mInfo->cache[(k << 5) + j] = mInfo->cache[(k << 5) + i]; mInfo->cache[(k << 5) + i] = mInfo->cache[(k << 5) + m]; mInfo->cache[(k << 5) + m] = cc; } return cc; } static void P2ssParaOut(mInfo) P2INFO *mInfo; { /*** nothing ***/ } static void P2ssParaIn(mInfo) P2INFO *mInfo; { DWORD *p; schar *pp; p = mInfo->vram_prev; mInfo->vram_prev = mInfo->vram_now; mInfo->vram_now = mInfo->vram_next; mInfo->vram_next = p; pp = mInfo->flag_now; mInfo->flag_now = mInfo->flag_next; mInfo->flag_next = pp; pp = mInfo->flag2_now; mInfo->flag2_now = mInfo->flag2_next; mInfo->flag2_next = mInfo->flag2_next2; mInfo->flag2_next2 = pp; } static void P2ssLineExpand(mInfo) P2INFO *mInfo; { WORD x,ymax,ynow; DWORD cc; P2ssParaOut(mInfo); ymax = mInfo->y_wid - 1; ynow = mInfo->ynow; if (mInfo->ynow == 0) { cc = 0; } else { cc = mInfo->vram_prev[mInfo->x_wid - 1]; } mInfo->vram_now[-1] = cc; for (x = 0;x < mInfo->x_wid;x++) { mInfo->flag2_next2[x] = mInfo->flag_next[x] = 0; } for (x = 0;x < mInfo->x_wid;x++) { if (mInfo->flag_now[x] < 0) { cc = mInfo->vram_now[x]; if (ynow < ymax) { P2ssExpandChain(mInfo,x,cc); } } else if (P2ssBitDecode(mInfo,mInfo->flag2_now[x])) { mInfo->flag2_now[x + 1]++; mInfo->flag2_now[x + 2]++; mInfo->flag2_next[x - 1]++; mInfo->flag2_next[x ]++; mInfo->flag2_next[x + 1]++; mInfo->flag2_next2[x - 1]++; mInfo->flag2_next2[x ]++; mInfo->flag2_next2[x + 1]++; mInfo->vram_now[x] = cc = (*mInfo->p2ss_read_color)(mInfo,x); if (ynow < ymax) { P2ssExpandChain(mInfo,x,cc); } } else { mInfo->vram_now[x] = cc; } } mInfo->ynow++; P2ssParaIn(mInfo); } static long P2sfReadLen(mInfo) P2INFO *mInfo; { int a; a = 0; while (GetBit(mInfo,1)) { a++; } if (a == 0) return 0; return GetBit(mInfo,a) + (1 << a) - 1; } static void P2sfExpandChain(mInfo,x,cc) P2INFO *mInfo; int x; DWORD cc; { if (GetBit(mInfo,1) != 0) { if (GetBit(mInfo,1) != 0) { mInfo->vram_next[x] = cc; mInfo->flag_next[x] = -1; } else if (GetBit(mInfo,1) != 0) { if (GetBit(mInfo,1) == 0) { mInfo->vram_next[x - 2] = cc; mInfo->flag_next[x - 2] = -1; } else { mInfo->vram_next[x - 1] = cc; mInfo->flag_next[x - 1] = -1; } } else { if (GetBit(mInfo,1) == 0) { mInfo->vram_next[x + 2] = cc; mInfo->flag_next[x + 2] = -1; } else { mInfo->vram_next[x + 1] = cc; mInfo->flag_next[x + 1] = -1; } } } } static DWORD P2sfReadColor24(mInfo,bc) P2INFO *mInfo; DWORD bc; { DWORD cc; int j,k,m; k = bc >> 16; if (GetBit(mInfo,1) == 0) { mInfo->cache_pos[k] = m = (mInfo->cache_pos[k] - 1) & 0x3f; cc = mInfo->cache[(k << 6) + m] = GetBit(mInfo,24); } else { j = GetBit(mInfo,6); m = mInfo->cache_pos[k]; cc = mInfo->cache[(k << 6) + ((m + j) & 0x3f)]; } return cc; } static DWORD P2sfReadColor15(mInfo,bc) P2INFO *mInfo; DWORD bc; { DWORD cc; int j,k,m; k = bc >> 8; if (GetBit(mInfo,1) == 0) { mInfo->cache_pos[k] = m = (mInfo->cache_pos[k] - 1) & 0x3f; cc = mInfo->cache[(k << 6) + m] = GetBit(mInfo,15) * 2; } else { j = GetBit(mInfo,6); m = mInfo->cache_pos[k]; cc = mInfo->cache[(k << 6) + ((m + j) & 0x3f)]; } return cc; } static BYTE P2sfReadColor8(mInfo) P2INFO *mInfo; { BYTE *cache8 = (BYTE*)(mInfo->cache_pos + 256); BYTE cc; int i,n; if (GetBit(mInfo,1) == 0) { for (i = 16;i > 0;i--) { cache8[i] = cache8[i - 1]; } cache8[0] = cc = GetBit(mInfo,8); } else { n = GetBit(mInfo,4); cc = cache8[n]; for (i = n;i > 0;i--) { cache8[i] = cache8[i - 1]; } cache8[0] = cc; } return cc; } static DWORD P2sfReadColor16(mInfo,bc) P2INFO *mInfo; DWORD bc; { DWORD cc; int i,n,k; k = bc & 255; if (GetBit(mInfo,1) == 0) { cc = P2sfReadColor8(mInfo); cc = (cc << 8) + P2sfReadColor8(mInfo); for (i = 16;i > 0;i--) { mInfo->cache[(k << 6) + i] = mInfo->cache[(k << 6) + i - 1]; } mInfo->cache[(k << 6)] = cc; } else { n = GetBit(mInfo,4); cc = mInfo->cache[(k << 6) + n]; for (i = n;i > 0;i--) { mInfo->cache[(k << 6) + i] = mInfo->cache[(k << 6) + i - 1]; } mInfo->cache[(k << 6)] = cc; } return cc; } static void P2sfParaOut(mInfo) P2INFO *mInfo; { } static void P2sfParaIn(mInfo) P2INFO *mInfo; { DWORD *p; schar *pp; p = mInfo->vram_prev; mInfo->vram_prev = mInfo->vram_now; mInfo->vram_now = mInfo->vram_next; mInfo->vram_next = p; pp = mInfo->flag_now; mInfo->flag_now = mInfo->flag_next; mInfo->flag_next = pp; } static void P2sfLineExpand(mInfo) P2INFO *mInfo; { int x; DWORD cc; long len = mInfo->len; long len2 = mInfo->len2; P2sfParaOut(mInfo); if (mInfo->ynow == 0) { len2 = 0; len = P2sfReadLen(mInfo); if (len == 1023) len2 = 1023; else if (len > 1023) { len--; } cc = 0; } else { cc = mInfo->vram_prev[mInfo->x_wid - 1]; } for (x = 0;x < mInfo->x_wid;x++) mInfo->flag_next[x] = 0; for (x = 0;x < mInfo->x_wid;x++) { char a = mInfo->flag_now[x]; if (len2 > 0) { if (a < 0) { cc = mInfo->vram_now[x]; P2sfExpandChain(mInfo,x,cc); if (--len2 == 0) { len = P2sfReadLen(mInfo); if (len == 1023) len2 = 1023; else if (len > 1023) { len--; } } } else { mInfo->vram_now[x] = cc; } } else { if (a < 0) { cc = mInfo->vram_now[x]; P2sfExpandChain(mInfo,x,cc); } else if (--len < 0) { cc = mInfo->vram_now[x] = (*mInfo->p2sf_read_color)(mInfo,cc); P2sfExpandChain(mInfo,x,cc); len = P2sfReadLen(mInfo); if (len == 1023) len2 = 1023; else if (len > 1023) { len--; } } else { mInfo->vram_now[x] = cc; } } } mInfo->ynow++; mInfo->len = len; mInfo->len2 = len2; P2sfParaIn(mInfo); } static void BetaLineExpand(mInfo) P2INFO *mInfo; { int x,i; DWORD *pd,r,g,b; pd = mInfo->vram_now; switch (mInfo->p2_head.depth) { case 24: for (x = mInfo->x_wid;x > 0;x--) { r = archive_getc(mInfo->ar); g = archive_getc(mInfo->ar); b = archive_getc(mInfo->ar); *pd++ = (r << 16) | (g << 8) | b; } break; case 15: if (strncmp(mInfo->p2_block.id,"P2BM",4) == 0) { for (x = mInfo->x_wid;x > 0;x--) { r = archive_getc(mInfo->ar); g = archive_getc(mInfo->ar); *pd++ = (r << 8) | g; } } else { for (x = mInfo->x_wid;x > 0;x--) { r = archive_getc(mInfo->ar); g = archive_getc(mInfo->ar); *pd++ = (g << 8) | r; } } break; case 8: i = mInfo->p2_block.x_wid; for (x = mInfo->x_wid;x > 0;x--) { r = (i > 0) ? archive_getc(mInfo->ar) : 0; i--; g = (i > 0) ? archive_getc(mInfo->ar) : 0; i--; *pd++ = (r << 8) | g; } break; default: break; } pd = mInfo->vram_prev; mInfo->vram_prev = mInfo->vram_now; mInfo->vram_now = mInfo->vram_next; mInfo->vram_next = pd; mInfo->ynow++; } static int LoadP2ssScreen(mInfo) P2INFO *mInfo; { int ret = PROC_OK; WORD p2b[512]; WORD i; BYTE buf[2]; switch (mInfo->p2_head.depth) { case 24: mInfo->p2ss_read_color = P2ssReadColor24; mInfo->x_wid = mInfo->p2_block.x_wid; mInfo->y_wid = mInfo->p2_block.y_wid; break; case 15: mInfo->p2ss_read_color = P2ssReadColor15; mInfo->x_wid = mInfo->p2_block.x_wid; mInfo->y_wid = mInfo->p2_block.y_wid; break; case 8: mInfo->p2ss_read_color = P2ssReadColor16; mInfo->x_wid = (mInfo->p2_block.x_wid + 1) >> 1; mInfo->y_wid = mInfo->p2_block.y_wid; break; default: return PROC_ERROR; } mInfo->vram_prev_o = (DWORD*)calloc(1,sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->vram_now_o = (DWORD*)calloc(1,sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->vram_next_o = (DWORD*)calloc(1,sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->flag_now_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->flag_next_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->flag2_now_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->flag2_next_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->flag2_next2_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->cache = (DWORD*)calloc(1,sizeof(DWORD) * 512 * 32); mInfo->cache_pos = (WORD*)calloc(1,sizeof(WORD) * 512); mInfo->mulu_tab = (WORD*)calloc(1,sizeof(WORD) * 16384); if (mInfo->vram_prev_o == NULL || mInfo->vram_now_o == NULL || \ mInfo->vram_next_o == NULL || mInfo->flag_now_o == NULL || \ mInfo->flag_next_o == NULL || mInfo->flag2_now_o == NULL || \ mInfo->flag2_next_o == NULL || mInfo->flag2_next2_o == NULL || \ mInfo->cache == NULL || mInfo->cache_pos == NULL || \ mInfo->mulu_tab == NULL) { ret = PROC_ERROR; goto err; } if (mInfo->p2_head.depth == 8) { BYTE *cache8 = (BYTE*)mInfo->cache_pos; for (i = 0;i < 256;i++) cache8[i] = i; } for (i = 0;i < 128;i++) { archive_read(mInfo->ar,buf,2); p2b[i] = (buf[0] << 8) + buf[1]; } for (i = 0;i < 16384;i++) { mInfo->mulu_tab[i] = (long)(i / 128 + 128) * (int)p2b[i & 127] / 256; if (mInfo->mulu_tab[i] == 0) mInfo->mulu_tab[i] = 1; } mInfo->aa = 0xffffu; archive_read(mInfo->ar,buf,2); mInfo->dd = (buf[0] << 8) + buf[1]; mInfo->cache_hit_c = 16; mInfo->vram_prev = mInfo->vram_prev_o + 4; mInfo->vram_now = mInfo->vram_now_o + 4; mInfo->vram_next = mInfo->vram_next_o + 4; mInfo->flag_now = mInfo->flag_now_o + 4; mInfo->flag_next = mInfo->flag_next_o + 4; mInfo->flag2_now = mInfo->flag2_now_o + 4; mInfo->flag2_next = mInfo->flag2_next_o + 4; mInfo->flag2_next2 = mInfo->flag2_next2_o + 4; mInfo->line_expand = P2ssLineExpand; mInfo->ynow = 0; DecodeScreen(mInfo); err: { if (mInfo->vram_prev_o) free(mInfo->vram_prev_o); if (mInfo->vram_now_o) free(mInfo->vram_now_o); if (mInfo->vram_next_o) free(mInfo->vram_next_o); if (mInfo->flag_now_o) free(mInfo->flag_now_o); if (mInfo->flag_next_o) free(mInfo->flag_next_o); if (mInfo->flag2_now_o) free(mInfo->flag2_now_o); if (mInfo->flag2_next_o) free(mInfo->flag2_next_o); if (mInfo->flag2_next2_o) free(mInfo->flag2_next2_o); if (mInfo->cache) free(mInfo->cache); if (mInfo->cache_pos) free(mInfo->cache_pos); if (mInfo->mulu_tab) free(mInfo->mulu_tab); return ret; } } static int LoadP2sfScreen(mInfo) P2INFO *mInfo; { int ret = PROC_OK; switch (mInfo->p2_head.depth) { case 24: mInfo->p2sf_read_color = P2sfReadColor24; mInfo->x_wid = mInfo->p2_block.x_wid; mInfo->y_wid = mInfo->p2_block.y_wid; break; case 15: mInfo->p2sf_read_color = P2sfReadColor15; mInfo->x_wid = mInfo->p2_block.x_wid; mInfo->y_wid = mInfo->p2_block.y_wid; break; case 8: mInfo->p2sf_read_color = P2sfReadColor16; mInfo->x_wid = (mInfo->p2_block.x_wid + 1) >> 1; mInfo->y_wid = mInfo->p2_block.y_wid; break; default: return PROC_ERROR; } mInfo->vram_prev_o = (DWORD*)calloc(1,sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->vram_now_o = (DWORD*)calloc(1,sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->vram_next_o = (DWORD*)calloc(1,sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->flag_now_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->flag_next_o = (schar*)calloc(1,sizeof(schar) * (mInfo->x_wid + 8)); mInfo->cache = (DWORD*)calloc(1,sizeof(DWORD) * 512 * 64); mInfo->cache_pos = (WORD*)calloc(1,sizeof(WORD) * 512); if (mInfo->vram_prev_o == NULL || mInfo->vram_now_o == NULL || \ mInfo->vram_next_o == NULL || mInfo->flag_now_o == NULL || \ mInfo->flag_next_o == NULL || mInfo->cache == NULL || \ mInfo->cache_pos == NULL) { ret = PROC_ERROR; goto err; } mInfo->vram_prev = mInfo->vram_prev_o + 4; mInfo->vram_now = mInfo->vram_now_o + 4; mInfo->vram_next = mInfo->vram_next_o + 4; mInfo->flag_now = mInfo->flag_now_o + 4; mInfo->flag_next = mInfo->flag_next_o + 4; mInfo->line_expand = P2sfLineExpand; mInfo->ynow = 0; DecodeScreen(mInfo); err: { if (mInfo->vram_prev_o) free(mInfo->vram_prev_o); if (mInfo->vram_now_o) free(mInfo->vram_now_o); if (mInfo->vram_next_o) free(mInfo->vram_next_o); if (mInfo->flag_now_o) free(mInfo->flag_now_o); if (mInfo->flag_next_o) free(mInfo->flag_next_o); if (mInfo->cache) free(mInfo->cache); if (mInfo->cache_pos) free(mInfo->cache_pos); return ret; } } static int LoadBetaScreen(mInfo) P2INFO *mInfo; { int ret = PROC_OK; if (mInfo->p2_head.depth == 8) { mInfo->x_wid = (mInfo->p2_block.x_wid + 1) / 2; mInfo->y_wid = mInfo->p2_block.y_wid; } else { mInfo->x_wid = mInfo->p2_block.x_wid; mInfo->y_wid = mInfo->p2_block.y_wid; } mInfo->vram_prev_o = (DWORD*)malloc(sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->vram_now_o = (DWORD*)malloc(sizeof(DWORD) * (mInfo->x_wid + 8)); mInfo->vram_next_o = (DWORD*)malloc(sizeof(DWORD) * (mInfo->x_wid + 8)); if (mInfo->vram_prev_o == NULL || mInfo->vram_now_o == NULL || \ mInfo->vram_next_o == NULL) { ret = PROC_ERROR; goto err; } mInfo->vram_prev = mInfo->vram_prev_o + 4; mInfo->vram_now = mInfo->vram_now_o + 4; mInfo->vram_next = mInfo->vram_next_o + 4; mInfo->line_expand = BetaLineExpand; mInfo->ynow = 0; DecodeScreen(mInfo); err: { if (mInfo->vram_prev_o) free(mInfo->vram_prev_o); if (mInfo->vram_now_o) free(mInfo->vram_now_o); if (mInfo->vram_next_o) free(mInfo->vram_next_o); return ret; } }