example: add texture_filtering and texture_filtering_maple

This commit is contained in:
Zack Buhman 2024-05-12 17:39:52 +08:00
parent bcaa9789cf
commit a4ae84124a
18 changed files with 1513 additions and 0 deletions

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

@ -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;
}
}

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")