PoP roomtest (план v2, шаг 2): общая геометрия в pop_geom

Сведены дубли, разъехавшиеся по модулям:
- x_bump[20] был в pop_kid (uint8_t!) и в pop_map (int16_t) — теперь одна
  таблица int16_t;
- y_land[5] — две копии;
- y_to_row_mod4 — в pop_bg и pop_map;
- 32-битный LCG оригинала (prandom) — в pop_bg и pop_trob; функция теперь
  одна, а СИДЫ остались раздельными (у раскладки кладки и у фаз факелов
  свои последовательности, смешивать нельзя — иначе поедет рисунок стен).

Экономия по коду скромная (_CODE 24462 -> 24421, W3 11643 -> 11632: часть
выигрыша съели межмодульные вызовы).  Главное здесь другое: pop_geom лежит
в W1/W2 и не трогает графику, то есть это тот самый «чистый» слой, который
сможет звать __banked-код стражей (docs/layout_plan_v2.md §4, §5.2).

Проверено в MAME: комната 1 после пересборки отрисована ПОБАЙТОВО так же,
как до правки (0 различающихся пикселей в области комнаты) — значит
последовательности PRNG и геометрия не поехали; Kid бегает.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 21:05:24 +03:00
parent 4cffbc9aa4
commit ecf5ecfc14
7 changed files with 87 additions and 52 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ MEMORY ?= small
# __banked-модулей (стражи): из банка резидентная страница W3 не видна — # __banked-модулей (стражи): из банка резидентная страница W3 не видна —
# ни напрямую, ни транзитивно. См. docs/layout_plan_v2.md §2 (R2), §4. # ни напрямую, ни транзитивно. См. docs/layout_plan_v2.md §2 (R2), §4.
EXTRA_FLAGS ?= --gfx 256 --w3 pop_bg.c EXTRA_FLAGS ?= --gfx 256 --w3 pop_bg.c
EXTRA_SRCS := pop_kid.c pop_ctrl.c pop_level.c pop_map.c pop_trob.c pop_redraw.c EXTRA_SRCS := pop_kid.c pop_ctrl.c pop_level.c pop_map.c pop_trob.c pop_redraw.c pop_geom.c
BG_DIR := $(CURDIR)/../poc/res/bg BG_DIR := $(CURDIR)/../poc/res/bg
KID_DIR := $(CURDIR)/../poc/res/kid KID_DIR := $(CURDIR)/../poc/res/kid
@@ -42,4 +42,4 @@ $(KID_DATA): $(TC)/pop_pack_kid.py $(TC)/pop_pack_bg.py
kid_data.h $(KID_BIN): $(TC)/pop_extract_kid_data.py kid_data.h $(KID_BIN): $(TC)/pop_extract_kid_data.py
cd $(TC) && python3 pop_extract_kid_data.py cd $(TC) && python3 pop_extract_kid_data.py
$(EXAMPLE).exe: pop_bg.c pop_bg.h pop_redraw.c pop_redraw.h pop_kid.c pop_kid.h pop_ctrl.c pop_ctrl.h pop_map.c pop_map.h pop_level.c pop_level.h pop_trob.c pop_trob.h kid_data.h $(BG_DATA) $(KID_DATA) $(KID_BIN) $(LVL_DATA) $(EXAMPLE).exe: pop_bg.c pop_bg.h pop_geom.c pop_geom.h pop_redraw.c pop_redraw.h pop_kid.c pop_kid.h pop_ctrl.c pop_ctrl.h pop_map.c pop_map.h pop_level.c pop_level.h pop_trob.c pop_trob.h kid_data.h $(BG_DATA) $(KID_DATA) $(KID_BIN) $(LVL_DATA)
+3 -9
View File
@@ -14,6 +14,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include "pop_bg.h" #include "pop_bg.h"
#include "pop_geom.h"
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */ #include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев (см. ниже) */ #include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев (см. ниже) */
@@ -311,11 +312,7 @@ static uint8_t wall_modifier(int row, int col)
/* ---- PRNG (seg009.c:321, 32-бит LCG) — только на ВХОД в комнату ---- */ /* ---- PRNG (seg009.c:321, 32-бит LCG) — только на ВХОД в комнату ---- */
static unsigned long rnd_seed; static unsigned long rnd_seed;
static uint16_t prandom(uint16_t maxv) #define prandom(maxv) pop_prandom(&rnd_seed, (maxv))
{
rnd_seed = rnd_seed * 214013UL + 2531011UL;
return (uint16_t)((uint16_t)(rnd_seed >> 16) % (uint16_t)(maxv + 1));
}
/* ---- Декали-марки стен (seg008.c:2041/2056) ------------------------ */ /* ---- Декали-марки стен (seg008.c:2041/2056) ------------------------ */
static void draw_left_mark(uint16_t dv, int arg2, int arg1, int row, int col) static void draw_left_mark(uint16_t dv, int arg2, int arg1, int row, int col)
@@ -1125,10 +1122,7 @@ static int8_t col_from_x(int xpos) /* get_tile_div_mod: колонка (
return (int8_t)xh; return (int8_t)xh;
} }
static int8_t y_to_row(int y) /* y_to_row_mod4 (seg006, TILE_SIZEY=63) */ #define y_to_row(y) pop_y_to_row((int16_t)(y)) /* общий (pop_geom) */
{
return (int8_t)((y + 60) / 63 % 4 - 1);
}
static void fore_only_tile(int row, int col) static void fore_only_tile(int row, int col)
{ {
+23
View File
@@ -0,0 +1,23 @@
/*
* pop_geom.c — общая геометрия + PRNG оригинала. См. pop_geom.h.
*/
#include "pop_geom.h"
/* data.h: шаг 14 (ширина тайла в координатах персонажа), [5] = col 0. */
const int16_t pop_x_bump[20] = {
-12, 2, 16, 30, 44, 58, 72, 86, 100, 114,
128, 142, 156, 170, 184, 198, 212, 226, 240, 254
};
const int16_t pop_y_land[5] = {-8, 55, 118, 181, 244};
int8_t pop_y_to_row(int16_t y)
{
return (int8_t)((y + 60) / TILE_SIZEY % 4 - 1);
}
uint16_t pop_prandom(unsigned long *seed, uint16_t maxv)
{
unsigned long s = *seed * 214013UL + 2531011UL;
*seed = s;
return (uint16_t)((uint16_t)(s >> 16) % (uint16_t)(maxv + 1));
}
+34
View File
@@ -0,0 +1,34 @@
/*
* pop_geom.h — общая геометрия PoP и PRNG оригинала.
*
* Сюда сведено то, что раньше дублировалось по модулям (x_bump/y_land в
* pop_kid и pop_map, y_to_row в pop_bg и pop_map, 32-битный LCG в pop_bg и
* pop_trob). Кроме экономии это ФУНДАМЕНТ bank-safe API: модуль живёт в
* W1/W2 и не трогает графику, поэтому его может звать и главный цикл, и
* резидент W3, и будущий __banked-код стражей (docs/layout_plan_v2.md §4).
*/
#ifndef POP_GEOM_H
#define POP_GEOM_H
#include <stdint.h>
#define FIRST_ONSCREEN_COLUMN 5 /* индекс col 0 комнаты в x_bump */
#define TILE_SIZEX 14 /* ширина тайла в координатах персонажа */
#define TILE_SIZEY 63 /* высота ряда */
/* x_bump (data.h): левая граница колонки в координатах персонажа; колонка
* комнаты col = x_bump[col + FIRST_ONSCREEN_COLUMN]. y_land: пол ряда
* (индекс row+1; [0] — ряд «над комнатой»). */
extern const int16_t pop_x_bump[20];
extern const int16_t pop_y_land[5];
/* y_to_row_mod4 (seg006): ряд по координате y с оборотом mod 4 (−1 = полоса
* над комнатой, 3 = под комнатой). */
int8_t pop_y_to_row(int16_t y);
/* prandom (seg009:321) — 32-битный LCG оригинала. Сид ВНЕШНИЙ: у стен
* (раскладка кладки) и у анимаций тайлов (фаза факелов) свои
* последовательности, смешивать их нельзя. */
uint16_t pop_prandom(unsigned long *seed, uint16_t maxv);
#endif
+3 -10
View File
@@ -12,6 +12,7 @@
#include "pop_kid.h" #include "pop_kid.h"
#include "pop_bg.h" /* POP_YOFF — вертикальное центрирование */ #include "pop_bg.h" /* POP_YOFF — вертикальное центрирование */
#include "pop_map.h" /* pop_clip_char_top (clip_char) */ #include "pop_map.h" /* pop_clip_char_top (clip_char) */
#include "pop_geom.h"
#include "kid_data.h" #include "kid_data.h"
kid_t Kid; kid_t Kid;
@@ -20,14 +21,6 @@ kid_t Kid;
* в play_seq, потребляется pop_check_knock (pop_map) — трясёт loose-полы. */ * в play_seq, потребляется pop_check_knock (pop_map) — трясёт loose-полы. */
int8_t knock; int8_t knock;
/* Координатные таблицы (data.h). */
static const uint8_t x_bump[20] = {
(uint8_t)-12, 2, 16, 30, 44, 58, 72, 86, 100, 114,
128, 142, 156, 170, 184, 198, 212, 226, 240, 254
};
static const int16_t y_land[5] = {-8, 55, 118, 181, 244};
#define FIRST_ONSCREEN_COLUMN 5
#define TILE_SIZEX 14
/* ---- Атласы Kid (прямая адресация image>>3) ------------------------ */ /* ---- Атласы Kid (прямая адресация image>>3) ------------------------ */
#define KID_MAXPAGES 28 #define KID_MAXPAGES 28
@@ -258,8 +251,8 @@ void kid_init(uint8_t seq_id, int8_t col, int8_t row, int8_t dir)
Kid.curr_col = col; Kid.curr_col = col;
Kid.curr_row = row; Kid.curr_row = row;
Kid.direction = dir; Kid.direction = dir;
Kid.x = (uint8_t)(x_bump[col + FIRST_ONSCREEN_COLUMN] + TILE_SIZEX); Kid.x = (uint8_t)(pop_x_bump[col + FIRST_ONSCREEN_COLUMN] + TILE_SIZEX);
Kid.y = (uint8_t)y_land[row + 1]; Kid.y = (uint8_t)pop_y_land[row + 1];
Kid.fall_x = Kid.fall_y = 0; Kid.fall_x = Kid.fall_y = 0;
Kid.repeat = 0; Kid.repeat = 0;
Kid.curr_seq = kid_seq_off[seq_id]; Kid.curr_seq = kid_seq_off[seq_id];
+20 -26
View File
@@ -5,7 +5,7 @@
* FRAME_NEEDS_FLOOR (0x40), под персонажем не floor -> start_fall(); * FRAME_NEEDS_FLOOR (0x40), под персонажем не floor -> start_fall();
* стена -> in_wall(); * стена -> in_wall();
* freefall (action 4) -> do_fall(): fall_y-ускорение (в fall_accel/speed), * freefall (action 4) -> do_fall(): fall_y-ускорение (в fall_accel/speed),
* достиг y_land[curr_row+1] -> land()/inc_curr_row. * достиг pop_y_land[curr_row+1] -> land()/inc_curr_row.
* *
* Координатная система PoP: экран.left = 58, тайл = 14 ед. (TILE_SIZEX); * Координатная система PoP: экран.left = 58, тайл = 14 ед. (TILE_SIZEX);
* col = (xpos-58)/14 (округл. вниз), xl = остаток; get_tile_div_mod_m7 = * col = (xpos-58)/14 (округл. вниз), xl = остаток; get_tile_div_mod_m7 =
@@ -19,6 +19,7 @@
#include "pop_kid.h" #include "pop_kid.h"
#include "pop_map.h" #include "pop_map.h"
#include "pop_ctrl.h" /* pop_ctrl_shift_held() — для check_grab */ #include "pop_ctrl.h" /* pop_ctrl_shift_held() — для check_grab */
#include "pop_geom.h" /* общая геометрия (x_bump/y_land/y_to_row) */
#include "pop_redraw.h" /* пометки перерисовки (порт set_redraw_*) */ #include "pop_redraw.h" /* пометки перерисовки (порт set_redraw_*) */
/* pop_bg нужен ТОЛЬКО падающему куску (mob): spawn/tick/pos — это движущийся /* pop_bg нужен ТОЛЬКО падающему куску (mob): spawn/tick/pos — это движущийся
* ОБЪЕКТ, а не перерисовка тайла (в оригинале он и живёт отдельно: mobs + * ОБЪЕКТ, а не перерисовка тайла (в оригинале он и живёт отдельно: mobs +
@@ -88,23 +89,17 @@
#define FRAME_NEEDS_FLOOR 0x40 #define FRAME_NEEDS_FLOOR 0x40
#define FRAME_WEIGHT_X 0x1F #define FRAME_WEIGHT_X 0x1F
#define TILE_SIZEX 14
#define TILE_RIGHTX 13 #define TILE_RIGHTX 13
#define SCREENSPACE_X 58 #define SCREENSPACE_X 58
#define FALL_ACCEL 3 #define FALL_ACCEL 3
#define FALL_MAX 33 #define FALL_MAX 33
#define TILE_MIDX 7 #define TILE_MIDX 7
#define FIRST_ONSCREEN_COLUMN 5
#define FRAME_THIN 0x20 #define FRAME_THIN 0x20
static const int16_t y_land[5] = {-8, 55, 118, 181, 244};
static const int8_t dir_front[2] = {-1, 1}; /* [dir+1]: dir=-1->-1, 0->+1 */ static const int8_t dir_front[2] = {-1, 1}; /* [dir+1]: dir=-1->-1, 0->+1 */
static const int8_t dir_behind[2] = {1, -1}; /* [dir+1]: назад по направлению */ static const int8_t dir_behind[2] = {1, -1}; /* [dir+1]: назад по направлению */
static const int16_t x_bump[20] = {
-12, 2, 16, 30, 44, 58, 72, 86, 100, 114,
128, 142, 156, 170, 184, 198, 212, 226, 240, 254
};
/* wall_type(tile): gate/doortop=1, mirror=2, chomper=3, wall=4, иначе 0. */ /* wall_type(tile): gate/doortop=1, mirror=2, chomper=3, wall=4, иначе 0. */
static const int8_t wall_dl[6] = {0, 10, 0, -1, 0, 0}; /* wall_dist_from_left */ static const int8_t wall_dl[6] = {0, 10, 0, -1, 0, 0}; /* wall_dist_from_left */
static const int8_t wall_dr[6] = {0, 0, 10, 13, 0, 0}; /* wall_dist_from_right */ static const int8_t wall_dr[6] = {0, 0, 10, 13, 0, 0}; /* wall_dist_from_right */
@@ -372,7 +367,7 @@ static int dist_from_wall_forward(uint8_t tiletype, int8_t tcol)
uint8_t type = wall_type(tiletype); uint8_t type = wall_type(tiletype);
int coll_left, cx; int coll_left, cx;
if (type == 0) return 127; if (type == 0) return 127;
coll_left = x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX; coll_left = pop_x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX;
cx = char_front_coll(); cx = char_front_coll();
if (Kid.direction < 0) /* лицом влево */ if (Kid.direction < 0) /* лицом влево */
return cx - (coll_left + TILE_RIGHTX - wall_dr[type]); return cx - (coll_left + TILE_RIGHTX - wall_dr[type]);
@@ -428,7 +423,7 @@ static uint8_t fell_on_spikes(void)
static void land(void) static void land(void)
{ {
uint8_t seq; uint8_t seq;
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
if (fell_on_spikes()) return; /* упал на вредные пики — смерть */ if (fell_on_spikes()) return; /* упал на вредные пики — смерть */
/* к краю пола — чуть назад (как оригинал) */ /* к краю пола — чуть назад (как оригинал) */
if (!tile_is_floor(get_tile_infrontof_char()) && distance_to_edge_weight() < 3) if (!tile_is_floor(get_tile_infrontof_char()) && distance_to_edge_weight() < 3)
@@ -523,7 +518,7 @@ static void check_grab(void)
uint8_t old_x; uint8_t old_x;
if (!pop_ctrl_shift_held()) return; /* Shift не зажат */ if (!pop_ctrl_shift_held()) return; /* Shift не зажат */
if ((uint8_t)Kid.fall_y >= 32) return; /* падает слишком быстро */ if ((uint8_t)Kid.fall_y >= 32) return; /* падает слишком быстро */
if ((uint16_t)y_land[Kid.curr_row + 1] > (uint16_t)(Kid.y + 25)) return; if ((uint16_t)pop_y_land[Kid.curr_row + 1] > (uint16_t)(Kid.y + 25)) return;
old_x = Kid.x; old_x = Kid.x;
Kid.x = (uint8_t)char_dx_forward(-8); Kid.x = (uint8_t)char_dx_forward(-8);
determine_col(); determine_col();
@@ -532,7 +527,7 @@ static void check_grab(void)
determine_col(); determine_col();
} else { } else {
Kid.x = (uint8_t)char_dx_forward((int8_t)distance_to_edge_weight()); Kid.x = (uint8_t)char_dx_forward((int8_t)distance_to_edge_weight());
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
Kid.fall_y = 0; Kid.fall_y = 0;
kid_set_seq(SEQ_15_GRAB_LEDGE_MIDAIR); kid_set_seq(SEQ_15_GRAB_LEDGE_MIDAIR);
play_seq(); play_seq();
@@ -544,8 +539,8 @@ static void check_grab(void)
static void do_fall(void) static void do_fall(void)
{ {
uint8_t nrow = (uint8_t)(Kid.curr_row + 1); uint8_t nrow = (uint8_t)(Kid.curr_row + 1);
if (nrow > 4) nrow = 4; /* защита y_land[] от выхода */ if (nrow > 4) nrow = 4; /* защита pop_y_land[] от выхода */
if ((uint16_t)y_land[nrow] > (uint16_t)Kid.y) { if ((uint16_t)pop_y_land[nrow] > (uint16_t)Kid.y) {
check_grab(); /* ещё летит — попытка зацепа */ check_grab(); /* ещё летит — попытка зацепа */
} else { } else {
if (get_tile_at_char() == TILE_WALL) if (get_tile_at_char() == TILE_WALL)
@@ -905,11 +900,11 @@ static void bumped_floor(void)
uint8_t frame; uint8_t frame;
/* Оригинал сравнивает БЕЗЗНАКОВО: если персонаж НИЖЕ уровня пола, /* Оригинал сравнивает БЕЗЗНАКОВО: если персонаж НИЖЕ уровня пола,
* разность заворачивается в большое число и тоже даёт «падать». */ * разность заворачивается в большое число и тоже даёт «падать». */
if ((uint16_t)(y_land[Kid.curr_row + 1] - (int16_t)Kid.y) >= 15) { if ((uint16_t)(pop_y_land[Kid.curr_row + 1] - (int16_t)Kid.y) >= 15) {
bumped_fall(); /* высоко над полом — в воздухе */ bumped_fall(); /* высоко над полом — в воздухе */
return; return;
} }
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; /* ПРИЖАТЬ к полу */ Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1]; /* ПРИЖАТЬ к полу */
if (Kid.fall_y >= 22) { /* влетел быстро — только отжать */ if (Kid.fall_y >= 22) { /* влетел быстро — только отжать */
Kid.x = (uint8_t)char_dx_forward(-5); Kid.x = (uint8_t)char_dx_forward(-5);
return; return;
@@ -947,7 +942,7 @@ static void check_bumped(void)
* hang->hang_fall->seq_11 (правильное приземление). */ * hang->hang_fall->seq_11 (правильное приземление). */
if (Kid.frame >= 87 && Kid.frame < 100) return; if (Kid.frame >= 87 && Kid.frame < 100) return;
/* Вне рядов комнаты (падение мимо пола): get_tile даёт WALL, а /* Вне рядов комнаты (падение мимо пола): get_tile даёт WALL, а
* dist_from_wall_forward/x_bump[] — мусор с большим отриц. сдвигом → * dist_from_wall_forward/pop_x_bump[] — мусор с большим отриц. сдвигом →
* underflow X и уход в стену. fell_out ловит do_fall. */ * underflow X и уход в стену. fell_out ловит do_fall. */
if (Kid.curr_row < 0 || Kid.curr_row > 2) return; if (Kid.curr_row < 0 || Kid.curr_row > 2) return;
/* seg004 check_collisions: на кадрах разворота коллизии НЕ считаются /* seg004 check_collisions: на кадрах разворота коллизии НЕ считаются
@@ -978,7 +973,7 @@ static void check_bumped(void)
{ {
uint8_t f = 0, prev, need; uint8_t f = 0, prev, need;
if (wt) { if (wt) {
int coll_left = x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX; int coll_left = pop_x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX;
int lw = wall_dl[wt] + coll_left; /* get_left_wall_xpos */ int lw = wall_dl[wt] + coll_left; /* get_left_wall_xpos */
int rw = coll_left - wall_dr[wt] + TILE_RIGHTX; /* get_right_wall_xpos */ int rw = coll_left - wall_dr[wt] + TILE_RIGHTX; /* get_right_wall_xpos */
int e = char_x_forward_edge(), wh = ((int)kid_fp_width() + 1) >> 1; int e = char_x_forward_edge(), wh = ((int)kid_fp_width() + 1) >> 1;
@@ -1157,7 +1152,7 @@ static void fell_on_your_head(void)
uint8_t frame = Kid.frame, action = Kid.action; uint8_t frame = Kid.frame, action = Kid.action;
if ((frame < 5 || frame >= 15) && if ((frame < 5 || frame >= 15) &&
(action < ACT_HANGCLIMB || action == ACT_TURN)) { (action < ACT_HANGCLIMB || action == ACT_TURN)) {
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
pop_kid_hurt = 1; /* hitp_delta<0 → draw_hurt_splash */ pop_kid_hurt = 1; /* hitp_delta<0 → draw_hurt_splash */
if (take_hp(1)) { if (take_hp(1)) {
kid_set_seq(SEQ_22_CRUSHED); kid_set_seq(SEQ_22_CRUSHED);
@@ -1269,8 +1264,7 @@ void pop_loose_tick(void)
} }
} }
/* y_to_row_mod4 (seg006): ряд по y с оборотом mod4 (TILE_SIZEY=63). */
static int8_t y_to_row(int16_t y) { return (int8_t)(((y + 60) / 63) % 4 - 1); }
/* ---- clip_char (seg006:1749), первый блок: обрезка спрайта СВЕРХУ ----- * /* ---- clip_char (seg006:1749), первый блок: обрезка спрайта СВЕРХУ ----- *
* Оригинал перед add_objtable кладёт в objtable прямоугольник клипа; блиттер * Оригинал перед add_objtable кладёт в objtable прямоугольник клипа; блиттер
@@ -1299,7 +1293,7 @@ int pop_clip_char_top(int obj_x, int obj_y, uint16_t w, uint16_t h)
xr = xl + wh; /* char_x_right */ xr = xl + wh; /* char_x_right */
top_y = obj_y - (int)h + 1; /* char_top_y */ top_y = obj_y - (int)h + 1; /* char_top_y */
if (top_y >= 192) top_y = 0; /* весь спрайт ниже комнаты */ if (top_y >= 192) top_y = 0; /* весь спрайт ниже комнаты */
trow = y_to_row((int16_t)top_y); /* char_top_row */ trow = pop_y_to_row((int16_t)top_y); /* char_top_row */
cL = get_tile_div_mod(xl); if (cL < 0) cL = 0; cL = get_tile_div_mod(xl); if (cL < 0) cL = 0;
cR = get_tile_div_mod(xr); if (cR > 9) cR = 9; cR = get_tile_div_mod(xr); if (cR > 9) cR = 9;
@@ -1337,13 +1331,13 @@ static void check_leave_below(void)
Kid.action != ACT_MIDAIR && Kid.action != ACT_MIDAIR &&
(int8_t)Kid.y < 10 && (int8_t)Kid.y > -16) { (int8_t)Kid.y < 10 && (int8_t)Kid.y > -16) {
Kid.y = (uint8_t)(Kid.y + 189); Kid.y = (uint8_t)(Kid.y + 189);
Kid.curr_row = y_to_row((int16_t)Kid.y); Kid.curr_row = pop_y_to_row((int16_t)Kid.y);
pop_leave_dir = 3; pop_leave_dir = 3;
return; return;
} }
if (Kid.y >= 211) { if (Kid.y >= 211) {
Kid.y = (uint8_t)(Kid.y - 189); Kid.y = (uint8_t)(Kid.y - 189);
Kid.curr_row = y_to_row((int16_t)Kid.y); Kid.curr_row = pop_y_to_row((int16_t)Kid.y);
pop_fell_out = 1; pop_fell_out = 1;
} }
} }
@@ -1429,8 +1423,8 @@ static int is_spike_harmful(uint8_t tilepos)
static void spiked(uint8_t tilepos) static void spiked(uint8_t tilepos)
{ {
pop_trob_modif(g_room)[tilepos] = 0xFF; pop_trob_modif(g_room)[tilepos] = 0xFF;
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
Kid.x = (uint8_t)(x_bump[Kid.curr_col + FIRST_ONSCREEN_COLUMN] + 10); Kid.x = (uint8_t)(pop_x_bump[Kid.curr_col + FIRST_ONSCREEN_COLUMN] + 10);
Kid.x = (uint8_t)char_dx_forward(8); Kid.x = (uint8_t)char_dx_forward(8);
Kid.fall_y = 0; Kid.fall_y = 0;
take_hp(100); /* (TODO: sound_48_spiked) */ take_hp(100); /* (TODO: sound_48_spiked) */
+2 -5
View File
@@ -5,6 +5,7 @@
*/ */
#include "pop_trob.h" #include "pop_trob.h"
#include "pop_level.h" #include "pop_level.h"
#include "pop_geom.h"
#include "pop_redraw.h" /* пометки перерисовки тайлов (вместо прямых вызовов) */ #include "pop_redraw.h" /* пометки перерисовки тайлов (вместо прямых вызовов) */
/* pop_bg нужен ТОЛЬКО для пламени факела и пузырька зелья: это не тайловая /* pop_bg нужен ТОЛЬКО для пламени факела и пузырька зелья: это не тайловая
* перерисовка, а покадровый оверлей поверх фона (в оригинале — свои * перерисовка, а покадровый оверлей поверх фона (в оригинале — свои
@@ -48,11 +49,7 @@ static uint8_t trob_drawn[POP_ROOMTILES];
* выбора следующего кадра пламени. */ * выбора следующего кадра пламени. */
static unsigned long trob_seed; static unsigned long trob_seed;
static uint16_t trob_prandom(uint16_t maxv) #define trob_prandom(maxv) pop_prandom(&trob_seed, (maxv))
{
trob_seed = trob_seed * 214013UL + 2531011UL;
return (uint16_t)((uint16_t)(trob_seed >> 16) % (uint16_t)(maxv + 1));
}
void pop_trob_reset(void) void pop_trob_reset(void)