Guest User

Hello World with scroll on SEGA Mega Drive - by BigEvilCorp

a guest
Apr 17th, 2017
477
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ROM_Start
  2.  
  3.     ; CPU vector table
  4.     dc.l   0x00FFE000           ; Initial stack pointer value
  5.     dc.l   CPU_EntryPoint       ; Start of program
  6.     dc.l   CPU_Exception        ; Bus error
  7.     dc.l   CPU_Exception        ; Address error
  8.     dc.l   CPU_Exception        ; Illegal instruction
  9.     dc.l   CPU_Exception        ; Division by zero
  10.     dc.l   CPU_Exception        ; CHK CPU_Exception
  11.     dc.l   CPU_Exception        ; TRAPV CPU_Exception
  12.     dc.l   CPU_Exception        ; Privilege violation
  13.     dc.l   INT_Null             ; TRACE exception
  14.     dc.l   INT_Null             ; Line-A emulator
  15.     dc.l   INT_Null             ; Line-F emulator
  16.     dc.l   INT_Null             ; Unused (reserved)
  17.     dc.l   INT_Null             ; Unused (reserved)
  18.     dc.l   INT_Null             ; Unused (reserved)
  19.     dc.l   INT_Null             ; Unused (reserved)
  20.     dc.l   INT_Null             ; Unused (reserved)
  21.     dc.l   INT_Null             ; Unused (reserved)
  22.     dc.l   INT_Null             ; Unused (reserved)
  23.     dc.l   INT_Null             ; Unused (reserved)
  24.     dc.l   INT_Null             ; Unused (reserved)
  25.     dc.l   INT_Null             ; Unused (reserved)
  26.     dc.l   INT_Null             ; Unused (reserved)
  27.     dc.l   INT_Null             ; Unused (reserved)
  28.     dc.l   INT_Null             ; Spurious exception
  29.     dc.l   INT_Null             ; IRQ level 1
  30.     dc.l   INT_Null             ; IRQ level 2
  31.     dc.l   INT_Null             ; IRQ level 3
  32.     dc.l   INT_HBlank           ; IRQ level 4 (horizontal retrace interrupt)
  33.     dc.l   INT_Null             ; IRQ level 5
  34.     dc.l   INT_VBlank           ; IRQ level 6 (vertical retrace interrupt)
  35.     dc.l   INT_Null             ; IRQ level 7
  36.     dc.l   INT_Null             ; TRAP #00 exception
  37.     dc.l   INT_Null             ; TRAP #01 exception
  38.     dc.l   INT_Null             ; TRAP #02 exception
  39.     dc.l   INT_Null             ; TRAP #03 exception
  40.     dc.l   INT_Null             ; TRAP #04 exception
  41.     dc.l   INT_Null             ; TRAP #05 exception
  42.     dc.l   INT_Null             ; TRAP #06 exception
  43.     dc.l   INT_Null             ; TRAP #07 exception
  44.     dc.l   INT_Null             ; TRAP #08 exception
  45.     dc.l   INT_Null             ; TRAP #09 exception
  46.     dc.l   INT_Null             ; TRAP #10 exception
  47.     dc.l   INT_Null             ; TRAP #11 exception
  48.     dc.l   INT_Null             ; TRAP #12 exception
  49.     dc.l   INT_Null             ; TRAP #13 exception
  50.     dc.l   INT_Null             ; TRAP #14 exception
  51.     dc.l   INT_Null             ; TRAP #15 exception
  52.     dc.l   INT_Null             ; Unused (reserved)
  53.     dc.l   INT_Null             ; Unused (reserved)
  54.     dc.l   INT_Null             ; Unused (reserved)
  55.     dc.l   INT_Null             ; Unused (reserved)
  56.     dc.l   INT_Null             ; Unused (reserved)
  57.     dc.l   INT_Null             ; Unused (reserved)
  58.     dc.l   INT_Null             ; Unused (reserved)
  59.     dc.l   INT_Null             ; Unused (reserved)
  60.     dc.l   INT_Null             ; Unused (reserved)
  61.     dc.l   INT_Null             ; Unused (reserved)
  62.     dc.l   INT_Null             ; Unused (reserved)
  63.     dc.l   INT_Null             ; Unused (reserved)
  64.     dc.l   INT_Null             ; Unused (reserved)
  65.     dc.l   INT_Null             ; Unused (reserved)
  66.     dc.l   INT_Null             ; Unused (reserved)
  67.     dc.l   INT_Null             ; Unused (reserved)
  68.    
  69. ;==============================================================
  70.  
  71.     ; ROM metadata
  72.     dc.b "SEGA MEGA DRIVE "                                 ; Console name
  73.     dc.b "BIGEVILCORP.    "                                 ; Copyright holder and release date
  74.     dc.b "HELLO WORLD                                     " ; Domestic name
  75.     dc.b "HELLO WORLD                                     " ; International name
  76.     dc.b "GM XXXXXXXX-XX"                                   ; Version number
  77.     dc.w 0x0000                                             ; Checksum
  78.     dc.b "J               "                                 ; I/O support
  79.     dc.l ROM_Start                                          ; Start address of ROM
  80.     dc.l ROM_End-1                                          ; End address of ROM
  81.     dc.l 0x00FF0000                                         ; Start address of RAM
  82.     dc.l 0x00FF0000+0x0000FFFF                              ; End address of RAM
  83.     dc.l 0x00000000                                         ; SRAM enabled
  84.     dc.l 0x00000000                                         ; Unused
  85.     dc.l 0x00000000                                         ; Start address of SRAM
  86.     dc.l 0x00000000                                         ; End address of SRAM
  87.     dc.l 0x00000000                                         ; Unused
  88.     dc.l 0x00000000                                         ; Unused
  89.     dc.b "                                        "         ; Notes (unused)
  90.     dc.b "  E             "                                 ; Country codes
  91.    
  92. ;==============================================================
  93.    
  94. ; Initial VDP register values
  95. VDPRegisters:
  96.     dc.b 0x14 ; 0:  H interrupt on, palettes on
  97.     dc.b 0x74 ; 1:  V interrupt on, display on, DMA on, Genesis mode on
  98.     dc.b 0x30 ; 2:  Pattern table for Scroll Plane A at VRAM 0xC000 (bits 3-5 = bits 13-15)
  99.     dc.b 0x00 ; 3:  Pattern table for Window Plane at VRAM 0x0000 (disabled) (bits 1-5 = bits 11-15)
  100.     dc.b 0x07 ; 4:  Pattern table for Scroll Plane B at VRAM 0xE000 (bits 0-2 = bits 11-15)
  101.     dc.b 0x78 ; 5:  Sprite table at VRAM 0xF000 (bits 0-6 = bits 9-15)
  102.     dc.b 0x00 ; 6:  Unused
  103.     dc.b 0x00 ; 7:  Background colour - bits 0-3 = colour, bits 4-5 = palette
  104.     dc.b 0x00 ; 8:  Unused
  105.     dc.b 0x00 ; 9:  Unused
  106.     dc.b 0x08 ; 10: Frequency of Horiz. interrupt in Rasters (number of lines travelled by the beam)
  107.     dc.b 0x00 ; 11: External interrupts off, V scroll fullscreen, H scroll fullscreen
  108.     dc.b 0x81 ; 12: Shadows and highlights off, interlace off, H40 mode (320 x 224 screen res)
  109.     dc.b 0x3F ; 13: Horiz. scroll table at VRAM 0xFC00 (bits 0-5)
  110.     dc.b 0x00 ; 14: Unused
  111.     dc.b 0x02 ; 15: Autoincrement 2 bytes
  112.     dc.b 0x01 ; 16: Vert. scroll 32, Horiz. scroll 64
  113.     dc.b 0x00 ; 17: Window Plane X pos 0 left (pos in bits 0-4, left/right in bit 7)
  114.     dc.b 0x00 ; 18: Window Plane Y pos 0 up (pos in bits 0-4, up/down in bit 7)
  115.     dc.b 0xFF ; 19: DMA length lo byte
  116.     dc.b 0xFF ; 20: DMA length hi byte
  117.     dc.b 0x00 ; 21: DMA source address lo byte
  118.     dc.b 0x00 ; 22: DMA source address mid byte
  119.     dc.b 0x80 ; 23: DMA source address hi byte, memory-to-VRAM mode (bits 6-7)
  120.    
  121.     even
  122.    
  123. ;==============================================================
  124.    
  125. ; VDP port addresses
  126. vdp_control             equ 0x00C00004
  127. vdp_data                equ 0x00C00000
  128.  
  129. ; VDP commands
  130. vdp_cmd_vram_write      equ 0x40000000
  131. vdp_cmd_cram_write      equ 0xC0000000
  132. vdp_cmd_vsram_write     equ 0x40000010
  133.  
  134. ; VDP memory addresses
  135. vram_addr_hscroll       equ 0xFC00
  136.  
  137. ; Hardware version address
  138. hardware_ver_address    equ 0x00A10001
  139.  
  140. ; TMSS
  141. tmss_address            equ 0x00A14000
  142. tmss_signature          equ 'SEGA'
  143.  
  144. ; Total number of glyphs in the font
  145. num_font_glyphs         equ 0x7
  146.  
  147. ; The size of one palette (in bytes, words, and longwords)
  148. size_palette_b          equ 0x10
  149. size_palette_w          equ size_palette_b*2
  150. size_palette_l          equ size_palette_b*4
  151.  
  152. ; The size of one graphics tile (in bytes, words, and longwords)
  153. size_tile_b             equ 0x20
  154. size_tile_w             equ size_tile_b*2
  155. size_tile_l             equ size_tile_b*4
  156.  
  157. ; Hello World draw position as a byte offset
  158. ; (there are 40 tiles IDs per line, each tile ID is 2 bytes)
  159. text_pos_x_offset       equ 0x18
  160. text_pos_y_offset       equ 0xC4
  161.  
  162. ;==============================================================
  163.    
  164. ; VDP data port setup macros
  165. SetVRAMWrite: macro addr
  166.     move.l  #(vdp_cmd_vram_write)|((\addr)&$3FFF)<<16|(\addr)>>14, vdp_control
  167.     endm
  168.    
  169. SetVSRAMWrite: macro addr
  170.     move.l  #(vdp_cmd_vsram_write)|((\addr)&$3FFF)<<16|(\addr)>>14, vdp_control
  171.     endm
  172.    
  173. SetCRAMWrite: macro addr
  174.     move.l  #(vdp_cmd_cram_write)|((\addr)&$3FFF)<<16|(\addr)>>14, vdp_control
  175.     endm
  176.    
  177. ;==============================================================
  178.  
  179.     ; Palette
  180. Palette:
  181.     dc.w 0x0000 ; Transparent
  182.     dc.w 0x0000 ; Black
  183.     dc.w 0x0EEE ; White
  184.     dc.w 0x000E ; Red
  185.     dc.w 0x00E0 ; Blue
  186.     dc.w 0x0E00 ; Green
  187.     dc.w 0x0E0E ; Pink
  188.     dc.w 0x0000
  189.     dc.w 0x0000
  190.     dc.w 0x0000
  191.     dc.w 0x0000
  192.     dc.w 0x0000
  193.     dc.w 0x0000
  194.     dc.w 0x0000
  195.     dc.w 0x0000
  196.     dc.w 0x0000
  197.    
  198. ;==============================================================
  199.    
  200.     ; Font glyphs for "HELO WRD"
  201.     ; 'SPACE' is first, which is unneccessary but it's a good teaching tool for
  202.     ; why we leave the first tile in memory blank
  203. CharacterSpace:
  204.     dc.l 0x00000000
  205.     dc.l 0x00000000
  206.     dc.l 0x00000000
  207.     dc.l 0x00000000
  208.     dc.l 0x00000000
  209.     dc.l 0x00000000
  210.     dc.l 0x00000000
  211.     dc.l 0x00000000
  212.    
  213. CharacterH:
  214.     dc.l 0x22000220
  215.     dc.l 0x22000220
  216.     dc.l 0x22000220
  217.     dc.l 0x22222220
  218.     dc.l 0x22000220
  219.     dc.l 0x22000220
  220.     dc.l 0x22000220
  221.     dc.l 0x00000000
  222.    
  223. CharacterE:
  224.     dc.l 0x22222220
  225.     dc.l 0x22000000
  226.     dc.l 0x22000000
  227.     dc.l 0x22222220
  228.     dc.l 0x22000000
  229.     dc.l 0x22000000
  230.     dc.l 0x22222220
  231.     dc.l 0x00000000
  232.    
  233. CharacterL:
  234.     dc.l 0x22000000
  235.     dc.l 0x22000000
  236.     dc.l 0x22000000
  237.     dc.l 0x22000000
  238.     dc.l 0x22000000
  239.     dc.l 0x22000000
  240.     dc.l 0x22222220
  241.     dc.l 0x00000000
  242.    
  243. CharacterO:
  244.     dc.l 0x22222220
  245.     dc.l 0x22000220
  246.     dc.l 0x22000220
  247.     dc.l 0x22000220
  248.     dc.l 0x22000220
  249.     dc.l 0x22000220
  250.     dc.l 0x22222220
  251.     dc.l 0x00000000
  252.    
  253. CharacterW:
  254.     dc.l 0x22000220
  255.     dc.l 0x22000220
  256.     dc.l 0x22000220
  257.     dc.l 0x22020220
  258.     dc.l 0x22020220
  259.     dc.l 0x22020220
  260.     dc.l 0x22222220
  261.     dc.l 0x00000000
  262.    
  263. CharacterR:
  264.     dc.l 0x22222200
  265.     dc.l 0x22000220
  266.     dc.l 0x22000220
  267.     dc.l 0x22222200
  268.     dc.l 0x22022000
  269.     dc.l 0x22002200
  270.     dc.l 0x22000220
  271.     dc.l 0x00000000
  272.    
  273. CharacterD:
  274.     dc.l 0x22222200
  275.     dc.l 0x22002220
  276.     dc.l 0x22000220
  277.     dc.l 0x22000220
  278.     dc.l 0x22000220
  279.     dc.l 0x22002220
  280.     dc.l 0x22222200
  281.     dc.l 0x00000000
  282.    
  283. ; Font glyph tile IDs
  284. tile_id_space   equ 0x0
  285. tile_id_h       equ 0x1
  286. tile_id_e       equ 0x2
  287. tile_id_l       equ 0x3
  288. tile_id_o       equ 0x4
  289. tile_id_w       equ 0x5
  290. tile_id_r       equ 0x6
  291. tile_id_d       equ 0x7
  292.    
  293. ;==============================================================
  294.  
  295. ; Memory map (named offsets from start of RAM)
  296.     rsset 0x00FFE000
  297. ram_vscroll         rs.w 1  ; Current value of vscroll (1 word)
  298. ram_hscroll         rs.w 1  ; Current value of hscroll (1 word)
  299.  
  300. ;==============================================================
  301.  
  302.     ; The "main()" function
  303. CPU_EntryPoint:
  304.  
  305.     ;==============================================================
  306.     ; Initialise the Mega Drive
  307.     ;==============================================================
  308.  
  309.     ; Write the TMSS signature (if a model 1+ Mega Drive)
  310.     jsr VDP_WriteTMSS
  311.    
  312.     ; Load the initial VDP registers
  313.     jsr VDP_LoadRegisters
  314.    
  315.     ;==============================================================
  316.     ; Initialise variables in RAM
  317.     ;==============================================================
  318.     move.w #0x0, ram_vscroll
  319.     move.w #0x0, ram_hscroll
  320.    
  321.     ;==============================================================
  322.     ; Initialise status register and set interrupt level
  323.     ;==============================================================
  324.     move.w #0x2300, sr
  325.    
  326.     ;==============================================================
  327.     ; Write a palette to colour memory
  328.     ;==============================================================
  329.    
  330.     ; Setup the VDP to write to CRAM address 0x0000 (first palette)
  331.     SetCRAMWrite 0x0000
  332.    
  333.     ; Write the palette
  334.     move.l #Palette, a0             ; Move palette address to a0
  335.     move.w #size_palette_l-1, d0    ; Loop counter = 8 words in palette (-1 for DBRA loop)
  336.     @PalLp:                         ; Start of loop
  337.     move.w (a0)+, vdp_data          ; Write palette entry, post-increment address
  338.     dbra d0, @PalLp                 ; Decrement d0 and loop until finished (when d0 reaches -1)
  339.    
  340.     ;==============================================================
  341.     ; Write the font to tile memory
  342.     ;==============================================================
  343.    
  344.     ; Setup the VDP to write to VRAM address 0x0000 (the address of the first graphics tile)
  345.     SetVRAMWrite 0x0000
  346.    
  347.     ; Write the font glyphs
  348.     move.l #CharacterSpace, a0                  ; Move the address of the first graphics tile into a0
  349.     move.w #(num_font_glyphs*size_tile_l)-1, d0 ; Loop counter = 8 longwords per tile (-1 for DBRA loop)
  350.     @CharLp:                                    ; Start of loop
  351.     move.l (a0)+, vdp_data                      ; Write tile line (4 bytes per line), post-increment address
  352.     dbra d0, @CharLp                            ; Decrement d0 and loop until finished (when d0 reaches -1)
  353.    
  354.     ;==============================================================
  355.     ; Write the tile IDs of "HELLO WORLD" to Plane A
  356.     ;==============================================================
  357.    
  358.     ; Setup the VDP to write the tile ID at text_pos_x,text_pos_y (just the address in memory)
  359.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset)
  360.    
  361.     ; then move the character tile ID
  362.     move.w #tile_id_h, vdp_data ; H
  363.    
  364.     ; Repeat for the remaining characters in the string (remembering to offset the X coord each time)
  365.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+2)
  366.     move.w #tile_id_e, vdp_data     ; E
  367.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+4)
  368.     move.w #tile_id_l, vdp_data     ; L
  369.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+6)
  370.     move.w #tile_id_l, vdp_data     ; L
  371.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+8)
  372.     move.w #tile_id_o, vdp_data     ; 0
  373.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+10)
  374.     move.w #tile_id_space, vdp_data ; SPACE
  375.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+12)
  376.     move.w #tile_id_w, vdp_data     ; W
  377.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+14)
  378.     move.w #tile_id_o, vdp_data     ; O
  379.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+16)
  380.     move.w #tile_id_r, vdp_data     ; R
  381.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+18)
  382.     move.w #tile_id_l, vdp_data     ; L
  383.     SetVRAMWrite ((text_pos_y_offset<<8)|text_pos_x_offset+20)
  384.     move.w #tile_id_d, vdp_data     ; D
  385.    
  386.     ;==============================================================
  387.     ; Loop forever
  388.     ;==============================================================
  389.     @InfiniteLp:
  390.     bra @InfiniteLp
  391.    
  392. ;==============================================================
  393.  
  394. INT_VBlank:
  395.  
  396.     ; Backup any registers we're about to use to the stack
  397.     move.l d0, -(sp)
  398.     move.l d1, -(sp)
  399.    
  400.     ; Fetch current values of VSCROLL and HSCROLL from RAM
  401.     move.w (ram_vscroll), d0
  402.     move.w (ram_hscroll), d1
  403.    
  404.     ; Increment values
  405.     add.w  #0x1, d0
  406.     add.w  #0x1, d1
  407.    
  408.     ; Store back in RAM
  409.     move.w d0, ram_vscroll
  410.     move.w d1, ram_hscroll
  411.    
  412.     ; Setup VDP to write to HSCROLL (it's at VRAM address 0xFC00) and write the word
  413.     SetVRAMWrite vram_addr_hscroll
  414.     move.w d1, vdp_data
  415.    
  416.     ; Setup VDP to write to VSCROLL (it has its own dedicated memory, so use the VSRAM macro) and write the word
  417.     SetVSRAMWrite 0x0000
  418.     move.w d0, vdp_data
  419.    
  420.     ; Restore registers from stack (in reverse order)
  421.     move.l (sp)+, d1
  422.     move.l (sp)+, d0
  423.    
  424.     rte
  425.  
  426. INT_HBlank:
  427.     rte
  428.  
  429. INT_Null:
  430.     rte
  431.  
  432. CPU_Exception:
  433.     stop   #0x2700
  434.     rte
  435.    
  436. ;==============================================================
  437.    
  438. VDP_WriteTMSS:
  439.  
  440.     move.b hardware_ver_address, d0         ; Move Megadrive hardware version to d0
  441.     andi.b #0x0F, d0                        ; The version is stored in last four bits, so mask it with 0F
  442.     beq @Skip                               ; If version is equal to 0, skip TMSS signature
  443.     move.l #tmss_signature, tmss_address    ; Move the string "SEGA" to 0xA14000
  444.     @Skip:
  445.  
  446.     ; Check VDP
  447.     move.w vdp_control, d0                  ; Read VDP status register (hangs if no access)
  448.    
  449.     rts
  450.    
  451. VDP_LoadRegisters:
  452.  
  453.     ; Set VDP registers
  454.     move.l #VDPRegisters, a0    ; Load address of register init table into a0
  455.     move.w #0x17, d0            ; 24 registers to write (-1 for loop counter)
  456.     move.w #0x8000, d1          ; 'Set register 0' command
  457.  
  458.     @CopyVDP:
  459.     move.b (a0)+, d1            ; Move register value to lower byte of d1
  460.     move.w d1, vdp_control      ; Write command and value to VDP control port
  461.     add.w  #0x0100, d1          ; Increment register #
  462.     dbra   d0, @CopyVDP
  463.    
  464.     rts
  465.    
  466. ROM_End
RAW Paste Data