scene: rotating triangle
This now works on real dreamcast hardware.
This commit is contained in:
parent
67f809c98d
commit
963aa75990
6
alt.lds
6
alt.lds
@ -39,6 +39,12 @@ SECTIONS
|
||||
*(.bss.*)
|
||||
} > p1ram
|
||||
|
||||
.text.p2ram ALIGN(4) : SUBALIGN(4)
|
||||
{
|
||||
*(.p2ram)
|
||||
*(.p2ram.*)
|
||||
} > p1ram
|
||||
|
||||
__p1ram_end = .;
|
||||
|
||||
/DISCARD/ :
|
||||
|
49
client.py
49
client.py
@ -3,36 +3,57 @@ import struct
|
||||
import sys
|
||||
import time
|
||||
|
||||
#dest = 0xac21_0000
|
||||
dest = 0xac02_0000
|
||||
|
||||
ret = []
|
||||
|
||||
def sync(ser, b):
|
||||
def sync(ser, b, wait=1):
|
||||
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(1000 / 1000000)
|
||||
if ser.in_waiting == 0:
|
||||
time.sleep(0.01)
|
||||
while ser.in_waiting > 0:
|
||||
res = ser.read(ser.in_waiting)
|
||||
for c in res:
|
||||
l.append(c)
|
||||
l.extend(res)
|
||||
time.sleep(0.01)
|
||||
|
||||
time.sleep(1)
|
||||
time.sleep(wait)
|
||||
res = ser.read(ser.in_waiting)
|
||||
for c in res:
|
||||
l.append(c)
|
||||
l.extend(res)
|
||||
|
||||
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)
|
||||
|
||||
def do(ser, b):
|
||||
ser.read(ser.in_waiting)
|
||||
_ = ser.read(ser.in_waiting)
|
||||
ser.flush()
|
||||
ser.flushInput()
|
||||
ser.flushOutput()
|
||||
@ -45,15 +66,19 @@ def do(ser, b):
|
||||
print("dargs", args)
|
||||
ret = sync(ser, args)
|
||||
print(ret)
|
||||
if ret != b'data\n':
|
||||
do(ser, b)
|
||||
|
||||
ret = sync(ser, b)
|
||||
ret = symmetric(ser, b)
|
||||
print(ret[-5:])
|
||||
if ret[:-5] != b:
|
||||
print("ret != b; dumped to asdf.bin")
|
||||
with open('asdf.bin', 'wb') as f:
|
||||
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)
|
||||
ser.write(args)
|
||||
print()
|
||||
|
@ -9,6 +9,7 @@ AFLAGS = --fatal-warnings
|
||||
CARCH = -m4-single-only -ml
|
||||
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 += -mfsca -funsafe-math-optimizations
|
||||
DEPFLAGS = -MMD -E
|
||||
# --print-gc-sections
|
||||
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
|
||||
$(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)
|
||||
$(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 $@
|
||||
|
||||
%.bin: %.elf
|
||||
@ -107,7 +111,7 @@ audio.pcm:
|
||||
mv $@.raw $@
|
||||
|
||||
1ST_READ.BIN: main.bin
|
||||
./scramble main.bin 1ST_READ.BIN
|
||||
./scramble $< $@
|
||||
|
||||
%.iso: 1ST_READ.BIN ip.bin
|
||||
mkisofs \
|
||||
|
@ -16,6 +16,8 @@ struct isp_tsp_parameter {
|
||||
vertex_parameter vertex[3];
|
||||
};
|
||||
|
||||
static_assert((sizeof (isp_tsp_parameter)) == (4 * 3 + 3) * 4);
|
||||
|
||||
void background_parameter(volatile uint32_t * 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].y = 0.f;
|
||||
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].y = 480.f;
|
||||
parameter->vertex[1].x = 639.f;
|
||||
parameter->vertex[1].y = 0.f;
|
||||
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].y = 0.f;
|
||||
parameter->vertex[2].x = 639.f;
|
||||
parameter->vertex[2].y = 479.f;
|
||||
parameter->vertex[2].z = 1.f/100000;
|
||||
parameter->vertex[2].base_color = 0xff300000;
|
||||
parameter->vertex[2].base_color = 0x00000000;
|
||||
}
|
||||
|
@ -47,6 +47,9 @@ void region_array(volatile uint32_t * buf,
|
||||
region_array[ix].tile = REGION_ARRAY__TILE_Y_POSITION(y)
|
||||
| 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;
|
||||
constexpr uint32_t opaque_list_opb_size = 16 * 4; // in bytes; this must match O_OPB in TA_ALLOC_CTRL
|
||||
region_array[ix].opaque_list_pointer = ol_base + (opaque_list_opb_size * tile_index);
|
||||
|
2
load.cpp
2
load.cpp
@ -1,6 +1,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sh7091.h"
|
||||
#include "sh7091_bits.h"
|
||||
#include "holly.h"
|
||||
|
||||
enum load_command {
|
||||
@ -47,6 +48,7 @@ void debug(const char * s)
|
||||
{
|
||||
char c;
|
||||
while ((c = *s++)) {
|
||||
while ((sh7091.SCIF.SCFSR2 & SCFSR2__TDFE) == 0);
|
||||
sh7091.SCIF.SCFTDR2 = (uint8_t)c;
|
||||
}
|
||||
}
|
||||
|
61
main.cpp
61
main.cpp
@ -7,6 +7,9 @@
|
||||
#include "sh7091.h"
|
||||
#include "sh7091_bits.h"
|
||||
#include "memorymap.h"
|
||||
#include "systembus.h"
|
||||
#include "holly.h"
|
||||
#include "holly/core_bits.h"
|
||||
|
||||
#include "rgb.h"
|
||||
#include "scene.h"
|
||||
@ -30,6 +33,22 @@ void serial()
|
||||
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"
|
||||
void main()
|
||||
{
|
||||
@ -42,7 +61,7 @@ void main()
|
||||
*start++ = 0;
|
||||
}
|
||||
|
||||
serial();
|
||||
//serial();
|
||||
|
||||
vga();
|
||||
|
||||
@ -58,39 +77,31 @@ void main()
|
||||
}
|
||||
|
||||
|
||||
while (1) {
|
||||
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) {
|
||||
scene_ta_init();
|
||||
scene_geometry_transfer();
|
||||
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
|
||||
// framebuffer.
|
||||
|
||||
v_sync_out();
|
||||
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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
89
scene.cpp
89
scene.cpp
@ -3,8 +3,10 @@
|
||||
#include "holly/region_array.h"
|
||||
#include "holly/background.h"
|
||||
#include "holly/ta_parameter.h"
|
||||
#include "holly/core_bits.h"
|
||||
#include "holly.h"
|
||||
#include "ta.h"
|
||||
#include "sh7091.h"
|
||||
|
||||
#include "memorymap.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 region_array[0x00002000 / 4]; // REGION_BASE
|
||||
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] = {
|
||||
{ 320.f, 120.f, 1/10.f},
|
||||
{ 440.f, 360.f, 1/10.f},
|
||||
{ 200.f, 360.f, 1/10.f},
|
||||
{ 0.f, -0.5f, 1/10.f},
|
||||
{ 0.5f, 0.5f, 1/10.f},
|
||||
{ -0.5f, 0.5f, 1/10.f},
|
||||
};
|
||||
|
||||
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_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_LIMIT = (offsetof (struct texture_memory_alloc, region_array)); // the end of the object_list
|
||||
holly.TA_NEXT_OPB_INIT = (offsetof (struct texture_memory_alloc, object_list))
|
||||
+ (640 / 32) * (320 / 32) * 16 * 4;
|
||||
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_LIST_INIT = TA_LIST_INIT__LIST_INIT;
|
||||
|
||||
@ -100,8 +110,12 @@ void scene_wait_opaque_list()
|
||||
system.ISTNRM = SB_ISTNRM__TAEOINT;
|
||||
}
|
||||
|
||||
static float theta = 0;
|
||||
constexpr float degree = 0.01745329f;
|
||||
|
||||
void scene_geometry_transfer()
|
||||
{
|
||||
/*
|
||||
triangle(store_queue);
|
||||
sq_transfer_32byte(ta_fifo_polygon_converter);
|
||||
|
||||
@ -120,6 +134,50 @@ void scene_geometry_transfer()
|
||||
|
||||
end_of_list(store_queue);
|
||||
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()
|
||||
@ -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.PARAM_BASE = (offsetof (struct texture_memory_alloc, isp_tsp_parameters));
|
||||
@ -144,10 +202,17 @@ void scene_start_render()
|
||||
| ISP_BACKGND_T__SKIP(1);
|
||||
holly.ISP_BACKGND_D = _i(1.f/100000);
|
||||
|
||||
holly.FB_W_CTRL = FB_W_CTRL__FB_PACKMODE__565_RGB;
|
||||
holly.FB_W_LINESTRIDE = 640 / 8;
|
||||
holly.FB_W_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer));
|
||||
holly.FB_R_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer));
|
||||
//holly.SOFTRESET = softreset::pipeline_soft_reset;
|
||||
|
||||
holly.FB_W_CTRL = 1 << 3 | FB_W_CTRL__FB_PACKMODE__565_RGB;
|
||||
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;
|
||||
}
|
||||
|
2
scene.h
2
scene.h
@ -5,4 +5,4 @@ void scene_ta_init();
|
||||
void scene_init_texture_memory();
|
||||
void scene_geometry_transfer();
|
||||
void scene_wait_opaque_list();
|
||||
void scene_start_render();
|
||||
void scene_start_render(int fb);
|
||||
|
32
serial_main.cpp
Normal file
32
serial_main.cpp
Normal 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);
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
|
||||
#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__TDFE (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 */
|
||||
|
@ -4,7 +4,8 @@
|
||||
void sq_transfer_32byte(volatile void * dst)
|
||||
{
|
||||
// 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
|
||||
asm volatile ("pref @%0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user