Skip to content

Commit

Permalink
[Decompilation] [th01] .PTN: Unaligned 16×16 blitting
Browse files Browse the repository at this point in the history
But no corresponding unblitting function…?

Completes P0096, funded by Ember2528.
  • Loading branch information
nmlgc committed Jun 13, 2020
1 parent 979f401 commit 8283c5e
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 305 deletions.
2 changes: 2 additions & 0 deletions ReC98.h
Expand Up @@ -117,6 +117,8 @@ typedef struct {
// Since array subscripts create slightly different assembly in places, we
// offer both variants.
extern dots8_t *VRAM_PLANE[PL_COUNT];
// And no. expressing these as a struct won't generate the same ASM.
// Been there, tried that.
extern dots8_t *VRAM_PLANE_B;
extern dots8_t *VRAM_PLANE_G;
extern dots8_t *VRAM_PLANE_R;
Expand Down
8 changes: 7 additions & 1 deletion th01/formats/ptn.hpp
Expand Up @@ -32,7 +32,10 @@ struct ptn_planar_t {
// On-disk per-image structure
struct ptn_file_image_t {
int8_t unused_zero;
ptn_planar_t planes;
union {
ptn_planar_t planes;
ptn_dots_t P[PL_COUNT][PTN_H];
};
};

// In-memory per-image structure
Expand Down Expand Up @@ -150,5 +153,8 @@ void ptn_unput_quarter_8(int left, int top, int ptn_id, int quarter);

// Displays the given [quarter] of the given [ptn_id] at (⌊left/8⌋*8, top).
void ptn_put_quarter_8(int left, int top, int ptn_id, int quarter);

// Displays the given [quarter] of the given [ptn_id] at (left, top).
void ptn_put_quarter(int left, int top, int ptn_id, int quarter);
// ------------
/// -----------------------------------------
103 changes: 103 additions & 0 deletions th01/formats/ptn_main.cpp
Expand Up @@ -42,6 +42,11 @@ static inline ptn_t* ptn_with_id_shift(int id)
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);

#define or_masked(plane, offset, w, dots, mask) \
if(dots) { \
VRAM_CHUNK(plane, offset, w) |= (dots & mask); \
}

void ptn_unput_8(int left, int top, int ptn_id)
{
ptn_dots_t mask = 0;
Expand Down Expand Up @@ -145,3 +150,101 @@ void ptn_put_quarter_8(int left, int top, int ptn_id, int quarter)
// 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]);
}
};

struct vram_planes_t {
dots8_t *P[PL_COUNT];
};

extern vram_planes_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;
dots_t(PTN_QUARTER_W) sprite[PL_COUNT];
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.P[PL_B] = VRAM_PLANE_B;
ptnpq_vram.P[PL_R] = VRAM_PLANE_R;
ptnpq_vram.P[PL_G] = VRAM_PLANE_G;
ptnpq_vram.P[PL_E] = VRAM_PLANE_E;

vram_planes_t vram_local = ptnpq_vram;

// 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->P[plane][y] >> q.x);
}
mask = ptn_alpha_from(sprite[0], sprite[1], sprite[2], sprite[3]);

if(first_bit == 0) {
if(mask != 0) {
grcg_clear_masked(vram_offset, PTN_QUARTER_W, mask);
or_masked(B, vram_offset, PTN_QUARTER_W, sprite[0], mask);
or_masked(R, vram_offset, PTN_QUARTER_W, sprite[1], mask);
or_masked(G, vram_offset, PTN_QUARTER_W, sprite[2], mask);
or_masked(E, vram_offset, PTN_QUARTER_W, sprite[3], mask);
}
} 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.P[plane] + vram_offset
) |= dots_unaligned.d32;
}
}
}
}
vram_offset += ROW_SIZE;
if(vram_offset > PLANE_SIZE) {
break;
}
}
}
4 changes: 4 additions & 0 deletions th01/formats/ptn_main[data].asm
@@ -1,2 +1,6 @@
public _ptn_unput_before_alpha_put
public _ptnpq_mask_unaligned_zero, _ptnpq_dots_unaligned_zero, _ptnpq_vram
_ptn_unput_before_alpha_put db 0
_ptnpq_mask_unaligned_zero dd 0
_ptnpq_dots_unaligned_zero dd 0
_ptnpq_vram dd 4 dup (0)

0 comments on commit 8283c5e

Please sign in to comment.