SprPoP: HDD-раскладка и пути от каталога EXE
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* _pop_file.h — внутренний файловый слой SprPoP для старых версий DSS.
|
||||
*
|
||||
* DSS до исправления относительных путей оставляет рабочий каталог внутри
|
||||
* последнего подкаталога. POP_PATH_CALL восстанавливает абсолютный каталог
|
||||
* приложения до и после операции. Это макрос намеренно: код исполняется в
|
||||
* банке вызывающего, где доступен переданный указатель, и не расходует W1.
|
||||
*/
|
||||
#ifndef _POP_FILE_H
|
||||
#define _POP_FILE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* BANK10: получить каталог EXE через APPINFO B=1 и сделать его текущим. */
|
||||
int8_t pop_path_init(void) __banked;
|
||||
int8_t pop_chdir_home(void) __banked;
|
||||
|
||||
/* expression вычисляется только после успешного chdir. errno файловой
|
||||
* операции сохраняется через завершающее восстановление каталога. */
|
||||
#define POP_PATH_CALL(result, expression) do { \
|
||||
if (pop_chdir_home() != 0) { \
|
||||
(result) = -1; \
|
||||
} else { \
|
||||
int _pop_path_errno; \
|
||||
(result) = (expression); \
|
||||
_pop_path_errno = errno; \
|
||||
(void)pop_chdir_home(); \
|
||||
errno = _pop_path_errno; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <string.h>
|
||||
#include <sprinter_mem.h>
|
||||
#include "pop_arc.h"
|
||||
#include "_pop_file.h"
|
||||
|
||||
/* Пути 8.3, как требует DSS. Держим их ЗДЕСЬ: строка обязана лежать в том
|
||||
* же банке, что и код, который её читает (см. pop_arc.h). */
|
||||
@@ -42,7 +43,7 @@ int8_t pop_arc_open(pop_arc_t *a, const char *path,
|
||||
|
||||
a->fd = -1;
|
||||
a->count = 0;
|
||||
fd = open(path, O_RDONLY);
|
||||
POP_PATH_CALL(fd, open(path, O_RDONLY));
|
||||
if (fd < 0) return -1;
|
||||
if (read(fd, head, sizeof(head)) != (int)sizeof(head) ||
|
||||
memcmp(head, "PBA1", 4) != 0 ||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "pop_cheat.h"
|
||||
#include "pop_sfx.h"
|
||||
#include "_pop_config.h"
|
||||
#include "_pop_file.h"
|
||||
|
||||
#define CFG_BASE 0x100
|
||||
|
||||
@@ -151,7 +152,7 @@ static uint8_t cfg_read_file(uint8_t *buf, uint16_t *size)
|
||||
int fd, got;
|
||||
long n;
|
||||
|
||||
fd = open("POP.CFG", O_RDONLY);
|
||||
POP_PATH_CALL(fd, open("POP.CFG", O_RDONLY));
|
||||
if (fd < 0) return 0;
|
||||
n = lseek(fd, 0, SEEK_END);
|
||||
if (n < POP_CFG_MIN_SIZE || n > POP_CFG_MAX_SIZE ||
|
||||
@@ -172,7 +173,7 @@ int8_t pop_cfg_load(void) __banked
|
||||
|
||||
if (!cfg_read_file(buf, &size) || !pop_cfg_decode(buf, size)) return 0;
|
||||
if (buf[9] != POP_PROFILE_VANILLA)
|
||||
printf("POP.CFG: ENHANCED profile -> VANILLA\n");
|
||||
puts("POP.CFG: ENHANCED profile -> VANILLA\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -192,7 +193,7 @@ int8_t pop_cfg_save(void) __banked
|
||||
gfx_w0_unmap();
|
||||
/* Не unlink: bank_save_file сам делает O_TRUNC и не создаёт лишнего
|
||||
* окна, когда POP.CFG вообще отсутствует после ошибки unlink. */
|
||||
rc = bank_save_file(page, CFG_BASE, "POP.CFG", sizeof(buf));
|
||||
POP_PATH_CALL(rc, bank_save_file(page, CFG_BASE, "POP.CFG", sizeof(buf)));
|
||||
mem_free_block(blk);
|
||||
return (rc == sizeof(buf)) ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "pop_title.h" /* титульная картинка после ввода имени */
|
||||
#include "pop_music.h" /* подкачка потоковой темы победы */
|
||||
#include "pop_hof.h"
|
||||
#include "_pop_file.h"
|
||||
|
||||
/* MAX_HOF_COUNT оригинала — шесть строк. */
|
||||
#define HOF_COUNT 6
|
||||
@@ -162,7 +163,7 @@ static void hof_load(void)
|
||||
if (!blk) return;
|
||||
page = mem_get_page(blk, 0);
|
||||
gfx_w0_page_prepare(page);
|
||||
got = bank_load_file(page, HOF_BASE, "POP.HOF", HOF_SIZE);
|
||||
POP_PATH_CALL(got, bank_load_file(page, HOF_BASE, "POP.HOF", HOF_SIZE));
|
||||
if (got == HOF_SIZE) {
|
||||
gfx_w0_map(page);
|
||||
for (i = 0; i < HOF_SIZE; i++)
|
||||
@@ -187,7 +188,11 @@ static void hof_save(void)
|
||||
gfx_w0_unmap();
|
||||
/* Неудача записи не меняет только что показанную таблицу: следующее
|
||||
* открытие разумно начнёт с прежнего файла или с пустого списка. */
|
||||
bank_save_file(page, HOF_BASE, "POP.HOF", HOF_SIZE);
|
||||
{
|
||||
int saved;
|
||||
POP_PATH_CALL(saved,
|
||||
bank_save_file(page, HOF_BASE, "POP.HOF", HOF_SIZE));
|
||||
}
|
||||
mem_free_block(blk);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "pop_guard.h" /* pop_guard_vflip_load — зеркала соперника */
|
||||
#include "pop_arc.h"
|
||||
#include "kid_arc.h"
|
||||
#include "_pop_file.h"
|
||||
|
||||
/* Серии в архиве обязаны лежать подряд — так их кладёт список в Makefile,
|
||||
* и только поэтому индекс считается сложением. Если порядок собьётся,
|
||||
@@ -75,7 +76,8 @@ int pop_kid_data_load(const char *path) __banked
|
||||
blk=mem_alloc_pages(1);
|
||||
if (!blk) return -1;
|
||||
page=mem_get_page(blk,0);
|
||||
n=bank_load_file(page,KD_DATA_OFF,path,16384-KD_DATA_OFF);
|
||||
POP_PATH_CALL(n, bank_load_file(page,KD_DATA_OFF,path,
|
||||
16384-KD_DATA_OFF));
|
||||
if (n < (int)(KID_BIN_SEQTBL_OFF + KID_SEQTBL_LEN)) {
|
||||
mem_free_block(blk); return -1;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ extern uint8_t pop_current_level;
|
||||
void pop_level_qsave(pop_qs_io_t *io);
|
||||
|
||||
/* Загрузить уровень НОМЕРОМ: освободить страницу прошлого, взять
|
||||
* `LEVELS\res20NN.bin` (fallback `a:\res20NN.bin`) и выставить
|
||||
* `LEVELS\res20NN.bin` относительно каталога EXE и выставить
|
||||
* pop_current_level. 0 — OK, -1 — файла нет / не влез (тогда
|
||||
* pop_current_level и страница НЕ тронуты — играем дальше на старом).
|
||||
* Порт связки load_lev_spr + load_level (seg000:1098/1169). */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "pop_level.h"
|
||||
#include "_pop_level.h"
|
||||
#include "pop_geom.h" /* pop_x_bump / FIRST_ONSCREEN_COLUMN — pos_guards */
|
||||
#include "_pop_file.h"
|
||||
|
||||
/* Низкоуровневое чтение через W3 выполняет резидентный bank_load_file();
|
||||
* остальная одноразовая подготовка уровня безопасно остаётся в банке 8. */
|
||||
@@ -58,7 +59,8 @@ static int level_read_file(const char *path)
|
||||
blk=mem_alloc_pages(1);
|
||||
if (!blk) return -1;
|
||||
page=mem_get_page(blk,0);
|
||||
n=bank_load_file(page,LVL_DATA_OFF,path,16384-LVL_DATA_OFF);
|
||||
POP_PATH_CALL(n, bank_load_file(page,LVL_DATA_OFF,path,
|
||||
16384-LVL_DATA_OFF));
|
||||
if (n < (int)MIN_SIZE) { mem_free_block(blk); return -1; }
|
||||
gfx_w0_page_prepare(page);
|
||||
gfx_w0_map(page);
|
||||
@@ -80,18 +82,17 @@ int pop_level_load_num(uint8_t n) __banked
|
||||
/* Имена патчим на месте, а не через sprintf: printf-семейство тянет в
|
||||
* резидент W1 форматтер, которого здесь больше негде применить. */
|
||||
static char pri[] = "LEVELS\\res2000.bin"; /* цифры — [12],[13] */
|
||||
static char alt[] = "a:\\res2000.bin"; /* цифры — [8],[9] */
|
||||
uint8_t saved_blk = pop_lvl_blk, saved_page = pop_lvl_page, saved_ok = pop_lvl_ok;
|
||||
|
||||
if (n > POP_LEVEL_LAST) return -1;
|
||||
pri[12] = alt[8] = (char)('0' + n / 10);
|
||||
pri[13] = alt[9] = (char)('0' + n % 10);
|
||||
pri[12] = (char)('0' + n / 10);
|
||||
pri[13] = (char)('0' + n % 10);
|
||||
|
||||
/* Старую страницу отпускаем ТОЛЬКО после успешной загрузки новой:
|
||||
* level_read_file сам аллоцирует страницу, и если файла нет — остаёмся
|
||||
* на текущем уровне вместо падения в пустой уровень. */
|
||||
pop_lvl_ok = 0; /* чтобы level_load_path не мешался */
|
||||
if (level_read_file(pri) != 0 && level_read_file(alt) != 0) {
|
||||
if (level_read_file(pri) != 0) {
|
||||
pop_lvl_blk = saved_blk; pop_lvl_page = saved_page; pop_lvl_ok = saved_ok;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "pop_music_tbl.h"
|
||||
#include "pop_sfx.h"
|
||||
#include "pop_app.h" /* POP_APP_DEMO — в демке музыки нет */
|
||||
#include "_pop_file.h"
|
||||
|
||||
uint8_t pop_mus_page[POP_MUS_PAGES];
|
||||
|
||||
@@ -141,7 +142,7 @@ int8_t pop_music_load_begin(uint8_t id) __banked
|
||||
/* Трек лежит ОДНИМ файлом, и fd остаётся открытым до последней
|
||||
* страницы: `open` стоит дороже самого чтения (51,4 мс против 32,6 мс
|
||||
* на 16 КБ), и платить его на каждую страницу — чистые потери. */
|
||||
ld_fd = open(name, O_RDONLY);
|
||||
POP_PATH_CALL(ld_fd, open(name, O_RDONLY));
|
||||
if (ld_fd < 0) return -1;
|
||||
slot_blk[n] = mem_alloc_pages(pages);
|
||||
if (!slot_blk[n]) { close(ld_fd); return -1; }
|
||||
@@ -288,7 +289,7 @@ int8_t pop_music_ring_start(uint8_t id) __banked
|
||||
pop_music_free(); /* обычные слоты кольцу не нужны */
|
||||
pop_music_ring_stop();
|
||||
mus_name(name, id);
|
||||
ring_fd = open(name, O_RDONLY);
|
||||
POP_PATH_CALL(ring_fd, open(name, O_RDONLY));
|
||||
if (ring_fd < 0) return -1;
|
||||
ring_fd_open = 1;
|
||||
ring_blk = mem_alloc_pages(RING_PAGES);
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
#include "pop_guard.h"
|
||||
#include "pop_pal.h"
|
||||
#include "pop_ui.h" /* POP_COL_OUTSIDE */
|
||||
#include "_pop_file.h"
|
||||
|
||||
static void pal_file_load(const char *path, const char *fallback)
|
||||
static void pal_file_load(const char *path)
|
||||
{
|
||||
if (gfx_pal_fload(0, path) < 0) gfx_pal_fload(0, fallback);
|
||||
int rc;
|
||||
POP_PATH_CALL(rc, gfx_pal_fload(0, path));
|
||||
gfx_pal_sync();
|
||||
pop_ui_palette_snapshot();
|
||||
}
|
||||
@@ -84,7 +86,7 @@ void pop_pal_menu_dim(uint8_t fade) __banked
|
||||
|
||||
void pop_pal_game_load(void) __banked
|
||||
{
|
||||
pal_file_load("KID\\kid.pal", "a:\\kid.pal");
|
||||
pal_file_load("KID\\kid.pal");
|
||||
/* kid.pal содержит все 256 записей и намеренно затирает эти три
|
||||
* динамических диапазона (тайлсет, Тень, набор соперника).
|
||||
* Восстановить их надо ДО snapshot. */
|
||||
@@ -110,7 +112,7 @@ void pop_pal_level_load(uint8_t full) __banked
|
||||
|
||||
void pop_pal_title_load(void) __banked
|
||||
{
|
||||
pal_file_load("TITLE\\title.pal", "a:\\title.pal");
|
||||
pal_file_load("TITLE\\title.pal");
|
||||
}
|
||||
|
||||
/* ЕДИНСТВЕННОЕ ОТЛИЧИЕ ФИНАЛА ОТ ИНТРО — цвет фона текстовой рамки.
|
||||
@@ -120,7 +122,7 @@ void pop_pal_title_load(void) __banked
|
||||
* файла и до нового снимка — как тайлсет/Тень в pop_pal_game_load. */
|
||||
void pop_pal_story_load(uint8_t ending) __banked
|
||||
{
|
||||
pal_file_load("PV\\story.pal", "a:\\story.pal");
|
||||
pal_file_load("PV\\story.pal");
|
||||
if (!ending) return;
|
||||
gfx_pal_set(0, POP_PAL_STORY_BG, 0x80, 0, 0);
|
||||
gfx_pal_set(1, POP_PAL_STORY_BG, 0x80, 0, 0);
|
||||
@@ -129,5 +131,5 @@ void pop_pal_story_load(uint8_t ending) __banked
|
||||
|
||||
void pop_pal_pv_load(void) __banked
|
||||
{
|
||||
pal_file_load("PV\\pv.pal", "a:\\pv.pal");
|
||||
pal_file_load("PV\\pv.pal");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* pop_path_bank.c — каталог приложения и восстановление cwd, BANK10.
|
||||
*
|
||||
* APPINFO B=1 возвращает абсолютный каталог запущенного EXE вместе с диском.
|
||||
* Получаем его один раз при старте. Буфер объявлен const намеренно: у
|
||||
* Sprinter банковые страницы — RAM, а --constseg кладёт объект в BANK10,
|
||||
* не расходуя дефицитную резидентную _DATA в W2. Записывает его только
|
||||
* ESTEX во время pop_path_init().
|
||||
*
|
||||
* ABI: публичные функции __banked; их вызывает POP_PATH_CALL из банка
|
||||
* файлового клиента. После возврата трамплин восстанавливает прежнюю W3,
|
||||
* поэтому переданный самой файловой операции указатель снова доступен.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "_pop_file.h"
|
||||
|
||||
static const char pop_app_dir[256] = { 0 };
|
||||
|
||||
/* ESTEX APPINFO ($47), B=1: HL=буфер, CF/A=ошибка. */
|
||||
static int appinfo_dir(const char *buf) __naked
|
||||
{
|
||||
(void)buf;
|
||||
__asm
|
||||
push ix
|
||||
ld b, #1
|
||||
ld c, #0x47
|
||||
rst #0x10
|
||||
pop ix
|
||||
jr c, _paid_err
|
||||
ld de, #0
|
||||
ret
|
||||
_paid_err:
|
||||
call __errno_set
|
||||
ld de, #-1
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
int8_t pop_path_init(void) __banked
|
||||
{
|
||||
const char *dir = pop_app_dir;
|
||||
|
||||
if (appinfo_dir(dir) != 0 || !dir[0]) return -1;
|
||||
return (int8_t)chdir(dir);
|
||||
}
|
||||
|
||||
int8_t pop_chdir_home(void) __banked
|
||||
{
|
||||
return (int8_t)chdir((const char *)pop_app_dir);
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "pop_pace.h"
|
||||
#include "pop_timer.h"
|
||||
#include "sprpop_cold.h"
|
||||
#include "_pop_file.h"
|
||||
|
||||
#define QS_VERSION 4
|
||||
#define QS_SAVE 1
|
||||
@@ -154,6 +155,7 @@ static int8_t qs_save(uint8_t page)
|
||||
uint8_t tail[4];
|
||||
const uint8_t h[7]={'P','O','P','Q',QS_VERSION,pop_current_level,0};
|
||||
uint16_t size;
|
||||
int rc;
|
||||
qs_init(&io,page,QS_LIMIT,0,0);
|
||||
pop_qs_raw_put(&io,h,sizeof(h));
|
||||
qs_payload(&io);
|
||||
@@ -162,14 +164,18 @@ static int8_t qs_save(uint8_t page)
|
||||
tail[2]=(uint8_t)io.checksum; tail[3]=(uint8_t)(io.checksum >> 8);
|
||||
pop_qs_raw_put(&io,tail,4); size=(uint16_t)(io.pos-QS_BASE);
|
||||
if (io.failed) return -1;
|
||||
unlink("POP.NEW");
|
||||
if (bank_save_file(page,QS_BASE,"POP.NEW",size) != size) {
|
||||
unlink("POP.NEW"); return -1;
|
||||
POP_PATH_CALL(rc, unlink("POP.NEW"));
|
||||
POP_PATH_CALL(rc, bank_save_file(page,QS_BASE,"POP.NEW",size));
|
||||
if (rc != size) {
|
||||
POP_PATH_CALL(rc, unlink("POP.NEW"));
|
||||
return -1;
|
||||
}
|
||||
unlink("POP.BAK");
|
||||
(void)rename("POP.SAV", "POP.BAK");
|
||||
if (rename("POP.NEW", "POP.SAV") != 0) {
|
||||
(void)rename("POP.BAK", "POP.SAV"); return -1;
|
||||
POP_PATH_CALL(rc, unlink("POP.BAK"));
|
||||
POP_PATH_CALL(rc, rename("POP.SAV", "POP.BAK"));
|
||||
POP_PATH_CALL(rc, rename("POP.NEW", "POP.SAV"));
|
||||
if (rc != 0) {
|
||||
POP_PATH_CALL(rc, rename("POP.BAK", "POP.SAV"));
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -178,7 +184,8 @@ static int8_t qs_load_one(const char *name, uint8_t page)
|
||||
{
|
||||
uint8_t level;
|
||||
uint16_t payload_size;
|
||||
int size=bank_load_file(page,QS_BASE,name,QS_LIMIT);
|
||||
int size;
|
||||
POP_PATH_CALL(size, bank_load_file(page,QS_BASE,name,QS_LIMIT));
|
||||
if (size <= 0 || !qs_validate_page(page,(uint16_t)size,&level,
|
||||
&payload_size)) return -1;
|
||||
if (level != pop_current_level) {
|
||||
@@ -205,11 +212,11 @@ uint8_t pop_qsave_probe(void) __banked
|
||||
page = mem_get_page(blk, 0);
|
||||
gfx_w0_page_prepare(page);
|
||||
|
||||
size = bank_load_file(page, QS_BASE, "POP.SAV", QS_LIMIT);
|
||||
POP_PATH_CALL(size, bank_load_file(page, QS_BASE, "POP.SAV", QS_LIMIT));
|
||||
if (size > 0 && qs_validate_page(page, (uint16_t)size, &level,
|
||||
&payload_size))
|
||||
slots |= POP_QS_SLOT_SAVE;
|
||||
size = bank_load_file(page, QS_BASE, "POP.BAK", QS_LIMIT);
|
||||
POP_PATH_CALL(size, bank_load_file(page, QS_BASE, "POP.BAK", QS_LIMIT));
|
||||
if (size > 0 && qs_validate_page(page, (uint16_t)size, &level,
|
||||
&payload_size))
|
||||
slots |= POP_QS_SLOT_BACKUP;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
||||
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
||||
#include "pop_map.h" /* pop_upside — переворот (зелье инверсии) */
|
||||
#include "_pop_file.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -83,7 +84,8 @@ static const char *bg_path(const char *name)
|
||||
static int bg_load_tile_pal(const char *name)
|
||||
{
|
||||
uint8_t buf[64];
|
||||
int fd = open(bg_path(name), O_RDONLY);
|
||||
int fd;
|
||||
POP_PATH_CALL(fd, open(bg_path(name), O_RDONLY));
|
||||
if (fd < 0) return -1;
|
||||
if (read(fd, buf, 64) != 64) { close(fd); return -1; }
|
||||
gfx_pal_load(0, POP_PAL_ENV, 16, buf);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "pop_ui.h"
|
||||
#include "pop_status.h"
|
||||
#include "pop_music.h" /* pop_music_service — подкачка кольца в долгих фейдах */
|
||||
#include "_pop_file.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t base;
|
||||
@@ -54,8 +55,10 @@ static uint8_t text_index(const pop_font_desc_t *font, uint8_t ch)
|
||||
|
||||
int pop_ui_init(void) __banked
|
||||
{
|
||||
int rc;
|
||||
if (font_ready) return 0;
|
||||
if (atlas_load(&font_at, "FONT\\font.atl") != 0) return -1;
|
||||
POP_PATH_CALL(rc, atlas_load(&font_at, "FONT\\font.atl"));
|
||||
if (rc != 0) return -1;
|
||||
font_ready = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -242,8 +245,10 @@ void pop_ui_palette_black(void) __banked
|
||||
uint8_t *black = pop_pal_buf;
|
||||
|
||||
/* BIOS принимает максимум 64 записи за вызов; одним буфером покрываем
|
||||
* все четыре четверти палитры, не занимая постоянную память. */
|
||||
for (i = 0; i < sizeof(black); i++) black[i] = 0;
|
||||
* все четыре четверти палитры, не занимая постоянную память.
|
||||
* sizeof(black) здесь нельзя: black — 16-битный указатель, и тогда
|
||||
* обнулятся лишь первые два байта, а цвет заливки останется случайным. */
|
||||
for (i = 0; i < sizeof(pop_pal_buf); i++) black[i] = 0;
|
||||
for (chunk = 0; chunk < 4; chunk++) {
|
||||
uint8_t start = (uint8_t)(chunk << 6);
|
||||
gfx_pal_load(0, start, 64, black);
|
||||
@@ -468,8 +473,10 @@ int pop_screen_blit_atlas_strips(const char * const *parts,
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
for (part = 0; part < count; part++) {
|
||||
atlas_t at;
|
||||
int rc;
|
||||
|
||||
if (atlas_load(&at, parts[part]) != 0) return -1;
|
||||
POP_PATH_CALL(rc, atlas_load(&at, parts[part]));
|
||||
if (rc != 0) return -1;
|
||||
strip_blit(&at, x, &y);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -40,15 +40,6 @@ int pop_vflip_take(const atlas_t *orig, const atlas_t *mirror)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pop_vflip_add(const atlas_t *orig, const char *path)
|
||||
{
|
||||
atlas_t m;
|
||||
|
||||
if (!orig || vf_n >= VF_MAX) return -1;
|
||||
if (atlas_load(&m, path) != 0) return -1;
|
||||
return pop_vflip_take(orig, &m);
|
||||
}
|
||||
|
||||
uint8_t pop_vflip_page(uint8_t src)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
@@ -26,11 +26,7 @@
|
||||
#include <stdint.h>
|
||||
#include <sprite.h>
|
||||
|
||||
/* Загрузить зеркальный файл path и связать его с атласом orig.
|
||||
* 0 — OK, -1 — файла нет / не хватило EMM / таблица полна. */
|
||||
int pop_vflip_add(const atlas_t *orig, const char *path);
|
||||
|
||||
/* То же, но зеркало УЖЕ загружено (например, прочитано из архива): таблица
|
||||
/* Зеркало УЖЕ загружено из архива: таблица
|
||||
* забирает его себе, и дальше он освобождается вместе с остальными. */
|
||||
int pop_vflip_take(const atlas_t *orig, const atlas_t *mirror);
|
||||
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
#include "pop_pal.h" /* lifecycle палитры title/intro/level */
|
||||
#include "pop_hof.h" /* persistent Hall of Fame — bank 9 */
|
||||
#include "pop_ui.h" /* чёрные обе страницы перед сменой палитры */
|
||||
#include "_pop_file.h" /* cwd приложения для старых DSS */
|
||||
|
||||
#include <sprinter_exit.h>
|
||||
#include <unistd.h>
|
||||
|
||||
__sfr __at (0xFE) io_border;
|
||||
|
||||
@@ -260,6 +264,11 @@ int main(void)
|
||||
uint8_t xdec_prev = 0, xinc_prev = 0, upsd_prev = 0;
|
||||
uint8_t failed = 0;
|
||||
|
||||
/* До первой файловой операции запоминаем абсолютный каталог EXE.
|
||||
* Без этого старый DSS теряет последний компонент cwd после OPEN пути
|
||||
* с подкаталогом и следующий файл ищет уровнем выше. */
|
||||
if (pop_path_init() != 0) return 1;
|
||||
|
||||
/* Загрузка ресурсов, палитра, первый экран — В БАНКЕ (sprpop_cold.c):
|
||||
* отрабатывает ровно один раз за игру, а кода там на полкилобайта. */
|
||||
pop_app_reset();
|
||||
|
||||
@@ -1151,7 +1151,7 @@ int pop_boot(void) __banked
|
||||
/* pop_cheats/speed применит pop_settings_apply после pop_sfx_init. */
|
||||
pop_guard_reset();
|
||||
if (pop_kid_data_load("KID\\kid.ani") != 0) { /* кадры+seqtbl в EMM-странице */
|
||||
printf("kid.ani load failed\n");
|
||||
puts("kid.ani load failed\n");
|
||||
return -1;
|
||||
}
|
||||
pop_guard_load(); /* атласы стража (GUARD\\g0..g4) */
|
||||
|
||||
Reference in New Issue
Block a user