Skip to content

Commit

Permalink
[Maintenance] [th01] Reorder shared .BOS code
Browse files Browse the repository at this point in the history
Part of P0123, funded by Yanga.
  • Loading branch information
nmlgc committed Oct 13, 2020
1 parent 1066613 commit b75556c
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 94 deletions.
70 changes: 31 additions & 39 deletions th01/formats/bos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,15 @@
// On-disk per-file header. Not the same as for .GRC!
struct bos_header_t {
char magic[sizeof(BOS_MAGIC) - 1];

// Yes, this means that the *format* itself isn't actually restricted to
// word-aligned / 16w×h sizes, …
uint8_t vram_w;

int8_t zero;
uint8_t h;
int8_t unknown;
spriteformat_header_inner_t inner;
};

#define BOS_IMAGES_PER_SLOT 8

// In-memory slot structures
struct bos_image_t {
// … as these types would suggest. That's purely an implementation choice.
Planar<dots16_t *> planes;
dots16_t *alpha;
};

struct bos_t {
bos_image_t image[BOS_IMAGES_PER_SLOT];
};

// Shared loading and freeing subfunctions
// ---------------------------------------
// Shared loading subfunctions
// ---------------------------

// Separate function to work around the `Condition is always true/false` and
// `Unreachable code` warnings
Expand All @@ -57,30 +40,39 @@ inline void bos_header_load_palette(Palette4 &pal, bool load) {
that->bos_image_count = header.outer.inner.image_count; \
plane_size = (that->vram_w * that->h); \
bos_header_load_palette(header.pal, needlessly_load_the_palette);
// ---------------------------

#define bos_image_new(image, plane_size) \
image.alpha = new dots16_t[plane_size / 2]; \
image.planes.B = new dots16_t[plane_size / 2]; \
image.planes.R = new dots16_t[plane_size / 2]; \
image.planes.G = new dots16_t[plane_size / 2]; \
image.planes.E = new dots16_t[plane_size / 2];
/// Shared blitting subfunctions
/// ----------------------------

// Always setting the pointer to NULL, for a change...
#define bos_image_ptr_free(ptr) \
if(ptr) { \
delete[] ptr; \
} \
ptr = NULL;
// Part of ZUN's attempt at clipping at the left or right edges of VRAM, by
// comparing [vram_offset] against the value returned from this function.
inline vram_y_t vram_intended_y_for(
vram_offset_t vram_offset, screen_x_t first_x
) {
return (first_x < 0)
? ((vram_offset / ROW_SIZE) + 1)
: ((vram_offset / ROW_SIZE) + 0);
}

#define bos_free(slot_ptr) \
for(int image = 0; image < BOS_IMAGES_PER_SLOT; image++) { \
bos_image_ptr_free(slot_ptr.image[image].alpha); \
bos_image_ptr_free(slot_ptr.image[image].planes.B); \
bos_image_ptr_free(slot_ptr.image[image].planes.R); \
bos_image_ptr_free(slot_ptr.image[image].planes.G); \
bos_image_ptr_free(slot_ptr.image[image].planes.E); \
#define vram_offset_at_intended_y_16(vram_offset, intended_y) \
(((vram_offset + 0) / ROW_SIZE) == intended_y) && \
(((vram_offset + 1) / ROW_SIZE) == intended_y)

#define vram_unput_masked_emptyopt(plane, offset, bit_count, mask, tmp_dots) \
graph_accesspage_func(1); \
VRAM_SNAP(tmp_dots, plane, offset, bit_count); \
if(tmp_dots) { \
graph_accesspage_func(0); \
VRAM_CHUNK(plane, offset, bit_count) |= (mask & tmp_dots); \
}
// ---------------------------------------

#define vram_unput_masked_emptyopt_planar(offset, bit_count, mask, tmp_dots) \
vram_unput_masked_emptyopt(B, offset, bit_count, mask, tmp_dots); \
vram_unput_masked_emptyopt(R, offset, bit_count, mask, tmp_dots); \
vram_unput_masked_emptyopt(G, offset, bit_count, mask, tmp_dots); \
vram_unput_masked_emptyopt(E, offset, bit_count, mask, tmp_dots);
/// ----------------------------

/// All functions that operate on this format are implemented redundantly for
/// both CBossEntity, CBossAnim, and CPlayerAnim with their own respective
Expand Down
18 changes: 7 additions & 11 deletions th01/formats/ptn_main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "th01/hardware/graph.h"
#include "th01/hardware/egc.h"
#include "th01/hardware/planar.h"
#include "th01/formats/ptn.hpp"

static inline ptn_t* ptn_with_id_shift(int id)
Expand All @@ -13,11 +14,6 @@ static inline ptn_t* ptn_with_id_shift(int id)
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); \
grcg_put(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); \
Expand All @@ -42,7 +38,7 @@ void ptn_unput_8(screen_x_t left, vram_y_t top, int ptn_id)
if(mask) {
planar_t(PTN_W) page1;

grcg_clear_masked(vram_offset, PTN_W, mask);
vram_erase(vram_offset, mask, PTN_W);

graph_accesspage_func(1);
vram_snap_planar_masked(page1, vram_offset, PTN_W, mask);
Expand Down Expand Up @@ -70,7 +66,7 @@ void ptn_put_8(screen_x_t left, vram_y_t top, int ptn_id)
for(y = 0; y < PTN_H; y++) {
mask = ptn->alpha[y];
if(mask) {
grcg_clear_masked(vram_offset, PTN_W, mask);
vram_erase(vram_offset, mask, PTN_W);
ptn_or_masked(vram_offset, PTN_W, ptn, mask);
}
vram_offset += ROW_SIZE;
Expand Down Expand Up @@ -100,7 +96,7 @@ void ptn_unput_quarter_8(

mask = (mask_full >> q.x);
if(mask) {
grcg_clear_masked(vram_offset, PTN_QUARTER_W, mask);
vram_erase(vram_offset, mask, PTN_QUARTER_W);
graph_accesspage_func(1);
vram_snap_planar_masked(page1, vram_offset, PTN_QUARTER_W, mask);
graph_accesspage_func(0);
Expand Down Expand Up @@ -128,7 +124,7 @@ void ptn_put_quarter_8(screen_x_t left, vram_y_t top, int ptn_id, int quarter)
mask_full = ptn->alpha[y];
mask = (mask_full >> q.x);
if(mask) {
grcg_clear_masked(vram_offset, PTN_QUARTER_W, mask);
vram_erase(vram_offset, mask, PTN_QUARTER_W);
ptn_or_quarter_masked(vram_offset, PTN_QUARTER_W, ptn, q, mask);
}
vram_offset += ROW_SIZE;
Expand Down Expand Up @@ -203,7 +199,7 @@ void ptn_put_quarter(screen_x_t left, vram_y_t top, int ptn_id, int quarter)
if(first_bit == 0) {
if(mask != 0) {
#define w PTN_QUARTER_W
grcg_clear_masked(vram_offset, w, mask);
vram_erase(vram_offset, mask, w);
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);
Expand All @@ -213,7 +209,7 @@ void ptn_put_quarter(screen_x_t left, vram_y_t top, int ptn_id, int quarter)
} else {
if(mask != 0) {
mask_unaligned.set(mask, first_bit);
grcg_clear_masked(vram_offset, 32, mask_unaligned.d32);
vram_erase(vram_offset, mask_unaligned.d32, 32);
for(plane = 0; plane < PL_COUNT; plane++) {
dots = sprite[plane];
if(dots) {
Expand Down
16 changes: 16 additions & 0 deletions th01/hardware/planar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* ReC98
* -----
* TH01-specific extensions to planar.h
*/

// *Not* grcg_*, because they fully abstract away the GRCG's existence
#define vram_erase(offset, dots, bit_count) \
grcg_setcolor_rmw(0); \
grcg_put(offset, dots, bit_count); \
grcg_off();

#define vram_erase_on_0(offset, dots, bit_count) \
grcg_setcolor_rmw(0); \
graph_accesspage_func(0); \
grcg_put(offset, dots, bit_count); \
grcg_off();
84 changes: 43 additions & 41 deletions th01/main/boss/entity_a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,53 @@
#include "th01/math/wave.hpp"
#include "th01/hardware/egc.h"
#include "th01/hardware/graph.h"
#include "th01/hardware/planar.h"
#include "th01/formats/sprfmt_h.hpp"
#include "th01/formats/pf.hpp"
#include "th01/formats/bos.hpp"
#include "th01/main/playfld.hpp"
#include "th01/main/player/orb.hpp"
#include "th01/main/boss/entity_a.hpp"

/// Helper functions
/// ----------------
// Part of ZUN's attempt at clipping at the left or right edges of VRAM, by
// comparing [vram_offset] against the value returned from this function.
inline vram_y_t vram_intended_y_for(
vram_offset_t vram_offset, screen_x_t first_x
) {
return (first_x < 0)
? ((vram_offset / ROW_SIZE) + 1)
: ((vram_offset / ROW_SIZE) + 0);
}

#define vram_offset_at_intended_y_16(vram_offset, intended_y) \
(((vram_offset + 0) / ROW_SIZE) == intended_y) && \
(((vram_offset + 1) / ROW_SIZE) == intended_y)
/// ----------------
// Slot structures
// ---------------
// Both CBossEntity and CBossAnim choose to restrict themselves to
// word-aligned / 16w×h image sizes, even though .BOS itself is byte-aligned.

#define BOS_IMAGES_PER_SLOT 8

struct bos_image_t {
Planar<dots16_t *> planes;
dots16_t *alpha;
};

struct bos_t {
bos_image_t image[BOS_IMAGES_PER_SLOT];
};

#define bos_image_new(image, plane_size) \
image.alpha = new dots16_t[plane_size / 2]; \
image.planes.B = new dots16_t[plane_size / 2]; \
image.planes.R = new dots16_t[plane_size / 2]; \
image.planes.G = new dots16_t[plane_size / 2]; \
image.planes.E = new dots16_t[plane_size / 2];

// Always setting the pointer to NULL, for a change...
#define bos_image_ptr_free(ptr) \
if(ptr) { \
delete[] ptr; \
} \
ptr = NULL;

#define bos_free(slot_ptr) \
for(int image = 0; image < BOS_IMAGES_PER_SLOT; image++) { \
bos_image_ptr_free(slot_ptr.image[image].alpha); \
bos_image_ptr_free(slot_ptr.image[image].planes.B); \
bos_image_ptr_free(slot_ptr.image[image].planes.R); \
bos_image_ptr_free(slot_ptr.image[image].planes.G); \
bos_image_ptr_free(slot_ptr.image[image].planes.E); \
}
// ---------------

/// Entities
/// --------
Expand Down Expand Up @@ -104,10 +128,7 @@ void CBossEntity::put_8(screen_x_t left, vram_y_t top, int image) const
for(bos_word_x = 0; (vram_w / 2) > bos_word_x; bos_word_x++) {
if((vram_offset / ROW_SIZE) == intended_y) {
if(~bos.alpha[bos_p]) {
grcg_setcolor_rmw(0);
grcg_put(vram_offset, ~bos.alpha[bos_p], 16);
grcg_off();

vram_erase(vram_offset, ~bos.alpha[bos_p], 16);
vram_or_emptyopt(B, vram_offset, bos.planes.B[bos_p], 16);
vram_or_emptyopt(R, vram_offset, bos.planes.R[bos_p], 16);
vram_or_emptyopt(G, vram_offset, bos.planes.G[bos_p], 16);
Expand Down Expand Up @@ -344,20 +365,6 @@ void CBossEntity::unput_and_put_8(
}
}

#define vram_unput_masked_emptyopt(plane, offset, bit_count, mask, tmp_dots) \
graph_accesspage_func(1); \
VRAM_SNAP(tmp_dots, plane, offset, bit_count); \
if(tmp_dots) { \
graph_accesspage_func(0); \
VRAM_CHUNK(plane, offset, bit_count) |= (mask & tmp_dots); \
}

#define vram_unput_masked_emptyopt_planar(offset, bit_count, mask, tmp_dots) \
vram_unput_masked_emptyopt(B, offset, bit_count, mask, tmp_dots); \
vram_unput_masked_emptyopt(R, offset, bit_count, mask, tmp_dots); \
vram_unput_masked_emptyopt(G, offset, bit_count, mask, tmp_dots); \
vram_unput_masked_emptyopt(E, offset, bit_count, mask, tmp_dots);

void CBossEntity::unput_8(screen_x_t left, vram_y_t top, int image) const
{
vram_offset_t vram_offset_row = vram_offset_divmul(left, top);
Expand All @@ -380,10 +387,7 @@ void CBossEntity::unput_8(screen_x_t left, vram_y_t top, int image) const
vram_offset_at_intended_y_16(vram_offset, intended_y) &&
(vram_offset >= 0) // Clip at the top edge
) {
grcg_setcolor_rmw(0);
graph_accesspage_func(0);
grcg_put(vram_offset, ~bos.alpha[bos_p], 16);
grcg_off();
vram_erase_on_0(vram_offset, ~bos.alpha[bos_p], 16);

if(~bos.alpha[bos_p]) {
dots16_t bg_dots;
Expand Down Expand Up @@ -655,9 +659,7 @@ void CBossAnim::put_8(void) const
for(bos_word_x = 0; (vram_w / 2) > bos_word_x; bos_word_x++) {
if((vram_offset / ROW_SIZE) == intended_y) {
if(bos.alpha[bos_p]) {
grcg_setcolor_rmw(0);
grcg_put(vram_offset, bos.alpha[bos_p], 16);
grcg_off();
vram_erase(vram_offset, bos.alpha[bos_p], 16);
}
vram_or_emptyopt(B, vram_offset, bos.planes.B[bos_p], 16);
vram_or_emptyopt(R, vram_offset, bos.planes.R[bos_p], 16);
Expand Down
5 changes: 2 additions & 3 deletions th01/main_13_.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
extern "C" {
#include "th01/th01.h"
#include "th01/math/wave.hpp"
#include "th01/hardware/planar.h"

#include "th01/hardware/grp2xscs.cpp"

Expand Down Expand Up @@ -44,9 +45,7 @@ void graph_hline_unput_masked(
px8.G = mask[x] & VRAM_PLANE_G[p];
px8.E = mask[x] & VRAM_PLANE_E[p];
graph_accesspage_func(0);
grcg_setcolor_rmw(0);
VRAM_PLANE_B[p] = mask[x];
grcg_off();
vram_erase(p, mask[x], 8);
VRAM_PLANE_B[p] |= px8.B;
VRAM_PLANE_R[p] |= px8.R;
VRAM_PLANE_G[p] |= px8.G;
Expand Down

0 comments on commit b75556c

Please sign in to comment.