megadrive_test2

changeset 0:ce1b05082ac4

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 14 Mar 2017 05:59:33 +0200
parents
children 2560a8be8cb8
files .hgignore Makefile megadrive.ldscript src/intr.s src/main.c src/romhdr.S src/startup.s src/vdp.c src/vdp.h
diffstat 9 files changed, 449 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Tue Mar 14 05:59:33 2017 +0200
     1.3 @@ -0,0 +1,6 @@
     1.4 +\.o$
     1.5 +\.swp$
     1.6 +\.d$
     1.7 +\.map$
     1.8 +\.elf$
     1.9 +\.bin$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Tue Mar 14 05:59:33 2017 +0200
     2.3 @@ -0,0 +1,51 @@
     2.4 +csrc = $(wildcard src/*.c) $(wildcard src/libc/*.c)
     2.5 +asrc = $(wildcard src/*.s)
     2.6 +aSsrc = $(wildcard src/*.S)
     2.7 +obj = $(asrc:.s=.o) $(aSsrc:.S=.o) $(csrc:.c=.o)
     2.8 +
     2.9 +name = test2
    2.10 +elf = $(name).elf
    2.11 +bin = $(name).bin
    2.12 +
    2.13 +warn = -pedantic -Wall
    2.14 +dbg = -g
    2.15 +def = -DGAMENAME=\"testgame\" -DVERSTR=\"01\" -D__NO_CTYPE
    2.16 +inc = -Isrc/libc
    2.17 +
    2.18 +tool_prefix = m68k-linux-gnu-
    2.19 +
    2.20 +CC = $(tool_prefix)gcc
    2.21 +AS = $(tool_prefix)as
    2.22 +LD = $(tool_prefix)ld
    2.23 +OBJCOPY = $(tool_prefix)objcopy
    2.24 +
    2.25 +CFLAGS = -m68000 -ffreestanding -fno-builtin $(warn) $(dbg) $(opt) $(def) $(inc)
    2.26 +CPPFLAGS = $(def)
    2.27 +ASFLAGS = -m68000
    2.28 +LDFLAGS = -T megadrive.ldscript -print-gc-sections \
    2.29 +		  -L/usr/lib/gcc-cross/m68k-linux-gnu/6 -lgcc
    2.30 +
    2.31 +$(bin): $(elf)
    2.32 +	$(OBJCOPY) -O binary $< $@
    2.33 +
    2.34 +$(elf): $(obj)
    2.35 +	$(LD) -o $@ $(obj) -Map link.map $(LDFLAGS)
    2.36 +
    2.37 +.PHONY: clean
    2.38 +clean:
    2.39 +	rm -f $(obj) $(elf) $(bin)
    2.40 +
    2.41 +.PHONY: run
    2.42 +run: $(bin)
    2.43 +	gens-sdl $<
    2.44 +
    2.45 +.PHONY: copy
    2.46 +copy: $(bin)
    2.47 +	mount /media/usbmass && cp $(bin) /media/usbmass/$(bin)
    2.48 +	umount /media/usbmass
    2.49 +
    2.50 +.PHONY: install
    2.51 +install: $(bin)
    2.52 +	mount /media/usbmass
    2.53 +	[ -f /media/usbmass/MEGA/MEGA.RBF ] || cp $(bin) /media/usbmass/MEGA/MEGA.BIN
    2.54 +	umount /media/usbmass
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/megadrive.ldscript	Tue Mar 14 05:59:33 2017 +0200
     3.3 @@ -0,0 +1,47 @@
     3.4 +OUTPUT_ARCH(m68k)
     3.5 +
     3.6 +MEMORY
     3.7 +{
     3.8 +	rom : ORIGIN = 0x00000000, LENGTH = 0x00a00000
     3.9 +	ram : ORIGIN = 0x00ff0000, LENGTH = 0x00010000
    3.10 +}
    3.11 +
    3.12 +PROVIDE (_stacktop = 0x01000000);
    3.13 +
    3.14 +SECTIONS {
    3.15 +	/* ---- start of ROM ---- */
    3.16 +	/* .vect section is used to place the m68k exception vectors at the
    3.17 +	 * beginning of the address space
    3.18 +	 */
    3.19 +	.vect : { * (.vect); } >rom
    3.20 +	/* .romhdr section is used to place the SEGA ROM header at 0x100 */
    3.21 +	. = 0x100;
    3.22 +	.romhdr : { * (.romhdr); } >rom
    3.23 +	.text : { * (.text); } >rom
    3.24 +	.rodata : { * (.rodata); } >rom
    3.25 +
    3.26 +	/* place the load address of the .data section after .rodata */
    3.27 +	. = ALIGN(4);
    3.28 +	_data_lma = .;
    3.29 +	_rom_end = _data_lma + _data_size;
    3.30 +
    3.31 +	/* ---- start of RAM ---- */
    3.32 +	. = 0xff0000;
    3.33 +	/* place the .data section at the start of RAM */
    3.34 +	.data ALIGN(4): AT (_data_lma) {
    3.35 +		_data_start = .;
    3.36 +		* (.data);
    3.37 +		. = ALIGN(4);
    3.38 +		_data_end = .;
    3.39 +	} >ram
    3.40 +	_data_size = SIZEOF(.data);
    3.41 +
    3.42 +	/* place the .bss section at the end */
    3.43 +	.bss ALIGN(4): {
    3.44 +		_bss_start = .;
    3.45 +		* (.bss);
    3.46 +		. = ALIGN(4);
    3.47 +		_bss_end = .;
    3.48 +	} >ram
    3.49 +	_bss_size = SIZEOF(.bss);
    3.50 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/intr.s	Tue Mar 14 05:59:33 2017 +0200
     4.3 @@ -0,0 +1,82 @@
     4.4 +| the following will go into the .vect section which will be placed at the very
     4.5 +| begining of the binary at address 0 by the linker (see lnkscript).
     4.6 +	.section .vect,"a"
     4.7 +	.extern start
     4.8 +| exception vectors
     4.9 +	.long _stacktop		| 00 reset - initial SSP
    4.10 +	.long start		| 01 reset - initial PC
    4.11 +	.long intr_fatal	| 02 bus error
    4.12 +	.long intr_fatal	| 03 address error
    4.13 +	.long intr_fatal	| 04 illegal instruction
    4.14 +	.long intr_fatal	| 05 zero divide
    4.15 +	.long intr_fatal	| 06 chk instruction
    4.16 +	.long intr_fatal	| 07 trapv instruction
    4.17 +	.long intr_fatal	| 08 privilege violation
    4.18 +	.long intr_fatal	| 09 trace
    4.19 +	.long intr_fatal	| 0a line 1010 emulator
    4.20 +	.long intr_fatal	| 0b line 1111 emulator
    4.21 +	.long intr_fatal	| 0c reserved
    4.22 +	.long intr_fatal	| 0d reserved
    4.23 +	.long intr_fatal	| 0e format error (mc68010 only)
    4.24 +	.long intr_fatal	| 0f uninitialized interrupt vector
    4.25 +	.long intr_fatal	| 10 \
    4.26 +	.long intr_fatal	| 11 |
    4.27 +	.long intr_fatal	| 12 |
    4.28 +	.long intr_fatal	| 13  > reserved
    4.29 +	.long intr_fatal	| 14 |
    4.30 +	.long intr_fatal	| 15 |
    4.31 +	.long intr_fatal	| 16 |
    4.32 +	.long intr_fatal	| 17 /
    4.33 +	.long intr_fatal	| 18 spurious interrupt 
    4.34 +	.long intr_fatal	| 19 level 1 interrupt
    4.35 +	.long intr_fatal	| 1a level 2 interrupt
    4.36 +	.long intr_fatal	| 1b level 3 interrupt
    4.37 +	.long intr_hblank	| 1c level 4 interrupt (hblank in the mega drive)
    4.38 +	.long intr_fatal	| 1d level 5 interrupt
    4.39 +	.long intr_vblank	| 1e level 6 interrupt (vblank in the mega drive)
    4.40 +	.long intr_fatal	| 1f level 7 interrupt
    4.41 +	.long intr_fatal	| 20 trap 0
    4.42 +	.long intr_fatal	| 21 trap 1
    4.43 +	.long intr_fatal	| 22 trap 2
    4.44 +	.long intr_fatal	| 23 trap 3
    4.45 +	.long intr_fatal	| 24 trap 4
    4.46 +	.long intr_fatal	| 25 trap 5
    4.47 +	.long intr_fatal	| 26 trap 6
    4.48 +	.long intr_fatal	| 27 trap 7
    4.49 +	.long intr_fatal	| 28 trap 8
    4.50 +	.long intr_fatal	| 29 trap 9
    4.51 +	.long intr_fatal	| 2a trap a
    4.52 +	.long intr_fatal	| 2b trap b
    4.53 +	.long intr_fatal	| 2c trap c
    4.54 +	.long intr_fatal	| 2d trap d
    4.55 +	.long intr_fatal	| 2e trap e
    4.56 +	.long intr_fatal	| 2f trap f
    4.57 +	.long intr_fatal	| 30 \
    4.58 +	.long intr_fatal	| 31 |
    4.59 +	.long intr_fatal	| 32 |
    4.60 +	.long intr_fatal	| 33 |
    4.61 +	.long intr_fatal	| 34 |
    4.62 +	.long intr_fatal	| 35 |
    4.63 +	.long intr_fatal	| 36 |
    4.64 +	.long intr_fatal	| 37 |
    4.65 +	.long intr_fatal	| 38  > reserved
    4.66 +	.long intr_fatal	| 39 |
    4.67 +	.long intr_fatal	| 3a |
    4.68 +	.long intr_fatal	| 3b |
    4.69 +	.long intr_fatal	| 3c |
    4.70 +	.long intr_fatal	| 3d |
    4.71 +	.long intr_fatal	| 3e |
    4.72 +	.long intr_fatal	| 3f /
    4.73 +
    4.74 +| from here on we continue in the regular .text section since we don't care
    4.75 +| where this code ends up.
    4.76 +	.text
    4.77 +| interrupt handlers
    4.78 +intr_fatal:
    4.79 +	stop #0x2700
    4.80 +
    4.81 +| TODO hblank/vblank code
    4.82 +intr_hblank:
    4.83 +	rte
    4.84 +intr_vblank:
    4.85 +	rte
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/main.c	Tue Mar 14 05:59:33 2017 +0200
     5.3 @@ -0,0 +1,13 @@
     5.4 +#include "vdp.h"
     5.5 +
     5.6 +int main(void)
     5.7 +{
     5.8 +	vdp_init();
     5.9 +
    5.10 +	vdp_set_pal_entry(0, 1, 7, 0, 3);
    5.11 +	vdp_set_bgcolor(0, 1);
    5.12 +
    5.13 +	for(;;);
    5.14 +
    5.15 +	return 0;
    5.16 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/romhdr.S	Tue Mar 14 05:59:33 2017 +0200
     6.3 @@ -0,0 +1,37 @@
     6.4 +| the following will go into the custom .romhdr section which will be placed at
     6.5 +| address 100h of the binary by the linker (see lnkscript).
     6.6 +	.section .romhdr,"a"
     6.7 +
     6.8 +#ifndef GAMENAME
     6.9 +#define GAMENAME "unnamed"
    6.10 +#endif
    6.11 +#ifndef VERSTR
    6.12 +#define VERSTR "00"
    6.13 +#endif
    6.14 +
    6.15 +	.ascii "SEGA MEGA DRIVE (C)MINDLAPSE2017"
    6.16 +hdr_game_dom:
    6.17 +	.ascii GAMENAME
    6.18 +hdr_game_dom_end:
    6.19 +	.fill 48 - (hdr_game_dom_end - hdr_game_dom),1,32 | pad to 48 bytes with spaces
    6.20 +hdr_game_int:
    6.21 +	.ascii GAMENAME
    6.22 +hdr_game_int_end:
    6.23 +	.fill 48 - (hdr_game_int_end - hdr_game_int),1,32 | pad to 48 bytes with spaces
    6.24 +	.ascii "GM"		| it's a game (who cares what it is?)
    6.25 +	.ascii "0000000-"	| product code
    6.26 +	.ascii VERSTR		| version string
    6.27 +	.short 0		| checksum
    6.28 +	.ascii "J               " | I/O support (joypad)
    6.29 +	.long 0			| start address of ROM
    6.30 +	.long _rom_end		| last address of ROM
    6.31 +	.long 0xff0000		| start address of RAM
    6.32 +	.long 0xffffff		| last address of RAM
    6.33 +	.long 0			| SRAM enabled(?)
    6.34 +	.long 0			| ???
    6.35 +	.long 0			| start address of SRAM
    6.36 +	.long 0			| last address of SRAM
    6.37 +	.long 0			| ???
    6.38 +	.long 0			| ???
    6.39 +	.fill 40,1,32		| notes (fill with spaces for now TODO)
    6.40 +	.ascii "JUE             " | country codes
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/startup.s	Tue Mar 14 05:59:33 2017 +0200
     7.3 @@ -0,0 +1,47 @@
     7.4 +	.text
     7.5 +	.extern main
     7.6 +
     7.7 +	.global start
     7.8 +	.global halt_cpu
     7.9 +start:
    7.10 +	bsr.s disable_intr
    7.11 +
    7.12 +	| copy .data section from ROM to RAM
    7.13 +	move.l #_data_lma, %a0
    7.14 +	move.l #_data_start, %a1
    7.15 +	move.l #_data_end, %a2
    7.16 +	cmp.l %a1, %a2
    7.17 +	beq.s 1f	| skip data copy if the section is empty
    7.18 +0:	move.l (%a0)+, (%a1)+
    7.19 +	cmp.l %a1, %a2
    7.20 +	bne.s 0b
    7.21 +1:
    7.22 +
    7.23 +	| zero the .bss section
    7.24 +	move.l #_bss_start, %a0
    7.25 +	move.l #_bss_end, %a1
    7.26 +	cmp.l %a0, %a1
    7.27 +	beq.s 1f	| skip bss zeroing if the section is empty
    7.28 +0:	clr.l (%a0)+
    7.29 +	cmp.l %a0, %a1
    7.30 +	bne.s 0b
    7.31 +1:
    7.32 +
    7.33 +	| setup the stack pointer stack
    7.34 +	move.l #_stacktop, %sp
    7.35 +	| now that we have a stack, we can enable interrupts
    7.36 +	bsr.s enable_intr
    7.37 +
    7.38 +	jsr main
    7.39 +halt_cpu:
    7.40 +	stop #0x2700
    7.41 +
    7.42 +.global enable_intr
    7.43 +enable_intr:
    7.44 +	andi.w #0xf8ff, %sr
    7.45 +	rts
    7.46 +
    7.47 +.global disable_intr
    7.48 +disable_intr:
    7.49 +	ori.w #0x0300, %sr
    7.50 +	rts
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/vdp.c	Tue Mar 14 05:59:33 2017 +0200
     8.3 @@ -0,0 +1,9 @@
     8.4 +#include "vdp.h"
     8.5 +
     8.6 +void vdp_init(void)
     8.7 +{
     8.8 +	vdp_setreg(VDP_REG_MODE1, VDP_MODE1_BASE);
     8.9 +	vdp_setreg(VDP_REG_MODE2, VDP_MODE2_BASE | VDP_MODE2_DISP);
    8.10 +
    8.11 +	vdp_set_autoinc(2);
    8.12 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/vdp.h	Tue Mar 14 05:59:33 2017 +0200
     9.3 @@ -0,0 +1,157 @@
     9.4 +#ifndef VDP_H_
     9.5 +#define VDP_H_
     9.6 +
     9.7 +#include <stdint.h>
     9.8 +
     9.9 +#define VDP_PORT_DATA		*((volatile uint16_t*)0xc00000)
    9.10 +#define VDP_PORT_DATA32		*((volatile uint32_t*)0xc00000)
    9.11 +#define VDP_PORT_CTL		*((volatile uint16_t*)0xc00004)
    9.12 +#define VDP_PORT_CTL32		*((volatile uint32_t*)0xc00004)
    9.13 +#define VDP_PORT_HVCNT		*((volatile uint16_t*)0xc00008)
    9.14 +#define VDP_PORT_PSG		*((volatile uint16_t*)0xc00010)
    9.15 +
    9.16 +#define VDP_PORT_STATUS		*((volatile uint16_t*)0xc00004)
    9.17 +
    9.18 +enum {
    9.19 +	VDP_REG_MODE1			= 0,
    9.20 +	VDP_REG_MODE2			= 1,
    9.21 +	VDP_REG_NAMETAB_A		= 2,
    9.22 +	VDP_REG_NAMETAB_WIN		= 3,
    9.23 +	VDP_REG_NAMETAB_B		= 4,
    9.24 +	VDP_REG_SPRITE_TAB		= 5,
    9.25 +	VDP_REG_BGCOL			= 7,
    9.26 +	VDP_REG_INTR			= 10,
    9.27 +	VDP_REG_MODE3			= 11,
    9.28 +	VDP_REG_MODE4			= 12,
    9.29 +	VDP_REG_SCROLL_TAB		= 13,
    9.30 +	VDP_REG_AUTOINC			= 15,
    9.31 +	VDP_REG_SCROLL_SIZE		= 16,
    9.32 +	VDP_REG_WIN_XPOS		= 17,
    9.33 +	VDP_REG_WIN_YPOS		= 18,
    9.34 +	VDP_REG_DMA_LEN_LOW		= 19,
    9.35 +	VDP_REG_DMA_LEN_HIGH	= 20,
    9.36 +	VDP_REG_DMA_SRC_LOW		= 21,
    9.37 +	VDP_REG_DMA_SRC_MID		= 22,
    9.38 +	VDP_REG_DMA_SRC_HIGH	= 23,
    9.39 +
    9.40 +	VDP_NUM_REGS
    9.41 +};
    9.42 +
    9.43 +uint16_t vdp_reg_shadow[VDP_NUM_REGS];
    9.44 +
    9.45 +/* access VDP memory */
    9.46 +enum { VDP_MEM_READ, VDP_MEM_WRITE };
    9.47 +enum {
    9.48 +	VDP_MEM_VRAM	= 0,
    9.49 +	VDP_MEM_CRAM	= 0xa,	/* CD5->CD0: 0 0 r 0 w 0 */
    9.50 +	VDP_MEM_VSRAM	= 4		/* CD5->CD0: 0 0 0 1 0 0 */
    9.51 +};
    9.52 +
    9.53 +static inline void vdp_setup_access(uint16_t addr, int rw, int memid)
    9.54 +{
    9.55 +	uint32_t type;
    9.56 +	if(rw == VDP_MEM_WRITE) {
    9.57 +		type = (memid & 7) | 1;
    9.58 +	} else {
    9.59 +		type = memid & 0xc;
    9.60 +	}
    9.61 +
    9.62 +	VDP_PORT_CTL32 = (((uint32_t)addr & 0x3fff) << 16) | ((addr >> 14) & 3) |
    9.63 +		((type << 2) & 0xf0) | (type << 30);
    9.64 +}
    9.65 +
    9.66 +
    9.67 +/* mode register 1 */
    9.68 +enum {
    9.69 +	VDP_MODE1_BASE	= 0x4,
    9.70 +	VDP_MODE1_HVCNT = 0x2,
    9.71 +	VDP_MODE1_HINTR = 0x10
    9.72 +};
    9.73 +
    9.74 +/* mode register 2 */
    9.75 +enum {
    9.76 +	VDP_MODE2_BASE		= 0x4,
    9.77 +	VDP_MODE2_V30CELL	= 0x8,
    9.78 +	VDP_MODE2_DMA		= 0x10,
    9.79 +	VDP_MODE2_VINTR		= 0x20,
    9.80 +	VDP_MODE2_DISP		= 0x40
    9.81 +};
    9.82 +
    9.83 +/* mode register 3 */
    9.84 +enum {
    9.85 +	VDP_MODE3_BASE			= 0,
    9.86 +	VDP_MODE3_HSCROLL_CELL	= 2,
    9.87 +	VDP_MODE3_HSCROLL_LINE	= 3,
    9.88 +	VDP_MODE3_VSCROLL_2CELL	= 4,
    9.89 +	VDP_MODE3_EXTINTR		= 8
    9.90 +};
    9.91 +
    9.92 +/* mode register 4 */
    9.93 +enum {
    9.94 +	VDP_MODE4_BASE			= 0,
    9.95 +	VDP_MODE4_H40CELL		= 0x81,
    9.96 +	VDP_MODE4_ILACE			= 2,
    9.97 +	VDP_MODE4_ILACE_2XRES	= 6,
    9.98 +	VDP_MODE4_SH			= 8	/* shadow/highlight enable */
    9.99 +};
   9.100 +
   9.101 +/* scroll size register */
   9.102 +enum {
   9.103 +	VDP_SCROLL_H32		= 0,
   9.104 +	VDP_SCROLL_H64		= 1,
   9.105 +	VDP_SCROLL_H128		= 3,
   9.106 +	VDP_SCROLL_V32		= 0,
   9.107 +	VDP_SCROLL_V64		= 0x10,
   9.108 +	VDP_SCROLL_V128		= 0x30
   9.109 +};
   9.110 +
   9.111 +/* window X/Y position register */
   9.112 +enum {
   9.113 +	VDP_WIN_LEFT	= 0,
   9.114 +	VDP_WIN_UP		= 0,
   9.115 +	VDP_WIN_RIGHT	= 0x80,
   9.116 +	VDP_WIN_DOWN	= 0x80,
   9.117 +	VDP_WIN_POSMASK	= 0x1f
   9.118 +};
   9.119 +
   9.120 +#define VDP_PACK_RGB(r, g, b)	\
   9.121 +	((((uint16_t)(r) & 7) << 1) | (((uint16_t)(g) & 7) << 5) | (((uint16_t)(b) & 7) << 9))
   9.122 +
   9.123 +
   9.124 +static inline void vdp_setreg(int reg, uint8_t value)
   9.125 +{
   9.126 +	/*vdp_reg_shadow[reg] = value;*/
   9.127 +	VDP_PORT_CTL = (uint16_t)value | (reg << 8) | (uint16_t)0x8000;
   9.128 +}
   9.129 +
   9.130 +static inline uint16_t vdp_getreg(int reg)
   9.131 +{
   9.132 +	return vdp_reg_shadow[reg];
   9.133 +}
   9.134 +
   9.135 +static inline uint16_t vdp_status(void)
   9.136 +{
   9.137 +	return VDP_PORT_CTL;
   9.138 +}
   9.139 +
   9.140 +static inline void vdp_set_bgcolor(int palidx, int colidx)
   9.141 +{
   9.142 +	vdp_setreg(VDP_REG_BGCOL, (colidx & 0xf) | (palidx << 4));
   9.143 +}
   9.144 +
   9.145 +static inline void vdp_set_autoinc(int stride)
   9.146 +{
   9.147 +	vdp_setreg(VDP_REG_AUTOINC, stride);
   9.148 +}
   9.149 +
   9.150 +static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b)
   9.151 +{
   9.152 +	uint16_t paddr = (pidx << 5) | (cidx << 1);
   9.153 +
   9.154 +	vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
   9.155 +	VDP_PORT_DATA = VDP_PACK_RGB(r, g, b);
   9.156 +}
   9.157 +
   9.158 +void vdp_init(void);
   9.159 +
   9.160 +#endif	/* VDP_H_ */