[Separate translation units] [th01] ptn_copy_8_0_to_1()
So, we have a problem. The ridiculously optimized graph_putsa_fx() used
in TH04 and TH05 swaps out the target of two CALL instructions at
run-time… because there *really* wasn't any free register left for an
indirect CALL, eh? Therefore, the necessary relative addresses have to
be calculated at assembly time, by subtracting the target function
label from the call site label.
Unfortunately, the resulting values are stored in the .DATA segment,
which we can't move out right now. Declaring the labels as EXTERN
wouldn't work either, since the linker can't do fancy arithmetic and is
limited to simply replacing address placeholders with one single
address. This is explained pretty well at:
http://computer-programming-forum.com/46-asm/48f3d4a463bb38d1.htm
Which means we're stuck, and can't separate out this function for the
foreseeable future.
So, time to approach the SHARED segment from the top instead, to at
least get everything around graph_putsa_fx() done now. 🤷
vram_planes_set() is the first common function there. But since it was
introduced in TH01, we've got some maintenance to do for that game
first…
Part of P0138, funded by [Anonymous] and Blue Bolt.
2021-04-11 12:24:21 +00:00
|
|
|
#include "th01/formats/ptn.hpp"
|
2020-03-17 20:04:24 +00:00
|
|
|
|
2020-08-20 19:59:45 +00:00
|
|
|
void ptn_snap_8(screen_x_t left, vram_y_t top, int ptn_id)
|
2020-03-17 20:04:24 +00:00
|
|
|
{
|
2020-08-21 17:18:28 +00:00
|
|
|
vram_offset_t vram_offset = vram_offset_muldiv(left, top);
|
2020-03-17 20:04:24 +00:00
|
|
|
ptn_t *ptn = ptn_with_id(ptn_id);
|
2020-08-21 18:13:08 +00:00
|
|
|
for(pixel_t y = 0; y < PTN_H; y++) {
|
2022-03-11 23:48:15 +00:00
|
|
|
vram_snap_ptn_planar(ptn, y, vram_offset);
|
2020-03-17 20:04:24 +00:00
|
|
|
vram_offset += ROW_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-07 12:36:07 +00:00
|
|
|
static inline ptn_plane_t::row_dots_t dot_mask(pixel_t x, pixel_t w) {
|
2021-04-17 18:08:30 +00:00
|
|
|
return static_cast<ptn_plane_t::row_dots_t>((1u << w) - 1u) << (w - x);
|
2020-03-17 20:04:24 +00:00
|
|
|
}
|
|
|
|
|
2020-08-20 19:59:45 +00:00
|
|
|
void ptn_snap_quarter_8(
|
|
|
|
screen_x_t left, vram_y_t top, int ptn_id, int quarter
|
|
|
|
)
|
2020-03-17 20:04:24 +00:00
|
|
|
{
|
2020-08-21 18:13:08 +00:00
|
|
|
pixel_t y;
|
2020-08-21 17:18:28 +00:00
|
|
|
vram_offset_t vram_offset = vram_offset_muldiv(left, top);
|
2020-08-21 18:13:08 +00:00
|
|
|
pixel_t q_y;
|
2021-04-17 18:08:30 +00:00
|
|
|
ptn_plane_t::row_dots_t q_mask;
|
2020-03-17 20:04:24 +00:00
|
|
|
long q_x;
|
|
|
|
ptn_t *ptn = ptn_with_id(ptn_id);
|
|
|
|
|
|
|
|
q_y = ptn_quarter_y(quarter);
|
|
|
|
q_mask = (quarter & 1)
|
|
|
|
? dot_mask(PTN_QUARTER_W, PTN_QUARTER_W)
|
|
|
|
: dot_mask( 0, PTN_QUARTER_W);
|
|
|
|
q_x = ptn_quarter_x(quarter);
|
|
|
|
|
|
|
|
for(y = q_y; y < (q_y + PTN_QUARTER_H); y++) {
|
|
|
|
#define snap_quarter_plane(P, offset, w) \
|
|
|
|
ptn->planes.P[y] &= q_mask; \
|
|
|
|
ptn->planes.P[y] |= (VRAM_CHUNK(P, offset, w) << q_x) & ~q_mask;
|
|
|
|
|
|
|
|
#define snap_quarter(offset, w) \
|
|
|
|
snap_quarter_plane(B, offset, w); \
|
|
|
|
snap_quarter_plane(R, offset, w); \
|
|
|
|
snap_quarter_plane(G, offset, w); \
|
|
|
|
snap_quarter_plane(E, offset, w);
|
|
|
|
|
|
|
|
snap_quarter(vram_offset, PTN_W);
|
|
|
|
|
|
|
|
#undef snap_quarter
|
|
|
|
#undef snap_quarter_plane
|
|
|
|
vram_offset += ROW_SIZE;
|
|
|
|
}
|
|
|
|
}
|