Advertisement
Guest User

SEGA Mega Drive Hello World with Scroll - by BigEvilCorp.

a guest
Mar 3rd, 2018
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.03 KB | None | 0 0
  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 0x00FF0000
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement