mirror of https://github.com/nmlgc/ReC98.git
169 lines
4.1 KiB
C++
169 lines
4.1 KiB
C++
#pragma option -zPmain_01 -G
|
|
|
|
#include "libs/master.lib/pc98_gfx.hpp"
|
|
#include "th01/rank.h"
|
|
#include "th02/v_colors.hpp"
|
|
#include "th02/core/globals.hpp"
|
|
#include "th02/hardware/pages.hpp"
|
|
#include "th02/formats/tile.hpp"
|
|
#include "th02/main/entity.hpp"
|
|
#include "th02/main/scroll.hpp"
|
|
#include "th02/main/pointnum/pointnum.hpp"
|
|
#include "th02/main/tile/tile.hpp"
|
|
#include "th02/sprites/pointnum.h"
|
|
|
|
#pragma option -a2
|
|
|
|
static const int POINTNUM_COUNT = 20;
|
|
|
|
struct CPointnums {
|
|
vc_t col;
|
|
int8_t unused;
|
|
screen_x_t left[POINTNUM_COUNT];
|
|
screen_y_t top[POINTNUM_COUNT][2];
|
|
uint16_t points[POINTNUM_COUNT];
|
|
entity_flag_t flag[POINTNUM_COUNT];
|
|
uint8_t age[POINTNUM_COUNT];
|
|
pointnum_cel_t op; // `operator` is a keyword.
|
|
pointnum_cel_t operand;
|
|
};
|
|
|
|
extern CPointnums pointnums;
|
|
|
|
// Function ordering fails
|
|
// -----------------------
|
|
|
|
// Blits the given [numeral] to the given position. Assumptions:
|
|
// • ES is already set to the beginning of a VRAM segment
|
|
// • The GRCG is active, and set to the intended color
|
|
void pascal near pointnum_put(screen_x_t left, vram_y_t top, int numeral);
|
|
// -----------------------
|
|
|
|
void near pointnums_init_for_rank_and_reset(void)
|
|
{
|
|
for(int i = 0; i < POINTNUM_COUNT; i++) {
|
|
pointnums.flag[i] = F_FREE;
|
|
}
|
|
pointnums.col = V_WHITE;
|
|
|
|
// Matches the score multiplier at the end of items_update_and_render().
|
|
switch(rank) {
|
|
case RANK_EASY:
|
|
case RANK_NORMAL:
|
|
pointnums.op = POINTNUM_EMPTY;
|
|
pointnums.operand = POINTNUM_EMPTY;
|
|
break;
|
|
|
|
case RANK_HARD:
|
|
pointnums.op = POINTNUM_MUL;
|
|
pointnums.operand = POINTNUM_2;
|
|
break;
|
|
|
|
case RANK_LUNATIC:
|
|
pointnums.op = POINTNUM_MUL;
|
|
pointnums.operand = POINTNUM_4;
|
|
break;
|
|
|
|
case RANK_EXTRA:
|
|
pointnums.op = POINTNUM_MUL;
|
|
pointnums.operand = POINTNUM_8;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void pascal near pointnums_add(
|
|
screen_x_t left_, screen_y_t top_, uint16_t points_
|
|
)
|
|
{
|
|
register screen_x_t left = left_;
|
|
register screen_y_t top = top_;
|
|
register uint16_t points = points_;
|
|
for(register int i = 0; i < POINTNUM_COUNT; i++) {
|
|
if(pointnums.flag[i] == F_FREE) {
|
|
pointnums.flag[i] = F_ALIVE;
|
|
pointnums.age[i] = 0;
|
|
pointnums.points[i] = points;
|
|
pointnums.left[i] = left;
|
|
pointnums.top[i][0] = top;
|
|
pointnums.top[i][1] = top;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void near pointnums_invalidate(void)
|
|
{
|
|
for(int i = 0; i < POINTNUM_COUNT; i++) {
|
|
if(pointnums.flag[i] == F_FREE) {
|
|
continue;
|
|
}
|
|
|
|
tiles_invalidate_rect(
|
|
pointnums.left[i],
|
|
pointnums.top[i][page_back],
|
|
|
|
// Adding the trailing 0, operator, and operand.
|
|
// ZUN bloat: And one unnecessary glyph?
|
|
(POINTNUM_W * (POINTNUM_DIGITS + 3 + 1)),
|
|
|
|
POINTNUM_H
|
|
);
|
|
|
|
if(pointnums.flag[i] == F_REMOVE) {
|
|
pointnums.flag[i] = F_FREE;
|
|
} else {
|
|
pointnums.top[i][page_back] = pointnums.top[i][page_front];
|
|
}
|
|
}
|
|
}
|
|
|
|
void pascal near pointnum_render(screen_x_t left, vram_y_t top, uint16_t points)
|
|
{
|
|
extern uint16_t FOUR_DIGIT_POWERS_OF_10[POINTNUM_DIGITS];
|
|
|
|
int i;
|
|
bool past_leading_zeroes = false;
|
|
for(i = 0; i < POINTNUM_DIGITS; (i++, left += POINTNUM_W)) {
|
|
// ZUN landmine: Since [FOUR_DIGIT_POWERS_OF_10] doesn't cover the
|
|
// full value range of an uint16_t, [numeral] should be limited to the
|
|
// 0-9 range.
|
|
int8_t numeral = (POINTNUM_0 + (points / FOUR_DIGIT_POWERS_OF_10[i]));
|
|
points %= FOUR_DIGIT_POWERS_OF_10[i];
|
|
if((numeral != POINTNUM_0) || past_leading_zeroes) {
|
|
past_leading_zeroes = true;
|
|
pointnum_put(left, top, numeral);
|
|
}
|
|
}
|
|
pointnum_put((left + (POINTNUM_W * 0)), top, POINTNUM_0);
|
|
pointnum_put((left + (POINTNUM_W * 1)), top, pointnums.op);
|
|
pointnum_put((left + (POINTNUM_W * 2)), top, pointnums.operand);
|
|
}
|
|
|
|
void near pointnums_update_and_render(void)
|
|
{
|
|
grcg_setcolor(GC_RMW, pointnums.col);
|
|
_ES = SEG_PLANE_B;
|
|
for(int i = 0; i < POINTNUM_COUNT; i++) {
|
|
if(pointnums.flag[i] != F_ALIVE) {
|
|
continue;
|
|
}
|
|
|
|
// Update
|
|
if(pointnums.age[i] > 6) {
|
|
pointnums.top[i][page_back] -= 1;
|
|
if(pointnums.age[i] > 24) {
|
|
pointnums.flag[i] = F_REMOVE;
|
|
continue;
|
|
}
|
|
}
|
|
pointnums.age[i]++;
|
|
|
|
// Render
|
|
vram_y_t top = scroll_screen_y_to_vram(
|
|
top, pointnums.top[i][page_back]
|
|
);
|
|
pointnum_render(pointnums.left[i], top, pointnums.points[i]);
|
|
}
|
|
grcg_off();
|
|
}
|