From e82dd735838d2e4b8f0e71596268b9dbfffd9f4a Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 7 Jan 2023 00:53:44 -0800 Subject: [PATCH] vdp1 experiments --- main.c | 87 ++++++++++++++++++++++++++++- type.h | 6 ++ vdp1.h | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 vdp1.h diff --git a/main.c b/main.c index 5cec3fa..9550284 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,5 @@ #include "vdp2.h" +#include "vdp1.h" void start(void) { // @@ -10,12 +11,12 @@ void start(void) { vdp2.reg.BGON = 0; + // BKTAU/BKTAL are shifted left 1: (0x4000 << 1 = 0x8000) vdp2.reg.BKTA = REG_UL(BKTAU__BKCLMD_SINGLE_COLOR, 0x4000); // background color, rgb15 vdp2.vram.u16[0x8000 / 2] = (0x05 << 0); // dark red - // // vdp2: define and place a single character on NBG0 // @@ -51,5 +52,89 @@ void start(void) { // (bit 5~0) * 0x4000 vdp2.vram.u32[(0x4000 / 4)] = PATTERN_NAME_TABLE_2WORD__CHARACTER(1); + + // + // vdp1: + // + + // The VBE setting must be set immediately after the V-blank IN interrupt. + // + // TVM settings must be performed from the second H-blank IN interrupt after + // the V-blank IN interrupt to the H-blank IN interrupt immediately after the + // V-blank OUT interrupt. + vdp1.reg.TVMR = ( TVMR__TVM__NTSC_PAL + | TVMR__TVM__FRAMEBUFFER_NONROTATION + | TVMR__TVM__16BPP + ); + + // make FCM and FCT settings immediately after V-blank OUT + vdp1.reg.FBCR = 0; + + // "A command table must always be stored at address 00000H to 0001EH." + // we can't trigger a plot yet because we have no (valid) table. + //vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE; + + vdp1.reg.EWDR = 0; // black + + // upper-left + vdp1.reg.EWLR = PTMR__EWLR__16BPP_X1(0) | PTMR__EWLR__Y1(0); + + // lower-right + vdp1.reg.EWRR = PTMR__EWRR__16BPP_X3(319) | PTMR__EWRR__Y3(239); + + vdp1.vram.cmd[0].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__USER_CLIP_COORDINATES; + vdp1.vram.cmd[0].LINK = 0; + vdp1.vram.cmd[0].XA = 0; + vdp1.vram.cmd[0].YA = 0; + vdp1.vram.cmd[0].XC = 319; + vdp1.vram.cmd[0].YC = 239; + + vdp1.vram.cmd[1].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__SYSTEM_CLIP_COORDINATES; + vdp1.vram.cmd[1].LINK = 0; + vdp1.vram.cmd[1].XC = 319; + vdp1.vram.cmd[1].YC = 239; + + vdp1.vram.cmd[2].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LOCAL_COORDINATE; + vdp1.vram.cmd[2].LINK = 0; + vdp1.vram.cmd[2].XA = 0; + vdp1.vram.cmd[2].YA = 0; + + vdp1.vram.cmd[3].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__POLYGON; + vdp1.vram.cmd[3].LINK = 0; + vdp1.vram.cmd[3].PMOD = CTRL__PMOD__ECD | CTRL__PMOD__SPD; + vdp1.vram.cmd[3].COLR = 0x2; // palette color #2 + vdp1.vram.cmd[3].XA = 50; + vdp1.vram.cmd[3].YA = 50; + vdp1.vram.cmd[3].XB = 150; + vdp1.vram.cmd[3].YB = 50; + vdp1.vram.cmd[3].XC = 150; + vdp1.vram.cmd[3].YC = 150; + vdp1.vram.cmd[3].XD = 50; + vdp1.vram.cmd[3].YD = 150; + + vdp1.vram.cmd[4].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__POLYGON; + vdp1.vram.cmd[4].LINK = 0; + vdp1.vram.cmd[4].PMOD = CTRL__PMOD__ECD | CTRL__PMOD__SPD; + vdp1.vram.cmd[4].COLR = (1 << 15) | (0x31 << 10) | (0x31 << 0); // RGB15 magenta + vdp1.vram.cmd[4].XA = 100; + vdp1.vram.cmd[4].YA = 50; + vdp1.vram.cmd[4].XB = 150; + vdp1.vram.cmd[4].YB = 100; + vdp1.vram.cmd[4].XC = 100; + vdp1.vram.cmd[4].YC = 150; + vdp1.vram.cmd[4].XD = 50; + vdp1.vram.cmd[4].YD = 100; + + vdp1.vram.cmd[5].CTRL = CTRL__END; + + // priorities + vdp2.reg.PRISA = 0x0101; + vdp2.reg.PRISB = 0x0101; + vdp2.reg.PRISC = 0x0101; + vdp2.reg.PRISD = 0x0101; + + // start drawing + vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE; + while (1) {} } diff --git a/type.h b/type.h index c5aafd9..743cf06 100644 --- a/type.h +++ b/type.h @@ -9,4 +9,10 @@ static_assert((sizeof (reg8)) == 1); static_assert((sizeof (reg16)) == 2); static_assert((sizeof (reg32)) == 4); +typedef volatile unsigned short u16; +typedef volatile short s16; + +static_assert((sizeof (u16)) == 2); +static_assert((sizeof (s16)) == 2); + #define REG_UL(U, L) (((U) << 16) | (L)) diff --git a/vdp1.h b/vdp1.h new file mode 100644 index 0000000..207c3b6 --- /dev/null +++ b/vdp1.h @@ -0,0 +1,170 @@ +#include "type.h" + +/* command table */ + +typedef struct vdp1_cmd { + u16 CTRL; + u16 LINK; + u16 PMOD; + u16 COLR; + u16 SRCA; + u16 SIZE; + s16 XA; + s16 YA; + s16 XB; + s16 YB; + s16 XC; + s16 YC; + s16 XD; + s16 YD; + u16 GDRA; + u16 _dummy; +} vdp1_cmd; + +static_assert((sizeof (struct vdp1_cmd)) == 0x20); + +/* command table bits */ + +enum bits_ctrl { + CTRL__END = (1 << 15), + + CTRL__JP__JUMP_NEXT = (0b000 << 12), + CTRL__JP__JUMP_ASSIGN = (0b001 << 12), + CTRL__JP__JUMP_CALL = (0b010 << 12), + CTRL__JP__JUMP_RETURN = (0b011 << 12), + + CTRL__JP__SKIP_NEXT = (0b100 << 12), + CTRL__JP__SKIP_ASSIGN = (0b101 << 12), + CTRL__JP__SKIP_CALL = (0b110 << 12), + CTRL__JP__SKIP_RETURN = (0b111 << 12), + + CTRL__ZP__TWO = (0b0000 << 8), + CTRL__ZP__UPPER_LEFT = (0b0101 << 8), + CTRL__ZP__UPPER_CENTER = (0b0110 << 8), + CTRL__ZP__UPPER_RIGHT = (0b0111 << 8), + CTRL__ZP__CENTER_LEFT = (0b1001 << 8), + CTRL__ZP__CENTER_CENTER = (0b1010 << 8), + CTRL__ZP__CENTER_RIGHT = (0b1011 << 8), + CTRL__ZP__LOWER_LEFT = (0b1101 << 8), + CTRL__ZP__LOWER_CENTER = (0b1110 << 8), + CTRL__ZP__LOWER_RIGHT = (0b1111 << 8), + + CTRL__DIR__INVERTED_HORIZONTALLY = (0b01 << 4), + CTRL__DIR__INVERTED_VERTICALLY = (0b10 << 4), + + CTRL__COMM__NORMAL_SPRITE = (0b0000), + CTRL__COMM__SCALED_SPRITE = (0b0001), + CTRL__COMM__DISTORTED_SPRITE = (0b0010), + CTRL__COMM__POLYGON = (0b0100), + CTRL__COMM__POLYLINE = (0b0101), + CTRL__COMM__LINE = (0b0110), + + CTRL__COMM__USER_CLIP_COORDINATES = (0b1000), + CTRL__COMM__SYSTEM_CLIP_COORDINATES = (0b1001), + CTRL__COMM__LOCAL_COORDINATE = (0b1010), +}; + +enum bits_pmod { + CTRL__PMOD__MON = (1 << 15), + CTRL__PMOD__HSS = (1 << 12), + CTRL__PMOD__PCLP = (1 << 11), + CTRL__PMOD__CLIP = (1 << 10), + CTRL__PMOD__CMOD = (1 << 9), + CTRL__PMOD__MESH = (1 << 8), + CTRL__PMOD__ECD = (1 << 7), + CTRL__PMOD__SPD = (1 << 6), +#define CTRL__PMOD__COLOR_MODE ( << 3) +#define CTRL__PMOD__COLOR_CALCULATION ( << 0) +}; + +/* memory offsets */ + +typedef union vdp1_vram { + unsigned char u8[0x080000 / 1]; + unsigned short u16[0x080000 / 2]; + unsigned long u32[0x080000 / 4]; + vdp1_cmd cmd[0x080000 / 0x20]; +} vdp1_vram; + +static_assert((sizeof (union vdp1_vram)) == 0x080000); + +typedef union vdp1_framebuffer { + unsigned char u8[0x040000 / 1]; + unsigned short u16[0x040000 / 2]; + unsigned long u32[0x040000 / 4]; +} vdp1_framebuffer; + +static_assert((sizeof (union vdp1_framebuffer)) == 0x040000); + +typedef unsigned char vdp1_res0[0x040000]; + +typedef struct vdp1_reg { + reg16 TVMR; /* TV MODE SELECTION */ + reg16 FBCR; /* FRAME BUFFER CHANGE MODE */ + reg16 PTMR; /* PLOT TROGGER */ + reg16 EWDR; /* ERASE/WRITE DATA */ + reg16 EWLR; /* ERASE/WRITE UPPER-LEFT COORDINATE */ + reg16 EWRR; /* ERASE/WRITE LOWER-RIGHT COORDINATE */ + reg16 ENDR; /* PLOT ABNORMAL END */ + reg16 _res0; + reg16 EDSR; /* TRANSFER END STATUS */ + reg16 LOPR; /* LAST OPERATION COMMAND ADDRESS */ + reg16 COPR; /* CURRENT OPERATION COMMAND ADDRESS */ + reg16 MODR; /* MODE STATUS */ +} vdp1_reg; + +static_assert((offsetof (struct vdp1_reg, ENDR)) == 0x0C); +static_assert((offsetof (struct vdp1_reg, EDSR)) == 0x10); +static_assert((sizeof (struct vdp1_reg)) == 24); + +struct vdp1 { + vdp1_vram vram; + vdp1_framebuffer framebuffer; + vdp1_res0 _res0; + vdp1_reg reg; +}; + +static_assert((sizeof (struct vdp1)) == 0x100018); +static_assert((offsetof (struct vdp1, vram)) == 0x000000); +static_assert((offsetof (struct vdp1, framebuffer)) == 0x080000); +static_assert((offsetof (struct vdp1, reg)) == 0x100000); + +extern struct vdp1 vdp1 __asm("vdp1"); + +/* register bits */ + +enum bits_tvmr { + TVMR__VBE = (1 << 3), + TVMR__TVM__NTSC_PAL = (0 << 2), + TVMR__TVM__HDTV_31KC = (1 << 2), + TVMR__TVM__FRAMEBUFFER_NONROTATION = (0 << 1), + TVMR__TVM__FRAMEBUFFER_ROTATION = (1 << 1), + TVMR__TVM__16BPP = (0 << 0), + TVMR__TVM__8BPP = (1 << 0), +}; + +enum bits_fbcr { + FBCR__EOS = (1 << 4), + FBCR__DIE = (1 << 3), + FBCR__DIL = (1 << 2), + FBCR__FCM = (1 << 1), + FBCR__FCT = (1 << 0), +}; + +enum bits__ptmr { + PTMR__PTM__IDLE = 0b00, + PTMR__PTM__NOW = 0b01, + PTMR__PTM__FRAME_CHANGE = 0b10, +}; + +// enum bits__ewlr { +#define PTMR__EWLR__16BPP_X1(n) ((n / 8 ) << 9) +#define PTMR__EWLR__8BPP_X1(n) ((n / 16) << 9) +#define PTMR__EWLR__Y1(n) (n << 0) +// } + +// enum bits__ewrr { +#define PTMR__EWRR__16BPP_X3(n) (((n + 1) / 8 ) << 9) +#define PTMR__EWLR__8BPP_X3(n) (((n + 1) / 16) << 9) +#define PTMR__EWRR__Y3(n) (n << 0) +// }