From fc0ede91e18d43d2d55971c67519f17a76ddd7b7 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Mon, 10 Aug 2026 20:43:27 +0300 Subject: [PATCH] =?UTF-8?q?scr=5Fx:=20=D0=B1=D0=B0=D0=B9=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=8F=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B0=20x/7?= =?UTF-8?q?=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D1=81=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=80=D0=BD=D0=BE=D0=B9=20=E2=80=94=201=20=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=20=D0=B1=D1=8B=D1=81=D1=82=D1=80=D0=B5=D0=B5?= =?UTF-8?q?,=20-1152=20=D0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Гипотеза «двухбайтная индексация съест выигрыш от сложения» не подтвердилась. Собраны ОБА варианта, такты посчитаны по сгенерированному asm (хвост после проверки границ): int16_t готовое: add hl,hl / add hl,de / ld e,(hl) / inc hl / ld d,(hl) = 132 такта, 2 304 байта int8_t x/7: add hl,bc / ld a,(hl) / ld l,a / rlca / sbc a,a / ld h,a / add hl,de = 131 такт, 1 152 байта Расширение знака плюс 16-битное сложение стоят ровно столько же, сколько лишний add hl,hl при двухбайтном индексе, а обращений к памяти на одно меньше — под wait-state'ами Sprinter (2,4x номинала именно на обращениях к ОЗУ) байтовый вариант ещё чуть выгоднее номинала. Банк 4: 9 394 -> 8 243 из 16 384 (свободно 8 141 вместо 6 990) — запас под рост pop_cdraw, о котором и был вопрос. Тест переименован в geom_mul8div7_table_rules и проверяет ОБА правила генерации таблицы: тождество 8x/7 == x + x/7 и усечение к нулю. tests-host: [geom] 1992 -> 3144, все 5 наборов прошли. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/TASKS_OPEN.md | 41 ++-- applications/PoP/roomtest/pop_cdraw.c | 185 ++++++++---------- applications/PoP/roomtest/tests-host/t_geom.c | 21 +- 3 files changed, 115 insertions(+), 132 deletions(-) diff --git a/applications/PoP/roomtest/TASKS_OPEN.md b/applications/PoP/roomtest/TASKS_OPEN.md index 5b1966b..967b047 100644 --- a/applications/PoP/roomtest/TASKS_OPEN.md +++ b/applications/PoP/roomtest/TASKS_OPEN.md @@ -454,8 +454,8 @@ awk '/^;[a-z_0-9]+\.[ch]:[0-9]+:/{s=$0} /^\tcall\t__(div|mod|mul)/{printf "%-22s | `pop_guard.c` `guard_col_from_x` | `/14` + `%14` **безусловно**, мимо `POP_TILE_DIV` | единственное 16-битное деление, у которого таблица вообще не была подключена | | `pop_trob.c` `animate_chomper` | `tp / 10` = `__divuchar` на чомпера каждый кадр | таблицы `TP_ROW`/`TP_COL` уже лежали в ЭТОМ ЖЕ файле, но ниже по тексту — чомперы их не видели | -Приём для `×8/7`: **таблица готовых значений** `SCRX[1152]` (int16_t) в -банке 4, индекс `x + 448`. 2 304 байта, резидент не тронут. +Приём для `×8/7`: **таблица** `SCRX7[1152]` (int8_t, хранит `x/7`) в банке 4, +индекс `x + 448`, результат `x + SCRX7[i]`. 1 152 байта, резидент не тронут. Два решения по дороге, оба проверены, а не угаданы: @@ -468,22 +468,33 @@ awk '/^;[a-z_0-9]+\.[ch]:[0-9]+:/{s=$0} /^\tcall\t__(div|mod|mul)/{printf "%-22s `render_dx ∈ {−140, 0, +140}` полный диапазон `obj_x` = **−416..695**. Таблица кроет −448..703, деление стало недостижимым (оставлено страховкой на третьего персонажа / другой `render_dx`). -2. **Хранить готовое значение, а не `x/7`.** Байтовая таблица вдвое меньше, - но со знаковыми значениями к ней добавляются расширение знака и 16-битное - сложение — ровно те же такты, что лишний `add hl,hl` при 2-байтном - индексе. Раз выигрыша нет, берём вариант без арифметики. +2. **Хранить `x/7` байтом, а не готовое `x*8/7` словом** — по тождеству + `8x/7 == x + x/7`. Первая версия хранила готовое, «раз всё равно + индексация двухбайтная». Собраны ОБА варианта, такты посчитаны по + сгенерированному asm: + + | вариант | хвост после проверки границ | тактов | байт | + |---|---|---|---| + | `int16_t` готовое | `add hl,hl / add hl,de / ld e,(hl) / inc hl / ld d,(hl)` | **132** | 2 304 | + | `int8_t` `x/7` | `add hl,bc / ld a,(hl) / ld l,a / rlca / sbc a,a / ld h,a / add hl,de` | **131** | 1 152 | + + Расширение знака и 16-битное сложение стоят ровно столько же, сколько + лишний `add hl,hl` при двухбайтном индексе, а обращений к памяти на одно + меньше — под wait-state'ами Sprinter (такт ≈ 2,4× номинала именно на + обращениях к ОЗУ) байтовый вариант ещё чуть выгоднее номинала. Итог: + байтовая таблица не хуже по скорости и на килобайт меньше. **Урок: + «двухбайтный индекс съест выигрыш» — гипотеза; она не подтвердилась.** Кодоген проверен глазами (`bank4_pop_cdraw.asm`): `ld hl,#0x01C0; add hl,de`, -16-битное беззнаковое сравнение, `add hl,hl; add hl,de; ld e,(hl); inc hl; -ld d,(hl)` — индекс полный, старший байт не теряется (грабли -`sdcc_z80_const_ptr_index_bug` обойдены отдельной `uint16_t`-переменной). -≈130 тактов номинала против ~1 000 у `__divsint`. +16-битное беззнаковое сравнение — индекс полный, старший байт не теряется +(грабли `sdcc_z80_const_ptr_index_bug` обойдены отдельной +`uint16_t`-переменной). 131 такт номинала против ~1 000 у `__divsint`. -Проверка таблицы: значения сверены питоном обратно из `.c` со всеми 1 152 -записями, а ПРАВИЛО генерации («усечение к нулю») — тестом -`geom_mul8div7_trunc_to_zero` на целевом компиляторе: округляй SDCC к минус -бесконечности, вся отрицательная половина уехала бы на пиксель, и поймалось -бы это только глазами на левой кромке. +Проверка таблицы: все 1 152 записи сверены питоном обратно из `.c`, а ПРАВИЛА +генерации (тождество + усечение к нулю) — тестом `geom_mul8div7_table_rules` +на целевом компиляторе: округляй SDCC к минус бесконечности, вся +отрицательная половина уехала бы на пиксель, и поймалось бы это только +глазами на левой кромке. Оставлено сознательно (НЕ трогать, это не забытые места): diff --git a/applications/PoP/roomtest/pop_cdraw.c b/applications/PoP/roomtest/pop_cdraw.c index f9ad0bc..8640613 100644 --- a/applications/PoP/roomtest/pop_cdraw.c +++ b/applications/PoP/roomtest/pop_cdraw.c @@ -117,12 +117,21 @@ void pop_guard_free(void) __banked * `__divsint` — 2 400 тактов на вызов, и зовётся оно на КАЖДОГО персонажа * КАЖДЫЙ кадр (последнее деление, остававшееся в горячем пути). * - * Таблица хранит ГОТОВЫЙ результат (int16_t), а не x/7 с последующим - * сложением по тождеству 8x/7 == x + x/7. Байтовая таблица вдвое меньше, - * но она обязана быть знаковой (x/7 при x<0 отрицателен), а значит к её - * значению добавляется расширение знака плюс 16-битное сложение — по - * тактам это ровно то же самое, что лишний `add hl,hl` при 2-байтном - * индексе. Раз выигрыша нет, берём вариант без арифметики вообще. + * ХРАНИМ x/7 БАЙТОМ, а не готовое x*8/7 словом. Тождество: 8x/7 == x + x/7 + * (7x делится нацело, поэтому усечение обеих частей совпадает — и для + * отрицательных с трункейтом к нулю тоже). Оба варианта собраны и + * посчитаны по сгенерированному asm: + * + * int16_t готовое: ... add hl,hl / add hl,de / ld e,(hl) / inc hl / + * ld d,(hl) = 132 такта, 2 304 байта + * int8_t x/7: ... add hl,bc / ld a,(hl) / ld l,a / rlca / sbc a,a / + * ld h,a / add hl,de = 131 такт, 1 152 байта + * + * Расширение знака и 16-битное сложение стоят РОВНО столько же, сколько + * лишний `add hl,hl` при двухбайтном индексе, а чтение из памяти на одно + * меньше — под wait-state'ами Sprinter (такт ≈ 2,4× номинала на обращениях + * к ОЗУ) байтовый вариант даже чуть выгоднее номинала. Плюс килобайт + * банка, который в pop_cdraw ещё понадобится. * * ДИАПАЗОН — весь, а не «обычный случай». Отрицательные X реальны: * obj_x = 2*fwd − 116 уходит в минус, как только fwd < 58 (левее @@ -133,109 +142,69 @@ void pop_guard_free(void) __banked * Деление ниже поэтому недостижимо и оставлено страховкой на случай * третьего персонажа или другого render_dx. * - * Цена: 2 304 байта в банке 4 (там было 9 048 свободно). - * - * Экранная X по логической: SCRX[x + SCRX_BIAS] == x*8/7 (усечение к - * нулю, как в C и как у 8086 idiv в оригинале). */ + * SCRX7[x + SCRX_BIAS] == x/7 (усечение к нулю, как в C и как у 8086 idiv + * в оригинале); экранная X = x + SCRX7[...]. */ #define SCRX_BIAS 448 #define SCRX_N 1152 -static const int16_t SCRX[SCRX_N] = { - -512, -510, -509, -508, -507, -506, -505, -504, -502, -501, -500, -499, - -498, -497, -496, -494, -493, -492, -491, -490, -489, -488, -486, -485, - -484, -483, -482, -481, -480, -478, -477, -476, -475, -474, -473, -472, - -470, -469, -468, -467, -466, -465, -464, -462, -461, -460, -459, -458, - -457, -456, -454, -453, -452, -451, -450, -449, -448, -446, -445, -444, - -443, -442, -441, -440, -438, -437, -436, -435, -434, -433, -432, -430, - -429, -428, -427, -426, -425, -424, -422, -421, -420, -419, -418, -417, - -416, -414, -413, -412, -411, -410, -409, -408, -406, -405, -404, -403, - -402, -401, -400, -398, -397, -396, -395, -394, -393, -392, -390, -389, - -388, -387, -386, -385, -384, -382, -381, -380, -379, -378, -377, -376, - -374, -373, -372, -371, -370, -369, -368, -366, -365, -364, -363, -362, - -361, -360, -358, -357, -356, -355, -354, -353, -352, -350, -349, -348, - -347, -346, -345, -344, -342, -341, -340, -339, -338, -337, -336, -334, - -333, -332, -331, -330, -329, -328, -326, -325, -324, -323, -322, -321, - -320, -318, -317, -316, -315, -314, -313, -312, -310, -309, -308, -307, - -306, -305, -304, -302, -301, -300, -299, -298, -297, -296, -294, -293, - -292, -291, -290, -289, -288, -286, -285, -284, -283, -282, -281, -280, - -278, -277, -276, -275, -274, -273, -272, -270, -269, -268, -267, -266, - -265, -264, -262, -261, -260, -259, -258, -257, -256, -254, -253, -252, - -251, -250, -249, -248, -246, -245, -244, -243, -242, -241, -240, -238, - -237, -236, -235, -234, -233, -232, -230, -229, -228, -227, -226, -225, - -224, -222, -221, -220, -219, -218, -217, -216, -214, -213, -212, -211, - -210, -209, -208, -206, -205, -204, -203, -202, -201, -200, -198, -197, - -196, -195, -194, -193, -192, -190, -189, -188, -187, -186, -185, -184, - -182, -181, -180, -179, -178, -177, -176, -174, -173, -172, -171, -170, - -169, -168, -166, -165, -164, -163, -162, -161, -160, -158, -157, -156, - -155, -154, -153, -152, -150, -149, -148, -147, -146, -145, -144, -142, - -141, -140, -139, -138, -137, -136, -134, -133, -132, -131, -130, -129, - -128, -126, -125, -124, -123, -122, -121, -120, -118, -117, -116, -115, - -114, -113, -112, -110, -109, -108, -107, -106, -105, -104, -102, -101, - -100, -99, -98, -97, -96, -94, -93, -92, -91, -90, -89, -88, - -86, -85, -84, -83, -82, -81, -80, -78, -77, -76, -75, -74, - -73, -72, -70, -69, -68, -67, -66, -65, -64, -62, -61, -60, - -59, -58, -57, -56, -54, -53, -52, -51, -50, -49, -48, -46, - -45, -44, -43, -42, -41, -40, -38, -37, -36, -35, -34, -33, - -32, -30, -29, -28, -27, -26, -25, -24, -22, -21, -20, -19, - -18, -17, -16, -14, -13, -12, -11, -10, -9, -8, -6, -5, - -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, - 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, - 22, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, - 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 48, 49, - 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, - 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, - 77, 78, 80, 81, 82, 83, 84, 85, 86, 88, 89, 90, - 91, 92, 93, 94, 96, 97, 98, 99, 100, 101, 102, 104, - 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, - 118, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, - 132, 133, 134, 136, 137, 138, 139, 140, 141, 142, 144, 145, - 146, 147, 148, 149, 150, 152, 153, 154, 155, 156, 157, 158, - 160, 161, 162, 163, 164, 165, 166, 168, 169, 170, 171, 172, - 173, 174, 176, 177, 178, 179, 180, 181, 182, 184, 185, 186, - 187, 188, 189, 190, 192, 193, 194, 195, 196, 197, 198, 200, - 201, 202, 203, 204, 205, 206, 208, 209, 210, 211, 212, 213, - 214, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, - 228, 229, 230, 232, 233, 234, 235, 236, 237, 238, 240, 241, - 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 254, - 256, 257, 258, 259, 260, 261, 262, 264, 265, 266, 267, 268, - 269, 270, 272, 273, 274, 275, 276, 277, 278, 280, 281, 282, - 283, 284, 285, 286, 288, 289, 290, 291, 292, 293, 294, 296, - 297, 298, 299, 300, 301, 302, 304, 305, 306, 307, 308, 309, - 310, 312, 313, 314, 315, 316, 317, 318, 320, 321, 322, 323, - 324, 325, 326, 328, 329, 330, 331, 332, 333, 334, 336, 337, - 338, 339, 340, 341, 342, 344, 345, 346, 347, 348, 349, 350, - 352, 353, 354, 355, 356, 357, 358, 360, 361, 362, 363, 364, - 365, 366, 368, 369, 370, 371, 372, 373, 374, 376, 377, 378, - 379, 380, 381, 382, 384, 385, 386, 387, 388, 389, 390, 392, - 393, 394, 395, 396, 397, 398, 400, 401, 402, 403, 404, 405, - 406, 408, 409, 410, 411, 412, 413, 414, 416, 417, 418, 419, - 420, 421, 422, 424, 425, 426, 427, 428, 429, 430, 432, 433, - 434, 435, 436, 437, 438, 440, 441, 442, 443, 444, 445, 446, - 448, 449, 450, 451, 452, 453, 454, 456, 457, 458, 459, 460, - 461, 462, 464, 465, 466, 467, 468, 469, 470, 472, 473, 474, - 475, 476, 477, 478, 480, 481, 482, 483, 484, 485, 486, 488, - 489, 490, 491, 492, 493, 494, 496, 497, 498, 499, 500, 501, - 502, 504, 505, 506, 507, 508, 509, 510, 512, 513, 514, 515, - 516, 517, 518, 520, 521, 522, 523, 524, 525, 526, 528, 529, - 530, 531, 532, 533, 534, 536, 537, 538, 539, 540, 541, 542, - 544, 545, 546, 547, 548, 549, 550, 552, 553, 554, 555, 556, - 557, 558, 560, 561, 562, 563, 564, 565, 566, 568, 569, 570, - 571, 572, 573, 574, 576, 577, 578, 579, 580, 581, 582, 584, - 585, 586, 587, 588, 589, 590, 592, 593, 594, 595, 596, 597, - 598, 600, 601, 602, 603, 604, 605, 606, 608, 609, 610, 611, - 612, 613, 614, 616, 617, 618, 619, 620, 621, 622, 624, 625, - 626, 627, 628, 629, 630, 632, 633, 634, 635, 636, 637, 638, - 640, 641, 642, 643, 644, 645, 646, 648, 649, 650, 651, 652, - 653, 654, 656, 657, 658, 659, 660, 661, 662, 664, 665, 666, - 667, 668, 669, 670, 672, 673, 674, 675, 676, 677, 678, 680, - 681, 682, 683, 684, 685, 686, 688, 689, 690, 691, 692, 693, - 694, 696, 697, 698, 699, 700, 701, 702, 704, 705, 706, 707, - 708, 709, 710, 712, 713, 714, 715, 716, 717, 718, 720, 721, - 722, 723, 724, 725, 726, 728, 729, 730, 731, 732, 733, 734, - 736, 737, 738, 739, 740, 741, 742, 744, 745, 746, 747, 748, - 749, 750, 752, 753, 754, 755, 756, 757, 758, 760, 761, 762, - 763, 764, 765, 766, 768, 769, 770, 771, 772, 773, 774, 776, - 777, 778, 779, 780, 781, 782, 784, 785, 786, 787, 788, 789, - 790, 792, 793, 794, 795, 796, 797, 798, 800, 801, 802, 803, +static const int8_t SCRX7[SCRX_N] = { + -64, -63, -63, -63, -63, -63, -63, -63, -62, -62, -62, -62, -62, -62, -62, -61, -61, -61, -61, -61, + -61, -61, -60, -60, -60, -60, -60, -60, -60, -59, -59, -59, -59, -59, -59, -59, -58, -58, -58, -58, + -58, -58, -58, -57, -57, -57, -57, -57, -57, -57, -56, -56, -56, -56, -56, -56, -56, -55, -55, -55, + -55, -55, -55, -55, -54, -54, -54, -54, -54, -54, -54, -53, -53, -53, -53, -53, -53, -53, -52, -52, + -52, -52, -52, -52, -52, -51, -51, -51, -51, -51, -51, -51, -50, -50, -50, -50, -50, -50, -50, -49, + -49, -49, -49, -49, -49, -49, -48, -48, -48, -48, -48, -48, -48, -47, -47, -47, -47, -47, -47, -47, + -46, -46, -46, -46, -46, -46, -46, -45, -45, -45, -45, -45, -45, -45, -44, -44, -44, -44, -44, -44, + -44, -43, -43, -43, -43, -43, -43, -43, -42, -42, -42, -42, -42, -42, -42, -41, -41, -41, -41, -41, + -41, -41, -40, -40, -40, -40, -40, -40, -40, -39, -39, -39, -39, -39, -39, -39, -38, -38, -38, -38, + -38, -38, -38, -37, -37, -37, -37, -37, -37, -37, -36, -36, -36, -36, -36, -36, -36, -35, -35, -35, + -35, -35, -35, -35, -34, -34, -34, -34, -34, -34, -34, -33, -33, -33, -33, -33, -33, -33, -32, -32, + -32, -32, -32, -32, -32, -31, -31, -31, -31, -31, -31, -31, -30, -30, -30, -30, -30, -30, -30, -29, + -29, -29, -29, -29, -29, -29, -28, -28, -28, -28, -28, -28, -28, -27, -27, -27, -27, -27, -27, -27, + -26, -26, -26, -26, -26, -26, -26, -25, -25, -25, -25, -25, -25, -25, -24, -24, -24, -24, -24, -24, + -24, -23, -23, -23, -23, -23, -23, -23, -22, -22, -22, -22, -22, -22, -22, -21, -21, -21, -21, -21, + -21, -21, -20, -20, -20, -20, -20, -20, -20, -19, -19, -19, -19, -19, -19, -19, -18, -18, -18, -18, + -18, -18, -18, -17, -17, -17, -17, -17, -17, -17, -16, -16, -16, -16, -16, -16, -16, -15, -15, -15, + -15, -15, -15, -15, -14, -14, -14, -14, -14, -14, -14, -13, -13, -13, -13, -13, -13, -13, -12, -12, + -12, -12, -12, -12, -12, -11, -11, -11, -11, -11, -11, -11, -10, -10, -10, -10, -10, -10, -10, -9, + -9, -9, -9, -9, -9, -9, -8, -8, -8, -8, -8, -8, -8, -7, -7, -7, -7, -7, -7, -7, + -6, -6, -6, -6, -6, -6, -6, -5, -5, -5, -5, -5, -5, -5, -4, -4, -4, -4, -4, -4, + -4, -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, + 18, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, + 21, 21, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, + 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, + 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, + 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 33, + 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, + 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, + 38, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, + 41, 41, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, + 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, + 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 50, 50, + 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 53, + 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, + 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, + 61, 61, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, + 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, + 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 70, 70, + 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, 73, + 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, + 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, + 78, 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, + 81, 81, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, + 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, + 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 90, 90, + 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 93, + 93, 93, 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, + 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, + 98, 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, }; static int scr_x(int x) @@ -245,7 +214,7 @@ static int scr_x(int x) * индекса (memory sdcc_z80_const_ptr_index_bug), а тут индекс как раз * больше 255. */ uint16_t i = (uint16_t)(x + SCRX_BIAS); - if (i < SCRX_N) return SCRX[i]; + if (i < SCRX_N) return x + SCRX7[i]; return x * 8 / 7; /* по данным кадров недостижимо */ } diff --git a/applications/PoP/roomtest/tests-host/t_geom.c b/applications/PoP/roomtest/tests-host/t_geom.c index 6c5e40d..0702db5 100644 --- a/applications/PoP/roomtest/tests-host/t_geom.c +++ b/applications/PoP/roomtest/tests-host/t_geom.c @@ -72,20 +72,23 @@ TC_TEST(geom_y_to_row_matches_formula) } } -/* calc_screen_x_coord (seg008:2602) считается в pop_cdraw.c ГОТОВОЙ таблицей - * SCRX (банк 4, сюда не линкуется). Таблица сгенерирована питоном по правилу - * «усечение К НУЛЮ»: значение = знак(x) * (|x|*8 / 7). Проверяем ИМЕННО это - * правило на целевом компиляторе: если бы __divsint у SDCC округлял иначе - * (к минус бесконечности), вся отрицательная половина таблицы уехала бы на - * пиксель, а поймалось бы это только глазами на левой кромке комнаты. */ -TC_TEST(geom_mul8div7_trunc_to_zero) +/* calc_screen_x_coord (seg008:2602) считается в pop_cdraw.c таблицей SCRX7 + * (банк 4, сюда не линкуется): хранится x/7 байтом, результат = x + SCRX7[..]. + * Таблица сгенерирована питоном, поэтому проверяем два правила, на которых + * держится генерация — ИМЕННО на целевом компиляторе: + * 1) тождество 8x/7 == x + x/7 (7x делится нацело); + * 2) усечение К НУЛЮ, а не к минус бесконечности. + * Округляй SDCC иначе — вся отрицательная половина уехала бы на пиксель, и + * поймалось бы это только глазами на левой кромке комнаты. */ +TC_TEST(geom_mul8div7_table_rules) { int16_t x; /* Полный диапазон obj_x по данным кадров: −416..695 (см. шапку scr_x). */ for (x = -448; x <= 703; x++) { int16_t want = (int16_t)(((x < 0) ? -x : x) * 8 / 7); if (x < 0) want = (int16_t)-want; - TC_EQ((int16_t)(x * 8 / 7), want); + TC_EQ((int16_t)(x * 8 / 7), want); /* усечение к нулю */ + TC_EQ((int16_t)(x * 8 / 7), (int16_t)(x + x / 7)); /* тождество */ } } @@ -171,7 +174,7 @@ int main(void) TC_RUN(geom_yland_rows); TC_RUN(geom_y_to_row); TC_RUN(geom_y_to_row_matches_formula); - TC_RUN(geom_mul8div7_trunc_to_zero); + TC_RUN(geom_mul8div7_table_rules); #if POP_PRANDOM_EXACT TC_RUN(geom_lcg_matches_reference); TC_RUN(geom_lcg_seed_zero);