Creating hexed from nshtest
authornotaz <notasas@gmail.com>
Mon, 16 Mar 2009 20:31:27 +0000 (20:31 +0000)
committernotaz <notasas@gmail.com>
Mon, 16 Mar 2009 20:31:27 +0000 (20:31 +0000)
hexed/Makefile [new file with mode: 0644]
hexed/md.ld [new file with mode: 0644]
hexed/sega_gcc.s [new file with mode: 0644]
hexed/test.s [new file with mode: 0644]

diff --git a/hexed/Makefile b/hexed/Makefile
new file mode 100644 (file)
index 0000000..bfe4a04
--- /dev/null
@@ -0,0 +1,21 @@
+CROSS = m68k-elf-\r
+AS = $(CROSS)as\r
+LD = $(CROSS)ld\r
+OBJCOPY = $(CROSS)objcopy\r
+\r
+ASFLAGS = -m68000 --register-prefix-optional --bitwise-or \r
+\r
+TARGET = nshtest.bin\r
+OBJS = sega_gcc.o test.o\r
+\r
+all : $(TARGET)\r
+\r
+$(TARGET) : a.out\r
+       $(OBJCOPY) -I elf32-m68k -O binary $^ $@\r
+\r
+a.out : $(OBJS)\r
+       $(LD) -Tmd.ld -Map $(TARGET).map $^\r
+\r
+clean:\r
+       $(RM) $(TARGET) $(OBJS) $(TARGET).map a.out\r
+\r
diff --git a/hexed/md.ld b/hexed/md.ld
new file mode 100644 (file)
index 0000000..208bfa7
--- /dev/null
@@ -0,0 +1,122 @@
+OUTPUT_ARCH(m68k)\r
+SEARCH_DIR(.)\r
+/*GROUP(-lbcc -lc -lgcc)*/\r
+__DYNAMIC  =  0;\r
+\r
+/*\r
+ * Setup the memory map of the SEGA Genesis.\r
+ * stack grows down from high memory.\r
+ *\r
+ * The memory map look like this:\r
+ * +--------------------+ <- low memory\r
+ * | .text              |\r
+ * |        _etext      |\r
+ * |        ctor list   | the ctor and dtor lists are for\r
+ * |        dtor list   | C++ support\r
+ * +--------------------+\r
+ * | .data              | initialized data goes here\r
+ * |        _edata      |\r
+ * +--------------------+\r
+ * | .bss               |\r
+ * |        __bss_start | start of bss, cleared by crt0\r
+ * |        _end        | start of heap, used by sbrk()\r
+ * +--------------------+\r
+ * .                    .\r
+ * .                    .\r
+ * .                    .\r
+ * |        __stack     | top of stack\r
+ * +--------------------+\r
+ */\r
+/*\r
+MEMORY\r
+{\r
+  rom     : ORIGIN = 0x00000000, LENGTH = 0x00400000\r
+  ram     : ORIGIN = 0xffff0000, LENGTH = 0x00010000\r
+}\r
+*/\r
+\r
+MEMORY {\r
+       ram : ORIGIN = 0x0, LENGTH = 0xfffffff\r
+}\r
+\r
+/*\r
+ * allocate the stack to be at the top of memory, since the stack\r
+ * grows down\r
+ */\r
+\r
+PROVIDE (__stack = 0x00fffff0);\r
+\r
+PROVIDE (ram = 0xffff0000);\r
+/*\r
+ * Initalize some symbols to be zero so we can reference them in the\r
+ * crt0 without core dumping. These functions are all optional, but\r
+ * we do this so we can have our crt0 always use them if they exist. \r
+ * This is so BSPs work better when using the crt0 installed with gcc.\r
+ * We have to initalize them twice, so we cover a.out (which prepends\r
+ * an underscore) and coff object file formats.\r
+ */\r
+PROVIDE (hardware_init_hook = 0);\r
+PROVIDE (_hardware_init_hook = 0);\r
+PROVIDE (software_init_hook = 0);\r
+PROVIDE (_software_init_hook = 0);\r
+\r
+SECTIONS\r
+{\r
+  .text 0x00000000:\r
+  {\r
+    *(.text)\r
+    . = ALIGN(0x4);\r
+     __CTOR_LIST__ = .;\r
+    LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)\r
+    *(.ctors)\r
+    LONG(0)\r
+    __CTOR_END__ = .;\r
+    __DTOR_LIST__ = .;\r
+    LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)\r
+    *(.dtors)\r
+     LONG(0)\r
+    __DTOR_END__ = .;\r
+    *(.rodata)\r
+    *(.gcc_except_table) \r
+\r
+    __INIT_SECTION__ = . ;\r
+    *(.init)\r
+    SHORT (0x4e75)     /* rts */\r
+\r
+    __FINI_SECTION__ = . ;\r
+    *(.fini)\r
+    SHORT (0x4e75)     /* rts */\r
+\r
+    _etext = .;\r
+    *(.lit)\r
+  } > ram\r
+\r
+  .data BLOCK (0x4) :\r
+  {\r
+    *(.shdata)\r
+    *(.data)\r
+    _edata = .;\r
+  } > ram\r
+\r
+  .bss 0xff0000 :\r
+  {\r
+    __bss_start = . ;\r
+    *(.shbss)\r
+    *(.bss)\r
+    *(COMMON)\r
+    *(.eh_fram)\r
+    *(.eh_frame)\r
+    _end =  ALIGN (0x8);\r
+    __end = _end;\r
+  } > ram\r
+\r
+  .stab 0 (NOLOAD) :\r
+  {\r
+    *(.stab)\r
+  }\r
+\r
+  .stabstr 0 (NOLOAD) :\r
+  {\r
+    *(.stabstr)\r
+  }\r
+}\r
diff --git a/hexed/sega_gcc.s b/hexed/sega_gcc.s
new file mode 100644 (file)
index 0000000..a295692
--- /dev/null
@@ -0,0 +1,443 @@
+*-------------------------------------------------------\r
+*\r
+*       Sega startup code for the GNU Assembler\r
+*       Translated from:\r
+*       Sega startup code for the Sozobon C compiler\r
+*       Written by Paul W. Lee\r
+*       Modified from Charles Coty's code\r
+*\r
+*-------------------------------------------------------\r
+\r
+        dc.l 0x0,0x200\r
+        dc.l INT,INT,INT,INT,INT,INT,INT\r
+        dc.l INT,INT,INT,INT,INT,INT,INT,INT\r
+        dc.l INT,INT,INT,INT,INT,INT,INT,INT\r
+        dc.l INT,INT,INT,HBL,INT,VBL,INT,INT\r
+        dc.l INT,INT,INT,INT,INT,INT,INT,INT\r
+        dc.l INT,INT,INT,INT,INT,INT,INT,INT\r
+        dc.l INT,INT,INT,INT,INT,INT,INT,INT\r
+        dc.l INT,INT,INT,INT,INT,INT,INT\r
+        .ascii "SEGA GENESIS                    "\r
+        .ascii "notaz's Shadow / Hilight test                   "\r
+        .ascii "NOTAZ'S SHADOW HILIGHT TEST                     "\r
+        .ascii "GM 00000000-00"\r
+        .byte 0xa5,0xfb\r
+        .ascii "JD              "\r
+        .byte 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00\r
+        .byte 0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff\r
+        .ascii "               "\r
+        .ascii "                        "\r
+        .ascii "                         "\r
+        .ascii "JUE             "\r
+*debugee:\r
+*        bra     debugee\r
+        tst.l   0xa10008\r
+       bne     SkipJoyDetect                               \r
+        tst.w   0xa1000c\r
+SkipJoyDetect:\r
+       bne     SkipSetup\r
+        lea     Table,%a5                       \r
+        movem.w (%a5)+,%d5-%d7\r
+        movem.l (%a5)+,%a0-%a4                       \r
+* Check Version Number                      \r
+        move.b  -0x10ff(%a1),%d0\r
+        andi.b  #0x0f,%d0                             \r
+       beq     WrongVersion                                   \r
+* Sega Security Code (SEGA)   \r
+        move.l  #0x53454741,0x2f00(%a1)\r
+WrongVersion:\r
+        move.w  (%a4),%d0\r
+        moveq   #0x00,%d0                                \r
+        movea.l %d0,%a6                                  \r
+        move    %a6,%usp\r
+* Set VDP registers\r
+        moveq   #0x17,%d1\r
+FillLoop:                           \r
+        move.b  (%a5)+,%d5\r
+        move.w  %d5,(%a4)                              \r
+        add.w   %d7,%d5                                 \r
+        dbra    %d1,FillLoop                           \r
+        move.l  (%a5)+,(%a4)                            \r
+        move.w  %d0,(%a3)                                 \r
+        move.w  %d7,(%a1)                                 \r
+        move.w  %d7,(%a2)                                 \r
+L0250:\r
+        btst    %d0,(%a1)\r
+       bne     L0250                                   \r
+* Put initial values into a00000                \r
+        moveq   #0x25,%d2\r
+Filla:                                 \r
+        move.b  (%a5)+,(%a0)+\r
+        dbra    %d2,Filla\r
+        move.w  %d0,(%a2)                                 \r
+        move.w  %d0,(%a1)                                 \r
+        move.w  %d7,(%a2)                                 \r
+L0262:\r
+        move.l  %d0,-(%a6)\r
+        dbra    %d6,L0262                            \r
+        move.l  (%a5)+,(%a4)                              \r
+        move.l  (%a5)+,(%a4)                              \r
+* Put initial values into c00000                  \r
+        moveq   #0x1f,%d3\r
+Filc0:                             \r
+        move.l  %d0,(%a3)\r
+        dbra    %d3,Filc0\r
+        move.l  (%a5)+,(%a4)                              \r
+* Put initial values into c00000                 \r
+        moveq   #0x13,%d4\r
+Fillc1:                            \r
+        move.l  %d0,(%a3)\r
+        dbra    %d4,Fillc1\r
+* Put initial values into c00011                 \r
+        moveq   #0x03,%d5\r
+Fillc2:                            \r
+        move.b  (%a5)+,0x0011(%a3)        \r
+        dbra    %d5,Fillc2                            \r
+        move.w  %d0,(%a2)                                 \r
+        movem.l (%a6),%d0-%d7/%a0-%a6                    \r
+        move    #0x2700,%sr                           \r
+SkipSetup:\r
+       bra     Continue\r
+Table:\r
+        dc.w    0x8000, 0x3fff, 0x0100, 0x00a0, 0x0000, 0x00a1, 0x1100, 0x00a1\r
+        dc.w    0x1200, 0x00c0, 0x0000, 0x00c0, 0x0004, 0x0414, 0x302c, 0x0754\r
+        dc.w    0x0000, 0x0000, 0x0000, 0x812b, 0x0001, 0x0100, 0x00ff, 0xff00                                   \r
+        dc.w    0x0080, 0x4000, 0x0080, 0xaf01, 0xd91f, 0x1127, 0x0021, 0x2600\r
+        dc.w    0xf977, 0xedb0, 0xdde1, 0xfde1, 0xed47, 0xed4f, 0xd1e1, 0xf108                                   \r
+        dc.w    0xd9c1, 0xd1e1, 0xf1f9, 0xf3ed, 0x5636, 0xe9e9, 0x8104, 0x8f01                \r
+        dc.w    0xc000, 0x0000, 0x4000, 0x0010, 0x9fbf, 0xdfff                                \r
+\r
+Continue:\r
+        tst.w    0x00C00004\r
+\r
+* set stack pointer\r
+*        clr.l   %a7\r
+        move.w   #0,%a7\r
+\r
+* user mode\r
+        move.w  #0x2300,%sr\r
+\r
+* clear Genesis RAM\r
+        lea     0xff0000,%a0\r
+        moveq   #0,%d0\r
+clrram: move.w  #0,(%a0)+\r
+        subq.w  #2,%d0\r
+       bne     clrram\r
+\r
+*----------------------------------------------------------        \r
+*\r
+*       Load driver into the Z80 memory\r
+*\r
+*----------------------------------------------------------        \r
+\r
+* halt the Z80\r
+        move.w  #0x100,0xa11100\r
+* reset it\r
+        move.w  #0x100,0xa11200\r
+\r
+        lea     Z80Driver,%a0\r
+        lea     0xa00000,%a1\r
+        move.l  #Z80DriverEnd,%d0\r
+        move.l  #Z80Driver,%d1\r
+        sub.l   %d1,%d0\r
+Z80loop:\r
+        move.b  (%a0)+,(%a1)+\r
+        subq.w  #1,%d0\r
+       bne     Z80loop\r
+\r
+* enable the Z80\r
+        move.w  #0x0,0xa11100\r
+\r
+*----------------------------------------------------------        \r
+        jmp      main\r
+\r
+INT:    \r
+       rte\r
+\r
+HBL:\r
+        /* addq.l   #1,htimer */\r
+       rte\r
+\r
+VBL:\r
+        /* addq.l   #1,vtimer */\r
+        move.l #vtimer,a0\r
+        addq.l #1,(a0)\r
+       rte\r
+\r
+*------------------------------------------------\r
+*\r
+*       Get a random number.  This routine\r
+*       was found in TOS.\r
+*\r
+*       Output\r
+*       ------\r
+*       d0 = random number\r
+*\r
+*------------------------------------------------\r
+\r
+        .globl  random\r
+\r
+random:\r
+                move.l      rand_num,%d0\r
+                tst.l       %d0\r
+                bne         .L1\r
+                moveq       #16,%d1\r
+                lsl.l       %d1,%d0\r
+                or.l        htimer,%d0\r
+                move.l      %d0,rand_num\r
+.L1:\r
+                move.l      #-1153374675,-(%sp)\r
+                move.l      rand_num,-(%sp)\r
+                bsr         lmul\r
+                addq.w      #8,%sp\r
+                addq.l      #1,%d0\r
+                move.l      %d0,rand_num\r
+\r
+                lsr.l       #8,%d0\r
+                and.l       #16777215,%d0\r
+                rts\r
+\r
+\r
+*------------------------------------------------\r
+*\r
+* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg\r
+*\r
+* Permission is granted to anyone to use this software for any purpose\r
+* on any computer system, and to redistribute it freely, with the\r
+* following restrictions:\r
+* 1) No charge may be made other than reasonable charges for reproduction.\r
+* 2) Modified versions must be clearly marked as such.\r
+* 3) The authors are not responsible for any harmful consequences\r
+*    of using this software, even if they result from defects in it.\r
+*\r
+*------------------------------------------------\r
+\r
+ldiv:\r
+        move.l  4(%a7),%d0\r
+       bpl     ld1\r
+        neg.l   %d0\r
+ld1:\r
+        move.l  8(%a7),%d1\r
+       bpl     ld2\r
+        neg.l   %d1\r
+        eor.b   #0x80,4(%a7)\r
+ld2:\r
+       bsr     i_ldiv          /* d0 = d0/d1 */\r
+        tst.b   4(%a7)\r
+       bpl     ld3\r
+        neg.l   %d0\r
+ld3:\r
+       rts\r
+\r
+lmul:\r
+        move.l  4(%a7),%d0\r
+       bpl     lm1\r
+        neg.l   %d0\r
+lm1:\r
+        move.l  8(%a7),%d1\r
+       bpl     lm2\r
+        neg.l   %d1\r
+        eor.b   #0x80,4(%a7)\r
+lm2:\r
+       bsr     i_lmul          /* d0 = d0*d1 */\r
+        tst.b   4(%a7)\r
+       bpl     lm3\r
+        neg.l   %d0\r
+lm3:\r
+       rts\r
+\r
+lrem:\r
+        move.l  4(%a7),%d0\r
+       bpl     lr1\r
+        neg.l   %d0\r
+lr1:\r
+        move.l  8(%a7),%d1\r
+       bpl     lr2\r
+        neg.l   %d1\r
+lr2:\r
+       bsr     i_ldiv          /* d1 = d0%d1 */\r
+        move.l  %d1,%d0\r
+        tst.b   4(%a7)\r
+       bpl     lr3\r
+        neg.l   %d0\r
+lr3:\r
+       rts\r
+\r
+ldivu:\r
+        move.l  4(%a7),%d0\r
+        move.l  8(%a7),%d1\r
+       bsr     i_ldiv\r
+       rts\r
+\r
+lmulu:\r
+        move.l  4(%a7),%d0\r
+        move.l  8(%a7),%d1\r
+       bsr     i_lmul\r
+       rts\r
+\r
+lremu:\r
+        move.l  4(%a7),%d0\r
+        move.l  8(%a7),%d1\r
+       bsr     i_ldiv\r
+        move.l  %d1,%d0\r
+       rts\r
+*\r
+* A in d0, B in d1, return A*B in d0\r
+*\r
+i_lmul:\r
+        move.l  %d3,%a2           /* save d3 */\r
+        move.w  %d1,%d2\r
+        mulu    %d0,%d2           /* d2 = Al * Bl */\r
+\r
+        move.l  %d1,%d3\r
+        swap    %d3\r
+        mulu    %d0,%d3           /* d3 = Al * Bh */\r
+\r
+        swap    %d0\r
+        mulu    %d1,%d0           /* d0 = Ah * Bl */\r
+\r
+        add.l   %d3,%d0           /* d0 = (Ah*Bl + Al*Bh) */\r
+        swap    %d0\r
+        clr.w   %d0              /* d0 = (Ah*Bl + Al*Bh) << 16 */\r
+\r
+        add.l   %d2,%d0           /* d0 = A*B */\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+*\r
+*A in d0, B in d1, return A/B in d0, A%B in d1\r
+*\r
+i_ldiv:\r
+        tst.l   %d1\r
+       bne     nz1\r
+\r
+*       divide by zero\r
+*       divu    #0,%d0           /* cause trap */\r
+        move.l  #0x80000000,%d0\r
+        move.l  %d0,%d1\r
+       rts\r
+nz1:\r
+        move.l  %d3,%a2           /* save d3 */\r
+        cmp.l   %d1,%d0\r
+       bhi     norm\r
+       beq     is1\r
+*       A<B, so ret 0, rem A\r
+        move.l  %d0,%d1\r
+        clr.l   %d0\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+*       A==B, so ret 1, rem 0\r
+is1:\r
+        moveq.l #1,%d0\r
+        clr.l   %d1\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+*       A>B and B is not 0\r
+norm:\r
+        cmp.l   #1,%d1\r
+       bne     not1\r
+*       B==1, so ret A, rem 0\r
+        clr.l   %d1\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+*  check for A short (implies B short also)\r
+not1:\r
+        cmp.l   #0xffff,%d0\r
+       bhi     slow\r
+*  A short and B short -- use 'divu'\r
+        divu    %d1,%d0           /* d0 = REM:ANS */\r
+        swap    %d0              /* d0 = ANS:REM */\r
+        clr.l   %d1\r
+        move.w  %d0,%d1           /* d1 = REM */\r
+        clr.w   %d0\r
+        swap    %d0\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+* check for B short\r
+slow:\r
+        cmp.l   #0xffff,%d1\r
+       bhi     slower\r
+* A long and B short -- use special stuff from gnu\r
+        move.l  %d0,%d2\r
+        clr.w   %d2\r
+        swap    %d2\r
+        divu    %d1,%d2           /* d2 = REM:ANS of Ahi/B */\r
+        clr.l   %d3\r
+        move.w  %d2,%d3           /* d3 = Ahi/B */\r
+        swap    %d3\r
+\r
+        move.w  %d0,%d2           /* d2 = REM << 16 + Alo */\r
+        divu    %d1,%d2           /* d2 = REM:ANS of stuff/B */\r
+\r
+        move.l  %d2,%d1\r
+        clr.w   %d1\r
+        swap    %d1              /* d1 = REM */\r
+\r
+        clr.l   %d0\r
+        move.w  %d2,%d0\r
+        add.l   %d3,%d0           /* d0 = ANS */\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+*       A>B, B > 1\r
+slower:\r
+        move.l  #1,%d2\r
+        clr.l   %d3\r
+moreadj:\r
+        cmp.l   %d0,%d1\r
+       bhs     adj\r
+        add.l   %d2,%d2\r
+        add.l   %d1,%d1\r
+       bpl     moreadj\r
+* we shifted B until its >A or sign bit set\r
+* we shifted #1 (d2) along with it\r
+adj:\r
+        cmp.l   %d0,%d1\r
+       bhi     ltuns\r
+        or.l    %d2,%d3\r
+        sub.l   %d1,%d0\r
+ltuns:\r
+        lsr.l   #1,%d1\r
+        lsr.l   #1,%d2\r
+       bne     adj\r
+* d3=answer, d0=rem\r
+        move.l  %d0,%d1\r
+        move.l  %d3,%d0\r
+        move.l  %a2,%d3           /* restore d3 */\r
+       rts\r
+*----------------------------------------------------------        \r
+*\r
+*       Z80 Sound Driver\r
+*\r
+*----------------------------------------------------------        \r
+Z80Driver:\r
+          dc.b  0xc3,0x46,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
+          dc.b  0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0xed\r
+          dc.b  0x56,0x31,0x00,0x20,0x3a,0x39,0x00,0xb7\r
+          dc.b  0xca,0x4c,0x00,0x21,0x3a,0x00,0x11,0x40\r
+          dc.b  0x00,0x01,0x06,0x00,0xed,0xb0,0x3e,0x00\r
+          dc.b  0x32,0x39,0x00,0x3e,0xb4,0x32,0x02,0x40\r
+          dc.b  0x3e,0xc0,0x32,0x03,0x40,0x3e,0x2b,0x32\r
+          dc.b  0x00,0x40,0x3e,0x80,0x32,0x01,0x40,0x3a\r
+          dc.b  0x43,0x00,0x4f,0x3a,0x44,0x00,0x47,0x3e\r
+          dc.b  0x06,0x3d,0xc2,0x81,0x00,0x21,0x00,0x60\r
+          dc.b  0x3a,0x41,0x00,0x07,0x77,0x3a,0x42,0x00\r
+          dc.b  0x77,0x0f,0x77,0x0f,0x77,0x0f,0x77,0x0f\r
+          dc.b  0x77,0x0f,0x77,0x0f,0x77,0x0f,0x77,0x3a\r
+          dc.b  0x40,0x00,0x6f,0x3a,0x41,0x00,0xf6,0x80\r
+          dc.b  0x67,0x3e,0x2a,0x32,0x00,0x40,0x7e,0x32\r
+          dc.b  0x01,0x40,0x21,0x40,0x00,0x7e,0xc6,0x01\r
+          dc.b  0x77,0x23,0x7e,0xce,0x00,0x77,0x23,0x7e\r
+          dc.b  0xce,0x00,0x77,0x3a,0x39,0x00,0xb7,0xc2\r
+          dc.b  0x4c,0x00,0x0b,0x78,0xb1,0xc2,0x7f,0x00\r
+          dc.b  0x3a,0x45,0x00,0xb7,0xca,0x4c,0x00,0x3d\r
+          dc.b  0x3a,0x45,0x00,0x06,0xff,0x0e,0xff,0xc3\r
+          dc.b  0x7f,0x00\r
+Z80DriverEnd:\r
+\r
+\r
diff --git a/hexed/test.s b/hexed/test.s
new file mode 100644 (file)
index 0000000..3802920
--- /dev/null
@@ -0,0 +1,443 @@
+##################################################
+#                                                #
+# Assemble with gas                              #
+#   --register-prefix-optional --bitwise-or      #
+#                                                #
+##################################################
+
+.text
+.globl main
+
+##################################################
+#                                                #
+#        Register and bitmask definitions        #
+#                                                #
+##################################################
+
+.equ GFXDATA,          0xc00000
+.equ GFXCNTL,          0xc00004
+
+.equ VDP0_E_HBI,       0x10
+.equ VDP0_E_DISPLAY,   0x02 
+.equ VDP0_PLTT_FULL,   0x04 
+
+.equ VDP1_SMS_MODE,    0x80
+.equ VDP1_E_DISPLAY,   0x40
+.equ VDP1_E_VBI,       0x20
+.equ VDP1_E_DMA,       0x10
+.equ VDP1_NTSC,                0x00
+.equ VDP1_PAL,         0x08
+.equ VDP1_RESERVED,    0x04
+
+.equ VDP12_SPR_SHADOWS,        0x08
+.equ VDP12_SCREEN_V224,        0x00
+.equ VDP12_SCREEN_V448,        0x04
+.equ VDP12_PROGRESSIVE,        0x00
+.equ VDP12_INTERLACED, 0x02
+.equ VDP12_SCREEN_H256,        0x00
+.equ VDP12_SCREEN_H320,        0x81
+
+.equ VDP16_MAP_V32,    0x00
+.equ VDP16_MAP_V64,    0x10
+.equ VDP16_MAP_V128,   0x30
+.equ VDP16_MAP_H32,    0x00
+.equ VDP16_MAP_H64,    0x01
+.equ VDP16_MAP_H128,   0x03
+
+
+
+##################################################
+#                                                #
+#                   MACROS                       #
+#                                                #
+##################################################
+
+
+/* Write val to VDP register reg */
+.macro write_vdp_reg reg val
+       move.w #((\reg << 8) + 0x8000 + \val),(a3)
+.endm
+
+
+/* For immediate addresses */
+.macro VRAM_ADDR reg adr
+       move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
+.endm
+
+
+/* For indirect (variable) addresses.
+   Destroys d6-d7. */
+.macro VRAM_ADDR_var reg adr
+       move.l \adr,d6
+       move.l \adr,d7
+       and.w #0x3fff,d6
+       lsr.w #7,d7
+       lsr.w #7,d7
+       add.w #0x4000,d6
+       lsl.l #7,d6
+       lsl.l #7,d6
+       lsl.l #2,d6
+       or.l d7,d6
+       move.l d6,\reg
+.endm
+
+
+.macro CRAM_ADDR reg adr
+       move.l  #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
+.endm
+
+
+/* For indirect (variable) addresses */
+.macro CRAM_ADDR_var reg adr
+       move.l \adr,d6
+       move.l \adr,d7
+       and.w #0x3fff,d6
+       lsr.w #7,d7
+       lsr.w #7,d7
+       add.w #0xc000,d6
+       lsl.l #7,d6
+       lsl.l #7,d6
+       lsl.l #2,d6
+       or.l d7,d6
+       move.l d6,\reg
+.endm
+
+
+.macro VSCROLL_ADDR reg adr
+       move.l  #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg
+.endm
+
+
+.macro HSCROLL_ADDR reg adr
+       move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
+.endm
+
+
+#################################################
+#                                               #
+#                    DATA                       #
+#                                               #
+#################################################
+
+colors:
+       dc.w 0x0040,0x0080,0x000e,0x00e0,0x0e00,0x00ee
+pattern:
+       dc.l 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
+       dc.l 0x22334455,0x22334455,0x22334455,0x22334455,0x22334455,0x22334455,0x22334455,0x22334455
+       /* shadow sprite */
+       dc.l 0x00000fff
+       dc.l 0x0000ffff
+       dc.l 0x00ffffff
+       dc.l 0x00ffffff
+       dc.l 0x0fffffff
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       /* */
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       dc.l 0x0fffffff
+       dc.l 0x00ffffff
+       dc.l 0x00ffffff
+       dc.l 0x0000ffff
+       dc.l 0x00000fff
+       /* */
+       dc.l 0xfff00000
+       dc.l 0xffff0000
+       dc.l 0xffffff00
+       dc.l 0xffffff00
+       dc.l 0xfffffff0
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       /* */
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       dc.l 0xffffffff
+       dc.l 0xfffffff0
+       dc.l 0xffffff00
+       dc.l 0xffffff00
+       dc.l 0xffff0000
+       dc.l 0xfff00000
+       /* hilight sprite */
+       dc.l 0x00000eee
+       dc.l 0x0000eeee
+       dc.l 0x00eeeeee
+       dc.l 0x00eeeeee
+       dc.l 0x0eeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       /* */
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0x0eeeeeee
+       dc.l 0x00eeeeee
+       dc.l 0x00eeeeee
+       dc.l 0x0000eeee
+       dc.l 0x00000eee
+       /* */
+       dc.l 0xeee00000
+       dc.l 0xeeee0000
+       dc.l 0xeeeeee00
+       dc.l 0xeeeeee00
+       dc.l 0xeeeeeee0
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       /* */
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeeee
+       dc.l 0xeeeeeee0
+       dc.l 0xeeeeee00
+       dc.l 0xeeeeee00
+       dc.l 0xeeee0000
+       dc.l 0xeee00000
+
+
+sprite_data:
+       /*         Y        size     link          attr        X */
+       dc.w  10+128;  dc.b 0x05;  dc.b 1;  dc.w 0x6002;  dc.w 0
+       dc.w  30+128;  dc.b 0x05;  dc.b 2;  dc.w 0x6006;  dc.w 0
+       dc.w  60+128;  dc.b 0x05;  dc.b 3;  dc.w 0xe002;  dc.w 0
+       dc.w  80+128;  dc.b 0x05;  dc.b 4;  dc.w 0xe006;  dc.w 0
+       dc.w 120+128;  dc.b 0x05;  dc.b 5;  dc.w 0x6002;  dc.w 0
+       dc.w 140+128;  dc.b 0x05;  dc.b 6;  dc.w 0x6006;  dc.w 0
+       dc.w 170+128;  dc.b 0x05;  dc.b 7;  dc.w 0xe002;  dc.w 0
+       dc.w 190+128;  dc.b 0x05;  dc.b 0;  dc.w 0xe006;  dc.w 0
+sprite_data_end:
+
+
+##################################################
+#                                                #
+#               MAIN PROGRAM                     #
+#                                                #
+##################################################
+main:
+       /* Initialize VDP */
+       jsr             init_gfx
+
+       /* Load color data */
+       movea.l         #0,a3
+       move.l          #colors,a4
+       moveq.l         #6,d4
+       jsr             load_colors
+
+       /* load patterns */
+       movea.l         #0,a3
+       movea.l         #pattern,a4
+       move.l          #10,d4
+       jsr             load_tiles
+
+       /* generate A layer map */
+       movea.l         #0xe000+10*2,a6
+       move.l          #28-1,d4
+lmaploop0:
+       movea.l         a6,a3
+       jsr             load_prepare
+
+       moveq.l         #6-1,d3
+0:     move.l          #0x00010001,(a3)
+       dbra            d3,0b
+
+       moveq.l         #9-1,d3
+0:     move.l          #0x80018001,(a3)
+       dbra            d3,0b
+
+       add.l           #64*2,a6
+       dbra            d4,lmaploop0
+
+       /* generate B layer map */
+       movea.l         #0xc000+64*14*2,a3
+       jsr             load_prepare
+
+       move.l          #64*14/2-1,d3
+0:     move.l          #0x80008000,(a3)
+       dbra            d3,0b
+
+       /* upload sprite data */
+       movea.l         #0xfc00,a3
+       jsr             load_prepare
+       movea.l         #sprite_data,a0
+
+       move.l          #(sprite_data_end-sprite_data)/2-1,d3
+0:     move.l          (a0)+,(a3)
+       dbra            d3,0b
+
+       jsr             wait_vsync
+
+##################################################
+#                                                #
+#                 MAIN LOOP                      #
+#                                                #
+##################################################
+
+forever:
+       movea.l         #vtimer,a0
+       move.l          (a0),d4
+       and.w           #0x1ff,d4
+       movea.l         #0xfc06,a6
+       moveq.l         #8-1,d5
+
+0:
+       movea.l         a6,a3
+       jsr             load_prepare
+       move.w          d4,(a3)
+       addq.w          #8,a6
+       dbra            d5,0b
+
+       jsr             wait_vsync
+       bra             forever
+       
+
+
+#################################################
+#                                               #
+#         Initialize VDP registers              #
+#                                               #
+#################################################
+
+init_gfx:
+       move.l          #GFXCNTL,a3
+       write_vdp_reg   0,(VDP0_E_DISPLAY + VDP0_PLTT_FULL)
+       write_vdp_reg   1,(VDP1_E_VBI + VDP1_E_DISPLAY + VDP1_E_DMA + VDP1_RESERVED)
+       write_vdp_reg   2,(0xe000 >> 10)        /* Screen map a adress */
+       write_vdp_reg   3,(0xe000 >> 10)        /* Window address */
+       write_vdp_reg   4,(0xc000 >> 13)        /* Screen map b address */
+       write_vdp_reg   5,(0xfc00 >>  9)        /* Sprite address */
+       write_vdp_reg   6,0     
+       write_vdp_reg   7,1                     /* Border color */
+       write_vdp_reg   10,1                    /* Lines per hblank interrupt */
+       write_vdp_reg   11,0                    /* 2-cell vertical scrolling */
+       write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_SPR_SHADOWS)
+       write_vdp_reg   13,(0x6000 >> 10)       /* Horizontal scroll address */
+       write_vdp_reg   15,2
+       write_vdp_reg   16,(VDP16_MAP_V32 + VDP16_MAP_H64)
+       write_vdp_reg   17,0
+       write_vdp_reg   18,0xff
+       rts
+
+
+
+#################################################
+#                                               #
+#        Load tile data from ROM                #
+#                                               #
+# Parameters:                                   #
+#  a3: VRAM base                                # 
+#  a4: pattern address                          #
+#  d4: number of tiles to load                  #
+#  Destroys a2,d0,d6-d7...                      #
+#                                               #
+#################################################
+
+load_tiles:
+       move.l          #GFXCNTL,a2
+       VRAM_ADDR_var   d0,a3
+       move.l          d0,(a2)
+       lsl             #3,d4
+       
+       move.l          #GFXDATA,a3
+       subq.l          #1,d4
+_copy_tile_data:
+       move.l          (a4)+,(a3)
+       dbra            d4,_copy_tile_data
+
+       rts
+
+
+load_prepare:
+       move.l          #GFXCNTL,a2
+       VRAM_ADDR_var   d0,a3
+       move.l          d0,(a2)
+       move.l          #GFXDATA,a3
+
+       rts
+
+
+#################################################
+#                                               #
+#        Clear one of the screen maps           #
+#                                               #
+# Parameters:                                   #
+#  a0: Map address                              # 
+#  d0: Data to write to each map entry          #
+#                                               #
+#################################################
+
+clear_map:
+       move.l          #GFXCNTL,a4
+       VRAM_ADDR_var   d1,a0
+       move.l          d1,(a4)
+       move.l          #GFXDATA,a3
+       move.w          #1023,d1        /* Loop counter */
+_clear_map_loop:
+       move.w          d0,(a3)
+       move.w          d0,(a3)
+       dbra            d1,_clear_map_loop
+       rts
+       
+
+#################################################
+#                                               #
+#        Load color data from ROM               #
+#                                               #
+# Parameters:                                   #
+#  a3: CRAM base                                # 
+#  a4: color list address                       #
+#  d4: number of colors to load                 #
+#                                               #
+#################################################
+
+load_colors:
+       move.l          #GFXCNTL,a2
+       CRAM_ADDR_var   d0,a3
+       move.l          d0,(a2)
+
+       move.l          #GFXDATA,a3
+       subq.w          #1,d4
+_copy_color_data:
+       move.w          (a4)+,(a3)
+       dbra            d4,_copy_color_data
+
+       rts
+
+
+#################################################
+#                                               #
+#       Wait for next VBlank interrupt          #
+#                                               #
+#################################################
+
+wait_vsync:
+       movea.l         #vtimer,a0
+       move.l          (a0),a1
+_wait_change:
+       stop            #0x2000
+       cmp.l           (a0),a1
+       beq             _wait_change
+       rts
+
+
+#################################################
+#                                               #
+#                 RAM DATA                      #
+#                                               #
+#################################################
+
+.bss
+.globl htimer
+.globl vtimer
+.globl rand_num
+htimer:                .long 0
+vtimer:                .long 0
+rand_num:      .long 0
+scrollx:       .long 0
+
+.end
+
+# vim:filetype=asmM68k