Код:
; ------------------------------------------------------------------------------
; Первоначальный текст для модификации:
; Copyright 2022 Nameless Algorithm
; See https://namelessalgorithm.com/ for more information.
;
; ------------------------------------------------------------------------------
; ЗАГОЛОВОК РОМА
; ------------------------------------------------------------------------------
rom_header:
dc.l $00FFFFFE ; Значение стека при старте
dc.l EntryPoint ; Адрес старта
;Вектора исключений и прерываний
dc.l ignore_handler ; Bus error
dc.l ignore_handler ; Address error
dc.l ignore_handler ; Illegal instruction
dc.l ignore_handler ; Division by zero
dc.l ignore_handler ; CHK exception
dc.l ignore_handler ; TRAPV exception
dc.l ignore_handler ; Privilege violation
dc.l ignore_handler ; TRACE exception
dc.l ignore_handler ; Line-A emulator
dc.l ignore_handler ; Line-F emulator
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Spurious exception
dc.l ignore_handler ; IRQ level 1
dc.l ignore_handler ; IRQ level 2
dc.l ignore_handler ; IRQ level 3
dc.l ignore_handler ; IRQ level 4 (horizontal retrace interrupt)
;^Вектор строчного прерывания от видеопроцесора. Не спользуем.
dc.l ignore_handler ; IRQ level 5
dc.l vblank_handler ; IRQ level 6 (vertical retrace interrupt)
;^Вектор кадрового прерывания от видеопроцесора. Используем.
dc.l ignore_handler ; IRQ level 7
dc.l ignore_handler ; TRAP #00 exception
dc.l ignore_handler ; TRAP #01 exception
dc.l ignore_handler ; TRAP #02 exception
dc.l ignore_handler ; TRAP #03 exception
dc.l ignore_handler ; TRAP #04 exception
dc.l ignore_handler ; TRAP #05 exception
dc.l ignore_handler ; TRAP #06 exception
dc.l ignore_handler ; TRAP #07 exception
dc.l ignore_handler ; TRAP #08 exception
dc.l ignore_handler ; TRAP #09 exception
dc.l ignore_handler ; TRAP #10 exception
dc.l ignore_handler ; TRAP #11 exception
dc.l ignore_handler ; TRAP #12 exception
dc.l ignore_handler ; TRAP #13 exception
dc.l ignore_handler ; TRAP #14 exception
dc.l ignore_handler ; TRAP #15 exception
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
dc.l ignore_handler ; Unused (reserved)
; Блок инфомационных данных.Блок занимает адреса $000100-$001FF
dc.b "SEGA GENESIS " ; Название приставки, 16 байт
dc.b "(C)YURI 2025.DEC" ; Copyright holder and release date, 16 байт
; Поле в формате "(C)XXXX YYYY.ZZZ"
; (C)Издатель сокр. год( числа).месяц( три буквы)
dc.b "VERY MINIMAL GENESIS CODE " ; Имя рома для систем Domest., 48 байт
dc.b "VERY MINIMAL GENESIS CODE " ; Имя рома для систем Intern., 48 байт
dc.b "GM VN151225-01" ; Serial and version number, 14 байт.
; Поле в формате "XX YYYYYYYY-ZZ"
; XX - GM( игра)
; YYYYYYYY - серийный номер
; ZZ - ревизия
dc.w $0000 ; Контрольная сумма РОМ, 2 байта. Для эмулятора значение не важно.
dc.b "J " ; Код доступных программе устройств ввода/вывода - текстовая строка(16 байт),
; каждый символ которой определяет тип периферийного устройства:
; джойстик для SEGA MASTER SYSTEM - D;
; джойстик для SEGA MEGA DRIVE - J;
; клавиатура - К;
; контроллер последовательного интерфейса - R; принтер — Р;
; контроллер дисковода - F; привод CD-ROM - С.
dc.l $00000000 ; Начало области ROM, 4 байта
dc.l __end ; Конец области ROM, 4 байта
; Для эмуляторов можно так.
; Для физического рома нужно указать настоящий размер. Распространённые размеры:
; $0007FFFF - 512 КБ
; $000FFFFF - 1 МБ
; $001FFFFF - 2 МБ
; $003FFFFF - 4 МБ
dc.l $00FF0000 ; Начало области RAM, 4 байта
dc.l $00FFFFFF ; Конец области RAM, 4 байта
dc.b $00, $00, $00, $00 ; Строка кодов, определяющая параметры установленного в картридже SRAM, 4 байтa
dc.l $00000000 ; Начало области SRAM, 4 байта
dc.l $00000000 ; Конец области SRAM, 4 байта
dc.b " " ; Поддержка модема, 12 байт
dc.b " " ; Резерв, 40 байт
dc.b "JUE" ; Код региона, 3 байта
dc.b " " ; Резерв, 13 байт
; CONSTANTS
; ------------------------------------------------------------------------------
vdp_control = $C00004; Адрес регистира контроля ВДП
vdp_data = $C00000; Адрес регистра данных ВДП
; INIT (ИНИЦИАЛИЗАЦИЯ ВНУТРЕННИХ УСТРОЙСТВ)
; ------------------------------------------------------------------------------
EntryPoint: ; ТОЧКА СТАРТА
move #$2700,sr ; Отключаем обработку прерываний процессором
; Очистку ОЗУ не нужно делать для этого примера
; Блок проверки системы защиты товарных знаков TMSS.
; НЕ ИМЕЕТ ЮРИДИЧЕСКОЙ СИЛЫ
; Законность этой системы была оспорена в США компанией Accolade в судебном процессе SEGA против Accolade,
; который завершился решением в пользу Accolade.
TMSS
move.b $00A10001,d0 ; Пересылаем версию платы в d0
andi.b #$0F,d0 ; Номер версии в 4 младших битах,
; их берём по маске $0F
beq .skip ; Если номер версии платы равен 0, пропускаем TMSS подтверждение,
move.l #'SEGA',$00A14000 ; иначе записываем значение "SEGA" по адресу $A14000
.skip
; Настройка сопроцессора
Z80
move.w #$0100,$00A11100 ; Делаем запрос на захват шин Z80
move.w #$0100,$00A11200 ; Удерживаем Z80 в состоянии сброса
.wait
btst #$0,$00A11101 ; Проверяем, свободны ли шины Z80
bne .wait ; Если они не освободились, возвращаемся к метке Wait
move.l #$00A00000,a1 ; Копируем адрес начала области RAM Z80 в a1
move.l #$00C30000,(a1) ; Записывам программу для Z80. В данном случае, процессор зацикливаем:
; nop
; jmp $0000.
move.w #$0000,$00A11200 ; снимаем сигнал сброса Z80
move.w #$0000,$00A11100 ; отдаем шины Z80
; Инициализация PSG-генератора
;move.l #$9fbfdfff,$00C00011 ; глушим генератор
; Типовой блок настройки видеопроцессора
init_vdp
move.l #VDPRegisters,a0 ; Загружаем адрес таблицы значений регистров в a0
move.l #$18,d0 ; Загружаем значение 24 в счетчик d0. 24 количество регистров.
move.l #$00008000,d1 ; Код команды 'Установить регистр 0' заносим в d1
copy_vdp
move.b (a0)+,d1 ; Пересылаем байт значения регистра из таблицы в младший байт d1
move.w d1,$00C00004 ; Отправляем команду с номером регистра в VDP control port
add.w #$0100,d1 ; Увеличиваем номер регистра в команде
dbra d0,copy_vdp ; Декремент счетчика
; Ignore I/O ports - we don't use them
; ПРОГРАММА
; ------------------------------------------------------------------------------
color_transfer = $FF0010; Адрес переменной для хранения компонентов цвета в ОЗУ, 16 бит.
color_step = 300; Значение приращения переменной color_transfer
time = $FF0020; Адрес переменной для счётчика времени в ОЗУ, 16 бит.
time_limit = 50; Предел времени
main
move.w #0,(color_transfer) ; Обнуляем переменную
move.w #0,(time) ; Обнуляем переменную
move.w #$8F00,vdp_control ; Выключаем автоинкремент адресов данных VDP
move.w #$8164,vdp_control ; Запуск VDP, разрешение vblank, отключение DMA, формат NTSC, Genesis mode
move #$2400,sr ; Включаем оработку прерываний процессором
move.l #$C0000000,vdp_control ; Настраиваем VDP на запись в CRAM по адресу $0000, что соответствует
; нулевому цвету нулевой палитры, выбранному в качестве цвета фона
loop
move.w (color_transfer),d0 ; Загружаем значение переменной в d0
addi.w #color_step,d0 ; Увеличиваем его на величину #color_step
move.w d0,(color_transfer) ; Сохраняем новое значение переменной и
move.w d0,vdp_data ; записываем его как значение фонового цвета
.wait
cmpi.w #time_limit,(time) ; Если время не достигло предела,
bne .wait ; то возвращаемся к .wait,
move.w #0,(time) ; иначе обнуляем значение времени
jmp loop
; ОБРАБОТЧИКИ ПРЕРЫВАНИЙ И ИСКЛЮЧЕНИЙ
; ----------------------------------------------------------------------------
align 2 ; Пословное выравнивание
; Оработчик-заглушка
ignore_handler
rte ;
; Обработчик vblank
vblank_handler
addq.w #1,(time) ; Инкремент переменной
rte
; Таблица значений регистров VDP
;------------------------------------------------------------------------------
align 2 ; Пословное выравнивание
VDPRegisters:
; Mode
reg00: dc.b %00000101 ; прерывания hblank откл, полный цвет, счетчик строк откл
reg01: dc.b %01000100 ; Display вкл, прерывания vblank откл, DMA откл, режим строк NTSC, Genesis mode
; VRAM layout
reg02: dc.b $38 ; Адрес таблицы имен Plane A как VRAM $E000
reg03: dc.b $00 ; Адрес таблицы имен Window Plane как VRAM $0000
reg04: dc.b $07 ; Адрес таблицы имен Plane B как VRAM $E000
reg05: dc.b $78 ; Адрес таблицы атрибутов спрайтов на VRAM $F000 (bits 0-6 = bits 9-15)
reg06: dc.b $00 ; ??? Sprite table 128KB VRAM (ignore)
; BG color
reg07: dc.b $00 ; Цвет фона - bits 0-3 = colour
; bits 4-5 = palette
; Unused
reg08: dc.b $00 ; ??? SMS HScroll reg
reg09: dc.b $00 ; ??? SMS VScroll reg
; General
reg0A: dc.b $00 ; Задает через сколько строк генертровать hblank (# scanlines between hblank)
reg0B: dc.b %0000000 ; Внешние прерывания откл, HScroll для всего экрана
reg0C: dc.b %1000001 ; Широкий экран H40 (320px), тень/подсветка откл, без интерлейса
reg0D: dc.b $3F ; Адрес таблицы горизонтальной прокрутки на VRAM $FC00 (bits 0-5)
reg0E: dc.b $00 ; Unused
reg0F: dc.b $02 ; Автоинкремент адресов в 2 байта
reg10: dc.b $00 ; Размеры прокручиваемой области Vert. scroll 32, Horiz. scroll 32
; Window
reg11: dc.b $00 ; Позиция Window Plane X = 0 , расположение слева от базовой точки
; (pos in bits 0-4, left/right in bit 7)
reg12: dc.b $00 ; Позиция Window Plane Y = 0 , расположение сверху от базовой точки
; (pos in bits 0-4, up/down in bit 7)
; DMA
reg13: dc.b $00 ; Длина пересылки DMA lo byte
reg14: dc.b $00 ; Длина пересылки DMA hi byte
reg15: dc.b $00 ; Адрес источника DMA lo byte
reg16: dc.b $00 ; Адрес источника DMA mid byte
reg17: dc.b $80 ; Адрес источника DMA hi byte,
; режим "memory-to-VRAM mode" (bits 6-7)
__end:
За основу взял код с сайта