/* * vsp.c extract VSP cg * * Copyright (C) 1997-1998 Masaki Chikama (Wren) * 1998- * * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 0.00 97/11/06 初版 * 0.01 97/11/12 TYPO * 0.01-01 97/11/13 ヘッダ情報の返しかたの変更 * 0.01-02 97/11/27 記憶子の変更 * 0.01-03 97/12/06 ヘッダの誤認識の修正 * 0.02 98/02/26 デバッグ済み * 0.03 98/03/20 ヘッダチェックのミス * 0.03 98/12/19 dalkで640x401なCGがあったのでその対策 * @version 1.5 00/09/17 rewrite for changeing interface */ /* $Id: vsp.c,v 1.6 2000/11/25 18:31:49 chikama Exp $ */ #include #include #include "portab.h" #include "LittleEndian.h" #include "graphics.h" #include "cg.h" #include "vsp.h" /* * static methods */ static vsp_header *extract_header(uint8_t *b); static void extract(vsp_header *vsp, uint8_t *pic, uint8_t *b); /* * Get information from cg header * b: raw data (pointer to header) * return: acquired vsp information object */ static vsp_header *extract_header(uint8_t *b) { vsp_header *vsp = malloc(sizeof(vsp_header)); vsp->vspX0 = LittleEndian_getW(b, 0); vsp->vspY0 = LittleEndian_getW(b, 2); vsp->vspXW = LittleEndian_getW(b, 4) - vsp->vspX0; vsp->vspYW = LittleEndian_getW(b, 6) - vsp->vspY0; vsp->vspPb = b[9]; vsp->vspPp = 0x0a; vsp->vspDp = 0x3a; return vsp; } /* * Get palette from raw data * b : raw data (pointer to palette) */ static Color *getpal(uint8_t *b) { Color *pal = malloc(sizeof(Color) * 256); for (int i = 0; i < 16; i++) { pal[i].b = b[i * 3 + 0] * 17; pal[i].r = b[i * 3 + 1] * 17; pal[i].g = b[i * 3 + 2] * 17; } return pal; } /* * Do extract vsp image * vsp: vsp header information * pic: pixel to be stored * b : raw data (pointer to pixel) */ static void extract(vsp_header *vsp, uint8_t *pic, uint8_t *b) { int c0; uint8_t b0, b1, b2, b3, mask = 0; uint8_t *bt; int i, l, x, y, pl, loc; // Extraction buffers. uint8_t *buf = malloc(vsp->vspYW * 8); uint8_t *bc[4]; uint8_t *bp[4]; for (int i = 0; i < 4; i++) { bc[i] = buf + vsp->vspYW * (i * 2); bp[i] = buf + vsp->vspYW * (i * 2 + 1); } for (x = 0; x < vsp->vspXW; x++) { for (pl = 0; pl < 4; pl++) { y = 0; while(y < vsp->vspYW) { c0 = *b++; if (c0 >= 0x08) { *(bc[pl] + y) = c0; y++; } else if (c0 == 0x00) { l = (*b) + 1; b++; memcpy(bc[pl] + y, bp[pl] + y, l); y+=l; } else if (c0 == 0x01) { l = (*b) + 1; b++; b0 = *b++; memset(bc[pl] + y, b0, l); y+=l; } else if (c0 == 0x02) { l = (*b) + 1; b++; b0 = *b++; b1 = *b++; for (i = 0; i < l; i++) { *(bc[pl] + y) = b0; y++; *(bc[pl] + y) = b1; y++; } } else if (c0 == 0x03) { l = (*b) + 1; b++; for (i = 0; i < l; i++) { *(bc[pl] + y) = (*(bc[0] + y) ^ mask); y++; } mask = 0; } else if (c0 == 0x04) { l = (*b) + 1; b++; for (i = 0; i < l; i++) { *(bc[pl] + y) = (*(bc[1] + y) ^ mask); y++; } mask = 0; } else if (c0 == 0x05) { l = (*b) + 1; b++; for (i = 0; i < l; i++) { *(bc[pl] + y) = (*(bc[2] + y) ^ mask); y++; } mask = 0; } else if (c0 == 0x06) { mask = 0xff; } else if (c0 == 0x07) { *(bc[pl] + y) = *b++ ; y++; } } } /* plane -> packed 展開 */ for (y = 0; y < vsp->vspYW; y++) { loc = (y * vsp->vspXW + x) * 8; b0 = bc[0][y]; b1 = bc[1][y]; b2 = bc[2][y]; b3 = bc[3][y]; *(pic + loc + 0) = ((b0>>7)&0x01)|((b1>>6)&0x02)|((b2>>5)&0x04)|((b3>>4)&0x08); *(pic + loc + 1) = ((b0>>6)&0x01)|((b1>>5)&0x02)|((b2>>4)&0x04)|((b3>>3)&0x08); *(pic + loc + 2) = ((b0>>5)&0x01)|((b1>>4)&0x02)|((b2>>3)&0x04)|((b3>>2)&0x08); *(pic + loc + 3) = ((b0>>4)&0x01)|((b1>>3)&0x02)|((b2>>2)&0x04)|((b3>>1)&0x08); *(pic + loc + 4) = ((b0>>3)&0x01)|((b1>>2)&0x02)|((b2>>1)&0x04)|((b3 )&0x08); *(pic + loc + 5) = ((b0>>2)&0x01)|((b1>>1)&0x02)|((b2 )&0x04)|((b3<<1)&0x08); *(pic + loc + 6) = ((b0>>1)&0x01)|((b1 )&0x02)|((b2<<1)&0x04)|((b3<<2)&0x08); *(pic + loc + 7) = ((b0 )&0x01)|((b1<<1)&0x02)|((b2<<2)&0x04)|((b3<<3)&0x08); } /* bc -> bpにコピー */ bt = bp[0]; bp[0] = bc[0]; bc[0] = bt; bt = bp[1]; bp[1] = bc[1]; bc[1] = bt; bt = bp[2]; bp[2] = bc[2]; bc[2] = bt; bt = bp[3]; bp[3] = bc[3]; bc[3] = bt; } free(buf); } /* * Check data is vsp format cg or not * data: raw data (pointer to data top) * return: TRUE if data is vsp */ boolean vsp_checkfmt(uint8_t *data) { int x0 = LittleEndian_getW(data, 0); int y0 = LittleEndian_getW(data, 2); int w = LittleEndian_getW(data, 4) - x0; int h = LittleEndian_getW(data, 6) - y0; if (x0 < 0 || x0 > 80 || y0 < 0 || y0 > 400) return FALSE; /* 401: for dalk's broken cg */ if (w < 0 || w > 80 || h < 0 || h > 401) return FALSE; return TRUE; } /* * Extract vsp, header, palette and pixel * data: raw data (pointer to data top) * return: extracted image data and information */ cgdata *vsp_extract(uint8_t *data) { cgdata *cg = calloc(1, sizeof(cgdata)); vsp_header *vsp = extract_header(data); cg->pal = getpal(data + vsp->vspPp); /* +10: margin for broken cg */ cg->pic = malloc(sizeof(uint8_t) * ((vsp->vspXW * 8 + 10) * (vsp->vspYW + 10))); extract(vsp, cg->pic, data + vsp->vspDp); cg->type = ALCG_VSP; cg->x = vsp->vspX0 * 8; cg->y = vsp->vspY0; cg->width = vsp->vspXW * 8; cg->height = vsp->vspYW; cg->depth = 8; cg->vsp_bank = vsp->vspPb; cg->alpha = NULL; free(vsp); return cg; }