Платформа: NES (Famicom) Dendy
Маппер: MMC1 (Плата SNROM).
Память: 256 КБ PRG-ROM (16 банков по 16 КБ), 8 КБ CHR-RAM.
Инструменты: Ассемблер ca65 и линкер ld65 под Linux.

Постановка задачи:
Необходимо реализовать код загрузчика игры (Bootloader), который считывает данные из zero page, настраивает маппер MMC1 и передает управление игре.
КРИТИЧЕСКИ ВАЖНО ПРАВИЛЬНО НАСТРАИВАТЬ MMC1. Найди информацию и примеры правильно записи в регистры!
ПОБИТОВАЯ ЗАПИСЬ: Помни, что MMC1 принимает данные последовательно.
Любая запись в регистры маппера ($8000, $A000, $C000, $E000) должна состоять ровно из 5 последовательных инструкций записи.
Данные считываются маппером исключительно из нулевого бита (D0) шины данных. Изменения применяются только на 5-ю запись.
ВАЖНО: Запись должна идти строго от младшего бита к старшему (Bit 0 отправляется ПЕРВЫМ, Bit 4 — ПЯТЫМ). При последовательном кодировании используй инструкцию сдвига вправо LSR A, а не сдвиг влево ASL A.

Так как игра (например, Super Mario Bros) может занимать 32 КБ и переключать оба окна PRG (включая область $C000–$FFFF),
код загрузчика обязан выполняться из оперативной памяти (RAM) по адресу $0600, иначе при переключении банков произойдет краш.
выделять отдельные сегменты не нужно, все будет в самом низу сегмента CODE
код загрузчика нужно копировать при вызове, а не прописывать в сегмент.
Для кода, который выполняется после релокации в RAM, использую относительные переходы, не допусти ошибок адресации.

Пошаговый алгоритм загрузчика:
1. копируем код загрузчика в RAM
2. загрузчик читает 7 байт сохраненной конфигурации игры (game_table) из $0032-$0038
3. Так как используется CHR-RAM, необходимо ПРЕДВАРИТЕЛЬНО скопировать графические тайлы выбранной игры из PRG-ROM в PPU CHR-RAM.
Переключаем на банк содержащий chr данные выбранной игры. копируем данные.
обязательно учти в какой области находится 8кб chr - Байт 4: Смещение CHR — Положение в банке для чтения CPU: 0 = $8000, 1 = $A000
4.  После копирования CHR, переключаем на банк где находится prg игры.
КРИТИЧЕСКИ ВАЖНО - PRG И CHR могут находится в разных банках.
Устанавливаем режим правильного зеркалирования и режима PRG (32 КБ или 16 КБ в зависимости от игры).
5. Старт игры:Выполнить переход на Reset-вектор запущенной игры.

Строгие правила синтаксиса ca65 (MOS 6502):
1.  Локальные метки: Должны начинаться ТОЛЬКО с символа `@` (например, `@copy_loop:` или `@bit_loop:`).
Начинать локальные метки с точки `.` категарически ЗАПРЕЩЕНО.
2.  16-битные адреса: При загрузке старшего/младшего байтов адресов меток всегда используй операторы `<` и `>`
(например: `lda #<repeat_table`, `ldx #>repeat_table`), чтобы избежать ошибок компиляции "range error".
3. учти строгие архитектурные ограничения процессора NES (Ricoh 2A03), который основан на NMOS 6502, а не на более новом CMOS 65C02.
Процессор NES не поддерживает инструкцию DEC A. В системе команд 6502 не существует адресации STA с индексацией по Y для Zero Page
В системе команд 6502 не существует режима адресации STA (zp) (косвенная адресация без индекса).
Для инструкции STA поддерживается только режим STA (zp, X) (косвенная адресация с индексацией по X).


; ==============================================================================
; СТРУКТУРА ДАННЫХ ТАБЛИЦЫ ИГР (Размер одной записи: 7 байт)
; ==============================================================================
; Байт 0: PRG Банк
; Байт 1: Размер PRG
; Байт 2: CHR Банк
; Байт 3: Зеркалирование (0 = Horizontal, 1 = Vertical)
; Байт 4: Смещение CHR (0 = $8000, 1 = $A000)
; Байт 5-6: Вектор сброса (Адрес старта игры, 2 байта, Little-Endian)
; ==============================================================================

game_table:
    ; 01: Super Mario Bros
    .byte 2, 2, 0, 0, 1
    .word $8000

    ; 02: Battle City
    .byte 4, 1, 5, 1, 0
    .word $E000

    ; 03: Galaxian
    .byte 1, 1, 1, 1, 1
    .word $F000

    ; 04: Lunar Ball
    .byte 6, 1, 5, 1, 1
    .word $C000

    ; 05: Duck Hunt
    .byte 7, 1, 8, 0, 0
    .word $8000

    ; 06: Wild Gunman
    .byte 9, 1, 8, 0, 1
    .word $F593

    ; 07: Balloon Fight
    .byte 10, 1, 11, 0, 0
    .word $C000

    ; 08: Bomberman
    .byte 12, 1, 11, 0, 1
    .word $C000

    ; 09: Ice Climber
    .byte 13, 1, 14, 1, 0
    .word $E000


