mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-30 10:58:15 +03:00
Plus a bit of SACT2 implementation, and fix a bug where global arrays were not initialized properly.
248 lines
6.9 KiB
C
248 lines
6.9 KiB
C
/*
|
|
* vsp.c extract VSP cg
|
|
*
|
|
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
|
|
* 1998- <masaki-c@is.aist-nara.ac.jp>
|
|
* 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "little_endian.h"
|
|
#include "graphics.h"
|
|
#include "cg.h"
|
|
#include "vsp.h"
|
|
|
|
/*
|
|
* static methods
|
|
*/
|
|
static struct vsp_header *extract_header(uint8_t *b);
|
|
static void getpal(Pallet256 *pal, uint8_t *b);
|
|
static void extract(struct vsp_header *vsp, uint8_t *pic, uint8_t *b);
|
|
|
|
/*
|
|
* extraction buffer
|
|
*/
|
|
static uint8_t _bc[4][480];
|
|
static uint8_t _bp[4][480];
|
|
static uint8_t *bc[4];
|
|
static uint8_t *bp[4];
|
|
|
|
/*
|
|
* Get information from cg header
|
|
* b: raw data (pointer to header)
|
|
* return: acquired vsp information object
|
|
*/
|
|
static struct vsp_header *extract_header(uint8_t *b) {
|
|
struct vsp_header *vsp = malloc(sizeof(struct 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 pallet from raw data
|
|
* pal: pallet to be stored
|
|
* b : raw data (pointer to pallet)
|
|
*/
|
|
static void getpal(Pallet256 *pal, uint8_t *b) {
|
|
int red, green, blue, i;
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
blue = b[i * 3 + 0];
|
|
red = b[i * 3 + 1];
|
|
green = b[i * 3 + 2];
|
|
pal->red[i] = (red << 4);
|
|
pal->green[i] = (green << 4);
|
|
pal->blue[i] = (blue << 4);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Do extract vsp image
|
|
* vsp: vsp header information
|
|
* pic: pixel to be stored
|
|
* b : raw data (pointer to pixel)
|
|
*/
|
|
static void extract(struct 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;
|
|
|
|
bp[0] = _bp[0]; bc[0] = _bc[0];
|
|
bp[1] = _bp[1]; bc[1] = _bc[1];
|
|
bp[2] = _bp[2]; bc[2] = _bc[2];
|
|
bp[3] = _bp[3]; bc[3] = _bc[3];
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check data is vsp format cg or not
|
|
* data: raw data (pointer to data top)
|
|
* return: true if data is vsp
|
|
*/
|
|
bool 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, pallet and pixel
|
|
* data: raw data (pointer to data top)
|
|
* return: extracted image data and information
|
|
*/
|
|
struct cg *vsp_extract(uint8_t *data) {
|
|
struct cg *cg = calloc(1, sizeof(struct cg));
|
|
struct vsp_header *vsp = extract_header(data);
|
|
|
|
cg->pal = malloc(sizeof(Pallet256));
|
|
getpal(cg->pal, 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->vsp_bank = vsp->vspPb;
|
|
cg->alpha = NULL;
|
|
|
|
free(vsp);
|
|
|
|
return cg;
|
|
}
|
|
|
|
/*
|
|
* Extract vsp pallet only
|
|
* data: raw data (pointer to data top)
|
|
* return: extracted pallet data
|
|
*/
|
|
struct cg *vsp_getpal(uint8_t *data) {
|
|
struct cg *cg = calloc(1, sizeof(struct cg));
|
|
struct vsp_header *vsp = extract_header(data);
|
|
|
|
cg->pal = malloc(sizeof(Pallet256));
|
|
getpal(cg->pal, data + vsp->vspPp);
|
|
|
|
cg->type = ALCG_VSP;
|
|
cg->pic = NULL;
|
|
cg->alpha = NULL;
|
|
|
|
free(vsp);
|
|
|
|
return cg;
|
|
}
|