2023-03-23 23:55:28 +00:00
|
|
|
#include "platform.h"
|
|
|
|
#include "pc98.h"
|
|
|
|
#include "planar.h"
|
|
|
|
#include "master.hpp"
|
|
|
|
#include "th01/math/overlap.hpp"
|
|
|
|
#include "th02/main/playfld.hpp"
|
|
|
|
#include "th02/main/scroll.hpp"
|
|
|
|
#include "th02/sprites/bombpart.h"
|
|
|
|
|
2020-08-22 23:21:56 +00:00
|
|
|
extern int bomb_frame;
|
2023-03-23 23:55:28 +00:00
|
|
|
extern point_t bomb_circle_center;
|
2020-08-22 23:21:56 +00:00
|
|
|
extern int bomb_circle_frame;
|
|
|
|
|
|
|
|
extern nearfunc_t_near playchar_bomb_func;
|
|
|
|
|
2023-03-23 23:55:28 +00:00
|
|
|
// Function ordering fails
|
|
|
|
// -----------------------
|
|
|
|
|
|
|
|
// These assume the GRCG to be set to RMW mode, with a tile in the intended
|
|
|
|
// color.
|
|
|
|
void pascal near bomb_circle_point_put(screen_x_t left, screen_y_t top);
|
2023-03-24 01:02:27 +00:00
|
|
|
void pascal near bomb_particle_put_8(screen_x_t left, screen_y_t top, int cel);
|
2023-03-23 23:55:28 +00:00
|
|
|
// -----------------------
|
|
|
|
|
2020-08-22 23:21:56 +00:00
|
|
|
void pascal near bomb_reimu_a(void);
|
|
|
|
void pascal near bomb_reimu_c(void);
|
|
|
|
void pascal near bomb_reimu_b(void);
|
2023-03-23 23:55:28 +00:00
|
|
|
|
|
|
|
// ZUN bloat: Needed to circumvent 16-bit promotion in a single comparison.
|
|
|
|
inline int8_t bomb_particle_h(void) {
|
|
|
|
return BOMB_PARTICLE_H;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pascal near bomb_circle_point_put(screen_x_t left, screen_y_t top)
|
|
|
|
{
|
|
|
|
#define vram_top static_cast<vram_y_t>(_DX)
|
|
|
|
#define first_bit_mirrored _DX
|
|
|
|
|
|
|
|
register const bomb_particle_dots_t near* sprite;
|
|
|
|
int8_t y;
|
|
|
|
unsigned int first_bit;
|
|
|
|
|
|
|
|
if(!overlap_xy_ltrb_lt_gt(
|
|
|
|
left, top,
|
|
|
|
(PLAYFIELD_LEFT - BOMB_PARTICLE_W),
|
|
|
|
(PLAYFIELD_TOP - BOMB_PARTICLE_H),
|
|
|
|
PLAYFIELD_RIGHT,
|
|
|
|
PLAYFIELD_BOTTOM
|
|
|
|
)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ES = SEG_PLANE_B;
|
|
|
|
vram_top = scroll_screen_y_to_vram(vram_top, top);
|
|
|
|
_BX = left;
|
|
|
|
vram_offset_shift_fast_asm(di, bx, vram_top);
|
|
|
|
|
|
|
|
// ZUN bloat: Turbo C++ 4.0J would otherwise only ever generate an 8-bit
|
|
|
|
// AND.
|
|
|
|
asm { and bx, BYTE_MASK; }
|
|
|
|
|
|
|
|
first_bit = _BX;
|
|
|
|
first_bit_mirrored = (sizeof(dots16_t) * BYTE_DOTS);
|
|
|
|
|
|
|
|
// ZUN bloat: first_bit_mirrored -= _BX;
|
|
|
|
asm { sub dx, bx; }
|
|
|
|
|
|
|
|
sprite = sBOMB_CIRCLE;
|
|
|
|
y = 0;
|
|
|
|
do {
|
|
|
|
// ZUN bloat: A manual 16-bit right rotation. Turbo C++ 4.0J has
|
|
|
|
// intrinsics for that, which compile into a single ROR instruction:
|
|
|
|
//
|
|
|
|
// *reinterpret_cast<dots16_t __es *>(vo) = __rotr__(
|
|
|
|
// *sprite, first_bit
|
|
|
|
// );
|
|
|
|
asm { xor ax, ax; }
|
|
|
|
_AL = *sprite;
|
|
|
|
asm { mov bx, ax; }
|
|
|
|
_CX = first_bit;
|
|
|
|
_BX >>= _CL;
|
|
|
|
asm { mov cx, dx; }
|
|
|
|
_AX <<= _CL;
|
|
|
|
asm { add ax, bx; }
|
|
|
|
*reinterpret_cast<dots16_t __es *>(_DI) = _AX;
|
|
|
|
|
|
|
|
vram_offset_add_and_roll(_DI, ROW_SIZE);
|
|
|
|
sprite++;
|
|
|
|
y++;
|
|
|
|
} while(y < bomb_particle_h());
|
|
|
|
|
|
|
|
#undef first_bit_mirrored
|
|
|
|
#undef vram_top
|
|
|
|
}
|
2023-03-24 01:02:27 +00:00
|
|
|
|
|
|
|
void pascal near bomb_particle_put_8(screen_x_t left, screen_y_t top, int cel)
|
|
|
|
{
|
|
|
|
#define _DI static_cast<vram_offset_t>(_DI)
|
|
|
|
|
|
|
|
_ES = SEG_PLANE_B;
|
|
|
|
_DX = scroll_screen_y_to_vram(static_cast<vram_y_t>(_DX), top);
|
|
|
|
vram_offset_shift_fast_asm(di, left, _DX);
|
|
|
|
|
|
|
|
// ZUN bloat: _SI = &sBOMB_PARTICLES[cel];
|
|
|
|
_SI = reinterpret_cast<uint16_t>(&sBOMB_PARTICLES[0][0]);
|
|
|
|
_AX = (cel * sizeof(sBOMB_PARTICLES[0]));
|
|
|
|
asm { add si, ax; }
|
|
|
|
|
|
|
|
_CX = BOMB_PARTICLE_H;
|
|
|
|
loop: {
|
|
|
|
asm { movsb; }
|
|
|
|
vram_offset_add_and_roll(
|
|
|
|
_DI, (ROW_SIZE - (BOMB_PARTICLE_W / BYTE_DOTS))
|
|
|
|
);
|
|
|
|
asm { loop loop; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef _DI
|
|
|
|
}
|