initial commit
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Thu, 2 Feb 2017 04:35:54 +0000 (06:35 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Thu, 2 Feb 2017 04:35:54 +0000 (06:35 +0200)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
megadrive.ldscript [new file with mode: 0644]
src/intr.s [new file with mode: 0644]
src/macros.inc [new file with mode: 0644]
src/megadrive.c [new file with mode: 0644]
src/megadrive.h [new file with mode: 0644]
src/romhdr.S [new file with mode: 0644]
src/util.s [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..499a618
--- /dev/null
@@ -0,0 +1,2 @@
+*.o
+*.swp
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..1114931
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,38 @@
+csrc = $(wildcard src/*.c)
+asrc = $(wildcard src/*.s)
+aSsrc = $(wildcard src/*.S)
+obj = $(asrc:.s=.o) $(aSsrc:.S=.o) $(csrc:.c=.o)
+
+name = tetris
+elf = $(name).elf
+bin = $(name).bin
+
+warn = -pedantic -Wall
+dbg = -g
+def = -DGAMENAME=\"tetris\" -DVERSTR=\"01\"
+
+tool_prefix = m68k-linux-gnu-
+
+CC = $(tool_prefix)gcc
+AS = $(tool_prefix)as
+LD = $(tool_prefix)ld
+OBJCOPY = $(tool_prefix)objcopy
+
+CFLAGS = -m68000 -fno-builtin $(warn) $(dbg) $(opt) $(def)
+CPPFLAGS = $(def)
+ASFLAGS = -m68000 -Isrc
+LDFLAGS = -T megadrive.ldscript -print-gc-sections
+
+$(bin): $(elf)
+       $(OBJCOPY) -O binary $< $@
+
+$(elf): $(obj)
+       $(LD) -o $@ $(LDFLAGS) $(obj) -Map link.map
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(elf) $(bin)
+
+.PHONY: run
+run: $(bin)
+       gens-sdl $<
diff --git a/megadrive.ldscript b/megadrive.ldscript
new file mode 100644 (file)
index 0000000..dce3828
--- /dev/null
@@ -0,0 +1,47 @@
+OUTPUT_ARCH(m68k)
+
+MEMORY
+{
+       rom : ORIGIN = 0x00000000, LENGTH = 0x00a00000
+       ram : ORIGIN = 0x00ff0000, LENGTH = 0x00010000
+}
+
+PROVIDE (_stacktop = 0x01000000);
+
+SECTIONS {
+       /* ---- start of ROM ---- */
+       /* .vect section is used to place the m68k exception vectors at the
+        * beginning of the address space
+        */
+       .vect : { * (.vect); } >rom
+       /* .romhdr section is used to place the SEGA ROM header at 0x100 */
+       . = 0x100;
+       .romhdr : { * (.romhdr); } >rom
+       .text : { * (.text); } >rom
+       .rodata : { * (.rodata); } >rom
+
+       /* place the load address of the .data section after .rodata */
+       . = ALIGN(4);
+       _data_lma = .;
+       _rom_end = _data_lma + _data_size;
+
+       /* ---- start of RAM ---- */
+       . = 0xff0000;
+       /* place the .data section at the start of RAM */
+       .data ALIGN(4): AT (_data_lma) {
+               _data_start = .;
+               * (.data);
+               . = ALIGN(4);
+               _data_end = .;
+       } >ram
+       _data_size = SIZEOF(.data);
+
+       /* place the .bss section at the end */
+       .bss ALIGN(4): {
+               _bss_start = .;
+               * (.bss);
+               . = ALIGN(4);
+               _bss_end = .;
+       } >ram
+       _bss_size = SIZEOF(.bss);
+}
diff --git a/src/intr.s b/src/intr.s
new file mode 100644 (file)
index 0000000..485d251
--- /dev/null
@@ -0,0 +1,82 @@
+| the following will go into the .vect section which will be placed at the very
+| begining of the binary at address 0 by the linker (see lnkscript).
+       .section .vect,"a"
+       .extern start
+| exception vectors
+       .long _stacktop         | 00 reset - initial SSP
+       .long start             | 01 reset - initial PC
+       .long intr_fatal        | 02 bus error
+       .long intr_fatal        | 03 address error
+       .long intr_fatal        | 04 illegal instruction
+       .long intr_fatal        | 05 zero divide
+       .long intr_fatal        | 06 chk instruction
+       .long intr_fatal        | 07 trapv instruction
+       .long intr_fatal        | 08 privilege violation
+       .long intr_fatal        | 09 trace
+       .long intr_fatal        | 0a line 1010 emulator
+       .long intr_fatal        | 0b line 1111 emulator
+       .long intr_fatal        | 0c reserved
+       .long intr_fatal        | 0d reserved
+       .long intr_fatal        | 0e format error (mc68010 only)
+       .long intr_fatal        | 0f uninitialized interrupt vector
+       .long intr_fatal        | 10 \
+       .long intr_fatal        | 11 |
+       .long intr_fatal        | 12 |
+       .long intr_fatal        | 13  > reserved
+       .long intr_fatal        | 14 |
+       .long intr_fatal        | 15 |
+       .long intr_fatal        | 16 |
+       .long intr_fatal        | 17 /
+       .long intr_fatal        | 18 spurious interrupt 
+       .long intr_fatal        | 19 level 1 interrupt
+       .long intr_fatal        | 1a level 2 interrupt
+       .long intr_fatal        | 1b level 3 interrupt
+       .long intr_hblank       | 1c level 4 interrupt (hblank in the mega drive)
+       .long intr_fatal        | 1d level 5 interrupt
+       .long intr_vblank       | 1e level 6 interrupt (vblank in the mega drive)
+       .long intr_fatal        | 1f level 7 interrupt
+       .long intr_fatal        | 20 trap 0
+       .long intr_fatal        | 21 trap 1
+       .long intr_fatal        | 22 trap 2
+       .long intr_fatal        | 23 trap 3
+       .long intr_fatal        | 24 trap 4
+       .long intr_fatal        | 25 trap 5
+       .long intr_fatal        | 26 trap 6
+       .long intr_fatal        | 27 trap 7
+       .long intr_fatal        | 28 trap 8
+       .long intr_fatal        | 29 trap 9
+       .long intr_fatal        | 2a trap a
+       .long intr_fatal        | 2b trap b
+       .long intr_fatal        | 2c trap c
+       .long intr_fatal        | 2d trap d
+       .long intr_fatal        | 2e trap e
+       .long intr_fatal        | 2f trap f
+       .long intr_fatal        | 30 \
+       .long intr_fatal        | 31 |
+       .long intr_fatal        | 32 |
+       .long intr_fatal        | 33 |
+       .long intr_fatal        | 34 |
+       .long intr_fatal        | 35 |
+       .long intr_fatal        | 36 |
+       .long intr_fatal        | 37 |
+       .long intr_fatal        | 38  > reserved
+       .long intr_fatal        | 39 |
+       .long intr_fatal        | 3a |
+       .long intr_fatal        | 3b |
+       .long intr_fatal        | 3c |
+       .long intr_fatal        | 3d |
+       .long intr_fatal        | 3e |
+       .long intr_fatal        | 3f /
+
+| from here on we continue in the regular .text section since we don't care
+| where this code ends up.
+       .text
+| interrupt handlers
+intr_fatal:
+       stop #0x2700
+
+| TODO hblank/vblank code
+intr_hblank:
+       rte
+intr_vblank:
+       rte
diff --git a/src/macros.inc b/src/macros.inc
new file mode 100644 (file)
index 0000000..a6e2861
--- /dev/null
@@ -0,0 +1,16 @@
+| Assembly macros
+| ---------------
+
+| pseudosubroutines (leaf functions)
+| ----------------------------------
+       | call a leaf subroutine - use a6 for the reutrn address
+       .macro pseudo_call addr
+       move.l #0f, %a6         | a6 will hold the return address
+       jmp \addr
+0:
+       .endm
+
+       | return from a leaf subroutine
+       .macro pseudo_ret
+       jmp (%a6)               | a6 better not have changed!
+       .endm
diff --git a/src/megadrive.c b/src/megadrive.c
new file mode 100644 (file)
index 0000000..45bc414
--- /dev/null
@@ -0,0 +1,4 @@
+#include "megadrive.h"
+
+int current_piece = 0x270;
+int frame_delay = 50;
diff --git a/src/megadrive.h b/src/megadrive.h
new file mode 100644 (file)
index 0000000..37a8f95
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef MEGADRIVE_H_
+#define MEGADRIVE_H_
+
+#include <stdint.h>
+
+/* Macros for the joypad buttons */
+#define DPAD_UP                0
+#define DPAD_DOWN      1
+#define DPAD_LEFT      2
+#define DPAD_RIGHT     3
+#define DPAD_A         12
+#define DPAD_B         4
+#define DPAD_C         5
+#define DPAD_START     13
+
+uint16_t dpad0;
+uint16_t dpad0_prev;
+uint16_t dpad0_presses;
+uint16_t frame_buffer[2048];
+
+int current_piece = 0x270;
+int frame_delay = 50;
+int frame_countdown;
+int current_piece_x;
+int current_piece_y;
+
+int tetromino_shapes[8];
+int statistics[16];
+
+int last_spawned_piece_index;
+
+int16_t rng_state[2];
+
+int auto_repeat_countdown;
+
+
+static inline dpad0_pressed(uint16_t key)
+{
+       return !(dpad0 & (1 << key));
+}
+
+int32_t rng_next(int32_t s);
+
+static inline int rand(void)
+{
+       int32_t *s = (int32_t*)rng_state;
+       *s = rng_next(*s);
+       return ((*s) >> 24) & 0xff;
+}
+
+
+#endif /* MEGADRIVE_H_ */
diff --git a/src/romhdr.S b/src/romhdr.S
new file mode 100644 (file)
index 0000000..1c1dd4f
--- /dev/null
@@ -0,0 +1,37 @@
+| the following will go into the custom .romhdr section which will be placed at
+| address 100 of the binary by the linker (see lnkscript).
+       .section .romhdr,"a"
+
+#ifndef GAMENAME
+#define GAMENAME "unnamed"
+#endif
+#ifndef VERSTR
+#define VERSTR "00"
+#endif
+
+       .ascii "SEGA MEGA DRIVE (C)MINDLAPSE2017"
+hdr_game_dom:
+       .ascii GAMENAME
+hdr_game_dom_end:
+       .fill 48 - (hdr_game_dom_end - hdr_game_dom),1,32 | pad to 48 bytes with spaces
+hdr_game_int:
+       .ascii GAMENAME
+hdr_game_int_end:
+       .fill 48 - (hdr_game_int_end - hdr_game_int),1,32 | pad to 48 bytes with spaces
+       .ascii "GM"             | it's a game (who cares what it is?)
+       .ascii "0000000-"       | product code
+       .ascii VERSTR           | version string
+       .short 0                | checksum
+       .ascii "J               " | I/O support (joypad)
+       .long 0                 | start address of ROM
+       .long _rom_end          | last address of ROM
+       .long 0xff0000          | start address of RAM
+       .long 0xffffff          | last address of RAM
+       .long 0                 | SRAM enabled(?)
+       .long 0                 | ???
+       .long 0                 | start address of SRAM
+       .long 0                 | last address of SRAM
+       .long 0                 | ???
+       .long 0                 | ???
+       .fill 40,1,32           | notes (fill with spaces for now TODO)
+       .ascii "JUE             " | country codes
diff --git a/src/util.s b/src/util.s
new file mode 100644 (file)
index 0000000..7b500ef
--- /dev/null
@@ -0,0 +1,66 @@
+| ------------------------------------------------------------------------
+|  Utilities
+| ------------------------------------------------------------------------
+
+       .include "macros.inc"
+
+|  Random number generator
+| ------------------------------------------------------------------------
+
+| Seed random number generator, using a 32 bit seed stored in d0 (s0s1s2s3 high
+| to low bytes) This needn't be a pseudoroutine, but just for symmetry with the
+| following routine, we'll make it one
+       .text
+rng_seed:
+       move.b %d0, %d4
+       lsr.l #8, %d0
+       move.b %d0, %d5
+       lsr.l #8, %d0
+       move.b %d0, %d6
+       lsr.l #8, %d0
+       move.b %d0, %d7
+       pseudo_ret
+
+| Reverse of seed: it will collect the seed from registers d4-d7 to d0 
+rng_unseed:
+       move.b  %d7, %d0
+       lsl.l   #8, %d0
+       move.b  %d6, %d0
+       lsl.l   #8, %d0
+       move.b  %d5, %d0
+       lsl.l   #8, %d0
+       move.b  %d4, %d0
+       lsl.l   #8, %d0
+       pseudo_ret
+       
+| Calculate next random number, it will be stored in the low byte of d7
+rng_calc_next:
+       add.l #1, %d4
+       eor.b %d7, %d5
+       eor.b %d4, %d5
+       add.b %d5, %d6
+       
+       lsl.w #8, %d4   | Hack  - shift d4 to the left, so we can use its 8 LSB for storing the intermediate value
+       move.b %d6, %d4 |               - Tmp store d6
+       lsr.b #1, %d4   |               - This will produce d6>>1 in the LSB
+       
+       add.b %d4, %d7  | Yup! I remebered it!
+       
+       lsr.w #8, %d4   | Hack  - Revert d4 to what it was before
+       
+       eor.b %d5, %d7
+       pseudo_ret
+
+| Function exposed to C - 1 longword argument
+       .global rng_next
+rng_next:
+       link %fp, #0
+       movem %d2-%d7/%a2-%a5, -(%sp)
+       move.l  8(%fp), %d0
+       pseudo_call rng_seed
+       pseudo_call rng_calc_next
+       pseudo_call rng_unseed
+       movem (%sp)+, %d2-%d7/%a2-%a5
+       unlk %fp
+       rts
+