scene: rotating triangle

This now works on real dreamcast hardware.
This commit is contained in:
Zack Buhman 2023-12-03 22:34:17 +08:00
parent 67f809c98d
commit 963aa75990
13 changed files with 219 additions and 65 deletions

View File

@ -39,6 +39,12 @@ SECTIONS
*(.bss.*) *(.bss.*)
} > p1ram } > p1ram
.text.p2ram ALIGN(4) : SUBALIGN(4)
{
*(.p2ram)
*(.p2ram.*)
} > p1ram
__p1ram_end = .; __p1ram_end = .;
/DISCARD/ : /DISCARD/ :

View File

@ -3,36 +3,57 @@ import struct
import sys import sys
import time import time
#dest = 0xac21_0000
dest = 0xac02_0000 dest = 0xac02_0000
ret = [] ret = []
def sync(ser, b): def sync(ser, b, wait=1):
l = [] l = []
for i, c in enumerate(b): for i, c in enumerate(b):
if i % 32 == 0: if i % 32 == 0:
print(i, end=' ') print(i, end=' ')
sys.stdout.flush() sys.stdout.flush()
ser.write(bytes([c])) ser.write(bytes([c]))
ser.flush() time.sleep(1000 / 1000000)
ser.flushInput() if ser.in_waiting == 0:
ser.flushOutput() time.sleep(0.01)
time.sleep(0.01)
while ser.in_waiting > 0: while ser.in_waiting > 0:
res = ser.read(ser.in_waiting) res = ser.read(ser.in_waiting)
for c in res: l.extend(res)
l.append(c)
time.sleep(0.01) time.sleep(0.01)
time.sleep(1) time.sleep(wait)
res = ser.read(ser.in_waiting) res = ser.read(ser.in_waiting)
for c in res: l.extend(res)
l.append(c)
return bytes(l)
def symmetric(ser, b):
l = []
for i, c in enumerate(b):
if i % 32 == 0:
print(i, end=' ')
sys.stdout.flush()
while True:
if ser.in_waiting:
res = ser.read(ser.in_waiting)
l.extend(res)
if len(l) + 8 >= i:
break
else:
time.sleep(0.001)
ser.write(bytes([c]))
time.sleep(0.1)
res = ser.read(ser.in_waiting)
l.extend(res)
return bytes(l) return bytes(l)
def do(ser, b): def do(ser, b):
ser.read(ser.in_waiting) _ = ser.read(ser.in_waiting)
ser.flush() ser.flush()
ser.flushInput() ser.flushInput()
ser.flushOutput() ser.flushOutput()
@ -45,15 +66,19 @@ def do(ser, b):
print("dargs", args) print("dargs", args)
ret = sync(ser, args) ret = sync(ser, args)
print(ret) print(ret)
if ret != b'data\n':
do(ser, b)
ret = sync(ser, b) ret = symmetric(ser, b)
print(ret[-5:]) print(ret[-5:])
if ret[:-5] != b: if ret[:-5] != b:
print("ret != b; dumped to asdf.bin") print("ret != b; dumped to asdf.bin")
with open('asdf.bin', 'wb') as f: with open('asdf.bin', 'wb') as f:
f.write(ret[:-5]) f.write(ret[:-5])
print("did not jump")
return
ret = sync(ser, b'JUMP') ret = sync(ser, b'JUMP', wait=0)
args = struct.pack("<I", dest) args = struct.pack("<I", dest)
ser.write(args) ser.write(args)
print() print()

View File

@ -9,6 +9,7 @@ AFLAGS = --fatal-warnings
CARCH = -m4-single-only -ml CARCH = -m4-single-only -ml
CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib -Wno-error=narrowing CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib -Wno-error=narrowing
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable
CFLAGS += -mfsca -funsafe-math-optimizations
DEPFLAGS = -MMD -E DEPFLAGS = -MMD -E
# --print-gc-sections # --print-gc-sections
LDFLAGS = --gc-sections --no-warn-rwx-segment --print-memory-usage --entry=_start --orphan-handling=error LDFLAGS = --gc-sections --no-warn-rwx-segment --print-memory-usage --entry=_start --orphan-handling=error
@ -82,10 +83,13 @@ all: main.cdi
%.o: %.cpp %.cpp.d %.o: %.cpp %.cpp.d
$(CXX) $(CARCH) $(CFLAGS) $(CXXFLAGS) $(OPT) $(DEBUG) -c $< -o $@ $(CXX) $(CARCH) $(CFLAGS) $(CXXFLAGS) $(OPT) $(DEBUG) -c $< -o $@
serial.elf: start.o serial_main.o load.o cache.o
$(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@
main.elf: $(MAIN_OBJ) main.elf: $(MAIN_OBJ)
$(LD) $(LDFLAGS) -T $(LIB)/main.lds $^ -o $@ $(LD) $(LDFLAGS) -T $(LIB)/main.lds $^ -o $@
test.elf: test.o rgb.o vga.o DSC08384.data.o test.elf: $(MAIN_OBJ)
$(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@ $(LD) $(LDFLAGS) -T $(LIB)/alt.lds $^ -o $@
%.bin: %.elf %.bin: %.elf
@ -107,7 +111,7 @@ audio.pcm:
mv $@.raw $@ mv $@.raw $@
1ST_READ.BIN: main.bin 1ST_READ.BIN: main.bin
./scramble main.bin 1ST_READ.BIN ./scramble $< $@
%.iso: 1ST_READ.BIN ip.bin %.iso: 1ST_READ.BIN ip.bin
mkisofs \ mkisofs \

View File

@ -16,6 +16,8 @@ struct isp_tsp_parameter {
vertex_parameter vertex[3]; vertex_parameter vertex[3];
}; };
static_assert((sizeof (isp_tsp_parameter)) == (4 * 3 + 3) * 4);
void background_parameter(volatile uint32_t * buf) void background_parameter(volatile uint32_t * buf)
{ {
volatile isp_tsp_parameter * parameter = reinterpret_cast<volatile isp_tsp_parameter *>(buf); volatile isp_tsp_parameter * parameter = reinterpret_cast<volatile isp_tsp_parameter *>(buf);
@ -35,15 +37,15 @@ void background_parameter(volatile uint32_t * buf)
parameter->vertex[0].x = 0.f; parameter->vertex[0].x = 0.f;
parameter->vertex[0].y = 0.f; parameter->vertex[0].y = 0.f;
parameter->vertex[0].z = 1.f/100000; parameter->vertex[0].z = 1.f/100000;
parameter->vertex[0].base_color = 0xff300000; parameter->vertex[0].base_color = 0x00000000;
parameter->vertex[1].x = 0.f; parameter->vertex[1].x = 639.f;
parameter->vertex[1].y = 480.f; parameter->vertex[1].y = 0.f;
parameter->vertex[1].z = 1.f/100000; parameter->vertex[1].z = 1.f/100000;
parameter->vertex[1].base_color = 0xff300000; parameter->vertex[1].base_color = 0x00000000;
parameter->vertex[2].x = 640.f; parameter->vertex[2].x = 639.f;
parameter->vertex[2].y = 0.f; parameter->vertex[2].y = 479.f;
parameter->vertex[2].z = 1.f/100000; parameter->vertex[2].z = 1.f/100000;
parameter->vertex[2].base_color = 0xff300000; parameter->vertex[2].base_color = 0x00000000;
} }

View File

@ -45,7 +45,10 @@ void region_array(volatile uint32_t * buf,
for (uint32_t y = 0; y < height; y++) { for (uint32_t y = 0; y < height; y++) {
for (uint32_t x = 0; x < width; x++) { for (uint32_t x = 0; x < width; x++) {
region_array[ix].tile = REGION_ARRAY__TILE_Y_POSITION(y) region_array[ix].tile = REGION_ARRAY__TILE_Y_POSITION(y)
| REGION_ARRAY__TILE_X_POSITION(x); | REGION_ARRAY__TILE_X_POSITION(x);
if (y == (height - 1) && x == (width - 1))
region_array[ix].tile |= REGION_ARRAY__LAST_REGION;
uint32_t tile_index = y * width + x; uint32_t tile_index = y * width + x;
constexpr uint32_t opaque_list_opb_size = 16 * 4; // in bytes; this must match O_OPB in TA_ALLOC_CTRL constexpr uint32_t opaque_list_opb_size = 16 * 4; // in bytes; this must match O_OPB in TA_ALLOC_CTRL

View File

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include "sh7091.h" #include "sh7091.h"
#include "sh7091_bits.h"
#include "holly.h" #include "holly.h"
enum load_command { enum load_command {
@ -47,6 +48,7 @@ void debug(const char * s)
{ {
char c; char c;
while ((c = *s++)) { while ((c = *s++)) {
while ((sh7091.SCIF.SCFSR2 & SCFSR2__TDFE) == 0);
sh7091.SCIF.SCFTDR2 = (uint8_t)c; sh7091.SCIF.SCFTDR2 = (uint8_t)c;
} }
} }

View File

@ -7,6 +7,9 @@
#include "sh7091.h" #include "sh7091.h"
#include "sh7091_bits.h" #include "sh7091_bits.h"
#include "memorymap.h" #include "memorymap.h"
#include "systembus.h"
#include "holly.h"
#include "holly/core_bits.h"
#include "rgb.h" #include "rgb.h"
#include "scene.h" #include "scene.h"
@ -30,6 +33,22 @@ void serial()
sh7091.SCIF.SCSCR2 = SCSCR2__TE | SCSCR2__RE; sh7091.SCIF.SCSCR2 = SCSCR2__TE | SCSCR2__RE;
} }
inline void serial_char(const char c)
{
// wait for transmit fifo to become empty
while ((sh7091.SCIF.SCFSR2 & SCFSR2__TDFE) == 0);
sh7091.SCIF.SCFTDR2 = static_cast<uint8_t>(c);
}
void serial_string(const char * s)
{
return;
while (*s != '\0') {
serial_char(*s++);
}
}
extern "C" extern "C"
void main() void main()
{ {
@ -42,7 +61,7 @@ void main()
*start++ = 0; *start++ = 0;
} }
serial(); //serial();
vga(); vga();
@ -58,39 +77,31 @@ void main()
} }
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
system.LMMODE0 = 1;
system.LMMODE1 = 1;
v_sync_out();
v_sync_in();
scene_holly_init();
scene_init_texture_memory();
int frame = 0;
while (1) { while (1) {
v_sync_in();
scene_holly_init();
scene_init_texture_memory();
scene_ta_init(); scene_ta_init();
scene_geometry_transfer(); scene_geometry_transfer();
scene_wait_opaque_list(); scene_wait_opaque_list();
scene_start_render(); scene_start_render(frame);
frame = !frame;
// I do not understand why, but flycast does not show the first-rendered // I do not understand why, but flycast does not show the first-rendered
// framebuffer. // framebuffer.
v_sync_out();
v_sync_in(); v_sync_in();
scene_ta_init();
scene_geometry_transfer();
scene_wait_opaque_list();
scene_start_render();
// do nothing forever
while(1);
/*
load_init();
while (1) {
while ((sh7091.SCIF.SCFSR2 & SCFSR2__RDF) == 0) {
// wait
}
while ((sh7091.SCIF.SCFDR2 & 0b11111) > 0) {
uint8_t c = sh7091.SCIF.SCFRDR2;
load_recv(c);
}
sh7091.SCIF.SCFSR2 = sh7091.SCIF.SCFSR2 & (~SCFSR2__RDF);
}
*/
} }
} }

View File

@ -3,8 +3,10 @@
#include "holly/region_array.h" #include "holly/region_array.h"
#include "holly/background.h" #include "holly/background.h"
#include "holly/ta_parameter.h" #include "holly/ta_parameter.h"
#include "holly/core_bits.h"
#include "holly.h" #include "holly.h"
#include "ta.h" #include "ta.h"
#include "sh7091.h"
#include "memorymap.h" #include "memorymap.h"
#include "storequeue.h" #include "storequeue.h"
@ -17,13 +19,20 @@ struct texture_memory_alloc {
uint32_t _res0[ 0x20 / 4]; // (the TA may clobber 4 bytes starting at TA_OL_LIMIT) uint32_t _res0[ 0x20 / 4]; // (the TA may clobber 4 bytes starting at TA_OL_LIMIT)
uint32_t region_array[0x00002000 / 4]; // REGION_BASE uint32_t region_array[0x00002000 / 4]; // REGION_BASE
uint32_t background[0x00000020 / 4]; // ISP_BACKGND_T uint32_t background[0x00000020 / 4]; // ISP_BACKGND_T
uint32_t framebuffer[0x00096000 / 4]; // FB_R_SOF1 / FB_W_SOF1 uint32_t framebuffer[2][0x00096000 / 4]; // FB_R_SOF1 / FB_W_SOF1
}; };
/*
0,-.5
|
---
-0.5,0.5 | 0.5,0.5
*/
float scene_triangle[3][3] = { float scene_triangle[3][3] = {
{ 320.f, 120.f, 1/10.f}, { 0.f, -0.5f, 1/10.f},
{ 440.f, 360.f, 1/10.f}, { 0.5f, 0.5f, 1/10.f},
{ 200.f, 360.f, 1/10.f}, { -0.5f, 0.5f, 1/10.f},
}; };
void scene_holly_init() void scene_holly_init()
@ -83,9 +92,10 @@ void scene_ta_init()
holly.TA_ISP_BASE = (offsetof (struct texture_memory_alloc, isp_tsp_parameters)); holly.TA_ISP_BASE = (offsetof (struct texture_memory_alloc, isp_tsp_parameters));
holly.TA_ISP_LIMIT = (offsetof (struct texture_memory_alloc, object_list)); // the end of isp_tsp_parameters holly.TA_ISP_LIMIT = (offsetof (struct texture_memory_alloc, object_list)); // the end of isp_tsp_parameters
holly.TA_OL_BASE = (offsetof (struct texture_memory_alloc, object_list)); holly.TA_OL_BASE = (offsetof (struct texture_memory_alloc, object_list));
holly.TA_OL_LIMIT = (offsetof (struct texture_memory_alloc, region_array)); // the end of the object_list holly.TA_OL_LIMIT = (offsetof (struct texture_memory_alloc, _res0)); // the end of the object_list
holly.TA_NEXT_OPB_INIT = (offsetof (struct texture_memory_alloc, object_list)) holly.TA_NEXT_OPB_INIT = (offsetof (struct texture_memory_alloc, object_list));
+ (640 / 32) * (320 / 32) * 16 * 4; //holly.TA_NEXT_OPB_INIT = (offsetof (struct texture_memory_alloc, object_list))
// + (640 / 32) * (320 / 32) * 16 * 4;
holly.TA_LIST_INIT = TA_LIST_INIT__LIST_INIT; holly.TA_LIST_INIT = TA_LIST_INIT__LIST_INIT;
@ -100,8 +110,12 @@ void scene_wait_opaque_list()
system.ISTNRM = SB_ISTNRM__TAEOINT; system.ISTNRM = SB_ISTNRM__TAEOINT;
} }
static float theta = 0;
constexpr float degree = 0.01745329f;
void scene_geometry_transfer() void scene_geometry_transfer()
{ {
/*
triangle(store_queue); triangle(store_queue);
sq_transfer_32byte(ta_fifo_polygon_converter); sq_transfer_32byte(ta_fifo_polygon_converter);
@ -120,6 +134,50 @@ void scene_geometry_transfer()
end_of_list(store_queue); end_of_list(store_queue);
sq_transfer_32byte(ta_fifo_polygon_converter); sq_transfer_32byte(ta_fifo_polygon_converter);
*/
uint32_t __attribute__((aligned(32))) scene[(32 * 5) / 4];
triangle(&scene[(32 * 0) / 4]);
for (int i = 0; i < 3; i++) {
bool end_of_strip = i == 2;
float x = scene_triangle[i][0];
float y = scene_triangle[i][1];
x = x * __builtin_cosf(theta) - y * __builtin_sinf(theta);
y = x * __builtin_sinf(theta) + y * __builtin_cosf(theta);
x *= 240.f;
y *= 240.f;
x += 320.f;
y += 240.f;
vertex(&scene[(32 * (i + 1)) / 4],
x, // x
y, // y
scene_triangle[i][2], // z
0xffff00ff, // base_color
end_of_strip);
}
end_of_list(&scene[(32 * 4) / 4]);
theta += degree;
volatile uint32_t _dummy = sh7091.DMAC.CHCR2;
(void)_dummy;
sh7091.DMAC.CHCR2 = 0;
sh7091.DMAC.SAR2 = reinterpret_cast<uint32_t>(&scene[0]);
sh7091.DMAC.DMATCR2 = (32 * 5) / 32;
// SM(1) {source address increment}
// | RS(2) {external request, single address mode}
// | TM {burst mode}
// | TS(2) {32-byte block}
// | DE {enable channel}
sh7091.DMAC.CHCR2 = 0x12c1;
sh7091.DMAC.DMAOR = 0x8201;
system.C2DSTAT = 0x10000000;
system.C2DLEN = 32 * 5;
system.C2DST = 1;
while ((system.ISTNRM & (1 << 19)) == 0);
system.ISTNRM = (1 << 19);
} }
void scene_init_texture_memory() void scene_init_texture_memory()
@ -134,7 +192,7 @@ void scene_init_texture_memory()
); );
} }
void scene_start_render() void scene_start_render(int fb)
{ {
holly.REGION_BASE = (offsetof (struct texture_memory_alloc, region_array)); holly.REGION_BASE = (offsetof (struct texture_memory_alloc, region_array));
holly.PARAM_BASE = (offsetof (struct texture_memory_alloc, isp_tsp_parameters)); holly.PARAM_BASE = (offsetof (struct texture_memory_alloc, isp_tsp_parameters));
@ -144,10 +202,17 @@ void scene_start_render()
| ISP_BACKGND_T__SKIP(1); | ISP_BACKGND_T__SKIP(1);
holly.ISP_BACKGND_D = _i(1.f/100000); holly.ISP_BACKGND_D = _i(1.f/100000);
holly.FB_W_CTRL = FB_W_CTRL__FB_PACKMODE__565_RGB; //holly.SOFTRESET = softreset::pipeline_soft_reset;
holly.FB_W_LINESTRIDE = 640 / 8;
holly.FB_W_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer)); holly.FB_W_CTRL = 1 << 3 | FB_W_CTRL__FB_PACKMODE__565_RGB;
holly.FB_R_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer)); holly.FB_W_LINESTRIDE = (640 * 2) / 8;
int w_fb = (!(!fb)) * 0x00096000;
int r_fb = (!fb) * 0x00096000;
holly.FB_W_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer)) + w_fb;
holly.FB_R_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer)) + r_fb;
//holly.SOFTRESET = 0;
holly.STARTRENDER = 1; holly.STARTRENDER = 1;
} }

View File

@ -5,4 +5,4 @@ void scene_ta_init();
void scene_init_texture_memory(); void scene_init_texture_memory();
void scene_geometry_transfer(); void scene_geometry_transfer();
void scene_wait_opaque_list(); void scene_wait_opaque_list();
void scene_start_render(); void scene_start_render(int fb);

32
serial_main.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "sh7091.h"
#include "sh7091_bits.h"
#include "cache.h"
#include "load.h"
extern uint32_t __bss_link_start __asm("__bss_link_start");
extern uint32_t __bss_link_end __asm("__bss_link_end");
void main()
{
cache_init();
uint32_t * start = &__bss_link_start;
uint32_t * end = &__bss_link_end;
while (start < end) {
*start++ = 0;
}
load_init();
while (1) {
while ((sh7091.SCIF.SCFSR2 & SCFSR2__TDFE) == 0) {
// wait
}
while ((sh7091.SCIF.SCFDR2 & 0b11111) > 0) {
uint8_t c = sh7091.SCIF.SCFRDR2;
load_recv(c);
}
sh7091.SCIF.SCFSR2 = sh7091.SCIF.SCFSR2 & (~SCFSR2__RDF);
}
}

View File

@ -22,7 +22,7 @@
#define SCFSR2__ER (1 << 7) /* read error */ #define SCFSR2__ER (1 << 7) /* read error */
#define SCFSR2__TEND (1 << 6) /* transmit end */ #define SCFSR2__TEND (1 << 6) /* transmit end */
#define SCFSR2__TFDE (1 << 5) /* transmit fifo data empty */ #define SCFSR2__TDFE (1 << 5) /* transmit fifo data empty */
#define SCFSR2__BRK (1 << 4) /* break detect */ #define SCFSR2__BRK (1 << 4) /* break detect */
#define SCFSR2__FER (1 << 3) /* framing error */ #define SCFSR2__FER (1 << 3) /* framing error */
#define SCFSR2__PER (1 << 2) /* parity error */ #define SCFSR2__PER (1 << 2) /* parity error */

View File

@ -4,7 +4,8 @@
void sq_transfer_32byte(volatile void * dst) void sq_transfer_32byte(volatile void * dst)
{ {
// dst typically 0x10000000 (ta polygon converter) // dst typically 0x10000000 (ta polygon converter)
sh7091.CCN.QACR0 = ((reinterpret_cast<uint32_t>(dst) >> 26) & 0b111) << 2; //sh7091.CCN.QACR0 = ((reinterpret_cast<uint32_t>(dst) >> 26) & 0b111) << 2;
sh7091.CCN.QACR0 = 0xac;
// start 32-byte transfer from store queue 0 (SQ0) to QACR0 // start 32-byte transfer from store queue 0 (SQ0) to QACR0
asm volatile ("pref @%0" asm volatile ("pref @%0"

View File

@ -136,6 +136,9 @@ void vga()
| vo_border_col::blue(0x00); | vo_border_col::blue(0x00);
holly.VO_CONTROL = vo_control::pclk_delay(0x16); holly.VO_CONTROL = vo_control::pclk_delay(0x16);
holly.SDRAM_CFG = 0x15D1C951;
holly.SDRAM_REFRESH = 0x00000020;
v_sync_in(); v_sync_in();
holly.SOFTRESET = 0; holly.SOFTRESET = 0;