ReC98/th01/formats/ptn_main.cpp

232 lines
6.4 KiB
C++

#include "th01/hardware/graph.h"
#include "th01/hardware/egc.h"
#include "th01/formats/ptn.hpp"
static inline ptn_t* ptn_with_id_shift(int id)
{
// Before we bother with doing compile-time integer logarithms...
// (MODDERS: This function shouldn't exist. Just use the regular
// ptn_with_id().)
if(PTN_IMAGES_PER_SLOT == 64) {
return &ptn_images[id >> 6][id % PTN_IMAGES_PER_SLOT];
}
return &ptn_images[id / PTN_IMAGES_PER_SLOT][id % PTN_IMAGES_PER_SLOT];
}
#define grcg_clear_masked(vram_offset, w, mask) \
grcg_setcolor_rmw(0); \
VRAM_PUT(B, vram_offset, mask, w); \
grcg_off();
#define ptn_or_masked(vram_offset, w, ptn, mask) \
VRAM_CHUNK(B, vram_offset, w) |= (ptn->planes.B[y] & mask); \
VRAM_CHUNK(R, vram_offset, w) |= (ptn->planes.R[y] & mask); \
VRAM_CHUNK(G, vram_offset, w) |= (ptn->planes.G[y] & mask); \
VRAM_CHUNK(E, vram_offset, w) |= (ptn->planes.E[y] & mask);
#define ptn_or_quarter_masked(vram_offset, w, ptn, q, mask) \
VRAM_CHUNK(B, vram_offset, w) |= ((ptn->planes.B[y] >> q.x) & mask); \
VRAM_CHUNK(R, vram_offset, w) |= ((ptn->planes.R[y] >> q.x) & mask); \
VRAM_CHUNK(G, vram_offset, w) |= ((ptn->planes.G[y] >> q.x) & mask); \
VRAM_CHUNK(E, vram_offset, w) |= ((ptn->planes.E[y] >> q.x) & mask);
void ptn_unput_8(int left, int top, int ptn_id)
{
ptn_dots_t mask = 0;
uint16_t vram_offset = vram_offset_shift(left, top);
ptn_t *ptn = ptn_with_id_shift(ptn_id);
for(unsigned int y = 0; y < PTN_H; y++) {
mask = ptn->alpha[y];
graph_accesspage_func(0);
if(mask) {
planar_t(PTN_W) page1;
grcg_clear_masked(vram_offset, PTN_W, mask);
graph_accesspage_func(1);
vram_snap_planar_masked(page1, vram_offset, PTN_W, mask);
graph_accesspage_func(0);
vram_or_planar(vram_offset, page1, PTN_W);
}
vram_offset += ROW_SIZE;
if(vram_offset > PLANE_SIZE) {
break;
}
}
}
void ptn_put_8(int left, int top, int ptn_id)
{
unsigned int y;
dots_t(PTN_W) mask = 0;
uint16_t vram_offset = vram_offset_shift(left, top);
ptn_t *ptn = ptn_with_id_shift(ptn_id);
if(ptn_unput_before_alpha_put) {
egc_copy_rect_1_to_0_16(left, top, PTN_W, PTN_H);
}
for(y = 0; y < PTN_H; y++) {
mask = ptn->alpha[y];
if(mask) {
grcg_clear_masked(vram_offset, PTN_W, mask);
ptn_or_masked(vram_offset, PTN_W, ptn, mask);
}
vram_offset += ROW_SIZE;
if(vram_offset > PLANE_SIZE) {
break;
}
}
}
void ptn_unput_quarter_8(int left, int top, int ptn_id, int quarter)
{
sdots_t(PTN_QUARTER_W) mask;
unsigned int y;
PTNQuarter q;
planar_t(PTN_QUARTER_W) page1;
sdots_t(PTN_W) mask_full = 0;
uint16_t vram_offset = vram_offset_shift(left, top);
ptn_t *ptn = ptn_with_id_shift(ptn_id);
q.init(quarter);
for(y = q.y; y < (q.y + PTN_QUARTER_H); y++) {
mask_full = ptn->alpha[y];
graph_accesspage_func(0);
mask = (mask_full >> q.x);
if(mask) {
grcg_clear_masked(vram_offset, PTN_QUARTER_W, mask);
graph_accesspage_func(1);
vram_snap_planar_masked(page1, vram_offset, PTN_QUARTER_W, mask);
graph_accesspage_func(0);
vram_or_planar(vram_offset, page1, PTN_QUARTER_W);
}
vram_offset += ROW_SIZE;
// No vram_offset bounds check here?!
}
}
void ptn_put_quarter_8(int left, int top, int ptn_id, int quarter)
{
sdots_t(PTN_QUARTER_W) mask;
unsigned int y;
PTNQuarter q;
sdots_t(PTN_W) mask_full = 0;
uint16_t vram_offset = vram_offset_shift(left, top);
ptn_t *ptn = ptn_with_id_shift(ptn_id);
q.init(quarter);
if(ptn_unput_before_alpha_put) {
egc_copy_rect_1_to_0_16(left, top, PTN_QUARTER_W, PTN_QUARTER_H);
}
for(y = q.y; y < (q.y + PTN_QUARTER_H); y++) {
mask_full = ptn->alpha[y];
mask = (mask_full >> q.x);
if(mask) {
grcg_clear_masked(vram_offset, PTN_QUARTER_W, mask);
ptn_or_quarter_masked(vram_offset, PTN_QUARTER_W, ptn, q, mask);
}
vram_offset += ROW_SIZE;
// No vram_offset bounds check here?!
}
}
void ptn_put_quarter(int left, int top, int ptn_id, int quarter)
{
union dots16_unaligned_t {
dots8_t d8[3];
dots32_t d32;
void set(const dots16_t& dots, const char& first_bit) {
d8[0] = ((dots & 0xFF) >> first_bit);
d8[1] = (
((dots & 0xFF) << (8 - first_bit)) |
((dots & 0xFF00) >> (8 + first_bit))
);
d8[2] = ((dots & 0xFF00) >> first_bit);
}
void set(
const dots16_t& dots,
const char& first_bit,
const dots16_unaligned_t& mask
) {
d8[0] = (((dots & 0xFF) >> first_bit) & mask.d8[0]);
d8[1] = ((
((dots & 0xFF) << (8 - first_bit)) |
((dots & 0xFF00) >> (8 + first_bit))
) & mask.d8[1]);
d8[2] = (((dots & 0xFF00) >> first_bit) & mask.d8[2]);
}
};
extern Planar<dots8_t *> ptnpq_vram;
extern dots16_unaligned_t ptnpq_mask_unaligned_zero;
extern dots16_unaligned_t ptnpq_dots_unaligned_zero;
unsigned int plane;
unsigned int y;
dots_t(PTN_QUARTER_W) mask;
PTNQuarter q;
char first_bit = (left % 8);
dots16_unaligned_t mask_unaligned = ptnpq_mask_unaligned_zero;
dots16_unaligned_t dots_unaligned = ptnpq_dots_unaligned_zero;
Planar<dots_t(PTN_QUARTER_W)> sprite;
dots_t(PTN_QUARTER_W) dots;
uint16_t vram_offset = vram_offset_shift(left, top);
ptn_t *ptn = ptn_with_id_shift(ptn_id);
ptnpq_vram.B = VRAM_PLANE_B;
ptnpq_vram.R = VRAM_PLANE_R;
ptnpq_vram.G = VRAM_PLANE_G;
ptnpq_vram.E = VRAM_PLANE_E;
Planar<dots8_t *> vram_local = ptnpq_vram;
// MODDERS: Yes, should have been || rather than &&...
if((left < 0) && (left > (RES_X - PTN_QUARTER_W))) {
return;
}
q.init(quarter);
for(y = q.y; y < (q.y + PTN_QUARTER_H); y++) {
for(plane = 0; plane < PL_COUNT; plane++) {
sprite[plane] = (ptn->planes[plane][y] >> q.x);
}
mask = ptn_alpha_from(sprite.B, sprite.R, sprite.G, sprite.E);
if(first_bit == 0) {
if(mask != 0) {
#define w PTN_QUARTER_W
grcg_clear_masked(vram_offset, w, mask);
vram_or_masked_emptyopt(B, vram_offset, w, sprite.B, mask);
vram_or_masked_emptyopt(R, vram_offset, w, sprite.R, mask);
vram_or_masked_emptyopt(G, vram_offset, w, sprite.G, mask);
vram_or_masked_emptyopt(E, vram_offset, w, sprite.E, mask);
#undef w
}
} else {
if(mask != 0) {
mask_unaligned.set(mask, first_bit);
grcg_clear_masked(vram_offset, 32, mask_unaligned.d32);
for(plane = 0; plane < PL_COUNT; plane++) {
dots = sprite[plane];
if(dots) {
dots_unaligned.set(dots, first_bit, mask_unaligned);
*reinterpret_cast<dots32_t far *>(
vram_local[plane] + vram_offset
) |= dots_unaligned.d32;
}
}
}
}
vram_offset += ROW_SIZE;
if(vram_offset > PLANE_SIZE) {
break;
}
}
}