vdp2 pattern name table and cell format

This commit is contained in:
Zack Buhman 2023-01-06 21:15:44 -08:00
parent 286f116d15
commit 471094d866
5 changed files with 537 additions and 37 deletions

View File

@ -1,6 +1,6 @@
AFLAGS = -g --isa=sh2 --big
AFLAGS = -g -gdwarf-4 --isa=sh2 --big
CFLAGS += -ffunction-sections -fshort-enums -ffreestanding -nostdlib
CFLAGS += -Wall -Werror -Wno-error=unused-but-set-variable -g -Og
CFLAGS += -Wall -Werror -Wno-error=unused-but-set-variable -g -gdwarf-4 -Og
CARCH = -m2 -mb
TARGET = sh2-none-elf-
@ -13,7 +13,7 @@ OBJDUMP = $(TARGET)objdump
all: main.iso
define COPYELF
$(OBJCOPY) -I coff-sh -O elf32-sh \
$(OBJCOPY) -I coff-sh -O elf32-sh -g \
--rename-section .text=.text.$1 \
$< $@
endef
@ -65,7 +65,7 @@ main.iso: main.bin ip.bin
main.bin
clean:
rm -f *.iso *.o *.bin *.elf
rm -f *.iso *.o *.bin *.elf dts/smpsys.o
.SUFFIXES:
.INTERMEDIATE:

3
ip.lds
View File

@ -14,6 +14,7 @@ SECTIONS
KEEP(*(.text.sec))
KEEP(*(.text.are))
KEEP(*(.text.init))
KEEP(*(.text.smp))
KEEP(*(.text.main))
KEEP(*(.text.*))
} > rom
}

45
main.c
View File

@ -1,14 +1,55 @@
#include "vdp2.h"
void start(void) {
//
// vdp2: enable and set Back Screen color
//
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__BDCLMD | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
vdp2.reg.BGON = 0;
vdp2.reg.BKTA = REG32_VAL(BKTAU__BKCLMD_SINGLE_COLOR, 0x4000);
vdp2.reg.BKTA = REG_UL(BKTAU__BKCLMD_SINGLE_COLOR, 0x4000);
*((reg16 *)&vdp2.vram[0x8000]) = 31; // red
// background color, rgb15
vdp2.vram.u16[0x8000 / 2] = (0x05 << 0); // dark red
//
// vdp2: define and place a single character on NBG0
//
vdp2.reg.BGON = BGON__N0ON;
vdp2.reg.CHCTLA = ( CHCTLA__N0CHCN__16_COLOR // 4 bits per pixel, palettized
| CHCTLA__N0BMSZ__512x512_DOT
| CHCTLA__N0BMEN__CELL_FORMAT
| CHCTLA__N0CHSZ__1x1_CELL
);
vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD;
vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1;
vdp2.vram.u16[16 + 0] = (1 << 12); // top left pixel of character # 1
vdp2.vram.u16[16 + 15] = (2 << 0 ); // bottom right pixel of character # 1
vdp2.cram.u16[1] = (0x31 << 5); // green
vdp2.cram.u16[2] = (0x31 << 10); // blue
// given:
// Plane Size: 1h X 1v
// Pattern Name Data Size: 2 Words
// only bits 5~0 are used for map address calculation
// so MPOFN is effectively ignored
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(1); // bits 5~0
vdp2.reg.MPCDN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(1); // bits 5~0
// Table 4.8 Address value of map designated register by setting
// (bit 5~0) * 0x4000
vdp2.vram.u32[(0x4000 / 4)] = PATTERN_NAME_TABLE_2WORD__CHARACTER(1);
while (1) {}
}

2
type.h
View File

@ -9,4 +9,4 @@ static_assert((sizeof (reg8)) == 1);
static_assert((sizeof (reg16)) == 2);
static_assert((sizeof (reg32)) == 4);
#define REG32_VAL(U, L) (((U) << 16) | (L))
#define REG_UL(U, L) (((U) << 16) | (L))

516
vdp2.h
View File

@ -2,9 +2,24 @@
/* memory offsets */
typedef unsigned char vdp2_vram[0x080000];
typedef union vdp2_vram {
unsigned char u8[0x080000 / 1];
unsigned short u16[0x080000 / 2];
unsigned long u32[0x080000 / 4];
} vdp2_vram;
static_assert((sizeof (union vdp2_vram)) == 0x080000);
typedef unsigned char vdp2_res0[0x080000];
typedef unsigned char vdp2_cram[0x001000];
typedef union vdp2_cram {
unsigned char u8[0x001000 / 1];
unsigned short u16[0x001000 / 2];
unsigned long u32[0x001000 / 4];
} vdp2_cram;
static_assert((sizeof (union vdp2_cram)) == 0x001000);
typedef unsigned char vdp2_res1[0x07f000];
typedef struct vdp2_reg {
@ -32,11 +47,11 @@ typedef struct vdp2_reg {
reg16 CHCTLB; /* CHARACTER CONTROL (NBG2, NBG3, RGB0) */
reg16 BMPNA; /* BITMAP PALETTE NUMBER (NBG0, NBG1) */
reg16 BMPNB; /* BITMAP PALETTE NUMBER (RGB0) */
reg16 NBG0; /* PATTERN NAME CONTROL (NBG0) */
reg16 NBG1; /* PATTERN NAME CONTROL (NBG1) */
reg16 NBG2; /* PATTERN NAME CONTROL (NBG2) */
reg16 NBG3; /* PATTERN NAME CONTROL (NBG2) */
reg16 RGB0; /* PATTERN NAME CONTROL (RGB0) */
reg16 PNCN0; /* PATTERN NAME CONTROL (NBG0) */
reg16 PNCN1; /* PATTERN NAME CONTROL (NBG1) */
reg16 PNCN2; /* PATTERN NAME CONTROL (NBG2) */
reg16 PNCN3; /* PATTERN NAME CONTROL (NBG2) */
reg16 PNCR; /* PATTERN NAME CONTROL (RGB0) */
reg16 PLSZ; /* PLANE SIZE */
reg16 MPOFN; /* MAP OFFSET (NBG0~NBG3) */
reg16 MPOFR; /* MAP OFFSET (ROTATION PARAMETER A,B) */
@ -178,30 +193,473 @@ extern struct vdp2 vdp2 __asm("vdp2");
/* register bits */
/* TVMD */
#define TVMD__DISP (1 << 15)
#define TVMD__BDCLMD (1 << 8) // display back screen
#define TVMD__LSMD__NON_INTERLACE (0b00 << 6)
#define TVMD__LSMD__SINGLE_DENSITY (0b10 << 6)
#define TVMD__LSMD__DOUBLE_DENSITY (0b11 << 6)
enum bits_tvmd {
TVMD__DISP = (1 << 15),
TVMD__BDCLMD = (1 << 8), // display back screen
TVMD__LSMD__NON_INTERLACE = (0b00 << 6),
TVMD__LSMD__SINGLE_DENSITY = (0b10 << 6),
TVMD__LSMD__DOUBLE_DENSITY = (0b11 << 6),
#define TVMD__VRESO__224 (0b00 << 4)
#define TVMD__VRESO__240 (0b01 << 4)
#define TVMD__VRESO__256 (0b10 << 4)
TVMD__VRESO__224 = (0b00 << 4),
TVMD__VRESO__240 = (0b01 << 4),
TVMD__VRESO__256 = (0b10 << 4),
#define TVMD__HRESO__NORMAL_320 (0b000 << 0)
#define TVMD__HRESO__NORMAL_352 (0b001 << 0)
#define TVMD__HRESO__HIRES_640 (0b010 << 0)
#define TVMD__HRESO__HIRES_704 (0b011 << 0)
TVMD__HRESO__NORMAL_320 = (0b000 << 0),
TVMD__HRESO__NORMAL_352 = (0b001 << 0),
TVMD__HRESO__HIRES_640 = (0b010 << 0),
TVMD__HRESO__HIRES_704 = (0b011 << 0),
#define TVMD__HRESO__EXCLUSIVE_320 (0b100 << 0)
#define TVMD__HRESO__EXCLUSIVE_352 (0b101 << 0)
#define TVMD__HRESO__EXCLUSIVE_640 (0b110 << 0)
#define TVMD__HRESO__EXCLUSIVE_704 (0b111 << 0)
TVMD__HRESO__EXCLUSIVE_320 = (0b100 << 0),
TVMD__HRESO__EXCLUSIVE_352 = (0b101 << 0),
TVMD__HRESO__EXCLUSIVE_640 = (0b110 << 0),
TVMD__HRESO__EXCLUSIVE_704 = (0b111 << 0),
};
// enum bits_exten {
// };
enum bits_tvstat {
TVSTAT__VBLANK = (1 << 3),
};
// enum bits_vrsize {
// };
// enum bits_hcnt {
// };
// enum bits_vcnt {
// };
// enum bits_ramctl {
// };
// enum bits_cyca0l {
// };
// enum bits_cyca0u {
// };
// enum bits_cyca1l {
// };
// enum bits_cyca1u {
// };
// enum bits_cycb0l {
// };
// enum bits_cycb0u {
// };
// enum bits_cycb1l {
// };
// enum bits_cycb1u {
// };
enum bits_bgon {
BGON__R0TPON = (1 << 12),
BGON__N3TPON = (1 << 11),
BGON__N2TPON = (1 << 10),
BGON__N1TPON = (1 << 9),
BGON__N0TPON = (1 << 8),
/* TVSTAT */
#define TVSTAT__VBLANK (1 << 3)
BGON__R1ON = (1 << 5),
BGON__R0ON = (1 << 4),
BGON__N3ON = (1 << 3),
BGON__N2ON = (1 << 2),
BGON__N1ON = (1 << 1),
BGON__N0ON = (1 << 0),
};
// enum bits_mzctl {
// };
// enum bits_sfsel {
// };
// enum bits_sfcode {
// };
enum bits_chctla {
CHCTLA__N1CHCN__16_COLOR = (0b00 << 12),
CHCTLA__N1CHCN__256_COLOR = (0b00 << 12),
CHCTLA__N1CHCN__2K_COLOR = (0b00 << 12),
CHCTLA__N1CHCN__32K_COLOR = (0b00 << 12),
/* BKTAU */
#define BKTAU__BKCLMD_SINGLE_COLOR (0 << 15)
#define BKTAU__BKCLMD_PER_LINE (1 << 15)
CHCTLA__N1BMSZ__512x256_DOT = (0b00 << 10),
CHCTLA__N1BMSZ__512x512_DOT = (0b01 << 10),
CHCTLA__N1BMSZ__1024x256_DOT = (0b10 << 10),
CHCTLA__N1BMSZ__1024x512_DOT = (0b11 << 10),
CHCTLA__N1BMEN__CELL_FORMAT = (0 << 9),
CHCTLA__N1BMEN__BITMAP_FORMAT = (1 << 9),
CHCTLA__N1CHSZ__1x1_CELL = (0 << 8),
CHCTLA__N1CHSZ__2x2_CELL = (1 << 8),
CHCTLA__N0CHCN__16_COLOR = (0b000 << 4),
CHCTLA__N0CHCN__256_COLOR = (0b001 << 4),
CHCTLA__N0CHCN__2K_COLOR = (0b010 << 4),
CHCTLA__N0CHCN__32K_COLOR = (0b011 << 4),
CHCTLA__N0CHCN__16M_COLOR = (0b100 << 4),
CHCTLA__N0BMSZ__512x256_DOT = (0b00 << 2),
CHCTLA__N0BMSZ__512x512_DOT = (0b01 << 2),
CHCTLA__N0BMSZ__1024x256_DOT = (0b10 << 2),
CHCTLA__N0BMSZ__1024x512_DOT = (0b11 << 2),
CHCTLA__N0BMEN__CELL_FORMAT = (0 << 1),
CHCTLA__N0BMEN__BITMAP_FORMAT = (0 << 1),
CHCTLA__N0CHSZ__1x1_CELL = (0 << 0),
CHCTLA__N0CHSZ__2x2_CELL = (1 << 0),
};
enum bits_chctlb {
CHCTLB__R0CHCN__16_COLOR = (0b000 << 12),
CHCTLB__R0CHCN__256_COLOR = (0b001 << 12),
CHCTLB__R0CHCN__2K_COLOR = (0b010 << 12),
CHCTLB__R0CHCN__32K_COLOR = (0b011 << 12),
CHCTLB__R0CHCN__16M_COLOR = (0b100 << 12),
CHCTLB__R0BMSZ__512x256_DOT = (0 << 10),
CHCTLB__R0BMSZ__512x512_DOT = (1 << 10),
CHCTLB__R0BMEN__CELL_FORMAT = (0 << 9),
CHCTLB__R0BMEN__BITMAP_FORMAT = (1 << 9),
CHCTLB__R0CHSZ__1x1_CELL = (0 << 8),
CHCTLB__R0CHSZ__2x2_CELL = (1 << 8),
CHCTLB__N3CHCN__16_COLOR = (0 << 5),
CHCTLB__N3CHCN__256_COLOR = (1 << 5),
CHCTLB__N3CHSZ__1x1_CELL = (0 << 4),
CHCTLB__N3CHSZ__2x2_CELL = (1 << 4),
CHCTLB__N2CHCN__16_COLOR = (0 << 1),
CHCTLB__N2CHCN__256_COLOR = (1 << 1),
CHCTLB__N2CHSZ__1x1_CELL = (0 << 4),
CHCTLB__N2CHSZ__2x2_CELL = (1 << 4),
};
// enum bits_bmpna {
// };
// enum bits_bmpnb {
// };
enum bits_pncn0 {
PNCN0__N0PNB__2WORD = (0 << 15),
PNCN0__N0PNB__1WORD = (1 << 15),
PNCN0__N0CNSM = (1 << 14),
PNCN0__N0SPR = (1 << 9),
PNCN0__N0SCC = (1 << 8),
#define PNCN0__N0SPLT(n) (n << 5)
#define PNCN0__N0SCN(n) (n << 0)
};
enum bits_pncn1 {
PNCN1__N1PNB__2WORD = (0 << 15),
PNCN1__N1PNB__1WORD = (1 << 15),
PNCN1__N1CNSM = (1 << 14),
PNCN1__N1SPR = (1 << 9),
PNCN1__N1SCC = (1 << 8),
#define PNCN1__N1SPLT(n) (n << 5)
#define PNCN1__N1SCN(n) (n << 0)
};
enum bits_pncn2 {
PNCN2__N2PNB__2WORD = (0 << 15),
PNCN2__N2PNB__1WORD = (1 << 15),
PNCN2__N2CNSM = (1 << 14),
PNCN2__N2SPR = (1 << 9),
PNCN2__N2SCC = (1 << 8),
#define PNCN2__N2SPLT(n) (n << 5)
#define PNCN2__N2SCN(n) (n << 0)
};
enum bits_pncn3 {
PNCN3__N3PNB__2WORD = (0 << 15),
PNCN3__N3PNB__1WORD = (1 << 15),
PNCN3__N3CNSM = (1 << 14),
PNCN3__N3SPR = (1 << 9),
PNCN3__N3SCC = (1 << 8),
#define PNCN3__N3SPLT(n) (n << 5)
#define PNCN3__N3SCN(n) (n << 0)
};
enum bits_pncr {
PNCR__R0PNB__2WORD = (0 << 15),
PNCR__R0PNB__1WORD = (1 << 15),
PNCR__R0CNSM = (1 << 14),
PNCR__R0SPR = (1 << 9),
PNCR__R0SCC = (1 << 8),
#define PNCR__R0SPLT(n) (n << 5)
#define PNCR__R0SCN(n) (n << 0)
};
enum bits_plsz {
PLSZ__RBOVR__ = (0b00 << 14),
PLSZ__RBPLSZ__ = (0b00 << 12),
PLSZ__RAOVR__ = (0b00 << 10),
PLSZ__RAPLSZ__ = (0b00 << 8),
PLSZ__N3PLSZ__1x1 = (0b00 << 6),
PLSZ__N3PLSZ__2x1 = (0b01 << 6),
PLSZ__N3PLSZ__2x2 = (0b11 << 6),
PLSZ__N2PLSZ__1x1 = (0b00 << 4),
PLSZ__N2PLSZ__2x1 = (0b01 << 4),
PLSZ__N2PLSZ__2x2 = (0b11 << 4),
PLSZ__N1PLSZ__1x1 = (0b00 << 2),
PLSZ__N1PLSZ__2x1 = (0b01 << 2),
PLSZ__N1PLSZ__2x2 = (0b11 << 2),
PLSZ__N0PLSZ__1x1 = (0b00 << 0),
PLSZ__N0PLSZ__2x1 = (0b01 << 0),
PLSZ__N0PLSZ__2x2 = (0b11 << 0),
};
// enum bits_mpofn {
#define MPOFN__N3MP(n) (n << 12)
#define MPOFN__N2MP(n) (n << 8)
#define MPOFN__N1MP(n) (n << 4)
#define MPOFN__N0MP(n) (n << 0)
// };
// enum bits_mpofr {
#define MPOFR__RBMP(n) (n << 4)
#define MPOFR__RAMP(n) (n << 0)
// };
// 4.8 Maps § Map Selection Register
// enum bits_mpabn0 {
#define MPABN0__N0MPB(n) (n << 8)
#define MPABN0__N0MPA(n) (n << 0)
// };
// enum bits_mpcdn0 {
#define MPABN0__N0MPD(n) (n << 8)
#define MPABN0__N0MPC(n) (n << 0)
// };
// enum bits_mpabn1 {
#define MPABN1__N1MPB(n) (n << 8)
#define MPABN1__N1MPA(n) (n << 0)
// };
// enum bits_mpcdn1 {
#define MPABN1__N1MPD(n) (n << 8)
#define MPABN1__N1MPC(n) (n << 0)
// };
// enum bits_mpabn2 {
#define MPABN2__N2MPB(n) (n << 8)
#define MPABN2__N2MPA(n) (n << 0)
// };
// enum bits_mpcdn2 {
#define MPABN2__N2MPD(n) (n << 8)
#define MPABN2__N2MPC(n) (n << 0)
// };
// enum bits_mpabn3 {
#define MPABN3__N3MPB(n) (n << 8)
#define MPABN3__N3MPA(n) (n << 0)
// };
// enum bits_mpcdn3 {
#define MPABN3__N3MPD(n) (n << 8)
#define MPABN3__N3MPC(n) (n << 0)
// };
// enum bits_mpabra {
// };
// enum bits_mpcdra {
// };
// enum bits_mpefra {
// };
// enum bits_mpghra {
// };
// enum bits_mpijra {
// };
// enum bits_mpklra {
// };
// enum bits_mpmnra {
// };
// enum bits_mpopra {
// };
// enum bits_mpabrb {
// };
// enum bits_mpcdrb {
// };
// enum bits_mpefrb {
// };
// enum bits_mpghrb {
// };
// enum bits_mpijrb {
// };
// enum bits_mpklrb {
// };
// enum bits_mpmnrb {
// };
// enum bits_mpoprb {
// };
// enum bits_scxin0 {
// };
// enum bits_scxdn0 {
// };
// enum bits_scyin0 {
// };
// enum bits_scydn0 {
// };
// enum bits_zmxin0 {
// };
// enum bits_zmxdn0 {
// };
// enum bits_zmyin0 {
// };
// enum bits_zmydn0 {
// };
// enum bits_scxin1 {
// };
// enum bits_scxdn1 {
// };
// enum bits_scyin1 {
// };
// enum bits_scydn1 {
// };
// enum bits_zmxin1 {
// };
// enum bits_zmxdn1 {
// };
// enum bits_zmyin1 {
// };
// enum bits_zmydn1 {
// };
// enum bits_scxn2 {
// };
// enum bits_scyn2 {
// };
// enum bits_scxn3 {
// };
// enum bits_scyn3 {
// };
// enum bits_zmctl {
// };
// enum bits_scrctl {
// };
// enum bits_vcstau {
// };
// enum bits_vcstal {
// };
// enum bits_lsta0u {
// };
// enum bits_lsta0l {
// };
// enum bits_lsta1u {
// };
// enum bits_lsta1l {
// };
// enum bits_lctau {
// };
// enum bits_lctal {
// };
enum bits_bktau {
BKTAU__BKCLMD_SINGLE_COLOR = (0 << 15),
BKTAU__BKCLMD_PER_LINE = (1 << 15),
};
// enum bits_bktal {
// };
// enum bits_rpmd {
// };
// enum bits_rprctl {
// };
// enum bits_ktctl {
// };
// enum bits_ktaof {
// };
// enum bits_ovpnra {
// };
// enum bits_ovpnrb {
// };
// enum bits_rptau {
// };
// enum bits_rptal {
// };
// enum bits_wpsx0 {
// };
// enum bits_wpsy0 {
// };
// enum bits_wpex0 {
// };
// enum bits_wpey0 {
// };
// enum bits_wpsx1 {
// };
// enum bits_wpsy1 {
// };
// enum bits_wpex1 {
// };
// enum bits_wpey1 {
// };
// enum bits_wctla {
// };
// enum bits_wctlb {
// };
// enum bits_wctlc {
// };
// enum bits_wctld {
// };
// enum bits_lwta0u {
// };
// enum bits_lwta0l {
// };
// enum bits_lwta1u {
// };
// enum bits_lwta1l {
// };
// enum bits_spctl {
// };
// enum bits_sdctl {
// };
// enum bits_craofa {
// };
// enum bits_craofb {
// };
// enum bits_lnclen {
// };
// enum bits_sfprmd {
// };
// enum bits_ccctl {
// };
// enum bits_sfccmd {
// };
// enum bits_prisa {
// };
// enum bits_prisb {
// };
// enum bits_prisc {
// };
// enum bits_prisd {
// };
// enum bits_prina {
// };
// enum bits_prinb {
// };
// enum bits_prir {
// };
// enum bits_ccrsa {
// };
// enum bits_ccrsb {
// };
// enum bits_ccrsc {
// };
// enum bits_ccrsd {
// };
// enum bits_ccrna {
// };
// enum bits_ccrnb {
// };
// enum bits_ccrr {
// };
// enum bits_ccrlb {
// };
// enum bits_clofen {
// };
// enum bits_clofsl {
// };
// enum bits_coar {
// };
// enum bits_coag {
// };
// enum bits_coab {
// };
// enum bits_cobr {
// };
// enum bits_cobg {
// };
// enum bits_cobb {
// };
//
// pattern name tables
//
#define PATTERN_NAME_TABLE_2WORD__CHARACTER(n) (n << 0)
#define PATTERN_NAME_TABLE_2WORD__PALETTE(n) (n << 16)