; ------------------------------------------------------------------------------
; Первоначальный текст для модификации:
; 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: