diff --git a/.gitignore b/.gitignore index 762b381..a610673 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ __pycache__ *.iso *.cdi *.o +*.out scramble -cdi4dc \ No newline at end of file +cdi4dc diff --git a/alt.lds b/alt.lds new file mode 100644 index 0000000..db089da --- /dev/null +++ b/alt.lds @@ -0,0 +1,71 @@ +OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl") +MEMORY +{ + p1ram : ORIGIN = 0xac020000, LENGTH = 16M +} +SECTIONS +{ + . = 0xac020000; + + .text ALIGN(4) : SUBALIGN(4) + { + KEEP(*(.text.start)) + *(.text.startup.*) + *(.text.*) + *(.text) + } > p1ram + + .data ALIGN(4) : SUBALIGN(4) + { + *(.data) + *(.data.*) + } > p1ram + + .rodata ALIGN(4) : SUBALIGN(4) + { + *(.rodata) + *(.rodata.*) + } > p1ram + + .ctors ALIGN(4) : SUBALIGN(4) + { + KEEP(*(.ctors)) + KEEP(*(.ctors.*)) + } > p1ram + + .bss ALIGN(4) (NOLOAD) : SUBALIGN(4) + { + *(.bss) + *(.bss.*) + } > p1ram + + __p1ram_end = .; + + /DISCARD/ : + { + *(.debug*) + *(.comment*) + *(.rela*) + } + + __bss_link_start = ADDR(.bss); + __bss_link_end = ADDR(.bss) + SIZEOF(.bss); + + __ctors_link_start = ADDR(.ctors); + __ctors_link_end = ADDR(.ctors) + SIZEOF(.ctors); +} + +__p1ram_start = ORIGIN(p1ram); +__p1ram_end = ORIGIN(p1ram) + LENGTH(p1ram); + +SH7091_IC_A = 0xf0000000; +SH7091_IC_D = 0xf1000000; +SH7091_OC_A = 0xf4000000; +SH7091_OC_D = 0xf5000000; +SH7091 = 0xff000000; +HOLLY = 0xa05f8000; +SYSTEM = 0xa05F6800; +MAPLE_IF = 0xa05F6C00; +G1_IF = 0xa05F7400; +G2_IF = 0xa05F7800; +PVR_IF = 0xa05F7C00; diff --git a/client.py b/client.py new file mode 100644 index 0000000..c88a1aa --- /dev/null +++ b/client.py @@ -0,0 +1,68 @@ +import serial +import struct +import sys +import time + +dest = 0xac02_0000 + +ret = [] + +def sync(ser, b): + l = [] + for i, c in enumerate(b): + if i % 32 == 0: + print(i, end=' ') + sys.stdout.flush() + ser.write(bytes([c])) + ser.flush() + ser.flushInput() + ser.flushOutput() + time.sleep(0.01) + while ser.in_waiting > 0: + res = ser.read(ser.in_waiting) + for c in res: + l.append(c) + time.sleep(0.01) + + time.sleep(1) + res = ser.read(ser.in_waiting) + for c in res: + l.append(c) + + return bytes(l) + +def do(ser, b): + ser.flush() + ser.flushInput() + ser.flushOutput() + + ret = sync(ser, b'DATA') + print(ret) + size = len(b) + args = struct.pack(" + +#include "sh7091.h" +#include "holly.h" + +enum load_command { + CMD_NONE, + CMD_DATA, // DATA 0000 0000 {data} + CMD_JUMP, // JUMP 0000 +}; + +struct load_state { + union { + uint8_t buf[12]; + struct { + uint8_t cmd[4]; + uint32_t addr1; + uint32_t addr2; + }; + }; + uint32_t len; + enum load_command command; +}; + +static struct load_state state; + +void move(void *dest, const void *src, size_t n) +{ + uint8_t *d = dest; + const uint8_t *s = src; + + if (d==s) return; + if (d= 4) { + if (state.buf[0] == 'D' && + state.buf[1] == 'A' && + state.buf[2] == 'T' && + state.buf[3] == 'A') { + if (state.len < 12) { + return; + } else { + debug("data\n"); + state.command = CMD_DATA; + return; + } + } else if (state.buf[0] == 'J' && + state.buf[1] == 'U' && + state.buf[2] == 'M' && + state.buf[3] == 'P') { + if (state.len < 8) { + return; + } else { + debug("jump\n"); + state.command = CMD_JUMP; + } + } else { + move(&state.buf[0], &state.buf[4], state.len - 4); + state.len -= 4; + } + } else { + return; + } + break; + case CMD_DATA: + { + uint32_t * size = &state.addr1; + uint8_t * dest = (uint8_t *)state.addr2; + if (size > 0) { + SH7091.SCIF.SCFTDR2 = c; + + // write c to dest + *dest = c; + state.addr2++; + + (*size)--; + } + if (*size == 0) { + state.len = 0; + state.command = CMD_NONE; + debug("next\n"); + } + return; + break; + case CMD_JUMP: + // jump + state.len = 0; + state.command = CMD_NONE; + debug("prejump\n"); + HOLLY.VO_BORDER_COL = (31 << 11); + void (*fptr)(void) = (void (*)(void))state.addr1; + HOLLY.VO_BORDER_COL = (63 << 5) | (31 << 0); + fptr(); + debug("postjump\n"); + return; + break; + } + } + } +} diff --git a/load.h b/load.h new file mode 100644 index 0000000..9ed6ce7 --- /dev/null +++ b/load.h @@ -0,0 +1,4 @@ +#pragma once + +void load_init(); +void load_recv(uint8_t c); diff --git a/main.c b/main.c index 9b6783a..ec6aef2 100644 --- a/main.c +++ b/main.c @@ -1,262 +1,66 @@ #include #include "cache.h" +#include "load.h" #include "sh7091.h" #include "sh7091_bits.h" -#include "holly.h" - -volatile uint32_t * RAM = (volatile uint32_t *)0xa5000000; - -volatile uint32_t * SPG_STATUS = (volatile uint32_t *)0xa05f810; - -uint32_t get_cable_type() -{ - /* set all pins to input */ - SH7091.BSC.PCTRA = 0; - - /* get cable type from pins 9 + 8 */ - return SH7091.BSC.PDTRA & PDTRA__MASK; -} - -void vga1() -{ - uint16_t pclk_delay = 0x0016; - uint32_t fb_r_ctrl = HOLLY.FB_R_CTRL; - HOLLY.FB_R_CTRL = fb_r_ctrl & ~(1 << 0); // fb_enable = 0 - HOLLY.VO_CONTROL = pclk_delay << 16 | (1 << 3); // blank_video - HOLLY.FB_R_CTRL = fb_r_ctrl & (1<<23); // vclk_div, for VGA - - HOLLY.FB_R_SIZE = 0; - - uint16_t vblank_in = 0x0208; - uint16_t vblank_out = 0x0015; - HOLLY.SPG_VBLANK_INT = (vblank_out << 16) | (vblank_in << 0); - - HOLLY.SPG_CONTROL = (1 << 8); // sync_direction__output ; non-default - - uint16_t hbstart = 0x0345; // default - uint16_t hbend = 0x007e; // default - HOLLY.SPG_HBLANK = (hbend << 16) | (hbstart << 0); - - uint16_t hcount = 0x0359; // default - uint16_t vcount = 0x020c; // non-default - HOLLY.SPG_LOAD = (vcount << 16) | (hcount << 0); - - uint16_t vbstart = 0x0208; // non-default - uint16_t vbend = 0x0028; // non-default - HOLLY.SPG_VBLANK = (vbend << 16) | (vbstart << 0); - - uint16_t hswidth = 0x003f; - uint16_t vswidth = 0x0003; - uint16_t bpwidth = 0x0319; - uint16_t eqwidth = 0x000f; - HOLLY.SPG_WIDTH = - (hswidth << 0) - | (vswidth << 8) - | (bpwidth << 12) - | (eqwidth << 22); - - uint16_t startx = 0x0a8; - uint16_t starty = 0x028; - HOLLY.VO_STARTX = startx; - HOLLY.VO_STARTY = (starty << 16) | (starty << 0); - - HOLLY.SPG_HBLANK_INT = hbstart << 16; -} - -void vga2() -{ - uint16_t xsize = 640; - uint16_t ysize = 480; - - uint16_t fb_xclip_min = 0; - uint16_t fb_xclip_max = xsize-1; - HOLLY.FB_X_CLIP = (fb_xclip_max << 16) | (fb_xclip_min << 0); - uint16_t fb_yclip_min = 0; - uint16_t fb_yclip_max = ysize-1; - HOLLY.FB_Y_CLIP = (fb_yclip_max << 16) | (fb_yclip_min << 0); - - uint16_t fb_latency = 0x09; - uint16_t fb_burstctrl = 15 - fb_latency; - uint16_t wr_burst = 0x08; - HOLLY.FB_BURSTCTRL = 0 - | (fb_burstctrl << 0) - | (fb_latency << 4) - | (wr_burst << 9) - ; - - uint32_t fb_xsize = (xsize * 16)/(32) - 1; - uint32_t fb_ysize = ysize - 3; - uint32_t fb_mod = 1; - HOLLY.FB_R_SIZE = 0 - | (fb_xsize << 0) - | (fb_ysize << 10) - | (fb_mod << 20); - - uint16_t coeff0 = 0x40; - uint16_t coeff1 = 0x80; - HOLLY.Y_COEFF = (coeff1 << 8) | (coeff0 << 0); - - uint16_t vscale_factor = 0x0400; - HOLLY.SCALER_CTL = (vscale_factor << 0); - - uint32_t fb_linestride = (xsize * 16) / 64; - HOLLY.FB_W_LINESTRIDE = fb_linestride; - - HOLLY.FB_W_CTRL = 0 - | 0b001 << 0 // fb_packmode: RGB 565 - ; - - HOLLY.FB_W_SOF1 = 0; - HOLLY.FB_W_SOF2 = 0; - HOLLY.FB_R_SOF1 = 0; - HOLLY.FB_R_SOF2 = 0; - - HOLLY.FB_R_CTRL = 0 - | 1 << 23 // vclk_div - | 0 << 22 // fb_strip_buf_en - | 0 << 16 // fb_strip_size - | 0 << 8 // fb_chroma_threshold - | 0 << 4 // fb_concat - | 1 << 2 // fb_depth - | 0 << 1 // fb_line_double - | 1 << 0 // fb_enable - ; - - *((reg32 *)0xa0702c00) = 0; -} - -void v_sync_in() -{ -#define V_SYNC (1<<13) - while (!(V_SYNC & HOLLY.SPG_STATUS)) { - asm volatile ("nop"); - } - while ((V_SYNC & HOLLY.SPG_STATUS)) { - asm volatile ("nop"); - } -#undef V_SYNC -} - -void vga() -{ - get_cable_type(); - - HOLLY.SOFTRESET = 0; - HOLLY.TEXT_CONTROL = 3; - HOLLY.FB_W_CTRL = 9; - - SH7091.SCIF.SCFTDR2 = 'g'; - /* - */ - SH7091.SCIF.SCFTDR2 = 'v'; - vga1(); - vga2(); - - v_sync_in(); - - HOLLY.VO_BORDER_COL = 31; - HOLLY.VO_CONTROL = 0x0016; -} extern uint32_t __bss_link_start __asm("__bss_link_start"); extern uint32_t __bss_link_end __asm("__bss_link_end"); -struct rgb +void serial() { - unsigned char r; - unsigned char g; - unsigned char b; -}; + SH7091.SCIF.SCSCR2 = 0; + SH7091.SCIF.SCSMR2 = 0; + SH7091.SCIF.SCBRR2 = 12; -struct hsv -{ - unsigned char h; - unsigned char s; - unsigned char v; -}; +#define SCFCR2__TFRST (1 << 2) +#define SCFCR2__RFRST (1 << 1) + SH7091.SCIF.SCFCR2 = SCFCR2__TFRST | SCFCR2__RFRST; + // tx/rx trigger on 1 byte + SH7091.SCIF.SCFCR2 = 0; -struct rgb hsv_to_rgb(struct hsv hsv) -{ - struct rgb rgb; - unsigned char region, remainder, p, q, t; + SH7091.SCIF.SCSPTR2 = 0; + SH7091.SCIF.SCLSR2 = 0; - if (hsv.s == 0) { - rgb.r = hsv.v; - rgb.g = hsv.v; - rgb.b = hsv.v; - return rgb; - } - - region = hsv.h / 43; - remainder = (hsv.h - (region * 43)) * 6; - - p = (hsv.v * (255 - hsv.s)) >> 8; - q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8; - t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8; - - switch (region) { - case 0: rgb.r = hsv.v; rgb.g = t; rgb.b = p; break; - case 1: rgb.r = q; rgb.g = hsv.v; rgb.b = p; break; - case 2: rgb.r = p; rgb.g = hsv.v; rgb.b = t; break; - case 3: rgb.r = p; rgb.g = q; rgb.b = hsv.v; break; - case 4: rgb.r = t; rgb.g = p; rgb.b = hsv.v; break; - default: rgb.r = hsv.v; rgb.g = p; rgb.b = q; break; - } - - return rgb; +#define SCSCR2__TE (1 << 5) +#define SCSCR2__RE (1 << 4) + SH7091.SCIF.SCSCR2 = SCSCR2__TE | SCSCR2__RE; } void main() { cache_init(); + // clear BSS uint32_t * start = &__bss_link_start; uint32_t * end = &__bss_link_end; while (start < end) { *start++ = 0; } - // clear BSS + serial(); -#define SCSCR2__TE (1 << 5) -#define SCSCR2__RE (1 << 4) - SH7091.SCIF.SCSCR2 = 0; - SH7091.SCIF.SCSMR2 = 0; - SH7091.SCIF.SCBRR2 = 12; - - SH7091.SCIF.SCFCR2 = (1 << 2) | (1 << 1); // tfrst rfrst - SH7091.SCIF.SCFCR2 = 0; - - SH7091.SCIF.SCSPTR2 = 0; - SH7091.SCIF.SCLSR2 = 0; - - SH7091.SCIF.SCSCR2 = SCSCR2__TE | SCSCR2__RE; - - SH7091.SCIF.SCFTDR2 = 'H'; - SH7091.SCIF.SCFTDR2 = 'e'; - SH7091.SCIF.SCFTDR2 = 'l'; - SH7091.SCIF.SCFTDR2 = 'o'; - - vga(); + load_init(); while (1) { - v_sync_in(); - SH7091.SCIF.SCFTDR2 = 'v'; - SH7091.SCIF.SCFTDR2 = 'g'; - SH7091.SCIF.SCFTDR2 = 'a'; +#define SCFSR2__ER (1 << 7) /* read error */ +#define SCFSR2__TEND (1 << 6) /* transmit end */ +#define SCFSR2__TFDE (1 << 5) /* transmit fifo data empty */ +#define SCFSR2__BRK (1 << 4) /* break detect */ +#define SCFSR2__FER (1 << 3) /* framing error */ +#define SCFSR2__PER (1 << 2) /* parity error */ +#define SCFSR2__RDF (1 << 1) /* receive FIFO data full */ +#define SCFSR2__DR (1 << 0) /* receive data ready */ - reg16 * vram = (reg16 *)0xa5000000; - for (int y = 0; y < 480; y++) { - for (int x = 0; x < 640; x++) { - struct hsv hsv = {(y * 255) / 480, 255, 255}; - struct rgb rgb = hsv_to_rgb(hsv); - vram[y * 640 + x] = (rgb.r >> 3) | ((rgb.g >> 2) << 5) | ((rgb.b >> 3) << 11); - } + while ((SH7091.SCIF.SCFSR2 & SCFSR2__RDF) == 0) { + // wait } - vram[0] = 0xf000; - vram[10] = 0xf0ff; - vram[11] = 0xf0ab; + while ((SH7091.SCIF.SCFDR2 & 0b11111) > 0) { + uint8_t c = SH7091.SCIF.SCFRDR2; + load_recv(c); + } + SH7091.SCIF.SCFSR2 = SH7091.SCIF.SCFSR2 & (~SCFSR2__RDF); } } diff --git a/regs/gen/systembus.py b/regs/gen/systembus.py index c42ce7d..a1d1c6e 100644 --- a/regs/gen/systembus.py +++ b/regs/gen/systembus.py @@ -6,10 +6,21 @@ from sh7091 import headers from sh7091 import blocks from generate import renderer +def blocks(rows): + blocks = [] + for row in rows: + block = row["block"] + if block not in blocks: + blocks.append(block) + + for block in blocks: + yield f'extern struct {block.lower()}_reg {block} __asm("{block}");' + input_file = sys.argv[1] rows = read_input(input_file) process = new_writer() render, out = renderer() render(headers()) render(process(rows)) +render(blocks(rows)) sys.stdout.write(out.getvalue()) diff --git a/regs/systembus.csv b/regs/systembus.csv index 7faf702..09244e7 100644 --- a/regs/systembus.csv +++ b/regs/systembus.csv @@ -45,118 +45,118 @@ "SYSTEM","150","4","G2DTNRM","RW","Normal interrupt G2-DMA startup mask" "SYSTEM","154","4","G2DTEXT","RW","External interrupt G2-DMA startup mask" ,,,,, -"MAPLE","04","4","MDSTAR","RW","Maple-DMA command table address" +"MAPLE_IF","04","4","MDSTAR","RW","Maple-DMA command table address" ,,,,, -"MAPLE","10","4","MDTSEL","RW","Maple-DMA trigger select" -"MAPLE","14","4","MDEN","RW","Maple-DMA enable" -"MAPLE","18","4","MDST","RW","Maple-DMA start" +"MAPLE_IF","10","4","MDTSEL","RW","Maple-DMA trigger select" +"MAPLE_IF","14","4","MDEN","RW","Maple-DMA enable" +"MAPLE_IF","18","4","MDST","RW","Maple-DMA start" ,,,,, -"MAPLE","80","4","MSYS","RW","Maple system control" -"MAPLE","84","4","MST","R","Maple status" -"MAPLE","88","4","MSHTCL","W","Maple-DMA hard trigger clear" -"MAPLE","8c","4","MDAPRO","W","Maple-DMA address range" +"MAPLE_IF","80","4","MSYS","RW","Maple system control" +"MAPLE_IF","84","4","MST","R","Maple status" +"MAPLE_IF","88","4","MSHTCL","W","Maple-DMA hard trigger clear" +"MAPLE_IF","8c","4","MDAPRO","W","Maple-DMA address range" ,,,,, -"MAPLE","e8","4","MMSEL","RW","Maple MSP selection" +"MAPLE_IF","e8","4","MMSEL","RW","Maple MSP selection" ,,,,, -"MAPLE","f4","4","MTXDAD","R","Maple TXD address counter" -"MAPLE","f8","4","MRXDAD","R","Maple RXD address counter" -"MAPLE","fc","4","MRXDBD","R","Maple RXD address base" +"MAPLE_IF","f4","4","MTXDAD","R","Maple TXD address counter" +"MAPLE_IF","f8","4","MRXDAD","R","Maple RXD address counter" +"MAPLE_IF","fc","4","MRXDBD","R","Maple RXD address base" ,,,,, -"G1","04","4","GDSTAR","RW","GD-DMA start address" -"G1","08","4","GDLEN","RW","GD-DMA length" -"G1","0c","4","GDDIR","RW","GD-DMA direction" +"G1_IF","04","4","GDSTAR","RW","GD-DMA start address" +"G1_IF","08","4","GDLEN","RW","GD-DMA length" +"G1_IF","0c","4","GDDIR","RW","GD-DMA direction" ,,,,, -"G1","14","4","GDEN","RW","GD-DMA enable" -"G1","18","4","GDST","RW","GD-DMA start" +"G1_IF","14","4","GDEN","RW","GD-DMA enable" +"G1_IF","18","4","GDST","RW","GD-DMA start" ,,,,, -"G1","80","4","G1RRC","W","System ROM read access timing" -"G1","84","4","G1RWC","W","System ROM write access timing" -"G1","88","4","G1FRC","W","Flash ROM read access timing" -"G1","8c","4","G1FWC","W","Flash ROM write access timing" -"G1","90","4","G1CRC","W","GD PIO read access timing" -"G1","94","4","G1CWC","W","GD PIO write access timing" +"G1_IF","80","4","G1RRC","W","System ROM read access timing" +"G1_IF","84","4","G1RWC","W","System ROM write access timing" +"G1_IF","88","4","G1FRC","W","Flash ROM read access timing" +"G1_IF","8c","4","G1FWC","W","Flash ROM write access timing" +"G1_IF","90","4","G1CRC","W","GD PIO read access timing" +"G1_IF","94","4","G1CWC","W","GD PIO write access timing" ,,,,, -"G1","a0","4","G1GDRC","W","GD-DMA read access timing" -"G1","a4","4","G1GDWC","W","GD-DMA write access timing" +"G1_IF","a0","4","G1GDRC","W","GD-DMA read access timing" +"G1_IF","a4","4","G1GDWC","W","GD-DMA write access timing" ,,,,, -"G1","b0","4","G1SYSM","R","System mode" -"G1","b4","4","G1CRDYC","W","G1IORDY signal control" -"G1","b8","4","GDAPRO","W","GD-DMA address range" +"G1_IF","b0","4","G1SYSM","R","System mode" +"G1_IF","b4","4","G1CRDYC","W","G1IORDY signal control" +"G1_IF","b8","4","GDAPRO","W","GD-DMA address range" ,,,,, -"G1","f4","4","GDSTARD","R","GD-DMA address count (on Root Bus)" -"G1","f8","4","GDLEND","R","GD-DMA transfer counter" +"G1_IF","f4","4","GDSTARD","R","GD-DMA address count (on Root Bus)" +"G1_IF","f8","4","GDLEND","R","GD-DMA transfer counter" ,,,,, -"G2","00","4","ADSTAG","RW","ACIA:G2-DMA G2 start address" -"G2","04","4","ADSTAR","RW","ACIA:G2-DMA system memory start address" -"G2","08","4","ADLEN","RW","ACIA:G2-DMA length" -"G2","0c","4","ADDIR","RW","ACIA:G2-DMA direction" -"G2","10","4","ADTSEL","RW","ACIA:G2-DMA trigger select" -"G2","14","4","ADEN","RW","ACIA:G2-DMA enable" -"G2","18","4","ADST","RW","ACIA:G2-DMA start" -"G2","1c","4","ADSUSP","RW","ACIA:G2-DMA suspend" +"G2_IF","00","4","ADSTAG","RW","ACIA:G2-DMA G2 start address" +"G2_IF","04","4","ADSTAR","RW","ACIA:G2-DMA system memory start address" +"G2_IF","08","4","ADLEN","RW","ACIA:G2-DMA length" +"G2_IF","0c","4","ADDIR","RW","ACIA:G2-DMA direction" +"G2_IF","10","4","ADTSEL","RW","ACIA:G2-DMA trigger select" +"G2_IF","14","4","ADEN","RW","ACIA:G2-DMA enable" +"G2_IF","18","4","ADST","RW","ACIA:G2-DMA start" +"G2_IF","1c","4","ADSUSP","RW","ACIA:G2-DMA suspend" ,,,,, -"G2","20","4","E1STAG","RW","Ext1:G2-DMA start address" -"G2","24","4","E1STAR","RW","Ext1:G2-DMA system memory start address" -"G2","28","4","E1LEN","RW","Ext1:G2-DMA length" -"G2","2c","4","E1DIR","RW","Ext1:G2-DMA direction" -"G2","30","4","E1TSEL","RW","Ext1:G2-DMA trigger select" -"G2","34","4","E1EN","RW","Ext1:G2-DMA enable" -"G2","38","4","E1ST","RW","Ext1:G2-DMA start" -"G2","3c","4","E1SUSP","RW","Ext1:G2-DMA suspend" +"G2_IF","20","4","E1STAG","RW","Ext1:G2-DMA start address" +"G2_IF","24","4","E1STAR","RW","Ext1:G2-DMA system memory start address" +"G2_IF","28","4","E1LEN","RW","Ext1:G2-DMA length" +"G2_IF","2c","4","E1DIR","RW","Ext1:G2-DMA direction" +"G2_IF","30","4","E1TSEL","RW","Ext1:G2-DMA trigger select" +"G2_IF","34","4","E1EN","RW","Ext1:G2-DMA enable" +"G2_IF","38","4","E1ST","RW","Ext1:G2-DMA start" +"G2_IF","3c","4","E1SUSP","RW","Ext1:G2-DMA suspend" ,,,,, -"G2","40","4","E2STAG","RW","Ext2:G2-DMA start address" -"G2","44","4","E2STAR","RW","Ext2:G2-DMA system memory start address" -"G2","48","4","E2LEN","RW","Ext2:G2-DMA length" -"G2","4c","4","E2DIR","RW","Ext2:G2-DMA direction" -"G2","50","4","E2TSEL","RW","Ext2:G2-DMA trigger select" -"G2","54","4","E2EN","RW","Ext2:G2-DMA enable" -"G2","58","4","E2ST","RW","Ext2:G2-DMA start" -"G2","5c","4","E2SUSP","RW","Ext2:G2-DMA suspend" +"G2_IF","40","4","E2STAG","RW","Ext2:G2-DMA start address" +"G2_IF","44","4","E2STAR","RW","Ext2:G2-DMA system memory start address" +"G2_IF","48","4","E2LEN","RW","Ext2:G2-DMA length" +"G2_IF","4c","4","E2DIR","RW","Ext2:G2-DMA direction" +"G2_IF","50","4","E2TSEL","RW","Ext2:G2-DMA trigger select" +"G2_IF","54","4","E2EN","RW","Ext2:G2-DMA enable" +"G2_IF","58","4","E2ST","RW","Ext2:G2-DMA start" +"G2_IF","5c","4","E2SUSP","RW","Ext2:G2-DMA suspend" ,,,,, -"G2","60","4","DDSTAG","RW","Dev:G2-DMA start address" -"G2","64","4","DDSTAR","RW","Dev:G2-DMA system memory start address" -"G2","68","4","DDLEN","RW","Dev:G2-DMA length" -"G2","6c","4","DDDIR","RW","Dev:G2-DMA direction" -"G2","70","4","DDTSEL","RW","Dev:G2-DMA trigger select" -"G2","74","4","DDEN","RW","Dev:G2-DMA enable" -"G2","78","4","DDST","RW","Dev:G2-DMA start" -"G2","7c","4","DDSUSP","RW","Dev:G2-DMA suspend" +"G2_IF","60","4","DDSTAG","RW","Dev:G2-DMA start address" +"G2_IF","64","4","DDSTAR","RW","Dev:G2-DMA system memory start address" +"G2_IF","68","4","DDLEN","RW","Dev:G2-DMA length" +"G2_IF","6c","4","DDDIR","RW","Dev:G2-DMA direction" +"G2_IF","70","4","DDTSEL","RW","Dev:G2-DMA trigger select" +"G2_IF","74","4","DDEN","RW","Dev:G2-DMA enable" +"G2_IF","78","4","DDST","RW","Dev:G2-DMA start" +"G2_IF","7c","4","DDSUSP","RW","Dev:G2-DMA suspend" ,,,,, -"G2","80","4","G2ID","R","G2 bus version" +"G2_IF","80","4","G2ID","R","G2 bus version" ,,,,, -"G2","90","4","G2DSTO","RW","G2/DS timeout" -"G2","94","4","G2TRTO","RW","G2/TR timeout" -"G2","98","4","G2MDMTO","RW","Modem unit wait timeout" -"G2","9c","4","G2MDMW","RW","Modem unit wait time" +"G2_IF","90","4","G2DSTO","RW","G2/DS timeout" +"G2_IF","94","4","G2TRTO","RW","G2/TR timeout" +"G2_IF","98","4","G2MDMTO","RW","Modem unit wait timeout" +"G2_IF","9c","4","G2MDMW","RW","Modem unit wait time" ,,,,, -"G2","bc","4","G2APRO","W","G2-DMA address range" +"G2_IF","bc","4","G2APRO","W","G2-DMA address range" ,,,,, -"G2","c0","4","ADSTAGD","R","AICA-DMA address counter (on AICA)" -"G2","c4","4","ADSTARD","R","AICA-DMA address counter (on root bus)" -"G2","c8","4","ADLEND","R","AICA-DMA transfer counter" +"G2_IF","c0","4","ADSTAGD","R","AICA-DMA address counter (on AICA)" +"G2_IF","c4","4","ADSTARD","R","AICA-DMA address counter (on root bus)" +"G2_IF","c8","4","ADLEND","R","AICA-DMA transfer counter" ,,,,, -"G2","d0","4","E1STAGD","R","Ext-DMA1 address counter (on Ext)" -"G2","d4","4","E1STARD","R","Ext-DMA1 address counter (on root bus)" -"G2","d8","4","E1LEND","R","Ext-DMA1 transfer counter" +"G2_IF","d0","4","E1STAGD","R","Ext-DMA1 address counter (on Ext)" +"G2_IF","d4","4","E1STARD","R","Ext-DMA1 address counter (on root bus)" +"G2_IF","d8","4","E1LEND","R","Ext-DMA1 transfer counter" ,,,,, -"G2","e0","4","E2STAGD","R","Ext-DMA2 address counter (on Ext)" -"G2","e4","4","E2STARD","R","Ext-DMA2 address counter (on root bus)" -"G2","e8","4","E2LEND","R","Ext-DMA2 transfer counter" +"G2_IF","e0","4","E2STAGD","R","Ext-DMA2 address counter (on Ext)" +"G2_IF","e4","4","E2STARD","R","Ext-DMA2 address counter (on root bus)" +"G2_IF","e8","4","E2LEND","R","Ext-DMA2 transfer counter" ,,,,, -"G2","f0","4","DDSTAGD","R","Dev-DMA address counter (on Dev)" -"G2","f4","4","DDSTARD","R","Dev-DMA address counter (on root bus)" -"G2","f8","4","DDLEND","R","Dev-DMA transfer counter" +"G2_IF","f0","4","DDSTAGD","R","Dev-DMA address counter (on Dev)" +"G2_IF","f4","4","DDSTARD","R","Dev-DMA address counter (on root bus)" +"G2_IF","f8","4","DDLEND","R","Dev-DMA transfer counter" ,,,,, -"PVR","00","4","PDSTAP","RW","PVR-DMA start address" -"PVR","04","4","PDSTAR","RW","PVR-DMA system memory start address" -"PVR","08","4","PDLEN","RW","PVR-DMA length" -"PVR","0c","4","PDDIR","RW","PVR-DMA direction" -"PVR","10","4","PDTSEL","RW","PVR-DMA trigger select" -"PVR","14","4","PDEN","RW","PVR-DMA enable" -"PVR","18","4","PDST","RW","PVR-DMA start" +"PVR_IF","00","4","PDSTAP","RW","PVR-DMA start address" +"PVR_IF","04","4","PDSTAR","RW","PVR-DMA system memory start address" +"PVR_IF","08","4","PDLEN","RW","PVR-DMA length" +"PVR_IF","0c","4","PDDIR","RW","PVR-DMA direction" +"PVR_IF","10","4","PDTSEL","RW","PVR-DMA trigger select" +"PVR_IF","14","4","PDEN","RW","PVR-DMA enable" +"PVR_IF","18","4","PDST","RW","PVR-DMA start" ,,,,, -"PVR","80","4","PDAPRO","W","PVR-DMA address range" +"PVR_IF","80","4","PDAPRO","W","PVR-DMA address range" ,,,,, -"PVR","f0","4","PDSTAPD","R","PVR-DMA address counter (on Ext)" -"PVR","f4","4","PDSTARD","R","PVR-DMA address counter (on root bus)" -"PVR","f8","4","PDLEND","R","PVR-DMA transfer counter" +"PVR_IF","f0","4","PDSTAPD","R","PVR-DMA address counter (on Ext)" +"PVR_IF","f4","4","PDSTARD","R","PVR-DMA address counter (on root bus)" +"PVR_IF","f8","4","PDLEND","R","PVR-DMA transfer counter" diff --git a/regs/systembus.ods b/regs/systembus.ods index fabd427..90f79c2 100644 Binary files a/regs/systembus.ods and b/regs/systembus.ods differ diff --git a/rgb.c b/rgb.c new file mode 100644 index 0000000..e7f34d4 --- /dev/null +++ b/rgb.c @@ -0,0 +1,32 @@ +#include "rgb.h" + +struct rgb hsv_to_rgb(struct hsv hsv) +{ + struct rgb rgb; + unsigned char region, remainder, p, q, t; + + if (hsv.s == 0) { + rgb.r = hsv.v; + rgb.g = hsv.v; + rgb.b = hsv.v; + return rgb; + } + + region = hsv.h / 43; + remainder = (hsv.h - (region * 43)) * 6; + + p = (hsv.v * (255 - hsv.s)) >> 8; + q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8; + t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8; + + switch (region) { + case 0: rgb.r = hsv.v; rgb.g = t; rgb.b = p; break; + case 1: rgb.r = q; rgb.g = hsv.v; rgb.b = p; break; + case 2: rgb.r = p; rgb.g = hsv.v; rgb.b = t; break; + case 3: rgb.r = p; rgb.g = q; rgb.b = hsv.v; break; + case 4: rgb.r = t; rgb.g = p; rgb.b = hsv.v; break; + default: rgb.r = hsv.v; rgb.g = p; rgb.b = q; break; + } + + return rgb; +} diff --git a/rgb.h b/rgb.h new file mode 100644 index 0000000..9ff614d --- /dev/null +++ b/rgb.h @@ -0,0 +1,15 @@ +struct rgb +{ + unsigned char r; + unsigned char g; + unsigned char b; +}; + +struct hsv +{ + unsigned char h; + unsigned char s; + unsigned char v; +}; + +struct rgb hsv_to_rgb(struct hsv hsv); diff --git a/systembus.h b/systembus.h index 3da02dc..d1a5fac 100644 --- a/systembus.h +++ b/systembus.h @@ -1,52 +1,54 @@ #include #include +#include "type.h" + struct system_reg { - uint32_t C2DSTAT; /* CH2-DMA destination address */ - uint32_t C2DLEN; /* CH2-DMA length */ - uint32_t C2DST; /* CH2-DMA start */ - uint8_t _pad0[4]; - uint32_t SDSTAW; /* Sort-DMA start link table address */ - uint32_t SDBAAW; /* Sort-DMA link base address */ - uint32_t SDWLT; /* Sort-DMA link address bit width */ - uint32_t SDLAS; /* Sort-DMA link address shift control */ - uint32_t SDST; /* Sort-DMA start */ - uint8_t _pad1[28]; - uint32_t DBREQM; /* DBREQ# signal mask control */ - uint32_t BAVLWC; /* BAVL# signal wait count */ - uint32_t C2DPYRC; /* DMA (TA/Root Bus) priority count */ - uint32_t DMAXL; /* CH2-DMA maximum burst length */ - uint8_t _pad2[48]; - uint32_t TFREM; /* TA FIFO remaining amount */ - uint32_t LMMODE0; /* Via TA texture memory bus select 0 */ - uint32_t LMMODE1; /* Via TA texture memory bus select 1 */ - uint32_t FFST; /* FIFO status */ - uint32_t SFRES; /* System reset */ - uint8_t _pad3[8]; - uint32_t SBREV; /* System bus revision number */ - uint32_t RBSPLT; /* SH4 Root Bus split enable */ - uint8_t _pad4[92]; - uint32_t ISTNRM; /* Normal interrupt status */ - uint32_t ISTEXT; /* External interrupt status */ - uint32_t ISTERR; /* Error interrupt status */ - uint8_t _pad5[4]; - uint32_t IML2NRM; /* Level 2 normal interrupt mask */ - uint32_t IML2EXT; /* Level 2 external interrupt mask */ - uint32_t IML2ERR; /* Level 2 error interrupt mask */ - uint8_t _pad6[4]; - uint32_t IML4NRM; /* Level 4 normal interrupt mask */ - uint32_t IML4EXT; /* Level 4 external interrupt mask */ - uint32_t IML4ERR; /* Level 4 error interrupt mask */ - uint8_t _pad7[4]; - uint32_t IML6NRM; /* Level 6 normal interrupt mask */ - uint32_t IML6EXT; /* Level 6 external interrupt mask */ - uint32_t IML6ERR; /* Level 6 error interrupt mask */ - uint8_t _pad8[4]; - uint32_t PDTNRM; /* Normal interrupt PVR-DMA startup mask */ - uint32_t PDTEXT; /* External interrupt PVR-DMA startup mask */ - uint8_t _pad9[8]; - uint32_t G2DTNRM; /* Normal interrupt G2-DMA startup mask */ - uint32_t G2DTEXT; /* External interrupt G2-DMA startup mask */ + reg32 C2DSTAT; /* CH2-DMA destination address */ + reg32 C2DLEN; /* CH2-DMA length */ + reg32 C2DST; /* CH2-DMA start */ + reg8 _pad0[4]; + reg32 SDSTAW; /* Sort-DMA start link table address */ + reg32 SDBAAW; /* Sort-DMA link base address */ + reg32 SDWLT; /* Sort-DMA link address bit width */ + reg32 SDLAS; /* Sort-DMA link address shift control */ + reg32 SDST; /* Sort-DMA start */ + reg8 _pad1[28]; + reg32 DBREQM; /* DBREQ# signal mask control */ + reg32 BAVLWC; /* BAVL# signal wait count */ + reg32 C2DPYRC; /* DMA (TA/Root Bus) priority count */ + reg32 DMAXL; /* CH2-DMA maximum burst length */ + reg8 _pad2[48]; + reg32 TFREM; /* TA FIFO remaining amount */ + reg32 LMMODE0; /* Via TA texture memory bus select 0 */ + reg32 LMMODE1; /* Via TA texture memory bus select 1 */ + reg32 FFST; /* FIFO status */ + reg32 SFRES; /* System reset */ + reg8 _pad3[8]; + reg32 SBREV; /* System bus revision number */ + reg32 RBSPLT; /* SH4 Root Bus split enable */ + reg8 _pad4[92]; + reg32 ISTNRM; /* Normal interrupt status */ + reg32 ISTEXT; /* External interrupt status */ + reg32 ISTERR; /* Error interrupt status */ + reg8 _pad5[4]; + reg32 IML2NRM; /* Level 2 normal interrupt mask */ + reg32 IML2EXT; /* Level 2 external interrupt mask */ + reg32 IML2ERR; /* Level 2 error interrupt mask */ + reg8 _pad6[4]; + reg32 IML4NRM; /* Level 4 normal interrupt mask */ + reg32 IML4EXT; /* Level 4 external interrupt mask */ + reg32 IML4ERR; /* Level 4 error interrupt mask */ + reg8 _pad7[4]; + reg32 IML6NRM; /* Level 6 normal interrupt mask */ + reg32 IML6EXT; /* Level 6 external interrupt mask */ + reg32 IML6ERR; /* Level 6 error interrupt mask */ + reg8 _pad8[4]; + reg32 PDTNRM; /* Normal interrupt PVR-DMA startup mask */ + reg32 PDTEXT; /* External interrupt PVR-DMA startup mask */ + reg8 _pad9[8]; + reg32 G2DTNRM; /* Normal interrupt G2-DMA startup mask */ + reg32 G2DTEXT; /* External interrupt G2-DMA startup mask */ }; static_assert((offsetof (struct system_reg, C2DSTAT)) == 0x0); @@ -85,217 +87,227 @@ static_assert((offsetof (struct system_reg, PDTEXT)) == 0x144); static_assert((offsetof (struct system_reg, G2DTNRM)) == 0x150); static_assert((offsetof (struct system_reg, G2DTEXT)) == 0x154); -struct maple_reg { - uint32_t MDSTAR; /* Maple-DMA command table address */ - uint8_t _pad0[8]; - uint32_t MDTSEL; /* Maple-DMA trigger select */ - uint32_t MDEN; /* Maple-DMA enable */ - uint32_t MDST; /* Maple-DMA start */ - uint8_t _pad1[100]; - uint32_t MSYS; /* Maple system control */ - uint32_t MST; /* Maple status */ - uint32_t MSHTCL; /* Maple-DMA hard trigger clear */ - uint32_t MDAPRO; /* Maple-DMA address range */ - uint8_t _pad2[88]; - uint32_t MMSEL; /* Maple MSP selection */ - uint8_t _pad3[8]; - uint32_t MTXDAD; /* Maple TXD address counter */ - uint32_t MRXDAD; /* Maple RXD address counter */ - uint32_t MRXDBD; /* Maple RXD address base */ +struct maple_if_reg { + reg32 MDSTAR; /* Maple-DMA command table address */ + reg8 _pad0[8]; + reg32 MDTSEL; /* Maple-DMA trigger select */ + reg32 MDEN; /* Maple-DMA enable */ + reg32 MDST; /* Maple-DMA start */ + reg8 _pad1[100]; + reg32 MSYS; /* Maple system control */ + reg32 MST; /* Maple status */ + reg32 MSHTCL; /* Maple-DMA hard trigger clear */ + reg32 MDAPRO; /* Maple-DMA address range */ + reg8 _pad2[88]; + reg32 MMSEL; /* Maple MSP selection */ + reg8 _pad3[8]; + reg32 MTXDAD; /* Maple TXD address counter */ + reg32 MRXDAD; /* Maple RXD address counter */ + reg32 MRXDBD; /* Maple RXD address base */ }; -static_assert((offsetof (struct maple_reg, MDSTAR)) == 0x0); -static_assert((offsetof (struct maple_reg, MDTSEL)) == 0xc); -static_assert((offsetof (struct maple_reg, MDEN)) == 0x10); -static_assert((offsetof (struct maple_reg, MDST)) == 0x14); -static_assert((offsetof (struct maple_reg, MSYS)) == 0x7c); -static_assert((offsetof (struct maple_reg, MST)) == 0x80); -static_assert((offsetof (struct maple_reg, MSHTCL)) == 0x84); -static_assert((offsetof (struct maple_reg, MDAPRO)) == 0x88); -static_assert((offsetof (struct maple_reg, MMSEL)) == 0xe4); -static_assert((offsetof (struct maple_reg, MTXDAD)) == 0xf0); -static_assert((offsetof (struct maple_reg, MRXDAD)) == 0xf4); -static_assert((offsetof (struct maple_reg, MRXDBD)) == 0xf8); +static_assert((offsetof (struct maple_if_reg, MDSTAR)) == 0x0); +static_assert((offsetof (struct maple_if_reg, MDTSEL)) == 0xc); +static_assert((offsetof (struct maple_if_reg, MDEN)) == 0x10); +static_assert((offsetof (struct maple_if_reg, MDST)) == 0x14); +static_assert((offsetof (struct maple_if_reg, MSYS)) == 0x7c); +static_assert((offsetof (struct maple_if_reg, MST)) == 0x80); +static_assert((offsetof (struct maple_if_reg, MSHTCL)) == 0x84); +static_assert((offsetof (struct maple_if_reg, MDAPRO)) == 0x88); +static_assert((offsetof (struct maple_if_reg, MMSEL)) == 0xe4); +static_assert((offsetof (struct maple_if_reg, MTXDAD)) == 0xf0); +static_assert((offsetof (struct maple_if_reg, MRXDAD)) == 0xf4); +static_assert((offsetof (struct maple_if_reg, MRXDBD)) == 0xf8); -struct g1_reg { - uint32_t GDSTAR; /* GD-DMA start address */ - uint32_t GDLEN; /* GD-DMA length */ - uint32_t GDDIR; /* GD-DMA direction */ - uint8_t _pad0[4]; - uint32_t GDEN; /* GD-DMA enable */ - uint32_t GDST; /* GD-DMA start */ - uint8_t _pad1[100]; - uint32_t G1RRC; /* System ROM read access timing */ - uint32_t G1RWC; /* System ROM write access timing */ - uint32_t G1FRC; /* Flash ROM read access timing */ - uint32_t G1FWC; /* Flash ROM write access timing */ - uint32_t G1CRC; /* GD PIO read access timing */ - uint32_t G1CWC; /* GD PIO write access timing */ - uint8_t _pad2[8]; - uint32_t G1GDRC; /* GD-DMA read access timing */ - uint32_t G1GDWC; /* GD-DMA write access timing */ - uint8_t _pad3[8]; - uint32_t G1SYSM; /* System mode */ - uint32_t G1CRDYC; /* G1IORDY signal control */ - uint32_t GDAPRO; /* GD-DMA address range */ - uint8_t _pad4[56]; - uint32_t GDSTARD; /* GD-DMA address count (on Root Bus) */ - uint32_t GDLEND; /* GD-DMA transfer counter */ +struct g1_if_reg { + reg32 GDSTAR; /* GD-DMA start address */ + reg32 GDLEN; /* GD-DMA length */ + reg32 GDDIR; /* GD-DMA direction */ + reg8 _pad0[4]; + reg32 GDEN; /* GD-DMA enable */ + reg32 GDST; /* GD-DMA start */ + reg8 _pad1[100]; + reg32 G1RRC; /* System ROM read access timing */ + reg32 G1RWC; /* System ROM write access timing */ + reg32 G1FRC; /* Flash ROM read access timing */ + reg32 G1FWC; /* Flash ROM write access timing */ + reg32 G1CRC; /* GD PIO read access timing */ + reg32 G1CWC; /* GD PIO write access timing */ + reg8 _pad2[8]; + reg32 G1GDRC; /* GD-DMA read access timing */ + reg32 G1GDWC; /* GD-DMA write access timing */ + reg8 _pad3[8]; + reg32 G1SYSM; /* System mode */ + reg32 G1CRDYC; /* G1IORDY signal control */ + reg32 GDAPRO; /* GD-DMA address range */ + reg8 _pad4[56]; + reg32 GDSTARD; /* GD-DMA address count (on Root Bus) */ + reg32 GDLEND; /* GD-DMA transfer counter */ }; -static_assert((offsetof (struct g1_reg, GDSTAR)) == 0x0); -static_assert((offsetof (struct g1_reg, GDLEN)) == 0x4); -static_assert((offsetof (struct g1_reg, GDDIR)) == 0x8); -static_assert((offsetof (struct g1_reg, GDEN)) == 0x10); -static_assert((offsetof (struct g1_reg, GDST)) == 0x14); -static_assert((offsetof (struct g1_reg, G1RRC)) == 0x7c); -static_assert((offsetof (struct g1_reg, G1RWC)) == 0x80); -static_assert((offsetof (struct g1_reg, G1FRC)) == 0x84); -static_assert((offsetof (struct g1_reg, G1FWC)) == 0x88); -static_assert((offsetof (struct g1_reg, G1CRC)) == 0x8c); -static_assert((offsetof (struct g1_reg, G1CWC)) == 0x90); -static_assert((offsetof (struct g1_reg, G1GDRC)) == 0x9c); -static_assert((offsetof (struct g1_reg, G1GDWC)) == 0xa0); -static_assert((offsetof (struct g1_reg, G1SYSM)) == 0xac); -static_assert((offsetof (struct g1_reg, G1CRDYC)) == 0xb0); -static_assert((offsetof (struct g1_reg, GDAPRO)) == 0xb4); -static_assert((offsetof (struct g1_reg, GDSTARD)) == 0xf0); -static_assert((offsetof (struct g1_reg, GDLEND)) == 0xf4); +static_assert((offsetof (struct g1_if_reg, GDSTAR)) == 0x0); +static_assert((offsetof (struct g1_if_reg, GDLEN)) == 0x4); +static_assert((offsetof (struct g1_if_reg, GDDIR)) == 0x8); +static_assert((offsetof (struct g1_if_reg, GDEN)) == 0x10); +static_assert((offsetof (struct g1_if_reg, GDST)) == 0x14); +static_assert((offsetof (struct g1_if_reg, G1RRC)) == 0x7c); +static_assert((offsetof (struct g1_if_reg, G1RWC)) == 0x80); +static_assert((offsetof (struct g1_if_reg, G1FRC)) == 0x84); +static_assert((offsetof (struct g1_if_reg, G1FWC)) == 0x88); +static_assert((offsetof (struct g1_if_reg, G1CRC)) == 0x8c); +static_assert((offsetof (struct g1_if_reg, G1CWC)) == 0x90); +static_assert((offsetof (struct g1_if_reg, G1GDRC)) == 0x9c); +static_assert((offsetof (struct g1_if_reg, G1GDWC)) == 0xa0); +static_assert((offsetof (struct g1_if_reg, G1SYSM)) == 0xac); +static_assert((offsetof (struct g1_if_reg, G1CRDYC)) == 0xb0); +static_assert((offsetof (struct g1_if_reg, GDAPRO)) == 0xb4); +static_assert((offsetof (struct g1_if_reg, GDSTARD)) == 0xf0); +static_assert((offsetof (struct g1_if_reg, GDLEND)) == 0xf4); -struct g2_reg { - uint32_t ADSTAG; /* ACIA:G2-DMA G2 start address */ - uint32_t ADSTAR; /* ACIA:G2-DMA system memory start address */ - uint32_t ADLEN; /* ACIA:G2-DMA length */ - uint32_t ADDIR; /* ACIA:G2-DMA direction */ - uint32_t ADTSEL; /* ACIA:G2-DMA trigger select */ - uint32_t ADEN; /* ACIA:G2-DMA enable */ - uint32_t ADST; /* ACIA:G2-DMA start */ - uint32_t ADSUSP; /* ACIA:G2-DMA suspend */ - uint32_t E1STAG; /* Ext1:G2-DMA start address */ - uint32_t E1STAR; /* Ext1:G2-DMA system memory start address */ - uint32_t E1LEN; /* Ext1:G2-DMA length */ - uint32_t E1DIR; /* Ext1:G2-DMA direction */ - uint32_t E1TSEL; /* Ext1:G2-DMA trigger select */ - uint32_t E1EN; /* Ext1:G2-DMA enable */ - uint32_t E1ST; /* Ext1:G2-DMA start */ - uint32_t E1SUSP; /* Ext1:G2-DMA suspend */ - uint32_t E2STAG; /* Ext2:G2-DMA start address */ - uint32_t E2STAR; /* Ext2:G2-DMA system memory start address */ - uint32_t E2LEN; /* Ext2:G2-DMA length */ - uint32_t E2DIR; /* Ext2:G2-DMA direction */ - uint32_t E2TSEL; /* Ext2:G2-DMA trigger select */ - uint32_t E2EN; /* Ext2:G2-DMA enable */ - uint32_t E2ST; /* Ext2:G2-DMA start */ - uint32_t E2SUSP; /* Ext2:G2-DMA suspend */ - uint32_t DDSTAG; /* Dev:G2-DMA start address */ - uint32_t DDSTAR; /* Dev:G2-DMA system memory start address */ - uint32_t DDLEN; /* Dev:G2-DMA length */ - uint32_t DDDIR; /* Dev:G2-DMA direction */ - uint32_t DDTSEL; /* Dev:G2-DMA trigger select */ - uint32_t DDEN; /* Dev:G2-DMA enable */ - uint32_t DDST; /* Dev:G2-DMA start */ - uint32_t DDSUSP; /* Dev:G2-DMA suspend */ - uint32_t G2ID; /* G2 bus version */ - uint8_t _pad0[12]; - uint32_t G2DSTO; /* G2/DS timeout */ - uint32_t G2TRTO; /* G2/TR timeout */ - uint32_t G2MDMTO; /* Modem unit wait timeout */ - uint32_t G2MDMW; /* Modem unit wait time */ - uint8_t _pad1[28]; - uint32_t G2APRO; /* G2-DMA address range */ - uint32_t ADSTAGD; /* AICA-DMA address counter (on AICA) */ - uint32_t ADSTARD; /* AICA-DMA address counter (on root bus) */ - uint32_t ADLEND; /* AICA-DMA transfer counter */ - uint8_t _pad2[4]; - uint32_t E1STAGD; /* Ext-DMA1 address counter (on Ext) */ - uint32_t E1STARD; /* Ext-DMA1 address counter (on root bus) */ - uint32_t E1LEND; /* Ext-DMA1 transfer counter */ - uint8_t _pad3[4]; - uint32_t E2STAGD; /* Ext-DMA2 address counter (on Ext) */ - uint32_t E2STARD; /* Ext-DMA2 address counter (on root bus) */ - uint32_t E2LEND; /* Ext-DMA2 transfer counter */ - uint8_t _pad4[4]; - uint32_t DDSTAGD; /* Dev-DMA address counter (on Dev) */ - uint32_t DDSTARD; /* Dev-DMA address counter (on root bus) */ - uint32_t DDLEND; /* Dev-DMA transfer counter */ +struct g2_if_reg { + reg32 ADSTAG; /* ACIA:G2-DMA G2 start address */ + reg32 ADSTAR; /* ACIA:G2-DMA system memory start address */ + reg32 ADLEN; /* ACIA:G2-DMA length */ + reg32 ADDIR; /* ACIA:G2-DMA direction */ + reg32 ADTSEL; /* ACIA:G2-DMA trigger select */ + reg32 ADEN; /* ACIA:G2-DMA enable */ + reg32 ADST; /* ACIA:G2-DMA start */ + reg32 ADSUSP; /* ACIA:G2-DMA suspend */ + reg32 E1STAG; /* Ext1:G2-DMA start address */ + reg32 E1STAR; /* Ext1:G2-DMA system memory start address */ + reg32 E1LEN; /* Ext1:G2-DMA length */ + reg32 E1DIR; /* Ext1:G2-DMA direction */ + reg32 E1TSEL; /* Ext1:G2-DMA trigger select */ + reg32 E1EN; /* Ext1:G2-DMA enable */ + reg32 E1ST; /* Ext1:G2-DMA start */ + reg32 E1SUSP; /* Ext1:G2-DMA suspend */ + reg32 E2STAG; /* Ext2:G2-DMA start address */ + reg32 E2STAR; /* Ext2:G2-DMA system memory start address */ + reg32 E2LEN; /* Ext2:G2-DMA length */ + reg32 E2DIR; /* Ext2:G2-DMA direction */ + reg32 E2TSEL; /* Ext2:G2-DMA trigger select */ + reg32 E2EN; /* Ext2:G2-DMA enable */ + reg32 E2ST; /* Ext2:G2-DMA start */ + reg32 E2SUSP; /* Ext2:G2-DMA suspend */ + reg32 DDSTAG; /* Dev:G2-DMA start address */ + reg32 DDSTAR; /* Dev:G2-DMA system memory start address */ + reg32 DDLEN; /* Dev:G2-DMA length */ + reg32 DDDIR; /* Dev:G2-DMA direction */ + reg32 DDTSEL; /* Dev:G2-DMA trigger select */ + reg32 DDEN; /* Dev:G2-DMA enable */ + reg32 DDST; /* Dev:G2-DMA start */ + reg32 DDSUSP; /* Dev:G2-DMA suspend */ + reg32 G2ID; /* G2 bus version */ + reg8 _pad0[12]; + reg32 G2DSTO; /* G2/DS timeout */ + reg32 G2TRTO; /* G2/TR timeout */ + reg32 G2MDMTO; /* Modem unit wait timeout */ + reg32 G2MDMW; /* Modem unit wait time */ + reg8 _pad1[28]; + reg32 G2APRO; /* G2-DMA address range */ + reg32 ADSTAGD; /* AICA-DMA address counter (on AICA) */ + reg32 ADSTARD; /* AICA-DMA address counter (on root bus) */ + reg32 ADLEND; /* AICA-DMA transfer counter */ + reg8 _pad2[4]; + reg32 E1STAGD; /* Ext-DMA1 address counter (on Ext) */ + reg32 E1STARD; /* Ext-DMA1 address counter (on root bus) */ + reg32 E1LEND; /* Ext-DMA1 transfer counter */ + reg8 _pad3[4]; + reg32 E2STAGD; /* Ext-DMA2 address counter (on Ext) */ + reg32 E2STARD; /* Ext-DMA2 address counter (on root bus) */ + reg32 E2LEND; /* Ext-DMA2 transfer counter */ + reg8 _pad4[4]; + reg32 DDSTAGD; /* Dev-DMA address counter (on Dev) */ + reg32 DDSTARD; /* Dev-DMA address counter (on root bus) */ + reg32 DDLEND; /* Dev-DMA transfer counter */ }; -static_assert((offsetof (struct g2_reg, ADSTAG)) == 0x0); -static_assert((offsetof (struct g2_reg, ADSTAR)) == 0x4); -static_assert((offsetof (struct g2_reg, ADLEN)) == 0x8); -static_assert((offsetof (struct g2_reg, ADDIR)) == 0xc); -static_assert((offsetof (struct g2_reg, ADTSEL)) == 0x10); -static_assert((offsetof (struct g2_reg, ADEN)) == 0x14); -static_assert((offsetof (struct g2_reg, ADST)) == 0x18); -static_assert((offsetof (struct g2_reg, ADSUSP)) == 0x1c); -static_assert((offsetof (struct g2_reg, E1STAG)) == 0x20); -static_assert((offsetof (struct g2_reg, E1STAR)) == 0x24); -static_assert((offsetof (struct g2_reg, E1LEN)) == 0x28); -static_assert((offsetof (struct g2_reg, E1DIR)) == 0x2c); -static_assert((offsetof (struct g2_reg, E1TSEL)) == 0x30); -static_assert((offsetof (struct g2_reg, E1EN)) == 0x34); -static_assert((offsetof (struct g2_reg, E1ST)) == 0x38); -static_assert((offsetof (struct g2_reg, E1SUSP)) == 0x3c); -static_assert((offsetof (struct g2_reg, E2STAG)) == 0x40); -static_assert((offsetof (struct g2_reg, E2STAR)) == 0x44); -static_assert((offsetof (struct g2_reg, E2LEN)) == 0x48); -static_assert((offsetof (struct g2_reg, E2DIR)) == 0x4c); -static_assert((offsetof (struct g2_reg, E2TSEL)) == 0x50); -static_assert((offsetof (struct g2_reg, E2EN)) == 0x54); -static_assert((offsetof (struct g2_reg, E2ST)) == 0x58); -static_assert((offsetof (struct g2_reg, E2SUSP)) == 0x5c); -static_assert((offsetof (struct g2_reg, DDSTAG)) == 0x60); -static_assert((offsetof (struct g2_reg, DDSTAR)) == 0x64); -static_assert((offsetof (struct g2_reg, DDLEN)) == 0x68); -static_assert((offsetof (struct g2_reg, DDDIR)) == 0x6c); -static_assert((offsetof (struct g2_reg, DDTSEL)) == 0x70); -static_assert((offsetof (struct g2_reg, DDEN)) == 0x74); -static_assert((offsetof (struct g2_reg, DDST)) == 0x78); -static_assert((offsetof (struct g2_reg, DDSUSP)) == 0x7c); -static_assert((offsetof (struct g2_reg, G2ID)) == 0x80); -static_assert((offsetof (struct g2_reg, G2DSTO)) == 0x90); -static_assert((offsetof (struct g2_reg, G2TRTO)) == 0x94); -static_assert((offsetof (struct g2_reg, G2MDMTO)) == 0x98); -static_assert((offsetof (struct g2_reg, G2MDMW)) == 0x9c); -static_assert((offsetof (struct g2_reg, G2APRO)) == 0xbc); -static_assert((offsetof (struct g2_reg, ADSTAGD)) == 0xc0); -static_assert((offsetof (struct g2_reg, ADSTARD)) == 0xc4); -static_assert((offsetof (struct g2_reg, ADLEND)) == 0xc8); -static_assert((offsetof (struct g2_reg, E1STAGD)) == 0xd0); -static_assert((offsetof (struct g2_reg, E1STARD)) == 0xd4); -static_assert((offsetof (struct g2_reg, E1LEND)) == 0xd8); -static_assert((offsetof (struct g2_reg, E2STAGD)) == 0xe0); -static_assert((offsetof (struct g2_reg, E2STARD)) == 0xe4); -static_assert((offsetof (struct g2_reg, E2LEND)) == 0xe8); -static_assert((offsetof (struct g2_reg, DDSTAGD)) == 0xf0); -static_assert((offsetof (struct g2_reg, DDSTARD)) == 0xf4); -static_assert((offsetof (struct g2_reg, DDLEND)) == 0xf8); +static_assert((offsetof (struct g2_if_reg, ADSTAG)) == 0x0); +static_assert((offsetof (struct g2_if_reg, ADSTAR)) == 0x4); +static_assert((offsetof (struct g2_if_reg, ADLEN)) == 0x8); +static_assert((offsetof (struct g2_if_reg, ADDIR)) == 0xc); +static_assert((offsetof (struct g2_if_reg, ADTSEL)) == 0x10); +static_assert((offsetof (struct g2_if_reg, ADEN)) == 0x14); +static_assert((offsetof (struct g2_if_reg, ADST)) == 0x18); +static_assert((offsetof (struct g2_if_reg, ADSUSP)) == 0x1c); +static_assert((offsetof (struct g2_if_reg, E1STAG)) == 0x20); +static_assert((offsetof (struct g2_if_reg, E1STAR)) == 0x24); +static_assert((offsetof (struct g2_if_reg, E1LEN)) == 0x28); +static_assert((offsetof (struct g2_if_reg, E1DIR)) == 0x2c); +static_assert((offsetof (struct g2_if_reg, E1TSEL)) == 0x30); +static_assert((offsetof (struct g2_if_reg, E1EN)) == 0x34); +static_assert((offsetof (struct g2_if_reg, E1ST)) == 0x38); +static_assert((offsetof (struct g2_if_reg, E1SUSP)) == 0x3c); +static_assert((offsetof (struct g2_if_reg, E2STAG)) == 0x40); +static_assert((offsetof (struct g2_if_reg, E2STAR)) == 0x44); +static_assert((offsetof (struct g2_if_reg, E2LEN)) == 0x48); +static_assert((offsetof (struct g2_if_reg, E2DIR)) == 0x4c); +static_assert((offsetof (struct g2_if_reg, E2TSEL)) == 0x50); +static_assert((offsetof (struct g2_if_reg, E2EN)) == 0x54); +static_assert((offsetof (struct g2_if_reg, E2ST)) == 0x58); +static_assert((offsetof (struct g2_if_reg, E2SUSP)) == 0x5c); +static_assert((offsetof (struct g2_if_reg, DDSTAG)) == 0x60); +static_assert((offsetof (struct g2_if_reg, DDSTAR)) == 0x64); +static_assert((offsetof (struct g2_if_reg, DDLEN)) == 0x68); +static_assert((offsetof (struct g2_if_reg, DDDIR)) == 0x6c); +static_assert((offsetof (struct g2_if_reg, DDTSEL)) == 0x70); +static_assert((offsetof (struct g2_if_reg, DDEN)) == 0x74); +static_assert((offsetof (struct g2_if_reg, DDST)) == 0x78); +static_assert((offsetof (struct g2_if_reg, DDSUSP)) == 0x7c); +static_assert((offsetof (struct g2_if_reg, G2ID)) == 0x80); +static_assert((offsetof (struct g2_if_reg, G2DSTO)) == 0x90); +static_assert((offsetof (struct g2_if_reg, G2TRTO)) == 0x94); +static_assert((offsetof (struct g2_if_reg, G2MDMTO)) == 0x98); +static_assert((offsetof (struct g2_if_reg, G2MDMW)) == 0x9c); +static_assert((offsetof (struct g2_if_reg, G2APRO)) == 0xbc); +static_assert((offsetof (struct g2_if_reg, ADSTAGD)) == 0xc0); +static_assert((offsetof (struct g2_if_reg, ADSTARD)) == 0xc4); +static_assert((offsetof (struct g2_if_reg, ADLEND)) == 0xc8); +static_assert((offsetof (struct g2_if_reg, E1STAGD)) == 0xd0); +static_assert((offsetof (struct g2_if_reg, E1STARD)) == 0xd4); +static_assert((offsetof (struct g2_if_reg, E1LEND)) == 0xd8); +static_assert((offsetof (struct g2_if_reg, E2STAGD)) == 0xe0); +static_assert((offsetof (struct g2_if_reg, E2STARD)) == 0xe4); +static_assert((offsetof (struct g2_if_reg, E2LEND)) == 0xe8); +static_assert((offsetof (struct g2_if_reg, DDSTAGD)) == 0xf0); +static_assert((offsetof (struct g2_if_reg, DDSTARD)) == 0xf4); +static_assert((offsetof (struct g2_if_reg, DDLEND)) == 0xf8); -struct pvr_reg { - uint32_t PDSTAP; /* PVR-DMA start address */ - uint32_t PDSTAR; /* PVR-DMA system memory start address */ - uint32_t PDLEN; /* PVR-DMA length */ - uint32_t PDDIR; /* PVR-DMA direction */ - uint32_t PDTSEL; /* PVR-DMA trigger select */ - uint32_t PDEN; /* PVR-DMA enable */ - uint32_t PDST; /* PVR-DMA start */ - uint8_t _pad0[100]; - uint32_t PDAPRO; /* PVR-DMA address range */ - uint8_t _pad1[108]; - uint32_t PDSTAPD; /* PVR-DMA address counter (on Ext) */ - uint32_t PDSTARD; /* PVR-DMA address counter (on root bus) */ - uint32_t PDLEND; /* PVR-DMA transfer counter */ +struct pvr_if_reg { + reg32 PDSTAP; /* PVR-DMA start address */ + reg32 PDSTAR; /* PVR-DMA system memory start address */ + reg32 PDLEN; /* PVR-DMA length */ + reg32 PDDIR; /* PVR-DMA direction */ + reg32 PDTSEL; /* PVR-DMA trigger select */ + reg32 PDEN; /* PVR-DMA enable */ + reg32 PDST; /* PVR-DMA start */ + reg8 _pad0[100]; + reg32 PDAPRO; /* PVR-DMA address range */ + reg8 _pad1[108]; + reg32 PDSTAPD; /* PVR-DMA address counter (on Ext) */ + reg32 PDSTARD; /* PVR-DMA address counter (on root bus) */ + reg32 PDLEND; /* PVR-DMA transfer counter */ }; -static_assert((offsetof (struct pvr_reg, PDSTAP)) == 0x0); -static_assert((offsetof (struct pvr_reg, PDSTAR)) == 0x4); -static_assert((offsetof (struct pvr_reg, PDLEN)) == 0x8); -static_assert((offsetof (struct pvr_reg, PDDIR)) == 0xc); -static_assert((offsetof (struct pvr_reg, PDTSEL)) == 0x10); -static_assert((offsetof (struct pvr_reg, PDEN)) == 0x14); -static_assert((offsetof (struct pvr_reg, PDST)) == 0x18); -static_assert((offsetof (struct pvr_reg, PDAPRO)) == 0x80); -static_assert((offsetof (struct pvr_reg, PDSTAPD)) == 0xf0); -static_assert((offsetof (struct pvr_reg, PDSTARD)) == 0xf4); -static_assert((offsetof (struct pvr_reg, PDLEND)) == 0xf8); +static_assert((offsetof (struct pvr_if_reg, PDSTAP)) == 0x0); +static_assert((offsetof (struct pvr_if_reg, PDSTAR)) == 0x4); +static_assert((offsetof (struct pvr_if_reg, PDLEN)) == 0x8); +static_assert((offsetof (struct pvr_if_reg, PDDIR)) == 0xc); +static_assert((offsetof (struct pvr_if_reg, PDTSEL)) == 0x10); +static_assert((offsetof (struct pvr_if_reg, PDEN)) == 0x14); +static_assert((offsetof (struct pvr_if_reg, PDST)) == 0x18); +static_assert((offsetof (struct pvr_if_reg, PDAPRO)) == 0x80); +static_assert((offsetof (struct pvr_if_reg, PDSTAPD)) == 0xf0); +static_assert((offsetof (struct pvr_if_reg, PDSTARD)) == 0xf4); +static_assert((offsetof (struct pvr_if_reg, PDLEND)) == 0xf8); + +extern struct system_reg SYSTEM __asm("SYSTEM"); + +extern struct maple_if_reg MAPLE_IF __asm("MAPLE_IF"); + +extern struct g1_if_reg G1_IF __asm("G1_IF"); + +extern struct g2_if_reg G2_IF __asm("G2_IF"); + +extern struct pvr_if_reg PVR_IF __asm("PVR_IF"); diff --git a/test.c b/test.c new file mode 100644 index 0000000..05f2a08 --- /dev/null +++ b/test.c @@ -0,0 +1,147 @@ +#include "type.h" + +#include "rgb.h" +#include "vga.h" +#include "systembus.h" +#include "holly.h" + +void *memcpy(void *restrict dest, const void *restrict src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + for (; n; n--) *d++ = *s++; + return dest; +} + +void start(void) +{ + /* + G2_IF.ADEN = 0; + G2_IF.E1EN = 0; + G2_IF.E2EN = 0; + G2_IF.DDEN = 0; + G1_IF.GDEN = 0; + MAPLE_IF.MDEN = 0; + G2_IF.G2APRO = 0x4659404f; + */ + + HOLLY.SOFTRESET = 0b111; + HOLLY.TEXT_CONTROL = 3; + + uint16_t xsize = 640; + uint16_t ysize = 480; + + uint16_t fb_xclip_min = 0; + uint16_t fb_xclip_max = xsize-1; + HOLLY.FB_X_CLIP = (fb_xclip_max << 16) | (fb_xclip_min << 0); + uint16_t fb_yclip_min = 0; + uint16_t fb_yclip_max = ysize-1; + HOLLY.FB_Y_CLIP = (fb_yclip_max << 16) | (fb_yclip_min << 0); + + uint32_t fb_xsize = (xsize * 16)/(32) - 1; + uint32_t fb_ysize = ysize - 3; + uint32_t fb_mod = 1; + HOLLY.FB_R_SIZE = 0 + | (fb_xsize << 0) + | (fb_ysize << 10) + | (fb_mod << 20); + + uint32_t fb_linestride = (xsize * 16) / 64; + HOLLY.FB_W_LINESTRIDE = fb_linestride; + + HOLLY.FB_W_CTRL = 0 + | 0b001 << 0 // fb_packmode: RGB 565 + ; + + HOLLY.FB_R_CTRL = 0 + | 1 << 23 // vclk_div + | 0 << 22 // fb_strip_buf_en + | 0 << 16 // fb_strip_size + | 0 << 8 // fb_chroma_threshold + | 0 << 4 // fb_concat + | 1 << 2 // fb_depth + | 0 << 1 // fb_line_double + | 1 << 0 // fb_enable + ; + + HOLLY.FB_W_SOF1 = 0; + HOLLY.FB_W_SOF2 = 0; + HOLLY.FB_R_SOF1 = 0; + HOLLY.FB_R_SOF2 = 0; + + HOLLY.VO_BORDER_COL = (31 << 11) | (31 << 0); + + uint16_t startx = 0x0a8; + uint16_t starty = 0x028; + HOLLY.VO_STARTX = startx; + HOLLY.VO_STARTY = (starty << 16) | (starty << 0); + + HOLLY.SPG_CONTROL = (1 << 8); // sync_direction__output ; non-default + + uint16_t hbstart = 0x0345; // default + uint16_t hbend = 0x007e; // default + HOLLY.SPG_HBLANK = (hbend << 16) | (hbstart << 0); + + uint16_t hcount = 0x0359; // default + uint16_t vcount = 0x020c; // non-default + HOLLY.SPG_LOAD = (vcount << 16) | (hcount << 0); + + uint16_t vbstart = 0x0208; // non-default + uint16_t vbend = 0x0028; // non-default + HOLLY.SPG_VBLANK = (vbend << 16) | (vbstart << 0); + + uint16_t hswidth = 0x003f; + uint16_t vswidth = 0x0003; + uint16_t bpwidth = 0x0319; + uint16_t eqwidth = 0x000f; + HOLLY.SPG_WIDTH = + (hswidth << 0) + | (vswidth << 8) + | (bpwidth << 12) + | (eqwidth << 22); + + HOLLY.SPG_HBLANK_INT = hbstart << 16; + + uint32_t hsync_pol = 0; + uint32_t vsync_pol = 0; + uint32_t blank_pol = 0; + uint32_t blank_video = 0; + uint32_t field_mode = 0; + uint32_t pixel_double = 0; + uint32_t pclk_delay = 0x16; + HOLLY.VO_CONTROL = 0 + | (( pclk_delay & 0x3f) << 16 ) + | (( pixel_double & 0x01) << 8 ) + | (( field_mode & 0x0f) << 4 ) + | (( blank_video & 0x01) << 3 ) + | (( blank_pol & 0x01) << 2 ) + | (( vsync_pol & 0x01) << 1 ) + | (( hsync_pol & 0x01) << 0 ); + + + HOLLY.SOFTRESET = 0b000; + + reg16 * vram = (reg16 *)0xa5000000; + v_sync_in(); + for (int y = 0; y < 480; y++) { + for (int x = 0; x < 640; x++) { + /* + struct hsv hsv = {(y * 255) / 480, 255, 255}; + struct rgb rgb = hsv_to_rgb(hsv); + vram[y * 640 + x] = ((rgb.r >> 3) << 11) | ((rgb.g >> 2) << 5) | ((rgb.b >> 3) << 0); + */ + vram[y * 640 + x] = 30 << 5 | 31 << 11; + } + } + vram[0] = 0xffff; + vram[10] = 0xffff; + vram[639] = 0xffff; + vram[307199 - (640 * 3) - 1] = 0xffff; + vram[307199 - (640 * 2) - 10] = 31 << 11; + vram[307199 - (640 * 1) - 1] = 0xffff; + //vram[307199 - (640 * 2) - 10] = 0xf0ff; + //vram[307199 - 640 - 10] = 0xf0ff; + //vram[307199 - 10] = 0xf0ff; + //vram[307199] = 0xf0ff; + +} diff --git a/vga.c b/vga.c new file mode 100644 index 0000000..a0d0308 --- /dev/null +++ b/vga.c @@ -0,0 +1,193 @@ +#include + +#include "sh7091.h" +#include "sh7091_bits.h" +#include "holly.h" + +#include "vga.h" +#include "rgb.h" + +uint32_t get_cable_type() +{ + /* set all pins to input */ + SH7091.BSC.PCTRA = 0; + + /* get cable type from pins 9 + 8 */ + return SH7091.BSC.PDTRA & PDTRA__MASK; +} + +void vga1() +{ + uint32_t fb_r_ctrl = HOLLY.FB_R_CTRL; + HOLLY.FB_R_CTRL = fb_r_ctrl & ~(1 << 0); // fb_enable = 0 + uint32_t blank_video = 1; + HOLLY.VO_CONTROL |= (blank_video << 3); // blank_video + + HOLLY.FB_R_SIZE = 0; + + uint32_t vblank_in = 0x0208; + uint32_t vblank_out = 0x0015; + HOLLY.SPG_VBLANK_INT = (vblank_out << 16) | (vblank_in << 0); + + uint32_t sync_direction = 1; + HOLLY.SPG_CONTROL = (sync_direction << 8); + + uint32_t hbstart = 0x0345; // default + uint32_t hbend = 0x007e; // default + HOLLY.SPG_HBLANK = (hbend << 16) | (hbstart << 0); + + uint32_t hcount = 0x0359; // default + uint32_t vcount = 0x020c; // non-default + HOLLY.SPG_LOAD = (vcount << 16) | (hcount << 0); + + uint32_t vbstart = 0x0208; // non-default + uint32_t vbend = 0x0028; // non-default + HOLLY.SPG_VBLANK = (vbend << 16) | (vbstart << 0); + + uint32_t hswidth = 0x003f; + uint32_t vswidth = 0x0003; + uint32_t bpwidth = 0x0319; + uint32_t eqwidth = 0x000f; + HOLLY.SPG_WIDTH = + (hswidth << 0) + | (vswidth << 8) + | (bpwidth << 12) + | (eqwidth << 22); + + uint32_t startx = 0x0a8; + uint32_t starty = 0x028; + HOLLY.VO_STARTX = startx; + HOLLY.VO_STARTY = (starty << 16) | (starty << 0); + + HOLLY.SPG_HBLANK_INT = hbstart << 16; +} + +void vga2() +{ + HOLLY.FB_BURSTCTRL = 0x00093f39; + + uint32_t xsize = 640; + uint32_t ysize = 480; + + uint32_t fb_xclip_min = 0; + uint32_t fb_xclip_max = xsize-1; + HOLLY.FB_X_CLIP = (fb_xclip_max << 16) | (fb_xclip_min << 0); + uint32_t fb_yclip_min = 0; + uint32_t fb_yclip_max = ysize-1; + HOLLY.FB_Y_CLIP = (fb_yclip_max << 16) | (fb_yclip_min << 0); + + uint32_t fb_xsize = (xsize * 16)/(32) - 1; + uint32_t fb_ysize = ysize - 3; + uint32_t fb_mod = 1; + HOLLY.FB_R_SIZE = 0 + | (fb_xsize << 0) + | (fb_ysize << 10) + | (fb_mod << 20); + + uint32_t coeff0 = 0x40; + uint32_t coeff1 = 0x80; + HOLLY.Y_COEFF = (coeff1 << 8) | (coeff0 << 0); + + uint32_t vscale_factor = 0x0400; + HOLLY.SCALER_CTL = (vscale_factor << 0); + + uint32_t fb_linestride = (xsize * 16) / 64; + HOLLY.FB_W_LINESTRIDE = fb_linestride; + + HOLLY.FB_W_CTRL = 0 + | 0b001 << 0 // fb_packmode: RGB 565 + ; + + HOLLY.FB_W_SOF1 = 0; + HOLLY.FB_W_SOF2 = 0; + HOLLY.FB_R_SOF1 = 0; + HOLLY.FB_R_SOF2 = 0; + + HOLLY.FB_R_CTRL = 0 + | 1 << 23 // vclk_div + | 0 << 22 // fb_strip_buf_en + | 0 << 16 // fb_strip_size + | 0 << 8 // fb_chroma_threshold + | 0 << 4 // fb_concat + | 1 << 2 // fb_depth + | 0 << 1 // fb_line_double + | 1 << 0 // fb_enable + ; + + uint32_t hsync_pol = 0; + uint32_t vsync_pol = 0; + uint32_t blank_pol = 0; + uint32_t blank_video = 0; + uint32_t field_mode = 0; + uint32_t pixel_double = 0; + uint32_t pclk_delay = 0x16; + HOLLY.VO_CONTROL = 0 + | (( pclk_delay & 0x3f) << 16 ) + | (( pixel_double & 0x01) << 8 ) + | (( field_mode & 0x0f) << 4 ) + | (( blank_video & 0x01) << 3 ) + | (( blank_pol & 0x01) << 2 ) + | (( vsync_pol & 0x01) << 1 ) + | (( hsync_pol & 0x01) << 0 ); + + *((reg32 *)0xa0702c00) = 0; +} + +void v_sync_in() +{ +#define V_SYNC (1<<13) + while (!(V_SYNC & HOLLY.SPG_STATUS)) { + asm volatile ("nop"); + } + while ((V_SYNC & HOLLY.SPG_STATUS)) { + asm volatile ("nop"); + } +#undef V_SYNC +} + +void v_sync_out() +{ +#define V_SYNC (1<<13) + while ((V_SYNC & HOLLY.SPG_STATUS)) { + asm volatile ("nop"); + } + while (!(V_SYNC & HOLLY.SPG_STATUS)) { + asm volatile ("nop"); + } +#undef V_SYNC +} + +void vga() +{ + get_cable_type(); + + HOLLY.SOFTRESET = 0b111; + HOLLY.TEXT_CONTROL = 3; + HOLLY.FB_W_CTRL = 9; + + /* + */ + vga1(); + vga2(); + + v_sync_in(); + + HOLLY.VO_BORDER_COL = (63 << 5) | (31 << 0); + HOLLY.VO_CONTROL = 0x0016; + + HOLLY.SOFTRESET = 0b000; +} + +void fill_framebuffer() +{ + reg16 * vram = (reg16 *)0xa5000000; + for (int y = 0; y < 480; y++) { + for (int x = 0; x < 640; x++) { + struct hsv hsv = {(y * 255) / 480, 255, 255}; + struct rgb rgb = hsv_to_rgb(hsv); + vram[y * 640 + x] = ((rgb.r >> 3) << 11) | ((rgb.g >> 2) << 5) | ((rgb.b >> 3) << 0); + } + } + vram[0] = 0xf0ff; + vram[10] = 0xf0ff; +} diff --git a/vga.h b/vga.h new file mode 100644 index 0000000..3555293 --- /dev/null +++ b/vga.h @@ -0,0 +1,5 @@ +#pragma once + +void vga(); +void v_sync_in(); +void v_sync_out();