Compare commits

...

2 Commits

Author SHA1 Message Date
a4ae84124a example: add texture_filtering and texture_filtering_maple 2024-05-12 17:39:52 +08:00
bcaa9789cf texture_memory_alloc: rework texture memory allocation
The previous texture_memory_alloc.hpp was written based on an
incorrect understanding of the "32-bit" and "64-bit" texture memory
address mapping.

The primary motivation is to rearrange the texture memory address map
so that "textures" (64-bit access) do not overlap with 32-bit
accesses, such as REGION_BASE or PARAM_BASE.
2024-05-12 17:06:00 +08:00
65 changed files with 2235 additions and 643 deletions

View File

@ -12,5 +12,6 @@ geometry/%.hpp: geometry/%.obj
mv $@.tmp $@
include example/example.mk
include pokemon/pokemon.mk
.PHONY: phony

11
base.mk
View File

@ -30,6 +30,17 @@ define BUILD_BINARY_O
$< $@
endef
as_obj_binary = _binary_$(subst .,_,$(subst /,_,$(1)))
define BUILD_BINARY_H
@echo gen $@
@echo '#pragma once' > $@
@echo '#include <cstdint>' >> $@
@echo 'extern uint32_t $(call as_obj_binary,$<)_start __asm("$(call as_obj_binary,$<)_start");' >> $@
@echo 'extern uint32_t $(call as_obj_binary,$<)_end __asm("$(call as_obj_binary,$<)_end");' >> $@
@echo 'extern uint32_t $(call as_obj_binary,$<)_size __asm("$(call as_obj_binary,$<)_size");' >> $@
endef
%.bin.o: %.bin
$(BUILD_BINARY_O)

69
bbb.data Normal file

File diff suppressed because one or more lines are too long

17
bbb.hpp Normal file
View File

@ -0,0 +1,17 @@
#include <cstdint>
extern uint32_t _binary_bbb_data_start __asm("_binary_bbb_data_start");
extern uint32_t _binary_bbb_data_end __asm("_binary_bbb_data_end");
extern uint32_t _binary_bbb_data_size __asm("_binary_bbb_data_size");
extern uint32_t _binary_bbb1_data_start __asm("_binary_bbb1_data_start");
extern uint32_t _binary_bbb2_data_start __asm("_binary_bbb2_data_start");
extern uint32_t _binary_bbb4_data_start __asm("_binary_bbb4_data_start");
extern uint32_t _binary_bbb8_data_start __asm("_binary_bbb8_data_start");
extern uint32_t _binary_bbb16_data_start __asm("_binary_bbb16_data_start");
extern uint32_t _binary_bbb32_data_start __asm("_binary_bbb32_data_start");
extern uint32_t _binary_bbb64_data_start __asm("_binary_bbb64_data_start");
extern uint32_t _binary_bbb128_data_start __asm("_binary_bbb128_data_start");
extern uint32_t _binary_bbb256_data_start __asm("_binary_bbb256_data_start");
extern uint32_t _binary_bbb512_data_start __asm("_binary_bbb512_data_start");
extern uint32_t _binary_bbb1024_data_start __asm("_binary_bbb1024_data_start");

BIN
bbb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

1
bbb1.data Normal file
View File

@ -0,0 +1 @@
ZTC

69
bbb1024.data Normal file

File diff suppressed because one or more lines are too long

1
bbb128.data Normal file

File diff suppressed because one or more lines are too long

1
bbb16.data Normal file
View File

@ -0,0 +1 @@
�籔�魤�鼥�玁稂玢�矘篲峊凒ㄇ�䐭���h�l�z�l�礯�蟼�蜬�槦w�i�ポ疥皉永���}�v~��b�r衮{�謯�鵽�槦╚滏ghj~�玳鮝悒椅忂峼𤍤�𢳂~Ê�u�c𦹄o�鶋�諀�糌�粜`ai�ǚ�ㄛu𥚃�𥋇�u夝虾w~𨛦�儫�f﹍�諅箾驟cgR^cf�my��]���醩z𠩯v𣸆w~dw~^{�薗肢�◣|C^hJkv\jzd]fmbR�iy𠻺iqXltTq�nlRu|bllXv𠰋0_�l<KUItwU|𪀔XgdSKw𨧣q�]brSe�l骲hoPm}ialRpW�𪊺cr_;WbDUbPt䱀IW\LIu�dr[W^MV_Q`vV[aQaTKSKfVp{^HY]A]iCr}Eq�H[ML]W_Jq�Zr[TxIO`FOnHUt\EdJXgZXaXIopBts:al7M`>EYA;KFI9NhE[岚XvPFbG;*539L=NLCYRK\P3<@0ZN/Wa-PcGQNcaEyw>}v2�1�4�/�)uv'wy+異5�1�-�)zx&tv$�~({+�-{,�,�)�'��%uw%fl#ト/葡)郃'祠'�%�$�)�*�:蚕��+�)�+�*{�+nx&虯K撮*玩+瑤)撩[侒7龔;飄-瞻q倰A遙L赻2趼4棩7テT冞I赽/欶3嗈8殫8岋(桻0硢,恀,卩1ㄘ&寊*厊&寎-庌.擠,恀5溯-倓l慱狍�?棦/歲%�*椥\珂K諘J冫+倢(桻)紗*噱H乾-

1
bbb2.data Normal file
View File

@ -0,0 +1 @@
Pns~Œkˆ†'|v1

1
bbb256.data Normal file

File diff suppressed because one or more lines are too long

1
bbb32.data Normal file
View File

@ -0,0 +1 @@
�鷿�爢�羱�鍺�鵴�欉�玁�齆�癰庚柵�塵讒厦蠲瀍麌枍徽卍帎�戲{��t�~匬��{~c�s�n�s�p�}�x�f�礯�礯�鵴�誺�罺�懠�檷�纊攮緁x}Vny𡠺⊙籓异風�銑駚����}�亳�﹙�y儍y�i�j�l���𠳖𠯫x麽�礯�礯�灚�魤�魟�魡�糌�鍺痻体{�_�~�逌蕩�纔㤧�銘�砟唂𣜖��w�~�k�t�p��~栄~~a�z�s鷼��}�礯�酁�欋�諃�蜬�魟�魟�槦�𦲽ktk�l�矽铜�彡𣜯�栳姘芴店��|𥗛㻛�𡯂~�]�p�p银�鷔𪂹�瑈𤩎~�q�鼁�蠉�欋�錆�魡�誽�魤颮狌�_qp`im~景�廴矽�豻岐�穹��𡶶��𡯂�v�i�h�n臁{vZ�l�m𢹸t�q�譇�蠌�礱�歖�樈�魤�翯瑣蒞x~[dhi�z�〧鬲�ポ厄�邪y䐭t�z~��w�x�𢁾�m�o�柾�z~庆�稪�e�q�i�謵�鶋�蠌�槧�糈�諃轚猲�mt_qxcfjs�u�空𩲭�‘q𡤻x������鰂�嶹trT�i~㤔|𤺧�蘐~𦮖�h�d�r㯂�鶋�縤�鬿�槧�糈螂沃pzSpq^�bowi{��y�掃z�c�a�|��𡺉竈z龗{�s|㞗~嚞𨜓u}[v{\{�}Ǒ筯~i軞紿瘖�糅�糅�糅痵瓤�Oy|OV]Ytx`u�k�t𧗾u秄�d�Yx|Z𥚕�脔�|�u~𠆫�lmrW�xpvVt�XrtW�𦷪|𨬓urY~ī倣伄敆�諀欏衾挬�𠿟wwGbhINQP__^�g�l矝俰dXrjO𦛚�拎�|w�r庆u�x胬v𡩣{䎗u�nnSx�vzZpmQw�rmX蘓�遙鸁婐坉袲�炦KQVFqkL}��^�`gsdZ_gbik^VrjP�ì䕪t𤏩x綕p}^m~chk[n]gfQu�osTx�uzXtzbs�v�池㴝�瘧㭻�鰾煫�EYcChtHx䱀|䵶{崾q�mebngXZlaNz糦v�z骲|𪆒e`OiyYn�ZcbLx𦷪lmYv夲nnUu}^nnShdTjoW�fu�𢜟e�i�xul?U_Aah@PTM�KTcVUc__o`XecPMnjW{𤎽y�t�n~[l�evZZ_JerUj~Vo实r头kjPln]o~TfkVfzS𩣪b嵈嚤c働Z�ePYT7@K:EODbjP�McuXx橗j�P[_QXcTIr{cx𩟔q}bv𦮖]]Iq馪_mU\ePbq]foVhnWfiUejXp蒓^oRVQR{䇭w��葘咲dwaAJO>df?ciEfpGapJXiSs�HVUHSZHM^JGltcs�r篺chU^iM]kQh嶹^pX^nTaqU\\G_aL^jPp𡤄ORAYr\�YYfNy变jwUfp[W]]=YcDs�y�\eHYiL^rKRcNFSTDLb]NdiTn㗝]cMd~cbyZV`JWhSSYFSVHi蒀XcK]s\UhSRhQNfKSuYk�ZbrZ�iy�dp_GdlA`i>R^BduEp�芦G`vFLaIGYNNaSKJ]]Iz𠺬t𥗛^z`_}cZnVThJWwSc𨃩RcESmKYVVnWK]MIgME\FYlVR^Vcq\p{WWeYDV]D[`Djl<IV>aq:FXCctG[sFEVII\MGAOP>UfJ`{YXv]UnVTkIQqMM[DPaIMdIPo=Lf<>A@G\QGbWL�dycUeYUaTT`N_l]G[`B_dCss;Vb<gq9Rd<ShGp𡅅?NDARD;CFF:GO9RpJWrUPgSUvRObG^�eJaHL`LYXU7%.7=R37IARBCaLL_UHWUL[WIc^FikBln:KN8Za7^`4HW6O`8Xm;Vj=J`>;K?8BJKBIP@TqINlEOjOQmO`𠰋i�Ry|JTVN<I/#,6>O0:L3DU5CO[o^I^W[k[EVQ>W]:^\9ij2[U6nj0LY3]n/M`2I\;i�48L9:HNVUW]<VV6ad>mnUmf0x|Xv�r�ghChd.cb._gMYgWVdYY`HIaQO^ZL\WI]Y7JN6bW0eSB�LpbWpc`oWotI~D|x3�0�/�0�0�/�/�-�.zv-�,�,�,zz(wx%dg#np$qs&tw&�I�K�D�?�1�.�,�+�)�'�'�'~|'wv(}z){x+�.}x.�.�.�.�.�,�*xu)vv'{|&}~$rt"uw$ei#fl#�0�/�-�,�)�)�){z'xx%xy%{|%||%{z'�(|z*�)�,�-{w-zw+~z,}z)ut(zv.vw&qt#y|$tt'�.|~'nq)�(蔆0釩,郊*�(�*�'�(�(�(�%�%�'�'�*岸,哈0�5�9撐m�5�+�,�+�<�/�4��(w~'qz'y�&nx&fp%衃2笰4倇E吇:兢0蝦+臍+撩*圻&�$�#牧(�'�(�+�-�,觛耒頑鱉��.�)�(�(�)w}&�*�.�/�3pz%~�:囡)鷗-鷓7豖3秦*匱*講.藍D臘_藷Sネ4藪:藍3恟<旃4藏1恇㨪�蜮y楈_偌.絮+鏽*蕭/鏽-擱7獐2�0�3�5車1咅+敢@擬3聶6昒2臏+擰+兢(藍,螢,藍*遛,侕1芼w藕E蝗A挸c陊虂�倅;寑:旼I珇6罈B倳1谿.謐1崷3棔3笳4硢F嗔T衃<犖*蝙*俵.旄2寎2靷3楉1謗(陰"�!蛹)侞,筇;蚝F冂A�A桫��;�/祴5疐1篊D撓+妨%饒+攪0酷(甄.囡/謊/赽-噯-皵4眐3寑0飄/衶7葠K萫6誺6觝1睕3眝.擘(鰻(玶)擬(玶,俵/垓)偃%夾$帖"鏽*眒,赹0旄.稌2瘊3祰5衭2玴2芡a捈f藩J斐Z昈a堄[婠r蚥氵垌盉a袼P謷9恀*� ~�𡵆"炳(衲:蕪<秤+虜'厊,接(瑤(犖%ヌ1藕)瑪&奷5勹d祴[昋a絞f萵b螃*悅'雲6齬E觛e棝l毓*�$撓*噱'毓(韌$溯M藕J佮`飄G藥.獌�罦馝}楗/笳.鬿4眒,炫#溶$遞%互>繳1謠2順2噱/

1
bbb4.data Normal file
View File

@ -0,0 +1 @@
�萵~剋z��據{`h|ny`pqZDff3EZGVD4@Pヨメ/ニチN賍Kマホ,

2
bbb512.data Normal file

File diff suppressed because one or more lines are too long

1
bbb64.data Normal file

File diff suppressed because one or more lines are too long

1
bbb8.data Normal file
View File

@ -0,0 +1 @@
�灚�諃Vpx蹦𧿹��蒓�j仪v�鶌�殫f�銜��𠻻~𢳂�c椳苡�f馭jad�wr�r}Xv��g8ITI^oZNXv�\gNgwZe|VZj\D[c:SfE@P[ySQeFN`K@KIbt[{��/�+�/�,mn'mp$岊:圮2牧5噢6縍��'�,�3眛V衶=羱7陁#�帑&眙9擘X

View File

@ -4,7 +4,8 @@ import sys
import time
#dest = 0xac21_0000
dest = 0xac02_0000
#dest = 0xac02_0000
dest = 0xac01_0000
ret = []
@ -100,13 +101,53 @@ def do(ser, b):
print()
console(ser)
def console(ser):
while True:
b = ser.read(1)
if b:
sys.stderr.buffer.write(b)
sys.stderr.flush()
seen_length = 16
def compare_str(s, seen, seen_ix):
assert len(s) <= seen_length, s
start = seen_length + (seen_ix - len(s))
for i, c in enumerate(s):
if c != seen[(start + i) % seen_length]:
return False
return True
framebuffer_mode = False
framebuffer = []
def console(ser):
global framebuffer_mode
global framebuffer
seen = [0] * seen_length
seen_ix = 0
while True:
b = ser.read(ser.in_waiting)
if b == b'':
continue
for c in b:
seen[seen_ix % seen_length] = c
seen_ix += 1
if framebuffer_mode:
framebuffer.append(c)
if len(framebuffer) % 1000 == 0:
print(len(framebuffer), (640 * 480 * 2), file=sys.stderr)
sys.stderr.flush()
else:
sys.stderr.buffer.write(bytes([c]))
sys.stderr.flush()
if compare_str(b"<<FRAMEBUFFER>>", seen, seen_ix):
sys.stderr.write("\nMATCH\n")
sys.stderr.flush()
framebuffer_mode = True
framebuffer = []
if compare_str(b"<</FRAMEBUFFER>>", seen, seen_ix):
framebuffer_mode = False
sys.stderr.write("<</FRAMEBUFFER>>\n")
sys.stderr.flush()
with open('framebuffer.bin', 'wb') as f:
f.write(bytes(framebuffer[:-16]))
with open(sys.argv[1], 'rb') as f:
b = f.read()

View File

@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
DIR := $(dir $(MAKEFILE_PATH))
LIB ?= .
OPT ?= -Og
OPT ?= -O2
GENERATED ?=
AARCH = --isa=sh4 --little
@ -79,9 +79,7 @@ sine.pcm: common.mk
/1ST_READ.BIN=./$< \
/=./COPYRIGH.TXT \
/=./ABSTRACT.TXT \
/=./BIBLIOGR.TXT \
/DUNE.PCM=./dune.pcm \
/REIGN.PCM=./reign.pcm
/=./BIBLIOGR.TXT
%.cdi: %.iso
./cdi4dc $< $@ >/dev/null

View File

@ -221,16 +221,11 @@ void transform(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff00ff00);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -267,7 +262,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
float x_pos = 0;
float y_pos = 0;
@ -311,14 +305,14 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
theta += (2.f * pi) / 720.f;
}
}

View File

@ -199,16 +199,11 @@ void transform(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -245,16 +240,12 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
float x_pos = 0;
float y_pos = 0;
while (1) {
do_get_condition(command_buf, receive_buf);
if (frame_ix % 120 == 0) {
serial::integer(data[0].analog_axis_3);
}
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
@ -290,13 +281,13 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -137,7 +137,7 @@ void transform(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -220,23 +220,18 @@ void transform(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
void init_macaw_texture()
{
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
uint16_t temp[size / 3];
for (uint32_t px = 0; px < size / 3; px++) {
@ -247,7 +242,7 @@ void init_macaw_texture()
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
temp[px] = rgb565;
}
twiddle::texture(mem->texture, temp, 128, 128);
twiddle::texture(texture, temp, 128, 128);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -285,7 +280,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
float x_pos = 0;
float y_pos = 0;
@ -328,13 +322,13 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -134,16 +134,11 @@ void transform(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * (5 * 6 + 1)) + 32) / 4];
@ -177,7 +172,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
vec3 lights[2] = {
@ -204,14 +198,14 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -125,22 +125,20 @@ uint32_t transform(uint32_t * ta_parameter_buf,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
auto object_list = &texture_memory32[texture_memory_alloc::object_list.start / 4];
auto isp_tsp_parameters = &texture_memory32[texture_memory_alloc::isp_tsp_parameters.start / 4];
// zeroize
for (uint32_t i = 0; i < 0x00100000 / 4; i++) {
mem->object_list[i] = 0xeeeeeeee;
mem->isp_tsp_parameters[i] = 0xeeeeeeee;
object_list[i] = 0xeeeeeeee;
isp_tsp_parameters[i] = 0xeeeeeeee;
}
background_parameter(mem->background, 0xff222200);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff222200);
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
@ -153,13 +151,13 @@ static_assert((sizeof (union u32_u8)) == 4);
void dump()
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
auto object_list = &texture_memory32[texture_memory_alloc::object_list.start / 4];
auto isp_tsp_parameters = &texture_memory32[texture_memory_alloc::isp_tsp_parameters.start / 4];
constexpr uint32_t screen_ol_size = 8 * 4 * (640 / 32) * (480 / 32);
for (uint32_t i = 0; i < (screen_ol_size + 0x100) / 4; i++) {
union u32_u8 n;
n.u32 = mem->object_list[i];
n.u32 = object_list[i];
if (((i * 4) & 0x1f) == 0)
serial::character('\n');
@ -175,7 +173,7 @@ void dump()
for (uint32_t i = 0; i < (0x100) / 4; i++) {
union u32_u8 n;
n.u32 = mem->isp_tsp_parameters[i];
n.u32 = isp_tsp_parameters[i];
if (((i * 4) & 0x1f) == 0)
serial::character('\n');
@ -213,7 +211,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
bool dumped = false;
while (true) {
@ -225,14 +222,14 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
if (frame_ix == 10 && dumped == false) {
dump();

View File

@ -7,7 +7,7 @@ VIDEO_OUTPUT_OBJ = \
holly/ta_fifo_polygon_converter.o \
sh7091/serial.o
example/video_output.elf: LDSCRIPT = $(LIB)/alt.lds
example/video_output.elf: LDSCRIPT = $(LIB)/main.lds
example/video_output.elf: $(START_OBJ) $(VIDEO_OUTPUT_OBJ)
SPRITE_OBJ = \
@ -17,10 +17,9 @@ SPRITE_OBJ = \
holly/region_array.o \
holly/background.o \
holly/ta_fifo_polygon_converter.o \
sh7091/serial.o \
$(LIBGCC)
example/sprite.elf: LDSCRIPT = $(LIB)/alt.lds
example/sprite.elf: LDSCRIPT = $(LIB)/main.lds
example/sprite.elf: $(START_OBJ) $(SPRITE_OBJ)
MACAW_OBJ = \
@ -30,9 +29,10 @@ MACAW_OBJ = \
holly/background.o \
holly/ta_fifo_polygon_converter.o \
holly/video_output.o \
sh7091/serial.o \
macaw.data.o
example/macaw.elf: LDSCRIPT = $(LIB)/alt.lds
example/macaw.elf: LDSCRIPT = $(LIB)/main.lds
example/macaw.elf: $(START_OBJ) $(MACAW_OBJ)
MACAW_TWIDDLE_OBJ = \
@ -44,7 +44,7 @@ MACAW_TWIDDLE_OBJ = \
holly/ta_fifo_polygon_converter.o \
macaw.data.o
example/macaw_twiddle.elf: LDSCRIPT = $(LIB)/alt.lds
example/macaw_twiddle.elf: LDSCRIPT = $(LIB)/main.lds
example/macaw_twiddle.elf: $(START_OBJ) $(MACAW_TWIDDLE_OBJ)
FONT_BITMAP_OBJ = \
@ -56,7 +56,7 @@ FONT_BITMAP_OBJ = \
holly/ta_fifo_polygon_converter.o \
sperrypc_8x8.data.o
example/font_bitmap.elf: LDSCRIPT = $(LIB)/alt.lds
example/font_bitmap.elf: LDSCRIPT = $(LIB)/main.lds
example/font_bitmap.elf: $(START_OBJ) $(FONT_BITMAP_OBJ)
FONT_OUTLINE_OBJ = \
@ -68,7 +68,7 @@ FONT_OUTLINE_OBJ = \
holly/ta_fifo_polygon_converter.o \
dejavusansmono.data.o
example/font_outline.elf: LDSCRIPT = $(LIB)/alt.lds
example/font_outline.elf: LDSCRIPT = $(LIB)/main.lds
example/font_outline.elf: $(START_OBJ) $(FONT_OUTLINE_OBJ)
FONT_OUTLINE_PUNCH_THROUGH_OBJ = \
@ -80,7 +80,7 @@ FONT_OUTLINE_PUNCH_THROUGH_OBJ = \
holly/ta_fifo_polygon_converter.o \
dejavusansmono_mono.data.o
example/font_outline_punch_through.elf: LDSCRIPT = $(LIB)/alt.lds
example/font_outline_punch_through.elf: LDSCRIPT = $(LIB)/main.lds
example/font_outline_punch_through.elf: $(START_OBJ) $(FONT_OUTLINE_PUNCH_THROUGH_OBJ)
MACAW_MULTIPASS_OBJ = \
@ -92,7 +92,7 @@ MACAW_MULTIPASS_OBJ = \
holly/ta_fifo_polygon_converter.o \
macaw.data.o
example/macaw_multipass.elf: LDSCRIPT = $(LIB)/alt.lds
example/macaw_multipass.elf: LDSCRIPT = $(LIB)/main.lds
example/macaw_multipass.elf: $(START_OBJ) $(MACAW_MULTIPASS_OBJ)
TRANSLUCENCY_OBJ = \
@ -104,7 +104,7 @@ TRANSLUCENCY_OBJ = \
holly/ta_fifo_polygon_converter.o \
macaw.data.o
example/translucency.elf: LDSCRIPT = $(LIB)/alt.lds
example/translucency.elf: LDSCRIPT = $(LIB)/main.lds
example/translucency.elf: $(START_OBJ) $(TRANSLUCENCY_OBJ)
CUBE_OBJ = \
@ -115,7 +115,7 @@ CUBE_OBJ = \
holly/background.o \
holly/ta_fifo_polygon_converter.o
example/cube.elf: LDSCRIPT = $(LIB)/alt.lds
example/cube.elf: LDSCRIPT = $(LIB)/main.lds
example/cube.elf: $(START_OBJ) $(CUBE_OBJ)
ICOSPHERE_OBJ = \
@ -126,7 +126,7 @@ ICOSPHERE_OBJ = \
holly/background.o \
holly/ta_fifo_polygon_converter.o
example/icosphere.elf: LDSCRIPT = $(LIB)/alt.lds
example/icosphere.elf: LDSCRIPT = $(LIB)/main.lds
example/icosphere.elf: $(START_OBJ) $(ICOSPHERE_OBJ)
SUZANNE_PROFILE_OBJ = \
@ -140,7 +140,7 @@ SUZANNE_PROFILE_OBJ = \
sh7091/serial.o \
verite_8x16.data.o
example/suzanne_profile.elf: LDSCRIPT = $(LIB)/alt.lds
example/suzanne_profile.elf: LDSCRIPT = $(LIB)/main.lds
example/suzanne_profile.elf: $(START_OBJ) $(SUZANNE_PROFILE_OBJ)
WIFFLE_ATTENUATION_OBJ = \
@ -162,7 +162,7 @@ MODIFIER_VOLUME_OBJ = \
holly/background.o \
holly/ta_fifo_polygon_converter.o
example/modifier_volume.elf: LDSCRIPT = $(LIB)/alt.lds
example/modifier_volume.elf: LDSCRIPT = $(LIB)/main.lds
example/modifier_volume.elf: $(START_OBJ) $(MODIFIER_VOLUME_OBJ)
MODIFIER_VOLUME_WITH_TWO_VOLUMES_OBJ = \
@ -177,7 +177,7 @@ MODIFIER_VOLUME_WITH_TWO_VOLUMES_OBJ = \
maple/maple.o \
$(LIBGCC)
example/modifier_volume_with_two_volumes.elf: LDSCRIPT = $(LIB)/alt.lds
example/modifier_volume_with_two_volumes.elf: LDSCRIPT = $(LIB)/main.lds
example/modifier_volume_with_two_volumes.elf: $(START_OBJ) $(MODIFIER_VOLUME_WITH_TWO_VOLUMES_OBJ)
HEART_OBJ = \
@ -188,7 +188,7 @@ HEART_OBJ = \
holly/background.o \
holly/ta_fifo_polygon_converter.o
example/heart.elf: LDSCRIPT = $(LIB)/alt.lds
example/heart.elf: LDSCRIPT = $(LIB)/main.lds
example/heart.elf: $(START_OBJ) $(HEART_OBJ)
VIEWING_SYSTEM_OBJ = \
@ -200,7 +200,7 @@ VIEWING_SYSTEM_OBJ = \
holly/ta_fifo_polygon_converter.o \
$(LIBGCC)
example/viewing_system.elf: LDSCRIPT = $(LIB)/alt.lds
example/viewing_system.elf: LDSCRIPT = $(LIB)/main.lds
example/viewing_system.elf: $(START_OBJ) $(VIEWING_SYSTEM_OBJ)
MACAW_CUBE_OBJ = \
@ -212,7 +212,7 @@ MACAW_CUBE_OBJ = \
holly/ta_fifo_polygon_converter.o \
macaw.data.o
example/macaw_cube.elf: LDSCRIPT = $(LIB)/alt.lds
example/macaw_cube.elf: LDSCRIPT = $(LIB)/main.lds
example/macaw_cube.elf: $(START_OBJ) $(MACAW_CUBE_OBJ)
MACAW_CUBE_RENDER_TO_TEXTURE_OBJ = \
@ -224,7 +224,7 @@ MACAW_CUBE_RENDER_TO_TEXTURE_OBJ = \
holly/ta_fifo_polygon_converter.o \
macaw.data.o
example/macaw_cube_render_to_texture.elf: LDSCRIPT = $(LIB)/alt.lds
example/macaw_cube_render_to_texture.elf: LDSCRIPT = $(LIB)/main.lds
example/macaw_cube_render_to_texture.elf: $(START_OBJ) $(MACAW_CUBE_RENDER_TO_TEXTURE_OBJ)
CLIPPING_OBJ = \
@ -236,7 +236,7 @@ CLIPPING_OBJ = \
holly/ta_fifo_polygon_converter.o \
maple/maple.o
example/clipping.elf: LDSCRIPT = $(LIB)/alt.lds
example/clipping.elf: LDSCRIPT = $(LIB)/main.lds
example/clipping.elf: $(START_OBJ) $(CLIPPING_OBJ)
CLIPPING2_OBJ = \
@ -250,7 +250,7 @@ CLIPPING2_OBJ = \
sh7091/serial.o \
$(LIBGCC)
example/clipping2.elf: LDSCRIPT = $(LIB)/alt.lds
example/clipping2.elf: LDSCRIPT = $(LIB)/main.lds
example/clipping2.elf: $(START_OBJ) $(CLIPPING2_OBJ)
CLIPPING_TEXTURED_OBJ = \
@ -265,7 +265,7 @@ CLIPPING_TEXTURED_OBJ = \
macaw.data.o \
$(LIBGCC)
example/clipping_textured.elf: LDSCRIPT = $(LIB)/alt.lds
example/clipping_textured.elf: LDSCRIPT = $(LIB)/main.lds
example/clipping_textured.elf: $(START_OBJ) $(CLIPPING_TEXTURED_OBJ)
MAPLE_DEVICE_REQUEST_OBJ = \
@ -274,7 +274,7 @@ MAPLE_DEVICE_REQUEST_OBJ = \
sh7091/serial.o \
maple/maple.o
example/maple_device_request.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_device_request.elf: LDSCRIPT = $(LIB)/main.lds
example/maple_device_request.elf: $(START_OBJ) $(MAPLE_DEVICE_REQUEST_OBJ)
MAPLE_CONTROLLER_OBJ = \
@ -283,7 +283,7 @@ MAPLE_CONTROLLER_OBJ = \
sh7091/serial.o \
maple/maple.o
example/maple_controller.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_controller.elf: LDSCRIPT = $(LIB)/main.lds
example/maple_controller.elf: $(START_OBJ) $(MAPLE_CONTROLLER_OBJ)
MAPLE_WINK_OBJ = \
@ -294,7 +294,7 @@ MAPLE_WINK_OBJ = \
maple/maple.o \
wink.data.o
example/maple_wink.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_wink.elf: LDSCRIPT = $(LIB)/main.lds
example/maple_wink.elf: $(START_OBJ) $(MAPLE_WINK_OBJ)
MAPLE_VIBRATOR_OBJ = \
@ -304,7 +304,7 @@ MAPLE_VIBRATOR_OBJ = \
sh7091/serial.o \
maple/maple.o
example/maple_vibrator.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_vibrator.elf: LDSCRIPT = $(LIB)/main.lds
example/maple_vibrator.elf: $(START_OBJ) $(MAPLE_VIBRATOR_OBJ)
MAPLE_ANALOG_OBJ = \
@ -316,7 +316,7 @@ MAPLE_ANALOG_OBJ = \
holly/ta_fifo_polygon_converter.o \
maple/maple.o
example/maple_analog.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_analog.elf: LDSCRIPT = $(LIB)/main.lds
example/maple_analog.elf: $(START_OBJ) $(MAPLE_ANALOG_OBJ)
SERIAL_TRANSFER_OBJ = \
@ -332,7 +332,7 @@ INTERRUPT_OBJ = \
example/illslot.o \
sh7091/serial.o
example/interrupt.elf: LDSCRIPT = $(LIB)/alt.lds
example/interrupt.elf: LDSCRIPT = $(LIB)/main.lds
example/interrupt.elf: $(START_OBJ) $(INTERRUPT_OBJ)
DUMP_OBJECT_LIST_OBJ = \
@ -344,14 +344,14 @@ DUMP_OBJECT_LIST_OBJ = \
holly/ta_fifo_polygon_converter.o \
sh7091/serial.o
example/dump_object_list.elf: LDSCRIPT = $(LIB)/alt.lds
example/dump_object_list.elf: LDSCRIPT = $(LIB)/main.lds
example/dump_object_list.elf: $(START_OBJ) $(DUMP_OBJECT_LIST_OBJ)
DUMP_RAM_OBJ = \
example/dump_ram.o \
sh7091/serial.o
example/dump_ram.elf: LDSCRIPT = $(LIB)/alt.lds
example/dump_ram.elf: LDSCRIPT = $(LIB)/main.lds
example/dump_ram.elf: $(START_OBJ) $(DUMP_RAM_OBJ)
SOFTWARE_TA_OBJ = \
@ -364,21 +364,21 @@ SOFTWARE_TA_OBJ = \
sh7091/serial.o \
libm.o
example/software_ta.elf: LDSCRIPT = $(LIB)/alt.lds
example/software_ta.elf: LDSCRIPT = $(LIB)/main.lds
example/software_ta.elf: $(START_OBJ) $(SOFTWARE_TA_OBJ)
GDROM_TEST_OBJ = \
example/gdrom_test.o \
sh7091/serial.o
example/gdrom_test.elf: LDSCRIPT = $(LIB)/alt.lds
example/gdrom_test.elf: LDSCRIPT = $(LIB)/main.lds
example/gdrom_test.elf: $(START_OBJ) $(GDROM_TEST_OBJ)
GDROM_ISO9660_OBJ = \
example/gdrom_iso9660.o \
sh7091/serial.o
example/gdrom_iso9660.elf: LDSCRIPT = $(LIB)/alt.lds
example/gdrom_iso9660.elf: LDSCRIPT = $(LIB)/main.lds
example/gdrom_iso9660.elf: $(START_OBJ) $(GDROM_ISO9660_OBJ)
AICA_OBJ = \
@ -386,7 +386,7 @@ AICA_OBJ = \
sh7091/serial.o \
example/arm/channel.bin.o
example/aica.elf: LDSCRIPT = $(LIB)/alt.lds
example/aica.elf: LDSCRIPT = $(LIB)/main.lds
example/aica.elf: $(START_OBJ) $(AICA_OBJ)
AICA_GDROM_OBJ = \
@ -394,5 +394,90 @@ AICA_GDROM_OBJ = \
sh7091/serial.o \
example/arm/sh4_interrupt.bin.o
example/aica_gdrom.elf: LDSCRIPT = $(LIB)/alt.lds
example/aica_gdrom.elf: LDSCRIPT = $(LIB)/main.lds
example/aica_gdrom.elf: $(START_OBJ) $(AICA_GDROM_OBJ)
MAC_SATURATION_OBJ = \
example/mac_saturation.o \
example/macl_saturation.o \
example/macw_saturation.o \
sh7091/serial.o
example/mac_saturation.elf: LDSCRIPT = $(LIB)/main.lds
example/mac_saturation.elf: $(START_OBJ) $(MAC_SATURATION_OBJ)
TA_INTERROGATION_OBJ = \
example/ta_interrogation.o \
holly/core.o \
holly/region_array.o \
holly/background.o \
holly/ta_fifo_polygon_converter.o \
holly/video_output.o \
sh7091/serial.o
example/ta_interrogation.elf: LDSCRIPT = $(LIB)/main.lds
example/ta_interrogation.elf: $(START_OBJ) $(TA_INTERROGATION_OBJ)
DECODE_TEST_OBJ = \
example/decode_test.o \
sh7091/serial.o
example/decode_test.elf: LDSCRIPT = $(LIB)/main.lds
example/decode_test.elf: $(START_OBJ) $(DECODE_TEST_OBJ)
TEXTURE_FILTERING_OBJ = \
example/texture_filtering.o \
holly/core.o \
holly/region_array.o \
holly/background.o \
holly/ta_fifo_polygon_converter.o \
holly/video_output.o \
bbb1.data.o \
bbb2.data.o \
bbb4.data.o \
bbb8.data.o \
bbb16.data.o \
bbb32.data.o \
bbb64.data.o \
bbb128.data.o \
bbb256.data.o \
bbb512.data.o \
bbb1024.data.o
example/texture_filtering.elf: LDSCRIPT = $(LIB)/main.lds
example/texture_filtering.elf: $(START_OBJ) $(TEXTURE_FILTERING_OBJ)
TEXTURE_FILTERING_MAPLE_OBJ = \
example/texture_filtering_maple.o \
holly/core.o \
holly/region_array.o \
holly/background.o \
holly/ta_fifo_polygon_converter.o \
holly/video_output.o \
bbb1.data.o \
bbb2.data.o \
bbb4.data.o \
bbb8.data.o \
bbb16.data.o \
bbb32.data.o \
bbb64.data.o \
bbb128.data.o \
bbb256.data.o \
bbb512.data.o \
bbb1024.data.o \
maple/maple.o \
sh7091/serial.o \
font/font_bitmap.o \
verite_8x16.data.o
example/texture_filtering_maple.elf: LDSCRIPT = $(LIB)/main.lds
example/texture_filtering_maple.elf: $(START_OBJ) $(TEXTURE_FILTERING_MAPLE_OBJ)
LFSR_OBJ = \
example/lfsr.o \
holly/core.o \
holly/video_output.o \
sh7091/serial.o
example/lfsr.elf: LDSCRIPT = $(LIB)/main.lds
example/lfsr.elf: $(START_OBJ) $(LFSR_OBJ)

View File

@ -30,7 +30,7 @@ struct vertex {
/*
// screen space coordinates
const struct vertex quad_verticies[4] = {
const struct vertex quad_vertices[4] = {
{ 0.f, 64.f, 0.01f, 0.f, 1.f },
{ 0.f, 0.f, 0.01f, 0.f, 0.f },
{ 64.f, 0.f, 0.01f, 1.f, 0.f },
@ -59,20 +59,20 @@ uint32_t transform(uint32_t * ta_parameter_buf)
parameter.append<global_sprite>() = sprite;
parameter.append<vertex_sprite_type_1>() =
vertex_sprite_type_1(quad_verticies[0].x,
quad_verticies[0].y,
quad_verticies[0].z,
quad_verticies[1].x,
quad_verticies[1].y,
quad_verticies[1].z,
quad_verticies[2].x,
quad_verticies[2].y,
quad_verticies[2].z,
quad_verticies[3].x,
quad_verticies[3].y,
uv_16bit(quad_verticies[0].u, quad_verticies[0].v),
uv_16bit(quad_verticies[1].u, quad_verticies[1].v),
uv_16bit(quad_verticies[2].u, quad_verticies[2].v));
vertex_sprite_type_1(quad_vertices[0].x,
quad_vertices[0].y,
quad_vertices[0].z,
quad_vertices[1].x,
quad_vertices[1].y,
quad_vertices[1].z,
quad_vertices[2].x,
quad_vertices[2].y,
quad_vertices[2].z,
quad_vertices[3].x,
quad_vertices[3].y,
uv_16bit(quad_vertices[0].u, quad_vertices[0].v),
uv_16bit(quad_vertices[1].u, quad_vertices[1].v),
uv_16bit(quad_vertices[2].u, quad_vertices[2].v));
// curiously, there is no `dz` in vertex_sprite_type_1
// curiously, there is no `du_dv` in vertex_sprite_type_1
@ -111,7 +111,7 @@ uint32_t transform(uint32_t * ta_parameter_buf, const char * s, const uint32_t l
| tsp_instruction_word::texture_v_size::from_int(8);
const uint32_t character_offset = ((8 * 8) / 2) * (s[string_ix] - ' ');
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address((texture_address + character_offset) / 8);
@ -157,16 +157,9 @@ uint32_t transform(uint32_t * ta_parameter_buf, const char * s, const uint32_t l
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(0xff0000ff);
background_parameter(mem->background, 0xff0000ff);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, 480 / 32, opb_size);
}
inline void inflate_character(const uint8_t * src, const uint8_t c)
@ -187,8 +180,7 @@ inline void inflate_character(const uint8_t * src, const uint8_t c)
//serial::character('\n');
}
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint32_t *>(mem->texture);
auto texture = reinterpret_cast<volatile uint32_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
uint32_t offset = ((8 * 8) / 2) * character_index;
@ -259,7 +251,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
const char ana[18] = "A from ana i know";
@ -272,13 +263,13 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix++;
frame_ix = (frame_ix + 1) & 1;
}
}

View File

@ -46,8 +46,6 @@ uint32_t transform(ta_parameter_writer& parameter,
const char * s, const uint32_t len,
const uint32_t y_offset)
{
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
uint32_t advance = 0; // in 26.6 fixed-point
for (uint32_t string_ix = 0; string_ix < len; string_ix++) {
@ -73,6 +71,7 @@ uint32_t transform(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(texture_width)
| tsp_instruction_word::texture_v_size::from_int(texture_height);
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -126,8 +125,6 @@ uint32_t transform(ta_parameter_writer& parameter,
uint32_t transform2(ta_parameter_writer& parameter,
const uint32_t texture_width, uint32_t texture_height)
{
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::translucent
| obj_control::col_type::packed_color
@ -142,6 +139,7 @@ uint32_t transform2(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(texture_width)
| tsp_instruction_word::texture_v_size::from_int(texture_height);
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -184,24 +182,18 @@ uint32_t transform2(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff0000ff);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff0000ff);
}
void inflate_font(const uint32_t * src,
const uint32_t stride,
const uint32_t curve_end_ix)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint32_t *>(mem->texture);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
twiddle::texture3<4, 8>(texture, reinterpret_cast<const uint8_t *>(src),
stride,
@ -260,7 +252,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
const char ana[18] = "A from ana i know";
const char cabal[27] = "where is this secret cabal";
@ -295,11 +286,11 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_translucent_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix++;

View File

@ -46,8 +46,6 @@ uint32_t transform(ta_parameter_writer& parameter,
const char * s, const uint32_t len,
const uint32_t y_offset)
{
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
uint32_t advance = 0; // in 26.6 fixed-point
for (uint32_t string_ix = 0; string_ix < len; string_ix++) {
@ -72,6 +70,7 @@ uint32_t transform(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(texture_width)
| tsp_instruction_word::texture_v_size::from_int(texture_height);
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -125,8 +124,6 @@ uint32_t transform(ta_parameter_writer& parameter,
uint32_t transform2(ta_parameter_writer& parameter,
const uint32_t texture_width, uint32_t texture_height)
{
uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| obj_control::col_type::packed_color
@ -141,6 +138,7 @@ uint32_t transform2(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(texture_width)
| tsp_instruction_word::texture_v_size::from_int(texture_height);
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -183,16 +181,11 @@ uint32_t transform2(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff0000ff);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff0000ff);
}
constexpr inline uint32_t b(uint32_t v, uint32_t n)
@ -204,8 +197,7 @@ void inflate_font(const uint32_t * src,
const uint32_t stride,
const uint32_t curve_end_ix)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint32_t *>(mem->texture);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
twiddle::texture3<4, 1>(texture, reinterpret_cast<const uint8_t *>(src),
stride,
@ -264,7 +256,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
const char ana[18] = "A from ana i know";
const char cabal[27] = "where is this secret cabal";
@ -301,11 +292,11 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_punch_through_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix++;

View File

@ -230,17 +230,11 @@ void transform_model(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
holly.VO_BORDER_COL = 0x00220000;
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -274,7 +268,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
@ -320,15 +313,15 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
constexpr float half_degree = 0.01745329f / 2;
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -219,16 +219,11 @@ void transform2(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -262,7 +257,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
vec3 lights[3] = {
@ -299,14 +293,14 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -59,7 +59,7 @@ uint32_t transform(uint32_t * ta_parameter_buf,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::non_twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -82,8 +82,8 @@ uint32_t transform(uint32_t * ta_parameter_buf,
x1 = x * __builtin_cosf(theta) - z * __builtin_sinf(theta);
z = x * __builtin_sinf(theta) + z * __builtin_cosf(theta);
x = x1;
x *= 240.f;
y *= 240.f;
x *= 300.f;
y *= 300.f;
x += 320.f;
y += 240.f;
z = 1.f / (z + 10.f);
@ -106,30 +106,25 @@ uint32_t transform(uint32_t * ta_parameter_buf,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff00ff00);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff00ff00);
}
void copy_macaw_texture()
{
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
for (uint32_t px = 0; px < size / 3; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
mem->texture[px] = rgb565;
texture[px] = rgb565;
}
}
@ -148,9 +143,9 @@ void main()
| ta_alloc_ctrl::tm_opb::no_list
| ta_alloc_ctrl::t_opb::no_list
| ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte;
| ta_alloc_ctrl::o_opb::_8x4byte;
constexpr struct opb_size opb_size = { .opaque = 16 * 4
constexpr struct opb_size opb_size = { .opaque = 8 * 4
, .opaque_modifier = 0
, .translucent = 0
, .translucent_modifier = 0
@ -165,7 +160,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
ta_polygon_converter_init(opb_size.total(),
@ -176,17 +170,14 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
if (frame_ix > 10)
break;
frame_ix = (frame_ix + 1) & 1;
}
}

View File

@ -78,7 +78,7 @@ void transform(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::non_twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -136,30 +136,25 @@ void transform(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xffff00ff);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
void copy_macaw_texture()
{
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
for (uint32_t px = 0; px < size / 3; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
mem->texture[px] = rgb565;
texture[px] = rgb565;
}
}
@ -195,7 +190,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (1) {
ta_polygon_converter_init(opb_size.total(),
@ -210,14 +204,14 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -180,14 +180,14 @@ void copy_macaw_texture()
{
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
for (uint32_t px = 0; px < size / 3; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
mem->texture[px] = rgb565;
texture[px] = rgb565;
}
}
@ -235,7 +235,7 @@ void main()
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
//uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
@ -243,23 +243,18 @@ void main()
core_init();
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
constexpr uint32_t texture_size = 256;
background_parameter(0xff220000);
while (1) {
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
texture_size / 32, // width
region_array2(texture_size / 32, // width
texture_size / 32, // height
opb_size
);
background_parameter(mem->background, 0xffff00ff);
/*
render(texture_size, texture_size,
(offsetof (struct texture_memory_alloc, texture)),
128,
@ -270,11 +265,7 @@ void main()
0, 0);
core_wait_end_of_render_video();
background_parameter(mem->background, 0xff0000ff);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
@ -288,12 +279,13 @@ void main()
0x00096000, // framesize
frame_ix, num_frames);
core_wait_end_of_render_video();
*/
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -63,7 +63,7 @@ uint32_t transform(uint32_t * ta_parameter_buf,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::non_twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -111,8 +111,8 @@ uint32_t transform(uint32_t * ta_parameter_buf,
x1 = x * __builtin_cosf(theta) - z * __builtin_sinf(theta);
z = x * __builtin_sinf(theta) + z * __builtin_cosf(theta);
x = x1;
x *= 256.f;
y *= 256.f;
x *= 640.f;
y *= 640.f;
x += 320.f;
y += 240.f;
z = 1.f / (z + 10.f);
@ -132,45 +132,38 @@ uint32_t transform(uint32_t * ta_parameter_buf,
return parameter.offset;
}
void init_texture_memory(uint32_t render_passes)
void init_texture_memory(const struct opb_size * opb_size, uint32_t render_passes)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff00ff00);
region_array_multipass(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array_multipass(640 / 32, // width
480 / 32, // height
render_passes // num_render_passes
opb_size,
render_passes
);
background_parameter(0xff00ff00);
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
void main()
void copy_macaw_texture()
{
video_output::set_mode_vga();
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
for (uint32_t px = 0; px < size / 3; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
mem->texture[px] = rgb565;
texture[px] = rgb565;
}
}
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
constexpr uint32_t render_passes = 2;
init_texture_memory(render_passes);
void main()
{
video_output::set_mode_vga();
copy_macaw_texture();
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
@ -205,11 +198,18 @@ void main()
}
};
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
constexpr uint32_t render_passes = 2;
init_texture_memory(opb_size, render_passes);
constexpr uint32_t tiles = (640 / 32) * (480 / 32);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
uint32_t ta_parameter_size[2];
uint32_t ta_parameter_size;
while (true) {
// first render pass
@ -217,25 +217,25 @@ void main()
ta_alloc[0],
640 / 32,
480 / 32);
ta_parameter_size[0] = transform(ta_parameter_buf, strip_vertices, strip_length, 0);
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size[0]);
ta_parameter_size = transform(ta_parameter_buf, strip_vertices, strip_length, 0);
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
// second render pass
ta_polygon_converter_cont(opb_size[0].total() * tiles,
ta_alloc[1]);
ta_parameter_size[1] = transform(ta_parameter_buf, strip_vertices, strip_length, 1);
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size[1]);
ta_parameter_size = transform(ta_parameter_buf, strip_vertices, strip_length, 1);
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_translucent_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;
}
}

View File

@ -60,7 +60,7 @@ uint32_t transform(uint32_t * ta_parameter_buf,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -107,23 +107,18 @@ uint32_t transform(uint32_t * ta_parameter_buf,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff00ff00);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
void init_macaw_texture()
{
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
uint16_t temp[size / 3];
for (uint32_t px = 0; px < size / 3; px++) {
@ -134,7 +129,7 @@ void init_macaw_texture()
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
temp[px] = rgb565;
}
twiddle::texture(mem->texture, temp, 128, 128);
twiddle::texture(texture, temp, 128, 128);
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
@ -169,7 +164,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
ta_polygon_converter_init(opb_size.total(),
@ -180,14 +174,14 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -145,16 +145,11 @@ void transform(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -191,7 +186,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (1) {
do_get_condition(command_buf, receive_buf);
@ -228,13 +222,13 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -168,16 +168,11 @@ void transform_modifier_volume(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -211,7 +206,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
@ -260,15 +254,15 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_modifier_volume_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
constexpr float half_degree = 0.01745329f / 2;
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -188,16 +188,18 @@ void transform_polygon(ta_parameter_writer& parameter,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
uint32_t texture_address0 = (offsetof (struct texture_memory_alloc, texture)) + 128 * 128 * 2 * 0;
uint32_t texture_address1 = (offsetof (struct texture_memory_alloc, texture)) + 128 * 128 * 2 * 1;
const uint32_t texture_address_0 = texture_memory_alloc::texture.start
+ 128 * 128 * 2 * 0;
const uint32_t texture_address_1 = texture_memory_alloc::texture.start
+ 128 * 128 * 2 * 1;
const uint32_t texture_control_word_0 = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address0 / 8);
| texture_control_word::texture_address(texture_address_0 / 8);
const uint32_t texture_control_word_1 = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address1 / 8);
| texture_control_word::texture_address(texture_address_1 / 8);
parameter.append<ta_global_parameter::polygon_type_3>() =
ta_global_parameter::polygon_type_3(parameter_control_word,
@ -294,16 +296,11 @@ void transform_modifier_volume(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
void
@ -311,7 +308,7 @@ load_texture(const uint8_t * src,
const uint32_t size,
const uint32_t ix)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
uint16_t temp[size / 3];
for (uint32_t px = 0; px < size / 3; px++) {
@ -322,7 +319,7 @@ load_texture(const uint8_t * src,
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
temp[px] = rgb565;
}
twiddle::texture(&mem->texture[(128 * 128 * 2 * ix) / 2], temp, 128, 128);
twiddle::texture(&texture[(128 * 128 * 2 * ix) / 2], temp, 128, 128);
}
void update_rot_pos(struct rot_pos& rot_pos)
@ -387,7 +384,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
struct rot_pos rot_pos = { 0.f, 0.f, 0.f };
@ -443,13 +439,13 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_modifier_volume_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -74,22 +74,20 @@ uint32_t transform(uint32_t * ta_parameter_buf,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
auto object_list = &texture_memory32[texture_memory_alloc::object_list.start / 4];
auto isp_tsp_parameters = &texture_memory32[texture_memory_alloc::isp_tsp_parameters.start / 4];
// zeroize
for (uint32_t i = 0; i < 0x00100000 / 4; i++) {
mem->object_list[i] = 0xeeeeeeee;
mem->isp_tsp_parameters[i] = 0xeeeeeeee;
object_list[i] = 0xeeeeeeee;
isp_tsp_parameters[i] = 0xeeeeeeee;
}
background_parameter(mem->background, 0xff222200);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff222200);
}
uint32_t _ta_parameter_buf[((32 * (32 + 2)) + 32) / 4];
@ -102,12 +100,13 @@ static_assert((sizeof (union u32_u8)) == 4);
void dump()
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
auto object_list = &texture_memory32[texture_memory_alloc::object_list.start / 4];
auto isp_tsp_parameters = &texture_memory32[texture_memory_alloc::isp_tsp_parameters.start / 4];
constexpr uint32_t screen_ol_size = 8 * 4 * (640 / 32) * (480 / 32);
for (uint32_t i = 0; i < (screen_ol_size + 0x100) / 4; i++) {
union u32_u8 n;
n.u32 = mem->object_list[i];
n.u32 = object_list[i];
if (((i * 4) & 0x1f) == 0)
serial::character('\n');
@ -123,7 +122,7 @@ void dump()
for (uint32_t i = 0; i < (0x100) / 4; i++) {
union u32_u8 n;
n.u32 = mem->isp_tsp_parameters[i];
n.u32 = isp_tsp_parameters[i];
if (((i * 4) & 0x1f) == 0)
serial::character('\n');
@ -182,7 +181,6 @@ void main()
float theta = 0;
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
bool hardware_ta = false;
@ -193,6 +191,9 @@ void main()
{ 0.5f, 0.5f},
};
auto object_list = &texture_memory32[texture_memory_alloc::object_list.start / 4];
auto isp_tsp_parameters = &texture_memory32[texture_memory_alloc::isp_tsp_parameters.start / 4];
while (true) {
if ((frame_ix & 255) == 0) {
holly.SOFTRESET = softreset::pipeline_soft_reset;
@ -210,7 +211,6 @@ void main()
qq.c = rotate(q.c, theta);
qq.d = rotate(q.d, theta);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
if (hardware_ta) {
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
@ -220,19 +220,19 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
} else {
software_ta::object_pointer_blocks<8>(mem->object_list, qq);
software_ta::isp_tsp_parameters(mem->isp_tsp_parameters, qq);
software_ta::object_pointer_blocks<8>(object_list, qq);
software_ta::isp_tsp_parameters(isp_tsp_parameters, qq);
}
software_ta::opb_checkerboard_pattern<8>(mem->object_list);
software_ta::opb_checkerboard_pattern<8>(object_list);
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
theta += half_degree;
}
}

View File

@ -79,16 +79,11 @@ uint32_t transform(uint32_t * ta_parameter_buf)
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 + 64 + 32) + 32) / 4];
@ -122,7 +117,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
ta_polygon_converter_init(opb_size.total(),
@ -133,13 +127,13 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -19,6 +19,7 @@
#include "sh7091/sh7091.hpp"
#include "sh7091/sh7091_bits.hpp"
#include "sh7091/serial.hpp"
#include "palette.hpp"
#include "geometry/suzanne.hpp"
#include "geometry/circle.hpp"
@ -226,16 +227,12 @@ void transform2(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -255,13 +252,15 @@ static inline void label_number(ta_parameter_writer& parameter,
8, 16, // glyph
16 + (8 * (max_label_len - len)), // position x
16 * row, // position y
label, len);
label, len,
para_control::list_type::opaque);
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + (8 * (max_label_len + 1)), // position x
16 * row, // position y
buf, 8);
buf, 8,
para_control::list_type::opaque);
}
void main()
@ -282,7 +281,7 @@ void main()
8, // texture_width
16, // texture_height
src);
font_bitmap::palette_data();
palette_data<3>();
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
@ -309,7 +308,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
vec3 lights[3] = {
@ -387,15 +385,15 @@ void main()
t_transfer_end = sh7091.TMU.TCNT0;
t_render_start = sh7091.TMU.TCNT0;
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
t_render_end = sh7091.TMU.TCNT0;
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree * 0.5;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;
}
}

View File

@ -0,0 +1,259 @@
#include <cstdint>
#include "align.hpp"
#include "memorymap.hpp"
#include "holly/holly.hpp"
#include "holly/core.hpp"
#include "holly/core_bits.hpp"
#include "holly/video_output.hpp"
#include "holly/ta_bits.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_global_parameter.hpp"
#include "holly/ta_vertex_parameter.hpp"
#include "holly/ta_fifo_polygon_converter.hpp"
#include "holly/isp_tsp.hpp"
#include "holly/texture_memory_alloc.hpp"
#include "holly/background.hpp"
#include "holly/region_array.hpp"
#include "sh7091/store_queue.hpp"
#include "sh7091/serial.hpp"
struct vertex {
float x;
float y;
float z;
};
// screen space coordinates
const struct vertex triangles[1][3] = {
{
{ 200.f, 360.f, 0.1f },
{ 200.f, 120.f, 0.1f },
{ 440.f, 120.f, 0.1f },
},
};
void transform()
{
/*
* QACR0 [4:2]: External address bits [28:26] corresponding to SQ0
* QACR1 [4:2]: External address bits [28:26] corresponding to SQ1
*/
/* PREF instruction:
*
* [31:26]: 111000 Store queue specification
* [25:6] : Address External memory address bits [25:6]
* [5] : 0/1 0: SQ0 specification
* 1: SQ1 specification and external memory address bit [5]
* [4:2] : No meaning in a prefetch
* [1:0] : Fixed at 0
*/
/* Store queue writes:
* [31:26]: 111000 Store queue specification
* [25:6] : Dont care Used for external memory transfer/access right
* [5] : 0/1 0: SQ0 specification
* 1: SQ1 specification
* [4:2] : Specifies longword position in SQ0/SQ1
* [1:0] : Fixed at 0
*/
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| obj_control::col_type::packed_color;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog;
const uint32_t texture_control_word = 0;
constexpr uint32_t base_color = 0xfff0f000;
*reinterpret_cast<ta_global_parameter::polygon_type_0 *>(store_queue) =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
sq_transfer_32byte(ta_fifo_polygon_converter);
constexpr uint32_t strip_length = 3;
for (uint32_t i = 0; i < strip_length; i++) {
float x = triangles[0][i].x;
float y = triangles[0][i].y;
float z = triangles[0][i].z;
bool end_of_strip = i == strip_length - 1;
*reinterpret_cast<ta_vertex_parameter::polygon_type_0 *>(store_queue) =
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(end_of_strip),
x, y, z,
base_color
);
sq_transfer_32byte(ta_fifo_polygon_converter);
}
*reinterpret_cast<ta_global_parameter::end_of_list *>(store_queue) =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
sq_transfer_32byte(ta_fifo_polygon_converter);
}
void transform2(ta_parameter_writer& parameter)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| obj_control::col_type::packed_color;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog;
const uint32_t texture_control_word = 0;
constexpr uint32_t base_color = 0xff0f00ff;
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
constexpr uint32_t strip_length = 3;
for (uint32_t i = 0; i < strip_length; i++) {
float x = triangles[0][i].x;
float y = triangles[0][i].y;
float z = triangles[0][i].z;
bool end_of_strip = i == strip_length - 1;
parameter.append<ta_vertex_parameter::polygon_type_0>() =
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(end_of_strip),
x, y, z,
base_color
);
}
parameter.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
void init_texture_memory(const struct opb_size& opb_size)
{
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * (10 + 2)) + 32) / 4];
void ta_copy(uint32_t * address, uint32_t size)
{
uint64_t * src = (uint64_t*)address;
uint64_t dst[size / 4];
//"Available only when PR=0 and SZ=1"
uint32_t fpscr = (1 << 20);
asm volatile
("lds %0,fpscr;"
:
: "r" (fpscr)
: "memory");
for (uint32_t i = 0; i < (size / 8); i++) {
//uint64_t * dst = (uint64_t*)ta_fifo_polygon_converter;
asm volatile
("fmov @%0,xd0;"
"fmov xd0,@%1;"
: // output
: "r" (&src[i]), "r"(&dst[0]) // input
: "memory");
}
uint32_t * src32 = (uint32_t *)&src[0];
uint32_t * dst32 = (uint32_t *)&dst[0];
for (uint32_t i = 0; i < (size / 4); i++) {
serial::integer<uint32_t>(src32[i], ' ');
serial::integer<uint32_t>(dst32[i]);
}
//serial::string("done\n");
}
void main()
{
video_output::set_mode_vga();
constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list
| ta_alloc_ctrl::tm_opb::no_list
| ta_alloc_ctrl::t_opb::no_list
| ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte;
constexpr struct opb_size opb_size = { .opaque = 16 * 4
, .opaque_modifier = 0
, .translucent = 0
, .translucent_modifier = 0
, .punch_through = 0
};
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
auto parameter = ta_parameter_writer(ta_parameter_buf);
while (true) {
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
640 / 32,
480 / 32);
transform2(parameter);
serial::string("BCR1 ");
serial::integer<uint32_t>(sh7091.BSC.BCR1);
serial::string("BCR2 ");
serial::integer<uint32_t>(sh7091.BSC.BCR2);
serial::string("MCR ");
serial::integer<uint32_t>(sh7091.BSC.MCR);
//break;
ta_copy(ta_parameter_buf, parameter.offset);
break;
ta_wait_opaque_list();
serial::string("opaque\n");
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix = (frame_ix + 1) & 1;;
if (frame_ix > 10)
break;
}
}

View File

@ -0,0 +1,366 @@
#include <cstdint>
#include "align.hpp"
#include "holly/texture_memory_alloc.hpp"
#include "holly/holly.hpp"
#include "holly/core.hpp"
#include "holly/core_bits.hpp"
#include "holly/ta_fifo_polygon_converter.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_global_parameter.hpp"
#include "holly/ta_vertex_parameter.hpp"
#include "holly/ta_bits.hpp"
#include "holly/isp_tsp.hpp"
#include "holly/region_array.hpp"
#include "holly/background.hpp"
#include "holly/video_output.hpp"
#include "memorymap.hpp"
#include "twiddle.hpp"
#include "sh7091/serial.hpp"
#include "bbb.hpp"
struct vertex {
float x;
float y;
float z;
float u;
float v;
uint32_t color;
};
const struct vertex strip_vertices[4] = {
// [ position ] [ uv coordinates ] [color ]
{ -0.5f, -0.5f, 0.f, 0.f, 0.f, 0xffffffff},
{ 0.5f, -0.5f, 0.f, 1.f, 0.f, 0xffffffff},
{ -0.5f, 0.5f, 0.f, 0.f, 1.f, 0xffffffff},
{ 0.5f, 0.5f, 0.f, 1.f, 1.f, 0xffffffff},
};
constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex));
static float theta = 0;
constexpr float half_degree = 0.01745329f / 2.f;
namespace defaults {
//constexpr uint32_t parameter_control_word = para_control::para_type::sprite
constexpr uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| obj_control::col_type::packed_color
| obj_control::texture
;
//| obj_control::_16bit_uv;
constexpr uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::no_culling;
constexpr uint32_t tsp_instruction_word = tsp_instruction_word::src_select::primary_accumulation_buffer
| tsp_instruction_word::dst_select::primary_accumulation_buffer
| tsp_instruction_word::fog_control::no_fog
| tsp_instruction_word::texture_u_size::_1024
| tsp_instruction_word::texture_v_size::_1024;
constexpr uint32_t texture_address = texture_memory_alloc::texture.start;
constexpr uint32_t texture_control_word = texture_control_word::mip_mapped
| texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
}
void append_parameter(ta_parameter_writer& parameter,
const uint32_t parameter_control_word,
const uint32_t isp_tsp_instruction_word,
const uint32_t tsp_instruction_word,
const uint32_t texture_control_word)
{
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
/*
constexpr uint32_t base_color = 0xffff0000;
parameter.append<ta_global_parameter::sprite>() =
ta_global_parameter::sprite(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
base_color,
0, // offset_color
0, // data_size_for_sort_dma
0); // next_address_for_sort_dma
*/
}
void append_point_sampled(ta_parameter_writer& parameter)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::opaque;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::point_sampled;
const uint32_t texture_control_word = defaults::texture_control_word;
append_parameter(parameter, parameter_control_word, isp_tsp_instruction_word, tsp_instruction_word, texture_control_word);
}
void append_bilinear(ta_parameter_writer& parameter)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::opaque;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::bilinear_filter;
const uint32_t texture_control_word = defaults::texture_control_word;
append_parameter(parameter, parameter_control_word, isp_tsp_instruction_word, tsp_instruction_word, texture_control_word);
}
void append_trilinear_pass_a(ta_parameter_writer& parameter)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::opaque;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::trilinear_pass_a;
const uint32_t texture_control_word = defaults::texture_control_word;
append_parameter(parameter, parameter_control_word, isp_tsp_instruction_word, tsp_instruction_word, texture_control_word);
}
void append_trilinear_pass_b(ta_parameter_writer& parameter)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::translucent;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::one
| tsp_instruction_word::filter_mode::trilinear_pass_b;
const uint32_t texture_control_word = defaults::texture_control_word;
append_parameter(parameter, parameter_control_word, isp_tsp_instruction_word, tsp_instruction_word, texture_control_word);
}
enum class filter_type {
point_sampled,
bilinear,
trilinear_pass_a,
trilinear_pass_b,
};
void transform(ta_parameter_writer& parameter,
const vertex * strip_vertices,
const uint32_t strip_length,
enum filter_type filter
)
{
switch (filter) {
case filter_type::point_sampled: append_point_sampled(parameter); break;
case filter_type::bilinear: append_bilinear(parameter); break;
case filter_type::trilinear_pass_a: append_trilinear_pass_a(parameter); break;
case filter_type::trilinear_pass_b: append_trilinear_pass_b(parameter); break;
}
//struct vertex v[strip_length];
for (uint32_t i = 0; i < strip_length; i++) {
float x = strip_vertices[i].x;
float y = strip_vertices[i].y;
float z = strip_vertices[i].z;
float x1;
x1 = x * __builtin_cosf(theta / 5.f) - z * __builtin_sinf(theta / 5.f);
z = x * __builtin_sinf(theta / 5.f) + z * __builtin_cosf(theta / 5.f);
x = x1;
x *= 1024.f * (__builtin_cosf(theta / 10.f) + 1.0f);
y *= 1024.f * (__builtin_cosf(theta / 10.f) + 1.0f);
x += 320.f;
y += 240.f;
z = 1.f / (z + 10.f);
bool end_of_strip = i == strip_length - 1;
parameter.append<ta_vertex_parameter::polygon_type_3>() =
ta_vertex_parameter::polygon_type_3(polygon_vertex_parameter_control_word(end_of_strip),
x, y, z,
strip_vertices[i].u,
strip_vertices[i].v,
strip_vertices[i].color,
0 // offset_color
);
/*
v[i].x = x;
v[i].y = y;
v[i].z = z;
v[i].u = strip_vertices[i].u;
v[i].v = strip_vertices[i].v;
*/
}
/*
parameter.append<ta_vertex_parameter::sprite_type_1>() =
ta_vertex_parameter::sprite_type_1(para_control::para_type::vertex_parameter,
v[0].x,
v[0].y,
v[0].z,
v[1].x,
v[1].y,
v[1].z,
v[2].x,
v[2].y,
v[2].z,
v[3].x,
v[3].y,
uv_16bit(v[0].u, v[0].v),
uv_16bit(v[1].u, v[1].v),
uv_16bit(v[2].u, v[2].v));
*/
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
void init_texture_memory(const struct opb_size& opb_size)
{
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff00ff00);
}
uint8_t const * const mips[] = {
reinterpret_cast<uint8_t *>(&_binary_bbb1_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb2_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb4_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb8_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb16_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb32_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb64_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb128_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb256_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb512_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb1024_data_start)
};
void _copy_bbb_texture(uint32_t dst_offset, uint8_t const * const src, uint32_t mip)
{
auto area = mip * mip;
uint16_t temp[area];
for (uint32_t px = 0; px < area; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
temp[px] = rgb565;
}
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
auto dst = &texture[dst_offset / 2];
twiddle::texture(dst, temp, mip, mip);
}
void copy_bbb_texture()
{
uint32_t dst_offset = 6;
uint32_t ix = 0;
for (uint32_t mip = 1; mip <= 1024; mip *= 2) {
_copy_bbb_texture(dst_offset, mips[ix], mip);
ix += 1;
dst_offset += mip * mip * 2;
}
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
void main()
{
video_output::set_mode_vga();
holly.TEXT_CONTROL = text_control::bank_bit(0);
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list
| ta_alloc_ctrl::tm_opb::no_list
//| ta_alloc_ctrl::t_opb::_16x4byte
| ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte
;
constexpr struct opb_size opb_size = { .opaque = 16 * 4
, .opaque_modifier = 0
//, .translucent = 16 * 4
, .translucent_modifier = 0
, .punch_through = 0
};
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
init_texture_memory(opb_size);
copy_bbb_texture();
uint32_t frame_ix = 0;
while (true) {
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
640 / 32,
480 / 32);
{
auto parameter = ta_parameter_writer(ta_parameter_buf);
transform(parameter, strip_vertices, strip_length, filter_type::trilinear_pass_a);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
}
/*
{
auto parameter = ta_parameter_writer(ta_parameter_buf);
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
//transform(parameter, strip_vertices, strip_length, filter_type::trilinear_pass_b);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_translucent_list();
}
*/
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix = (frame_ix + 1) & 1;
}
}

View File

@ -0,0 +1,701 @@
#include <cstdint>
#include <bit>
#include "align.hpp"
#include "holly/texture_memory_alloc.hpp"
#include "holly/holly.hpp"
#include "holly/core.hpp"
#include "holly/core_bits.hpp"
#include "holly/ta_fifo_polygon_converter.hpp"
#include "holly/ta_parameter.hpp"
#include "holly/ta_global_parameter.hpp"
#include "holly/ta_vertex_parameter.hpp"
#include "holly/ta_bits.hpp"
#include "holly/isp_tsp.hpp"
#include "holly/region_array.hpp"
#include "holly/background.hpp"
#include "holly/video_output.hpp"
#include "memorymap.hpp"
#include "twiddle.hpp"
#include "palette.hpp"
#include "maple/maple.hpp"
#include "maple/maple_impl.hpp"
#include "maple/maple_bus_bits.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp"
#include "font/font_bitmap.hpp"
#include "verite_8x16.hpp"
#include "sh7091/serial.hpp"
#include "bbb.hpp"
struct vertex {
float x;
float y;
float z;
float u;
float v;
uint32_t color;
};
const struct vertex strip_vertices[4] = {
// [ position ] [ uv coordinates ] [color ]
{ -0.5f, 0.5f, 0.f, 0.f , 127.f/128.f, 0xffffffff}, // the first two base colors in a
{ -0.5f, -0.5f, 0.f, 0.f , 0.f , 0xffffffff}, // non-Gouraud triangle strip are ignored
{ 0.5f, 0.5f, 0.f, 127.f/128.f, 127.f/128.f, 0xffffffff},
{ 0.5f, -0.5f, 0.f, 127.f/128.f, 0.f , 0xffffffff},
};
constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex));
constexpr float half_degree = 0.01745329f / 2.f;
namespace defaults {
constexpr uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| obj_control::col_type::packed_color
| obj_control::texture;
constexpr uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::no_culling;
constexpr uint32_t tsp_instruction_word = tsp_instruction_word::src_select::primary_accumulation_buffer
| tsp_instruction_word::dst_select::primary_accumulation_buffer
| tsp_instruction_word::fog_control::no_fog;
constexpr uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled;
}
void append_point_sampled(ta_parameter_writer& parameter, uint32_t texture_control_word, uint32_t size)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::opaque;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::point_sampled
| tsp_instruction_word::texture_u_size::from_int(size)
| tsp_instruction_word::texture_v_size::from_int(size);
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
}
void append_bilinear(ta_parameter_writer& parameter, uint32_t texture_control_word, uint32_t size)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::opaque;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::bilinear_filter
| tsp_instruction_word::texture_u_size::from_int(size)
| tsp_instruction_word::texture_v_size::from_int(size);
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
}
void append_trilinear_pass_a(ta_parameter_writer& parameter, uint32_t texture_control_word, uint32_t size)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::opaque;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::trilinear_pass_a
| tsp_instruction_word::texture_u_size::from_int(size)
| tsp_instruction_word::texture_v_size::from_int(size);
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
}
void append_trilinear_pass_b(ta_parameter_writer& parameter, uint32_t texture_control_word, uint32_t size)
{
const uint32_t parameter_control_word = defaults::parameter_control_word
| para_control::list_type::translucent;
const uint32_t isp_tsp_instruction_word = defaults::isp_tsp_instruction_word;
const uint32_t tsp_instruction_word = defaults::tsp_instruction_word
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::one
| tsp_instruction_word::filter_mode::trilinear_pass_b
| tsp_instruction_word::texture_u_size::from_int(size)
| tsp_instruction_word::texture_v_size::from_int(size);
parameter.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0, // data_size_for_sort_dma
0 // next_address_for_sort_dma
);
}
uint8_t const * const mips[] = {
reinterpret_cast<uint8_t *>(&_binary_bbb1_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb2_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb4_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb8_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb16_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb32_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb64_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb128_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb256_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb512_data_start),
reinterpret_cast<uint8_t *>(&_binary_bbb1024_data_start)
};
void _copy_bbb_texture(uint32_t dst_offset, uint8_t const * const src, uint32_t mip)
{
auto area = mip * mip;
uint16_t temp[area];
for (uint32_t px = 0; px < area; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
temp[px] = rgb565;
}
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
auto dst = &texture[dst_offset / 2];
twiddle::texture(dst, temp, mip, mip);
}
uint32_t copy_bbb_texture(uint32_t top)
{
uint32_t dst_offset = top + 6;
uint32_t ix = 0;
for (uint32_t mip = 1; mip <= 1024; mip *= 2) {
_copy_bbb_texture(dst_offset, mips[ix], mip);
ix += 1;
dst_offset += mip * mip * 2;
}
return dst_offset;
}
uint32_t _command_buf[(1024 + 32) / 4];
uint32_t _receive_buf[(1024 + 32) / 4];
struct button_state {
bool ra;
bool la;
bool da;
bool ua;
bool a;
bool b;
bool x;
bool y;
bool start;
void reset()
{
ra = la = da = ua = 0;
a = b = x = y = 0;
start = 0;
}
};
void do_get_condition(uint32_t * command_buf,
uint32_t * receive_buf,
button_state& buttons)
{
using command_type = get_condition;
using response_type = data_transfer<ft0::data_transfer::data_format>;
get_condition::data_fields data_fields = {
.function_type = std::byteswap(function_type::controller)
};
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size,
receive_buf, maple::sizeof_command(host_response));
buttons.reset();
for (uint8_t port = 0; port < 4; port++) {
auto& bus_data = host_response[port].bus_data;
if (bus_data.command_code != response_type::command_code) {
return;
}
auto& data_fields = bus_data.data_fields;
if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) {
return;
}
buttons.ra |= ft0::data_transfer::digital_button::ra(data_fields.data.digital_button) == 0;
buttons.la |= ft0::data_transfer::digital_button::la(data_fields.data.digital_button) == 0;
buttons.da |= ft0::data_transfer::digital_button::da(data_fields.data.digital_button) == 0;
buttons.ua |= ft0::data_transfer::digital_button::ua(data_fields.data.digital_button) == 0;
buttons.a |= ft0::data_transfer::digital_button::a(data_fields.data.digital_button) == 0;
buttons.b |= ft0::data_transfer::digital_button::b(data_fields.data.digital_button) == 0;
buttons.x |= ft0::data_transfer::digital_button::x(data_fields.data.digital_button) == 0;
buttons.y |= ft0::data_transfer::digital_button::y(data_fields.data.digital_button) == 0;
buttons.start |= ft0::data_transfer::digital_button::start(data_fields.data.digital_button) == 0;
}
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) + 32) / 4];
struct mipmap_state {
enum type : int {
disabled,
enabled
};
};
static char const * const mipmap_state_names[] = {
[mipmap_state::disabled] = "mipmap disabled",
[mipmap_state::enabled] = "mipmap enabled"
};
struct filter_state {
enum type : int {
point_sampled,
bilinear,
trilinear_a_b,
trilinear_a,
trilinear_b
};
};
static char const * const filter_state_names[] = {
[filter_state::point_sampled] = "point sampled",
[filter_state::bilinear] = "bilinear",
[filter_state::trilinear_a_b] = "trilinear pass A and B",
[filter_state::trilinear_a] = "trilinear pass A only",
[filter_state::trilinear_b] = "trilinear pass B only"
};
struct demo_state {
mipmap_state::type mipmap;
filter_state::type filter;
float y_axis_rotate;
float scale;
int32_t size;
};
bool has_translucent(filter_state::type filter)
{
switch (filter) {
default: [[fallthrough]];
case filter_state::point_sampled: return false;
case filter_state::bilinear: return false;
case filter_state::trilinear_a_b: return true;
case filter_state::trilinear_a: return false;
case filter_state::trilinear_b: return true;
}
}
bool has_opaque(filter_state::type filter)
{
switch (filter) {
default: [[fallthrough]];
case filter_state::point_sampled: return true;
case filter_state::bilinear: return true;
case filter_state::trilinear_a_b: return true;
case filter_state::trilinear_a: return true;
case filter_state::trilinear_b: return false;
}
}
uint32_t get_ta_alloc(filter_state::type filter)
{
return
ta_alloc_ctrl::pt_opb::_16x4byte
| ta_alloc_ctrl::tm_opb::no_list
| (has_translucent(filter) ? ta_alloc_ctrl::t_opb::_16x4byte : ta_alloc_ctrl::t_opb::no_list)
| ta_alloc_ctrl::om_opb::no_list
| (has_opaque(filter) ? ta_alloc_ctrl::o_opb::_16x4byte : ta_alloc_ctrl::o_opb::no_list)
;
}
struct opb_size get_opb_size(filter_state::type filter)
{
return
{ .opaque = has_opaque(filter) ? 16u * 4 : 0
, .opaque_modifier = 0
, .translucent = has_translucent(filter) ? 16u * 4 : 0
, .translucent_modifier = 0
, .punch_through = 16 * 4
};
}
enum struct filter_type {
point_sampled,
bilinear,
trilinear_pass_a,
trilinear_pass_b,
};
const uint32_t mip_offset[] = {
0x00006, // 1
0x00008, // 2
0x00010, // 4
0x00030, // 8
0x000b0, // 16
0x002b0, // 32
0x00ab0, // 64
0x02ab0, // 128
0x0aab0, // 256
0x2aab0, // 512
0xaaab0, // 1024
};
const char * texture_size_names[] = {
"1x1",
"2x2",
"4x4",
"8x8",
"16x16",
"32x32",
"64x64",
"128x128",
"256x256",
"512x512",
"1024x1024"
};
uint32_t get_texture_control_word(const uint32_t bbb_offset, mipmap_state::type mipmap, int32_t size)
{
const uint32_t texture_address = texture_memory_alloc::texture.start + bbb_offset;
switch (mipmap) {
default: [[fallthrough]];
case mipmap_state::enabled:
return defaults::texture_control_word
| texture_control_word::texture_address(texture_address / 8)
| texture_control_word::mip_mapped;
case mipmap_state::disabled:
return defaults::texture_control_word
| texture_control_word::texture_address((texture_address + mip_offset[size]) / 8);
}
}
void transform(ta_parameter_writer& parameter,
const vertex * strip_vertices,
const uint32_t strip_length,
const enum filter_type filter,
const demo_state& state,
uint32_t bbb_offset
)
{
const uint32_t texture_control_word = get_texture_control_word(bbb_offset, state.mipmap, state.size);
switch (filter) {
case filter_type::point_sampled: append_point_sampled( parameter, texture_control_word, (1 << state.size)); break;
case filter_type::bilinear: append_bilinear( parameter, texture_control_word, (1 << state.size)); break;
case filter_type::trilinear_pass_a: append_trilinear_pass_a(parameter, texture_control_word, (1 << state.size)); break;
case filter_type::trilinear_pass_b: append_trilinear_pass_b(parameter, texture_control_word, (1 << state.size)); break;
}
for (uint32_t i = 0; i < strip_length; i++) {
float x = strip_vertices[i].x;
float y = strip_vertices[i].y;
float z = strip_vertices[i].z;
float x1;
x1 = x * __builtin_cosf(state.y_axis_rotate) - z * __builtin_sinf(state.y_axis_rotate);
z = x * __builtin_sinf(state.y_axis_rotate) + z * __builtin_cosf(state.y_axis_rotate);
x = x1;
x *= state.scale;
y *= state.scale;
x += 320.f;
y += 240.f;
z = 1.f / (z + 10.f);
bool end_of_strip = i == strip_length - 1;
parameter.append<ta_vertex_parameter::polygon_type_3>() =
ta_vertex_parameter::polygon_type_3(polygon_vertex_parameter_control_word(end_of_strip),
x, y, z,
strip_vertices[i].u,
strip_vertices[i].v,
strip_vertices[i].color,
0 // offset_color
);
}
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
void update_state(button_state& prev, button_state& next, demo_state& state)
{
/* key bindings:
x: previous texture size
y: next texture size
a: previous filter state
b: next filter state
up: enlarge scale
down: reduce scale
left: rotate Y axis -
right: rotate Y axis +
start: toggle mipmap
*/
if ((next.start == true) && (next.start != prev.start)) {
if (state.mipmap == mipmap_state::disabled) state.mipmap = mipmap_state::enabled;
else state.mipmap = mipmap_state::disabled;
}
if ((next.x == true) && (next.x != prev.x)) {
state.size -= 1;
if (state.size < 3) state.size = 10;
}
if ((next.y == true) && (next.y != prev.y)) {
state.size += 1;
if (state.size > 10) state.size = 3;
}
if ((next.a == true) && (next.a != prev.a)) {
state.filter = static_cast<filter_state::type>(state.filter - 1);
if (state.filter < filter_state::point_sampled) state.filter = filter_state::trilinear_b;
}
if ((next.b == true) && (next.b != prev.b)) {
state.filter = static_cast<filter_state::type>(state.filter + 1);
if (state.filter > filter_state::trilinear_b) state.filter = filter_state::point_sampled;
}
if (next.la == true) {
state.y_axis_rotate -= half_degree;
}
if (next.ra == true) {
state.y_axis_rotate += half_degree;
}
if (next.ua == true) {
state.scale += 1.0f;
}
if (next.da == true) {
state.scale -= 1.0f;
}
}
void transform_hud(ta_parameter_writer& parameter, const demo_state& state)
{
int row = 0;
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + 2 * 8, // position x
16 + row * 16, // position y
"(X/Y)", 5,
para_control::list_type::punch_through);
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + 8 * 8, // position x
16 + row * 16, // position y
texture_size_names[state.size], -1,
para_control::list_type::punch_through);
row++;
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + 2 * 8, // position x
16 + row * 16, // position y
"(A/B)", 5,
para_control::list_type::punch_through);
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + 8 * 8, // position x
16 + row * 16, // position y
filter_state_names[state.filter], -1,
para_control::list_type::punch_through);
row++;
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + 0 * 8, // position x
16 + row * 16, // position y
"(start)", 7,
para_control::list_type::punch_through);
font_bitmap::transform_string(parameter,
8, 16, // texture
8, 16, // glyph
16 + 8 * 8, // position x
16 + row * 16, // position y
mipmap_state_names[state.mipmap], -1,
para_control::list_type::punch_through);
row++;
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
void main()
{
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
holly.SOFTRESET = 0;
core_init();
holly.PT_ALPHA_REF = 0x1;
background_parameter(0xff00ff00);
auto src = reinterpret_cast<const uint8_t *>(&_binary_verite_8x16_data_start);
uint32_t bbb_offset = font_bitmap::inflate(1, // pitch
8, // width
16, // height
8, // texture_width
16, // texture_height
src);
palette_data<3>();
copy_bbb_texture(bbb_offset);
video_output::set_mode_vga();
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
// This is mandatory for ch2-dma to the ta fifo polygon converter.
uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf);
uint32_t frame_ix = 0;
uint32_t * command_buf = align_32byte(_command_buf);
uint32_t * receive_buf = align_32byte(_receive_buf);
struct button_state buttons[2] = { 0 };
struct demo_state state = {
.mipmap = mipmap_state::disabled,
.filter = filter_state::point_sampled,
.y_axis_rotate = 0.f,
.scale = 512.f,
.size = 10, // 1024
};
filter_state::type last_filter_state = static_cast<filter_state::type>(state.filter + 1);
uint32_t ta_alloc = 0;
struct opb_size opb_size;
while (true) {
do_get_condition(command_buf, receive_buf, buttons[frame_ix & 1]);
update_state(buttons[(frame_ix + 1) & 1], buttons[frame_ix & 1], state);
if (state.filter != last_filter_state) {
ta_alloc = get_ta_alloc(state.filter);
opb_size = get_opb_size(state.filter);
region_array2(640 / 32, 480 / 32, opb_size);
last_filter_state = state.filter;
}
ta_polygon_converter_init(opb_size.total(),
ta_alloc,
640 / 32,
480 / 32);
switch (state.filter) {
case filter_state::point_sampled:
{
auto parameter_o = ta_parameter_writer(ta_parameter_buf);
transform(parameter_o, strip_vertices, strip_length, filter_type::point_sampled, state, bbb_offset);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_o.offset);
ta_wait_opaque_list();
break;
}
case filter_state::bilinear:
{
auto parameter_o = ta_parameter_writer(ta_parameter_buf);
transform(parameter_o, strip_vertices, strip_length, filter_type::bilinear, state, bbb_offset);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_o.offset);
ta_wait_opaque_list();
break;
}
case filter_state::trilinear_a_b:
{
auto parameter_o = ta_parameter_writer(ta_parameter_buf);
transform(parameter_o, strip_vertices, strip_length, filter_type::trilinear_pass_a, state, bbb_offset);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_o.offset);
ta_wait_opaque_list();
auto parameter_t = ta_parameter_writer(ta_parameter_buf);
transform(parameter_t, strip_vertices, strip_length, filter_type::trilinear_pass_b, state, bbb_offset);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_t.offset);
ta_wait_translucent_list();
break;
}
case filter_state::trilinear_a:
{
auto parameter_o = ta_parameter_writer(ta_parameter_buf);
transform(parameter_o, strip_vertices, strip_length, filter_type::trilinear_pass_a, state, bbb_offset);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_o.offset);
ta_wait_opaque_list();
break;
}
case filter_state::trilinear_b:
{
auto parameter_t = ta_parameter_writer(ta_parameter_buf);
transform(parameter_t, strip_vertices, strip_length, filter_type::trilinear_pass_b, state, bbb_offset);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_t.offset);
ta_wait_translucent_list();
break;
}
}
auto parameter_pt = ta_parameter_writer(ta_parameter_buf);
transform_hud(parameter_pt, state);
ta_polygon_converter_transfer(ta_parameter_buf, parameter_pt.offset);
ta_wait_punch_through_list();
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix = (frame_ix + 1) & 1;
}
}

View File

@ -84,7 +84,7 @@ uint32_t transform(uint32_t * ta_parameter_buf,
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128);
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::non_twiddled
| texture_control_word::texture_address(texture_address / 8);
@ -132,16 +132,11 @@ uint32_t transform(uint32_t * ta_parameter_buf,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xffffff00);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * (strip_length + 2)) * 2 + 32) / 4];
@ -152,14 +147,14 @@ void main()
auto src = reinterpret_cast<const uint8_t *>(&_binary_macaw_data_start);
auto size = reinterpret_cast<const uint32_t>(&_binary_macaw_data_size);
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint16_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
for (uint32_t px = 0; px < size / 3; px++) {
uint8_t r = src[px * 3 + 0];
uint8_t g = src[px * 3 + 1];
uint8_t b = src[px * 3 + 2];
uint16_t rgb565 = ((r / 8) << 11) | ((g / 4) << 5) | ((b / 8) << 0);
mem->texture[px] = rgb565;
texture[px] = rgb565;
}
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.
@ -187,7 +182,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
ta_polygon_converter_init(opb_size.total(),
@ -200,14 +194,14 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_translucent_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -110,13 +110,9 @@ uint32_t transform(uint32_t * ta_parameter_buf,
void init_texture_memory(const struct opb_size& opb_size, const struct video_output::framebuffer_resolution& framebuffer_resolution)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(0xff220000);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
framebuffer_resolution.width / 32, // width
region_array2(framebuffer_resolution.width / 32, // width
framebuffer_resolution.height / 32, // height
opb_size
);
@ -153,7 +149,6 @@ void main()
float theta = 0;
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
ta_polygon_converter_init(opb_size.total(),
@ -164,14 +159,12 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, ta_parameter_size);
ta_wait_opaque_list();
core_start_render((offsetof (struct texture_memory_alloc, framebuffer)),
framebuffer_resolution.width, // frame_width
0x00096000, // frame_size
frame_ix, num_frames);;
core_start_render(framebuffer_resolution.width, // frame_width
frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
if (cable_type != video_output::get_cable_type()) {
cable_type = video_output::get_cable_type();
framebuffer_resolution = video_output::set_mode_by_cable_type(cable_type);
@ -182,6 +175,6 @@ void main()
constexpr float half_degree = 0.01745329f / 2.f;
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -103,17 +103,11 @@ void ta_upload(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
holly.VO_BORDER_COL = 0x00220000;
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
void main()
@ -147,7 +141,6 @@ void main()
float delta = 0;
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
while (true) {
@ -212,14 +205,14 @@ void main()
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
delta += pi * 2 / 360;
}
}

View File

@ -230,16 +230,11 @@ void transform2(ta_parameter_writer& parameter,
void init_texture_memory(const struct opb_size& opb_size)
{
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory32);
background_parameter(mem->background, 0xff220000);
region_array2(mem->region_array,
(offsetof (struct texture_memory_alloc, object_list)),
640 / 32, // width
480 / 32, // height
opb_size
);
region_array2(640 / 32, // width
480 / 32, // height
opb_size
);
background_parameter(0xff220000);
}
uint32_t _ta_parameter_buf[((32 * 8192) + 32) / 4];
@ -273,7 +268,6 @@ void main()
init_texture_memory(opb_size);
uint32_t frame_ix = 0;
constexpr uint32_t num_frames = 1;
float theta = 0;
vec3 lights[3] = {
@ -310,14 +304,14 @@ void main()
parameter.append<ta_global_parameter::end_of_list>() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset);
ta_wait_opaque_list();
core_start_render(frame_ix, num_frames);
core_start_render(frame_ix);
core_wait_end_of_render_video();
while (!spg_status::vsync(holly.SPG_STATUS));
core_flip(frame_ix, num_frames);
core_flip(frame_ix);
while (spg_status::vsync(holly.SPG_STATUS));
theta += half_degree;
frame_ix += 1;
frame_ix = (frame_ix + 1) & 1;;
}
}

View File

@ -47,8 +47,7 @@ static inline void inflate_character(const uint32_t pitch,
}
}
auto mem = reinterpret_cast<volatile texture_memory_alloc *>(texture_memory64);
auto texture = reinterpret_cast<volatile uint32_t *>(mem->texture);
auto texture = reinterpret_cast<volatile uint32_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
const uint32_t texture_offset = texture_width * texture_height * character_index / 2;
twiddle::texture2<4>(&texture[texture_offset / 4], // uint32_t *
@ -57,14 +56,14 @@ static inline void inflate_character(const uint32_t pitch,
texture_width * texture_height);
}
void inflate(const uint32_t pitch,
const uint32_t width,
const uint32_t height,
const uint32_t texture_width,
const uint32_t texture_height,
const uint8_t * src)
uint32_t inflate(const uint32_t pitch,
const uint32_t width,
const uint32_t height,
const uint32_t texture_width,
const uint32_t texture_height,
const uint8_t * src)
{
for (uint8_t ix = 0x20; ix < 0x7f; ix++) {
for (uint8_t ix = 0x20; ix <= 0x7f; ix++) {
inflate_character(pitch,
width,
height,
@ -73,6 +72,7 @@ void inflate(const uint32_t pitch,
src,
ix);
}
return ((0x7f - 0x20) + 1) * texture_width * texture_height / 2;
}
void palette_data()
@ -108,25 +108,30 @@ void transform_string(ta_parameter_writer& parameter,
const int32_t position_x,
const int32_t position_y,
const char * s,
const uint32_t len
const int32_t len,
const uint32_t list_type
)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| list_type
| obj_control::col_type::packed_color
| obj_control::texture;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always
| isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::src_alpha
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog
| tsp_instruction_word::texture_u_size::from_int(texture_width)
| tsp_instruction_word::texture_v_size::from_int(texture_height);
for (uint32_t string_ix = 0; string_ix < len; string_ix++) {
const uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture));
int32_t string_ix = 0;
while (true) {
if (len < 0) {
if (s[string_ix] == 0) break;
} else if (string_ix >= len) break;
const uint32_t texture_address = texture_memory_alloc::texture.start;
const uint32_t glyph_address = texture_address + texture_width * texture_height * (s[string_ix] - ' ') / 2;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled
@ -154,7 +159,7 @@ void transform_string(ta_parameter_writer& parameter,
y *= static_cast<float>(glyph_height * 1);
x += static_cast<float>(position_x + glyph_width * string_ix);
y += static_cast<float>(position_y);
z = 1.f / (z + 10.f);
z = 1.f;
u *= static_cast<float>(glyph_width) / static_cast<float>(texture_width);
v *= static_cast<float>(glyph_height) / static_cast<float>(texture_height);
@ -167,6 +172,7 @@ void transform_string(ta_parameter_writer& parameter,
0 // offset_color
);
}
string_ix++;
}
}

View File

@ -6,14 +6,12 @@
namespace font_bitmap {
void inflate(const uint32_t pitch,
const uint32_t width,
const uint32_t height,
const uint32_t texture_width,
const uint32_t texture_height,
const uint8_t * src);
void palette_data();
uint32_t inflate(const uint32_t pitch,
const uint32_t width,
const uint32_t height,
const uint32_t texture_width,
const uint32_t texture_height,
const uint8_t * src);
void transform_string(ta_parameter_writer& parameter,
const uint32_t texture_width,
@ -23,7 +21,8 @@ void transform_string(ta_parameter_writer& parameter,
const int32_t position_x,
const int32_t position_y,
const char * s,
const uint32_t len
const int32_t len,
const uint32_t list_type
);
}

21
framebuffer.py Normal file
View File

@ -0,0 +1,21 @@
# 565
from PIL import Image
import struct
with open('framebuffer.bin', 'rb') as f:
buf = f.read()
image = Image.new('RGB', (640, 480), color=None)
for i in range(len(buf) // 2):
b, = struct.unpack('<H', buf[i*2:(i+1)*2])
blue = (b >> 0 ) & 31
green = (b >> 5 ) & 63
red = (b >> 11) & 31
x = i % 640
y = i // 640
image.putpixel((x, y), (red * 8, green * 4, blue * 8))
image.save("framebuffer.png")

View File

@ -1,6 +1,8 @@
#include <cstdint>
#include "isp_tsp.hpp"
#include "texture_memory_alloc.hpp"
#include "memorymap.hpp"
struct vertex_parameter {
float x;
@ -18,9 +20,10 @@ struct isp_tsp_parameter {
static_assert((sizeof (isp_tsp_parameter)) == (4 * 3 + 3) * 4);
void background_parameter(volatile uint32_t * buf, uint32_t color)
void background_parameter(const uint32_t color)
{
volatile isp_tsp_parameter * parameter = reinterpret_cast<volatile isp_tsp_parameter *>(buf);
auto parameter = reinterpret_cast<volatile isp_tsp_parameter *>
(&texture_memory32[texture_memory_alloc::background.start / 4]);
parameter->isp_tsp_instruction_word
= isp_tsp_instruction_word::depth_compare_mode::always

View File

@ -2,4 +2,4 @@
#include <cstdint>
void background_parameter(volatile uint32_t * buf, uint32_t color);
void background_parameter(const uint32_t color);

View File

@ -52,14 +52,15 @@ void core_init()
}
void core_start_render(uint32_t frame_address,
uint32_t frame_width, // in pixels
uint32_t frame_size, // in bytes
uint32_t frame_ix, uint32_t num_frames)
uint32_t frame_width // in pixels
)
{
holly.REGION_BASE = (offsetof (struct texture_memory_alloc, region_array));
holly.PARAM_BASE = (offsetof (struct texture_memory_alloc, isp_tsp_parameters));
holly.REGION_BASE = texture_memory_alloc::region_array.start;
holly.PARAM_BASE = texture_memory_alloc::isp_tsp_parameters.start;
holly.ISP_BACKGND_T = isp_backgnd_t::tag_address((offsetof (struct texture_memory_alloc, background)) / 4)
constexpr int32_t background_offset = (texture_memory_alloc::background.start - texture_memory_alloc::isp_tsp_parameters.start);
static_assert(background_offset >= 0);
holly.ISP_BACKGND_T = isp_backgnd_t::tag_address(background_offset / 4)
| isp_backgnd_t::tag_offset(0)
| isp_backgnd_t::skip(1);
holly.ISP_BACKGND_D = _i(1.f/100000.f);
@ -68,18 +69,18 @@ void core_start_render(uint32_t frame_address,
constexpr uint32_t bytes_per_pixel = 2;
holly.FB_W_LINESTRIDE = (frame_width * bytes_per_pixel) / 8;
const uint32_t w_fb = (frame_ix & num_frames) * frame_size;
holly.FB_W_SOF1 = frame_address + w_fb;
holly.FB_W_SOF1 = frame_address;
holly.STARTRENDER = 1;
}
void core_start_render(uint32_t frame_ix, uint32_t num_frames)
constexpr uint32_t framebuffer_frame_size = 0x00096000 * 2;
void core_start_render(uint32_t frame_ix)
{
core_start_render((offsetof (struct texture_memory_alloc, framebuffer)),
640, // frame_width
0x00096000, // frame_size
frame_ix, num_frames);
core_start_render(texture_memory_alloc::framebuffer[frame_ix].start,
640
);
}
void core_wait_end_of_render_video()
@ -94,8 +95,7 @@ void core_wait_end_of_render_video()
| istnrm::end_of_render_video;
}
void core_flip(uint32_t frame_ix, uint32_t num_frames)
void core_flip(uint32_t frame_ix)
{
uint32_t r_fb = (frame_ix & num_frames) * 0x00096000;
holly.FB_R_SOF1 = (offsetof (struct texture_memory_alloc, framebuffer)) + r_fb;
holly.FB_R_SOF1 = texture_memory_alloc::framebuffer[frame_ix].start;
}

View File

@ -3,10 +3,9 @@
void core_init();
void core_start_render(uint32_t frame_address,
uint32_t frame_width, // in pixels
uint32_t frame_size, // in bytes
uint32_t frame_ix, uint32_t num_frames);
void core_start_render(uint32_t frame_ix, uint32_t num_frames);
uint32_t frame_width); // in pixels
void core_start_render(uint32_t frame_ix);
void core_wait_end_of_render_video();
void core_flip(uint32_t frame_ix, uint32_t num_frames);
void core_flip(uint32_t frame_ix);

View File

@ -59,8 +59,15 @@ namespace tsp_instruction_word {
constexpr uint32_t inverse_dst_alpha = 7 << 26;
}
constexpr uint32_t src_select = 1 << 25;
constexpr uint32_t dst_select = 1 << 24;
namespace src_select {
constexpr uint32_t primary_accumulation_buffer = 0 << 25;
constexpr uint32_t secondary_accumulation_buffer = 1 << 25;
}
namespace dst_select {
constexpr uint32_t primary_accumulation_buffer = 0 << 24;
constexpr uint32_t secondary_accumulation_buffer = 1 << 24;
}
namespace fog_control {
constexpr uint32_t look_up_table = 0b00 << 22;
@ -177,6 +184,11 @@ namespace texture_control_word {
constexpr uint32_t twiddled = 0 << 26;
constexpr uint32_t non_twiddled = 1 << 26;
}
constexpr uint32_t palette_selector(uint32_t a) {
return (a & 0x3f) << 21;
}
constexpr uint32_t stride_select = 1 << 25;
// in 8-byte units

View File

@ -1,6 +1,8 @@
#include <cstdint>
#include "region_array.hpp"
#include "texture_memory_alloc.hpp"
#include "memorymap.hpp"
#define REGION_ARRAY__LAST_REGION (1 << 31)
#define REGION_ARRAY__Z_CLEAR (1 << 30)
@ -25,12 +27,14 @@ struct region_array_entry {
// opaque list pointer offset: OPB size * tile index * 4
void region_array(volatile uint32_t * buf,
const uint32_t ol_base,
const uint32_t width, // in tile units (1 tile unit = 32 pixels)
void region_array(const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height) // in tile units (1 tile unit = 32 pixels)
{
volatile region_array_entry * region_array = reinterpret_cast<volatile region_array_entry *>(buf);
auto region_array = reinterpret_cast<volatile region_array_entry *>
(&texture_memory32[texture_memory_alloc::region_array.start / 4]);
const uint32_t ol_base = texture_memory_alloc::object_list.start;
uint32_t ix = 0;
// create a "dummy region array [item]" for CORE & TA-related bug #21:
@ -66,13 +70,15 @@ void region_array(volatile uint32_t * buf,
}
}
void region_array2(volatile uint32_t * buf,
const uint32_t ol_base,
const uint32_t width, // in tile units (1 tile unit = 32 pixels)
void region_array2(const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height, // in tile units (1 tile unit = 32 pixels)
const struct opb_size& opb_size)
{
volatile region_array_entry * region_array = reinterpret_cast<volatile region_array_entry *>(buf);
auto region_array = reinterpret_cast<volatile region_array_entry *>
(&texture_memory32[texture_memory_alloc::region_array.start / 4]);
const uint32_t ol_base = texture_memory_alloc::object_list.start;
const uint32_t num_tiles = width * height;
uint32_t ix = 0;
@ -101,29 +107,29 @@ void region_array2(volatile uint32_t * buf,
region_array[ix].opaque_modifier_volume_list_pointer = (opb_size.opaque_modifier == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base + num_tiles * ( opb_size.opaque
)
)
+ (opb_size.opaque_modifier * tile_index)
);
region_array[ix].translucent_list_pointer = (opb_size.translucent == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base + num_tiles * ( opb_size.opaque
+ opb_size.opaque_modifier
)
+ opb_size.opaque_modifier
)
+ (opb_size.translucent * tile_index)
);
region_array[ix].translucent_modifier_volume_list_pointer = (opb_size.translucent_modifier == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base + num_tiles * ( opb_size.opaque
+ opb_size.opaque_modifier
+ opb_size.translucent
)
+ opb_size.opaque_modifier
+ opb_size.translucent
)
+ (opb_size.translucent_modifier * tile_index)
);
region_array[ix].punch_through_list_pointer = (opb_size.punch_through == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base + num_tiles * ( opb_size.opaque
+ opb_size.opaque_modifier
+ opb_size.translucent
+ opb_size.translucent_modifier
)
+ opb_size.opaque_modifier
+ opb_size.translucent
+ opb_size.translucent_modifier
)
+ (opb_size.punch_through * tile_index)
);
@ -132,68 +138,71 @@ void region_array2(volatile uint32_t * buf,
}
}
void region_array_multipass(volatile uint32_t * buf,
const uint32_t ol_base,
const uint32_t width, // in tile units (1 tile unit = 32 pixels)
void region_array_multipass(const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height, // in tile units (1 tile unit = 32 pixels)
const struct opb_size * opb_size,
const uint32_t num_render_passes)
{
volatile region_array_entry * region_array = reinterpret_cast<volatile region_array_entry *>(buf);
auto region_array = reinterpret_cast<volatile region_array_entry *>
(&texture_memory32[texture_memory_alloc::region_array.start / 4]);
const uint32_t num_tiles = width * height;
uint32_t ol_base[num_render_passes];
ol_base[0] = texture_memory_alloc::object_list.start;
for (uint32_t pass = 1; pass < num_render_passes; pass++) {
ol_base[pass] = ol_base[pass - 1] + num_tiles * opb_size[pass - 1].total();
}
uint32_t ix = 0;
/*
// create a "dummy region array [item]" for CORE & TA-related bug #21:
// "Misshapen tiles or missing tiles occur"
region_array[ix].tile = REGION_ARRAY__FLUSH_ACCUMULATE;
region_array[ix].opaque_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].opaque_modifier_volume_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].translucent_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].translucent_modifier_volume_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].punch_through_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
ix += 1;
*/
constexpr uint32_t list_opb_size = 16 * 4; // for a single OPB in bytes; this must match O_OPB in TA_ALLOC_CTRL
const uint32_t opb_render_pass_size = width * height * list_opb_size; // the sum of the size of all OPB for a single pass
for (uint32_t y = 0; y < height; y++) {
for (uint32_t x = 0; x < width; x++) {
for (uint32_t pass = 0; pass < num_render_passes; pass++) {
region_array[ix].tile = REGION_ARRAY__TILE_Y_POSITION(y)
| REGION_ARRAY__TILE_X_POSITION(x);
region_array[ix].tile = REGION_ARRAY__TILE_Y_POSITION(y)
| REGION_ARRAY__TILE_X_POSITION(x);
if (pass == (num_render_passes - 1) && y == (height - 1) && x == (width - 1))
region_array[ix].tile |= REGION_ARRAY__LAST_REGION;
/* 0x10 = FLUSH_ACCUMULATE
0x50 = FLUSH_ACCUMULATE | Z_CLEAR
0x40 = Z_CLEAR
*/
for (uint32_t render_pass = 0; render_pass < num_render_passes; render_pass++) {
if (render_pass != (num_render_passes - 1))
if (pass != (num_render_passes - 1))
region_array[ix].tile |= REGION_ARRAY__FLUSH_ACCUMULATE;
if (render_pass > 0)
if (pass > 0)
region_array[ix].tile |= REGION_ARRAY__Z_CLEAR;
uint32_t tile_index = y * width + x;
uint32_t pass_ol_base = ol_base + (opb_render_pass_size * render_pass);
if (render_pass == 0) {
region_array[ix].opaque_list_pointer = pass_ol_base + (list_opb_size * tile_index);
region_array[ix].opaque_modifier_volume_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].translucent_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].translucent_modifier_volume_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].punch_through_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
} else {
// (list_opb_size * width * height) +
region_array[ix].opaque_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].opaque_modifier_volume_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].translucent_list_pointer = pass_ol_base + (list_opb_size * tile_index);
region_array[ix].translucent_modifier_volume_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
region_array[ix].punch_through_list_pointer = REGION_ARRAY__LIST_POINTER__EMPTY;
}
region_array[ix].opaque_list_pointer = (opb_size[pass].opaque == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base[pass] + (opb_size[pass].opaque * tile_index)
);
if (y == (height - 1) && x == (width - 1))
region_array[ix].tile |= REGION_ARRAY__LAST_REGION;
region_array[ix].opaque_modifier_volume_list_pointer = (opb_size[pass].opaque_modifier == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base[pass] + num_tiles * ( opb_size[pass].opaque
)
+ (opb_size[pass].opaque_modifier * tile_index)
);
region_array[ix].translucent_list_pointer = (opb_size[pass].translucent == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base[pass] + num_tiles * ( opb_size[pass].opaque
+ opb_size[pass].opaque_modifier
)
+ (opb_size[pass].translucent * tile_index)
);
region_array[ix].translucent_modifier_volume_list_pointer = (opb_size[pass].translucent_modifier == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base[pass] + num_tiles * ( opb_size[pass].opaque
+ opb_size[pass].opaque_modifier
+ opb_size[pass].translucent
)
+ (opb_size[pass].translucent_modifier * tile_index)
);
region_array[ix].punch_through_list_pointer = (opb_size[pass].punch_through == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
(ol_base[pass] + num_tiles * ( opb_size[pass].opaque
+ opb_size[pass].opaque_modifier
+ opb_size[pass].translucent
+ opb_size[pass].translucent_modifier
)
+ (opb_size[pass].punch_through * tile_index)
);
ix += 1;
}
}

View File

@ -19,19 +19,14 @@ struct opb_size {
}
};
void region_array(volatile uint32_t * buf,
const uint32_t ol_base,
const uint32_t width, // in tile units (1 tile unit = 32 pixels)
void region_array(const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height); // in tile units (1 tile unit = 32 pixels)
void region_array2(volatile uint32_t * buf,
const uint32_t ol_base,
const uint32_t width, // in tile units (1 tile unit = 32 pixels)
void region_array2(const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height, // in tile units (1 tile unit = 32 pixels)
const struct opb_size& opb_size);
void region_array_multipass(volatile uint32_t * buf,
const uint32_t ol_base,
const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height, // in tile units (1 tile unit = 32 pixels)
const uint32_t num_render_passes);
void region_array_multipass(const uint32_t width, // in tile units (1 tile unit = 32 pixels)
const uint32_t height, // in tile units (1 tile unit = 32 pixels)
const struct opb_size * opb_size,
const uint32_t num_render_passes);

View File

@ -29,12 +29,11 @@ void ta_polygon_converter_init(uint32_t opb_total_size, // for one tile, for all
holly.TA_ALLOC_CTRL = ta_alloc_ctrl::opb_mode::increasing_addresses
| ta_alloc;
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, _res0)); // the end of the object_list
holly.TA_NEXT_OPB_INIT = (offsetof (struct texture_memory_alloc, object_list))
+ ta_next_opb_offset;
holly.TA_ISP_BASE = texture_memory_alloc::isp_tsp_parameters.start;
holly.TA_ISP_LIMIT = texture_memory_alloc::isp_tsp_parameters.end; // the end of isp_tsp_parameters
holly.TA_OL_BASE = texture_memory_alloc::object_list.start;
holly.TA_OL_LIMIT = texture_memory_alloc::object_list.end; // the end of the object_list
holly.TA_NEXT_OPB_INIT = texture_memory_alloc::object_list.start + ta_next_opb_offset;
holly.TA_LIST_INIT = ta_list_init::list_init;
@ -47,8 +46,7 @@ void ta_polygon_converter_cont(uint32_t ol_base_offset,
{
holly.TA_ALLOC_CTRL = ta_alloc_ctrl::opb_mode::increasing_addresses
| ta_alloc;
holly.TA_OL_BASE = (offsetof (struct texture_memory_alloc, object_list))
+ ol_base_offset;
holly.TA_OL_BASE = texture_memory_alloc::object_list.start + ol_base_offset;
holly.TA_LIST_CONT = ta_list_cont::list_cont;

View File

@ -1,30 +1,82 @@
#pragma once
#include <cstdint>
#include <cstddef>
/*
object_list[0x00100000 / 4] is enough space for 54 sets of
19200-byte lists (16 * 4 * (640 / 32) * (480 / 32))
* A 0x10000-byte region array is sufficient for 9 render passes:
*
* ((640 / 32) * (480 / 32) * 6 * 4) * 9 == 0xfd20
*/
(that is, it is significantly more space than required for trivial
TA/CORE drawings)
namespace texture_memory_alloc {
region-array[0x00004000 / 4] is enough space for 2 render passes.
(640 // 32) * (480 // 32) * 6 * 4 * 2 == 0x3840
(640 // 32) * (512 // 32) * 6 * 4 * 2 == 0x3c00
(512 // 32) * (512 // 32) * 6 * 4 * 2 == 0x3000
*/
constexpr uint32_t address_64to32(uint32_t addr)
{
uint32_t value = ((addr & 0xfffffff8) >> 1) + (addr & 0x3);
if ((addr & 0x4) != 0)
value += 0x400000;
if (addr >= 0x800000)
value += 0x400000;
return value;
}
struct texture_memory_alloc {
uint32_t isp_tsp_parameters[0x00100000 / 4]; // TA_ISP_BASE / PARAM_BASE (the actual objects)
uint32_t object_list[0x00100000 / 4]; // TA_OL_BASE (contains object pointer blocks)
uint32_t _res0[ 0x20 / 4]; // (the TA may clobber 4 bytes starting at TA_OL_LIMIT)
uint32_t region_array[0x00004000 / 4]; // REGION_BASE
uint32_t background[0x00000040 / 4]; // ISP_BACKGND_T
uint32_t framebuffer[2][0x00096000 / 4]; // FB_R_SOF1 / FB_W_SOF1
uint32_t _res1[ 0x20 / 4]; // (re-align texture to a 64-byte boundary)
uint16_t texturebuffer[512 * 512 * 2 / 2];
uint16_t texture[128 * 128 * 2 / 2]; // texture_control_word::texture_address
struct start_end {
uint32_t start;
uint32_t end;
};
static_assert((sizeof (texture_memory_alloc)) < 0x1000000);
// 32-bit transfer
constexpr start_end isp_tsp_parameters = {
.start = address_64to32(0x00'0000),
.end = address_64to32(0x00'0000) + 0x10'0000, // next: 0x20'0000
};
constexpr start_end object_list = {
.start = address_64to32(0x00'0004),
.end = address_64to32(0x00'0004) + 0x10'0000 - 0x20, // next: 0x20'0004
};
constexpr start_end framebuffer[2] = {
{
.start = address_64to32(0x20'0000),
.end = address_64to32(0x20'0000) + 0x9'6000, // next: 0x32'c000
},
{
.start = address_64to32(0x20'0004),
.end = address_64to32(0x20'0004) + 0x9'6000, // next: 0x32'c004
}
};
constexpr start_end background = {
.start = address_64to32(0x32'c000),
.end = address_64to32(0x32'c000) + 0x40, // next: 0x32'c080
};
constexpr start_end region_array = {
.start = address_64to32(0x32'c080),
.end = address_64to32(0x32'c080) + 0x1'0000, // next: 0x34'c080
};
// 64-bit transfer
constexpr start_end texture = {
.start = 0x40'0000,
.end = 0x80'0000,
};
}
/*
struct texture_memory_alloc {
union {
struct {
uint32_t isp_tsp_parameters[0x0010'0000 / 4]; // TA_ISP_BASE / PARAM_BASE (the actual objects)
uint32_t object_list[0x0010'0000 / 4]; // TA_OL_BASE (contains object pointer blocks)
uint32_t _res0[ 0x20 * 2 / 4]; // (the TA may clobber 4 bytes starting at TA_OL_LIMIT)
uint32_t background[0x00000040 * 2 / 4]; // ISP_BACKGND_T
uint32_t region_array[0x00004000 * 2 / 4]; // REGION_BASE
uint32_t framebuffer[2][0x0009'6000 * 2 / 4]; // FB_R_SOF1 / FB_W_SOF1
};
uint32_t bank0[0x400000 / 4];
};
uint16_t texture[0x200000 / 2]; // texture_control_word::texture_address
};
static_assert((sizeof (texture_memory_alloc)) <= 0x800000);
//static_assert((offsetof (struct texture_memory_alloc, texture)) == 0x400000);
*/

View File

@ -54,6 +54,15 @@ SECTIONS
. = ALIGN(4);
} > ldram
.text.vbr ALIGN(4) : SUBALIGN(4)
{
KEEP(*(.vbr.100))
. = ALIGN(0x300);
KEEP(*(.vbr.400))
. = ALIGN(0x200);
KEEP(*(.vbr.600))
} > p1ram
INCLUDE "debug.lds"
}
__stack_reservation = 0x0000;

View File

@ -11,4 +11,4 @@ extern volatile uint32_t ta_fifo_texture_memory[0x800000] __asm("ta_fifo_texture
extern volatile uint32_t ta_fifo_polygon_converter_mirror[0x800000] __asm("ta_fifo_polygon_converter_mirror");
extern volatile uint32_t ta_fifo_yuv_converter_mirror[0x800000] __asm("ta_fifo_yuv_converter_mirror");
extern volatile uint32_t ta_fifo_texture_memory_mirror[0x800000] __asm("ta_fifo_texture_memory_mirror");
extern volatile uint32_t store_queue[0x4000000] __asm("store_queue");
extern uint32_t store_queue[0x4000000] __asm("store_queue");

View File

@ -1,5 +1,7 @@
#pragma once
#include "holly/core_bits.hpp"
constexpr inline uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b)
{
return ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);
@ -48,3 +50,13 @@ void palette_data<2>()
holly.PALETTE_RAM[0] = 0x0000;
holly.PALETTE_RAM[1] = 0xffff;
}
template <>
void palette_data<3>()
{
holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::argb1555;
holly.PALETTE_RAM[0] = 0x0000;
holly.PALETTE_RAM[1] = 0xffff;
holly.PALETTE_RAM[2] = 0x8000;
}

View File

@ -70,7 +70,7 @@ void character(const char c)
// wait for transmit fifo to become empty
while ((sh7091.SCIF.SCFSR2 & scfsr2::tdfe::bit_mask) == 0);
for (int i = 0; i < 10000; i++) {
for (int i = 0; i < 1000; i++) {
asm volatile ("nop;");
}

View File

@ -1,7 +1,9 @@
#pragma once
#include "sh7091.hpp"
#include "memorymap.hpp"
void sq_transfer_32byte(volatile void * dst)
static inline void sq_transfer_32byte(volatile void * dst)
{
// dst typically 0x10000000 (ta polygon converter)
sh7091.CCN.QACR0 = ((reinterpret_cast<uint32_t>(dst) >> 26) & 0b111) << 2;
@ -10,11 +12,11 @@ void sq_transfer_32byte(volatile void * dst)
asm volatile ("pref @%0"
: // output
: "r" (&store_queue[0]) // input
);
: "memory");
}
void sq_transfer_64byte(volatile void * dst)
static inline void sq_transfer_64byte(volatile void * dst)
{
// dst typically 0x10000000 (ta polygon converter)
sh7091.CCN.QACR0 = ((reinterpret_cast<uint32_t>(dst) >> 26) & 0b111) << 2;
@ -24,11 +26,11 @@ void sq_transfer_64byte(volatile void * dst)
asm volatile ("pref @%0"
: // output
: "r" (&store_queue[0]) // input
);
: "memory");
// start 32-byte transfer from store queue 1 (SQ1) to QACR1
asm volatile ("pref @%0"
: // output
: "r" (&store_queue[8]) // input
);
: "memory");
}

View File

@ -1,4 +0,0 @@
#pragma once
void sq_transfer_32byte(volatile void * dst);
void sq_transfer_64byte(volatile void * dst);