DMA and sprites (not working yet)
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 19 Dec 2023 15:05:17 +0000 (17:05 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 19 Dec 2023 15:05:17 +0000 (17:05 +0200)
15 files changed:
Makefile
doc/vmem
src/data.s
src/dma.S [new file with mode: 0644]
src/dma.h [new file with mode: 0644]
src/hwregs.h
src/libc/stdio.h
src/libc/string.c
src/main.c
src/sprite.S [new file with mode: 0644]
src/sprite.c [new file with mode: 0644]
src/sprite.h [new file with mode: 0644]
src/vdp.S
src/vdp.h
src/vdp.inc [new file with mode: 0644]

index 8f84751..4420eb1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ $(elf): $(obj)
 $(z80bin): $(z80obj)
        $(Z80LD) -o $@ $(Z80LDFLAGS) $(z80obj)
 
-src/data.o: src/data.s data/font8x8.img
+src/data.o: src/data.s data/font8x8.img data/cellspr.img
 src/z80prog-asm.o: src/z80prog.s $(z80bin)
 
 -include $(dep)
@@ -55,7 +55,7 @@ src/z80prog-asm.o: src/z80prog.s $(z80bin)
        $(AS) -o $@ $(ASFLAGS) $<
 
 %-asm.o: %.S
-       $(CC) -o $@ $(ASFLAGS) -c $<
+       $(CC) -o $@ $(ASFLAGS) -DASM -c $<
 
 %.z80: %.asm
        $(Z80AS) -o $@ $(Z80ASFLAGS) $< >/dev/null
index 266a06d..efdd934 100644 (file)
--- a/doc/vmem
+++ b/doc/vmem
@@ -1,5 +1,5 @@
 0000
-8000
+8000   sprite tiles
 b400   font 96 glyphs * 8x8 / 2 = 3072 bytes
 c000   nametable A (64x32 * 2 = 4096)
 d000   nametable B
index 2c07f8a..4bb94b6 100644 (file)
@@ -2,8 +2,15 @@
 
        .globl font8x8_data
        .globl font8x8_data_end
+       .globl cellspr_data
+       .globl cellspr_data_end
 font8x8_data:
        .incbin "data/font8x8.img"
 font8x8_data_end:
 
+       .align 2
+cellspr_data:
+       .incbin "data/cellspr.img"
+cellspr_data_end:
+
 | vi:ft=gas68k:
diff --git a/src/dma.S b/src/dma.S
new file mode 100644 (file)
index 0000000..b3f9d86
--- /dev/null
+++ b/src/dma.S
@@ -0,0 +1,44 @@
+       .text
+
+#include "hwregs.h"
+#include "vdp.inc"
+
+       | dma_systovram(vmem_addr, src, count)
+       .globl dma_systovram
+dma_systovram:
+       vdp_setreg VDP_REG_MODE2, VDP_M2_INIT + VDP_M2_DISP + VDP_M2_DMA
+
+       | set source address
+       move.l 8(%sp), %d0
+       move.l %d0, %d1
+       vdp_setreg_reg VDP_REG_DMASRCL, %d0
+       lsr.w #8, %d1
+       vdp_setreg_reg VDP_REG_DMASRCM, %d1
+       swap %d0
+       vdp_setreg_reg VDP_REG_DMASRCH, %d0
+       | set count (in words)
+       move.w 14(%sp), %d0
+       move.w %d0, %d1
+       vdp_setreg_reg VDP_REG_DMACNTL, %d0
+       lsr.w #8, %d1
+       vdp_setreg_reg VDP_REG_DMACNTH, %d1
+       | set the destination address.
+       move.w 6(%sp), %d0
+       move.w %d0, %d1
+       and.w #0x3fff, %d0
+       or.w #(VDP_VRAM_DMA >> 16), %d0
+       move.w %d0, VDP_CTL_PORT
+       | 2 upper bits and rest of the type flags
+       rol.w #2, %d1
+       and.w #3, %d1
+       or.w #(VDP_VRAM_DMA & 0xf0), %d1
+       | last word needs to come from RAM, so we push it on the stack
+       move.w %d1, -(%sp)
+       move.w (%sp), VDP_CTL_PORT
+       add.l #2, %sp
+
+       | after DMA ends the cpu can continue, turn DMA off
+       vdp_setreg VDP_REG_MODE2, VDP_M2_INIT + VDP_M2_DISP
+       rts
+       
+| vi:ft=gas68k:
diff --git a/src/dma.h b/src/dma.h
new file mode 100644 (file)
index 0000000..5e52234
--- /dev/null
+++ b/src/dma.h
@@ -0,0 +1,14 @@
+#ifndef DMA_H_
+#define DMA_H_
+
+#include "vdp.h"
+
+#define dma_enable() \
+       vdp_setreg(VDP_REG_MODE2, VDP_M2_INIT | VDP_M2_DISP | VDP_M2_DMA)
+
+#define dma_disable() \
+       vdp_setreg(VDP_REG_MODE2, VDP_M2_INIT | VDP_M2_DISP)
+
+void dma_systovram(uint32_t vaddr, void *src, int count);
+
+#endif /* DMA_H_ */
index c018023..2838026 100644 (file)
@@ -9,6 +9,10 @@
 #define VDP_CRAM       0xc0000000
 #define VDP_VSRAM      0x40000010
 
+#define VDP_VRAM_DMA   0x40000080
+#define VDP_CRAM_DMA   0xc0000080
+#define VDP_VSRAM_DMA  0x40000090
+
 #ifndef ASM
 #include <stdint.h>
 
index 3b3e905..866ed70 100644 (file)
@@ -16,6 +16,4 @@ int vsprintf(char *buf, const char *fmt, va_list ap);
 int snprintf(char *buf, size_t sz, const char *fmt, ...);
 int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap);
 
-void perror(const char *s);
-
 #endif /* STDIO_H_ */
index 81aa415..4124df5 100644 (file)
@@ -3,15 +3,18 @@
 #include <stdint.h>
 #include <stddef.h>
 
+void *memset(void *s, int c, size_t n)
+{
+       char *ptr = s;
+       while(n--) *ptr++ = c;
+       return s;
+}
+
 void *memcpy(void *dest, const void *src, size_t n)
 {
-       size_t i;
        char *dptr = dest;
        const char *sptr = src;
-       for(i=0; i<n; i++) {
-               dptr[i] = sptr[i];
-       }
-
+       while(n--) *dptr++ = *sptr++;
        return dest;
 }
 
index 66efdda..9b02e61 100644 (file)
@@ -1,9 +1,17 @@
+#include <stdio.h>
 #include "z80.h"
 #include "vdp.h"
+#include "sprite.h"
 #include "debug.h"
 
+#define SPRITE_BASE            0x8000
+extern uint16_t cellspr_data[], cellspr_data_end[];
+
 int main(void)
 {
+       uint16_t *src;
+       int tile;
+
        z80_init();
        vdp_init();
        dbg_init();
@@ -11,7 +19,21 @@ int main(void)
        vdp_setcolor(0, 0, 2, 2, 2);
        vdp_setcolor(0, 15, 15, 15, 15);
 
-       dbg_printstr(0, 0, "Mindlapse");
+       /* upload sprite tiles */
+       src = cellspr_data;
+       vdp_setup_addr(VDP_VRAM, SPRITE_BASE);
+       while(src < cellspr_data_end) {
+               VDP_DATA = *src++;
+       }
+
+       for(;;) {
+               spr_begin();
+               tile = SPRITE_BASE / 32 + 2;
+               spr_add(160, 100, VDP_TILENAME(tile, 0, VDP_TILE_FG), SPR_SIZE(1,1));
+
+               vdp_wait_vblank();
+               spr_submit();
+       }
 
        return 0;
 }
diff --git a/src/sprite.S b/src/sprite.S
new file mode 100644 (file)
index 0000000..42e4efd
--- /dev/null
@@ -0,0 +1,18 @@
+       .text
+
+#include "hwregs.h"
+
+       .extern spr_shadow
+       .extern spr_count
+       .extern dma_systovram
+
+       .globl spr_submit
+spr_submit:
+       move.l spr_count, -(%sp)
+       move.l #spr_shadow, -(%sp)
+       move.l #0x8000, -(%sp)
+       jsr dma_systovram
+       add.l #12, %sp
+       rts
+
+| vi:ft=gas68k:
diff --git a/src/sprite.c b/src/sprite.c
new file mode 100644 (file)
index 0000000..63305f3
--- /dev/null
@@ -0,0 +1,33 @@
+#include <string.h>
+#include "sprite.h"
+#include "vdp.h"
+
+struct hwsprite spr_shadow[MAX_HWSPRITES];
+int spr_count;
+
+void spr_begin(void)
+{
+       memset(spr_shadow, 0, sizeof spr_shadow[0]);
+       spr_count = 0;
+}
+
+void spr_add(int x, int y, unsigned int tile, int sprsz)
+{
+       int id;
+       struct hwsprite *spr;
+
+       if(spr_count >= MAX_HWSPRITES) {
+               return;
+       }
+       id = spr_count++;
+       spr = spr_shadow + id;
+       if(id > 0) {
+               spr[-1].next = id;
+       }
+
+       spr->x = x + 128;
+       spr->y = y + 128;
+       spr->sz = sprsz;
+       spr->tile = tile;
+       spr->next = 0;
+}
diff --git a/src/sprite.h b/src/sprite.h
new file mode 100644 (file)
index 0000000..78d10b9
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef SPRITE_H_
+#define SPRITE_H_
+
+#include <stdint.h>
+
+struct hwsprite {
+       uint16_t y;
+       uint8_t sz;
+       uint8_t next;
+       uint16_t tile;
+       uint16_t x;
+} __attribute__((packed));
+
+#define SPR_SIZE(x, y) ((((x) - 1) << 2) | ((y) - 1))
+
+#define MAX_HWSPRITES  64
+extern struct hwsprite spr_shadow[MAX_HWSPRITES];
+extern int spr_count;
+
+void spr_begin(void);
+void spr_add(int x, int y, unsigned int tile, int sprsz);
+void spr_submit(void);
+
+#endif /* SPRITE_H_ */
index b3c6553..1d62565 100644 (file)
--- a/src/vdp.S
+++ b/src/vdp.S
@@ -1,6 +1,5 @@
        .text
 
-#define ASM
 #include "hwregs.h"
 
        .globl vdp_init
index 82e6747..628f7b0 100644 (file)
--- a/src/vdp.h
+++ b/src/vdp.h
@@ -9,6 +9,16 @@
 #define vdp_setreg(reg, val) \
        (VDP_CTL = 0x8000 | ((reg) << 8) | (val))
 
+#define vdp_wait_vblank() \
+       while(!(VDP_STAT & VDP_ST_VBLANK))
+
+#define vdp_wait_vblank_end() \
+       while((VDP_STAT & VDP_ST_VBLANK))
+
+#define vdp_vsync() \
+       (vdp_wait_vblank_end(), vdp_wait_vblank())
+
+
 #define VDP_TILE_BG                    0
 #define VDP_TILE_FG                    0x8000
 #define VDP_TILE_PAL(x)                ((x) << 13)
diff --git a/src/vdp.inc b/src/vdp.inc
new file mode 100644 (file)
index 0000000..2e00c93
--- /dev/null
@@ -0,0 +1,12 @@
+       .macro vdp_setreg reg val
+       move.w #(\val), %d0
+       or.w #(0x8000 + (\reg << 8)), %d0
+       move.w %d0, VDP_CTL_PORT
+       .endm
+
+       .macro vdp_setreg_reg reg val
+       or.w #(0x8000 + (\reg << 8)), \val
+       move.w \val, VDP_CTL_PORT
+       .endm
+
+| vi:ft=gas68k: