mdview2: HEX-режим (F4) — дамп оригинального файла; версия v1.0 (b1)

Новый модуль mdview2_hex.c (WITH_HEX в conf): формат
' 0x012340 │ 16×hex │ 16 print', 30 строк, один атрибут.

- Дамп всегда ОРИГИНАЛЬНОГО файла (orig_file_phys), не активного буфера;
  ряд выровнен на 16 → один bank_read на ряд (не пересекает EMM-страницу),
  fb()/W3 не используются.
- Printable по текущей кодировке: CP866 как есть, CP1251/KOI8 через
  g_remap, UTF-8 — глиф на позиции лид-байта (continuation → '.') через
  новый utf_cp_glyph(), выделенный из конвертера enc-модуля.
- Навигация: ±16 / ±480 / Home / End; одна строка — аппаратный scroll()
  + подрисовка одного ряда (как MD/RAW); процент в статусе.
- F4 — тумблер HEX ↔ прежний вид; F2 из HEX уводит в MD; позиция при
  всех переходах через view_pos/view_reanchor (map_off orig ↔ active).
- F8 в HEX: hex-колонка неизменна, printable перерисовывается в новой
  кодировке; позиция не двигается.
- Help: версия v1.0 (b1), строка F4.

exe 25725 → 27893 (+2168). Проверено в MAME.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 13:19:08 +03:00
parent e5866d6ba4
commit ae23d2dea2
8 changed files with 334 additions and 24 deletions
+77 -9
View File
@@ -199,6 +199,9 @@ uint8_t g_view = VIEW_MD; /* extern: активный
#if WITH_RAW
uint8_t g_ready; /* extern: 1 когда первичный документ построен — F2 (RAW) рабочий */
static uint8_t g_raw_last = VIEW_RAW_WRAP; /* последний под-режим RAW (возврат по F2) */
#if WITH_HEX
static uint8_t g_hex_last = VIEW_MD; /* вид, из которого вошли в HEX (возврат по F4) */
#endif
#endif
uint8_t g_loading; /* extern: 1 во время index_lines() */
static uint8_t g_first_drawn; /* первый экран уже нарисован */
@@ -720,6 +723,12 @@ void progress_tick(void)
* не MD-вид (иначе мелькал бы MD). Индекс при этом строится дальше (нужен
* для MD-вида). */
if (g_view != VIEW_MD) {
#if WITH_HEX
if (g_view == VIEW_HEX) { /* HEX показывает оригинал — экран уже актуален */
spinner_tick();
return;
}
#endif
if (!g_first_drawn) {
raw_draw();
// render_raw_status();
@@ -845,18 +854,33 @@ static uint32_t map_off(uint32_t off, uint32_t from, uint32_t to)
}
/* Байт-позиция текущего вида (верх экрана) — единая «валюта» для переноса
* позиции между видами/наборами. */
* позиции между видами/наборами. Валюта = offset АКТИВНОГО буфера; HEX живёт
* в байтах оригинала, для UTF-набора конвертируем через map_off. */
static uint32_t view_pos(void)
{
#if WITH_HEX
if (g_view == VIEW_HEX)
return (g_active_doc == DOC_UTF8)
? map_off(hex_pos(), orig_file_size, file_size)
: hex_pos();
#endif
#if WITH_RAW
if (g_view != VIEW_MD) return raw_pos();
#endif
return seg_off(top_line);
}
/* Поставить текущий вид на байт-позицию off (после doc_switch). */
/* Поставить текущий вид на байт-позицию off (активного буфера). */
static void view_reanchor(uint32_t off)
{
#if WITH_HEX
if (g_view == VIEW_HEX) {
hex_reanchor((g_active_doc == DOC_UTF8)
? map_off(off, file_size, orig_file_size)
: off);
return;
}
#endif
#if WITH_RAW
if (g_view != VIEW_MD) { raw_reanchor(off); return; }
#endif
@@ -893,7 +917,7 @@ static void switch_encoding(uint8_t next)
doc_save_live(g_active_doc); /* сохранить текущий (позиция и т.п.) */
#if WITH_RAW
uint32_t raw_save = raw_pos();
if (g_view != VIEW_MD)
if (VIEW_IS_RAW(g_view)) /* HEX показывает оригинал — его позиция инвариантна */
raw_reanchor(0); /* прогрессивный показ нового буфера — с начала */
g_ready = 0;
render_menu(); /* идёт индексация — прячем F2 */
@@ -911,7 +935,7 @@ static void switch_encoding(uint8_t next)
g_utf_failed = 1;
doc_load_live(g_active_doc);
#if WITH_RAW
if (g_view != VIEW_MD)
if (VIEW_IS_RAW(g_view))
raw_reanchor(raw_save); /* буфер прежний — вернуть позицию RAW */
#endif
return;
@@ -1072,27 +1096,58 @@ int main(int argc, char **argv)
show_help();
continue;
} /* show_help сам перерисует */
/* F2 — тумблер RAW ↔ MD (рабочий только после постройки документа). */
/* F2 — тумблер RAW ↔ MD (из HEX тоже уводит в MD).
* Рабочий только после постройки документа. */
if (scan == KEY_F2) {
if (!g_ready) continue;
if (g_view == VIEW_MD) {
g_view = g_raw_last; /* → RAW (последний под-режим) */
raw_seed_from(top_line); /* позиция из MD */
raw_screen_init();
status_encoding();
status_encoding();
render_menu();
render_raw_status();
render_raw_status();
raw_draw();
} else {
g_raw_last = g_view; /* запомнить под-режим RAW */
uint32_t off = view_pos(); /* позиция из RAW/HEX */
if (VIEW_IS_RAW(g_view))
g_raw_last = g_view; /* запомнить под-режим RAW */
g_view = VIEW_MD;
top_line = line_at_off(raw_pos()); /* позиция из RAW */
top_line = line_at_off(off);
clamp_top();
render_full_status(); render_menu();
draw_viewport_from_cache();
}
continue;
}
#if WITH_HEX
/* F4 — тумблер HEX ↔ прежний вид (MD/RAW). */
if (scan == KEY_F4) {
if (!g_ready) continue;
uint32_t off = view_pos(); /* позиция текущего вида */
if (g_view == VIEW_HEX) { /* HEX → прежний вид */
g_view = g_hex_last;
view_reanchor(off);
if (g_view == VIEW_MD) {
clamp_top();
render_full_status(); render_menu();
draw_viewport_from_cache();
} else {
raw_screen_init();
status_encoding(); render_menu();
render_raw_status(); raw_draw();
}
} else { /* MD/RAW → HEX */
g_hex_last = g_view;
g_view = VIEW_HEX;
view_reanchor(off); /* active → байты оригинала */
hex_screen_init();
status_encoding(); render_menu();
render_hex_status(); hex_draw();
}
continue;
}
#endif
/* цикл CP866→CP1251→KOI8R→UTF8→CP866; набор дособерётся лениво */
if (scan == KEY_F8) {
uint8_t next = (g_encoding == ENC_CP866) ? ENC_CP1251 :
@@ -1104,6 +1159,14 @@ int main(int argc, char **argv)
if (g_abort)
exit(0); /* Esc/F10 во время ленивой досборки */
/* Перерисовка — по текущему виду (switch_encoding сам не рисует). */
#if WITH_HEX
if (g_view == VIEW_HEX) {
status_encoding();
render_hex_status();
hex_draw(); /* printable-колонка в новой кодировке */
continue;
}
#endif
#if WITH_RAW
if (g_view != VIEW_MD) {
status_encoding();
@@ -1121,6 +1184,11 @@ int main(int argc, char **argv)
/* MD-режим: F1/F8/F10 здесь, навигация — в md_key() (peer к raw_key). */
md_key(scan); /* навигация MD (сама рисует+статус); незнакомые игнорит */
continue;
#if WITH_HEX
case VIEW_HEX:
hex_key(scan); /* навигация HEX (сама рисует+процент) */
continue;
#endif
#if WITH_RAW
case VIEW_RAW_WRAP:
case VIEW_RAW_HSCROLL: