dreamcast2: add triangle_core
This commit is contained in:
parent
b99d646365
commit
dacdad6132
@ -7,3 +7,9 @@ CFLAGS += -I$(MAKEFILE_PATH)
|
||||
LIB ?= $(MAKEFILE_PATH)
|
||||
|
||||
include example/example.mk
|
||||
|
||||
clean:
|
||||
find -P \
|
||||
-regextype posix-egrep \
|
||||
-regex '.*\.(iso|o|d|bin|elf|cue|gch)$$' \
|
||||
-exec rm {} \;
|
||||
|
@ -1,6 +1,6 @@
|
||||
system_boot_rom = 0xa0000000;
|
||||
|
||||
system = 0xa05f6800;
|
||||
systembus = 0xa05f6800;
|
||||
maple_if = 0xa05f6c00;
|
||||
gdrom_if = 0xa05f7000;
|
||||
g1_if = 0xa05f7400;
|
||||
|
@ -2,15 +2,15 @@ SECTIONS
|
||||
{
|
||||
. = ORIGIN(p2ram);
|
||||
|
||||
.text.start :
|
||||
.text.start ALIGN(4) :
|
||||
{
|
||||
KEEP(*(.text.start))
|
||||
*(.text.startup.*)
|
||||
*(.text.start.*)
|
||||
} > p2ram AT>p1ram
|
||||
|
||||
. = ORIGIN(p1ram) + (. - ORIGIN(p2ram));
|
||||
|
||||
.text :
|
||||
.text ALIGN(4) : SUBALIGN(4)
|
||||
{
|
||||
*(.text.*)
|
||||
*(.text)
|
||||
|
@ -7,3 +7,10 @@ FRAMEBUFFER_SHADED_OBJ = \
|
||||
|
||||
example/framebuffer_shaded.elf: LDSCRIPT = $(LIB)/main.lds
|
||||
example/framebuffer_shaded.elf: $(START_OBJ) $(FRAMEBUFFER_SHADED_OBJ)
|
||||
|
||||
TRIANGLE_CORE_OBJ = \
|
||||
holly/core/region_array.o \
|
||||
example/triangle_core.o
|
||||
|
||||
example/triangle_core.elf: LDSCRIPT = $(LIB)/main.lds
|
||||
example/triangle_core.elf: $(START_OBJ) $(TRIANGLE_CORE_OBJ)
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
volatile uint32_t * framebuffer = (volatile uint32_t * )texture_memory32;
|
||||
volatile uint32_t * framebuffer = (volatile uint32_t * )&texture_memory32[0x200000];
|
||||
|
||||
for (int y = 0; y < 480; y++) {
|
||||
for (int x = 0; x < 640; x++) {
|
||||
|
180
dreamcast2/example/triangle_core.cpp
Normal file
180
dreamcast2/example/triangle_core.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
#include "memorymap.hpp"
|
||||
|
||||
#include "holly/core/object_list_bits.hpp"
|
||||
#include "holly/core/region_array.hpp"
|
||||
#include "holly/core/region_array_bits.hpp"
|
||||
#include "holly/core/parameter_bits.hpp"
|
||||
#include "holly/core/parameter.hpp"
|
||||
#include "holly/holly.hpp"
|
||||
#include "holly/holly_bits.hpp"
|
||||
|
||||
void transfer_object_list(uint32_t object_list_start, uint32_t triangle_array_offset)
|
||||
{
|
||||
using namespace holly::core;
|
||||
|
||||
volatile uint32_t * object_list = (volatile uint32_t *)&texture_memory32[object_list_start];
|
||||
|
||||
object_list[0] = object_list::pointer_type::triangle_array
|
||||
| object_list::triangle_array::number_of_triangles(0)
|
||||
| object_list::triangle_array::skip(1)
|
||||
| object_list::triangle_array::start(triangle_array_offset / 4);
|
||||
|
||||
object_list[1] = object_list::pointer_type::object_pointer_block_link
|
||||
| object_list::object_pointer_block_link::end_of_list;
|
||||
}
|
||||
|
||||
void transfer_background_polygon(uint32_t isp_tsp_parameter_start)
|
||||
{
|
||||
using namespace holly::core::parameter;
|
||||
|
||||
using parameter = isp_tsp_parameter<3>;
|
||||
|
||||
volatile parameter * polygon = (volatile parameter *)&texture_memory32[isp_tsp_parameter_start];
|
||||
|
||||
polygon->isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always
|
||||
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||
|
||||
polygon->tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
|
||||
| tsp_instruction_word::dst_alpha_instr::zero
|
||||
| tsp_instruction_word::fog_control::no_fog;
|
||||
|
||||
polygon->texture_control_word = 0;
|
||||
|
||||
polygon->vertex[0].x = 0.0f;
|
||||
polygon->vertex[0].y = 0.0f;
|
||||
polygon->vertex[0].z = 0.00001f;
|
||||
polygon->vertex[0].base_color = 0xff00ff;
|
||||
|
||||
polygon->vertex[1].x = 32.0f;
|
||||
polygon->vertex[1].y = 0.0f;
|
||||
polygon->vertex[1].z = 0.00001f;
|
||||
polygon->vertex[1].base_color = 0xff00ff;
|
||||
|
||||
polygon->vertex[2].x = 32.0f;
|
||||
polygon->vertex[2].y = 32.0f;
|
||||
polygon->vertex[2].z = 0.00001f;
|
||||
polygon->vertex[2].base_color = 0xff00ff;
|
||||
}
|
||||
|
||||
void transfer_triangle_polygon(uint32_t isp_tsp_parameter_start)
|
||||
{
|
||||
using namespace holly::core::parameter;
|
||||
|
||||
using parameter = isp_tsp_parameter<3>;
|
||||
|
||||
volatile parameter * polygon = (volatile parameter *)&texture_memory32[isp_tsp_parameter_start];
|
||||
|
||||
polygon->isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::always
|
||||
| isp_tsp_instruction_word::culling_mode::no_culling
|
||||
| isp_tsp_instruction_word::gouraud_shading;
|
||||
|
||||
polygon->tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
|
||||
| tsp_instruction_word::dst_alpha_instr::zero
|
||||
| tsp_instruction_word::fog_control::no_fog;
|
||||
|
||||
polygon->texture_control_word = 0;
|
||||
|
||||
polygon->vertex[0].x = 1.0f;
|
||||
polygon->vertex[0].y = 29.0f;
|
||||
polygon->vertex[0].z = 0.1f;
|
||||
polygon->vertex[0].base_color = 0xff0000;
|
||||
|
||||
polygon->vertex[1].x = 16.0f;
|
||||
polygon->vertex[1].y = 3.0f;
|
||||
polygon->vertex[1].z = 0.1f;
|
||||
polygon->vertex[1].base_color = 0x00ff00;
|
||||
|
||||
polygon->vertex[2].x = 31.0f;
|
||||
polygon->vertex[2].y = 29.0f;
|
||||
polygon->vertex[2].z = 0.1f;
|
||||
polygon->vertex[2].base_color = 0x0000ff;
|
||||
}
|
||||
|
||||
|
||||
void transfer_region_array(uint32_t region_array_start,
|
||||
uint32_t opaque_list_pointer)
|
||||
{
|
||||
using namespace holly::core::region_array;
|
||||
/*
|
||||
Create a minimal region array with a single entry:
|
||||
- one tile at tile coordinate (0, 0) with one opaque list pointer
|
||||
*/
|
||||
|
||||
/*
|
||||
Holly reads the region array from "32-bit" texture memory address space,
|
||||
so the region array is correspondingly written from "32-bit" address space.
|
||||
*/
|
||||
volatile region_array_entry * region_array = (volatile region_array_entry *)&texture_memory32[region_array_start];
|
||||
|
||||
region_array[0].tile
|
||||
= tile::last_region
|
||||
| tile::y_position(0)
|
||||
| tile::x_position(0);
|
||||
|
||||
/*
|
||||
list pointers are offsets relative to the beginning of "32-bit" texture memory.
|
||||
|
||||
each list type uses different rasterization steps, "opaque" being the fastest and most efficient.
|
||||
*/
|
||||
region_array[0].list_pointer.opaque = list_pointer::object_list(opaque_list_pointer);
|
||||
region_array[0].list_pointer.opaque_modifier_volume = list_pointer::empty;
|
||||
region_array[0].list_pointer.translucent = list_pointer::empty;
|
||||
region_array[0].list_pointer.translucent_modifier_volume = list_pointer::empty;
|
||||
region_array[0].list_pointer.punch_through = list_pointer::empty;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint32_t framebuffer_start = 0x200000;
|
||||
uint32_t isp_tsp_parameter_start = 0x400000;
|
||||
uint32_t region_array_start = 0x500000;
|
||||
uint32_t object_list_start = 0x100000;
|
||||
|
||||
transfer_region_array(region_array_start,
|
||||
object_list_start);
|
||||
|
||||
using polygon = holly::core::parameter::isp_tsp_parameter<3>;
|
||||
|
||||
uint32_t triangle_offset = (sizeof (polygon)) * 0;
|
||||
uint32_t background_offset = (sizeof (polygon)) * 1;
|
||||
|
||||
transfer_object_list(object_list_start,
|
||||
triangle_offset);
|
||||
|
||||
transfer_triangle_polygon(isp_tsp_parameter_start + triangle_offset);
|
||||
|
||||
transfer_background_polygon(isp_tsp_parameter_start + background_offset);
|
||||
|
||||
{
|
||||
using namespace holly;
|
||||
using holly::holly;
|
||||
|
||||
// REGION_BASE is the (texture memory-relative) address of the region array.
|
||||
holly.REGION_BASE = region_array_start;
|
||||
|
||||
// PARAM_BASE is the (texture memory-relative) address of ISP/TSP parameters.
|
||||
// Anything that references an ISP/TSP parameter does so relative to this
|
||||
// address (and not relative to the beginning of texture memory).
|
||||
holly.PARAM_BASE = isp_tsp_parameter_start;
|
||||
|
||||
// Set the offset of the background ISP/TSP parameter, relative to PARAM_BASE
|
||||
// SKIP is related to the size of each vertex
|
||||
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 = 0.000001f;
|
||||
|
||||
// FB_W_SOF1 is the (texture memory-relative) address of the framebuffer that
|
||||
// will be written to when a tile is rendered/flushed.
|
||||
holly.FB_W_SOF1 = framebuffer_start;
|
||||
|
||||
// start the actual render--the rendering process begins by interpreting the
|
||||
// region array
|
||||
holly.STARTRENDER = 1;
|
||||
|
||||
// without waiting for rendering to actually complete, immediately display the
|
||||
// framebuffer.
|
||||
holly.FB_R_SOF1 = framebuffer_start;
|
||||
}
|
||||
}
|
51
dreamcast2/holly/core/object_list_bits.hpp
Normal file
51
dreamcast2/holly/core/object_list_bits.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly::core::object_list {
|
||||
namespace pointer_type {
|
||||
constexpr uint32_t triangle_strip = 0b000 << 29;
|
||||
constexpr uint32_t triangle_array = 0b100 << 29;
|
||||
constexpr uint32_t quad_array = 0b101 << 29;
|
||||
constexpr uint32_t object_pointer_block_link = 0b111 << 29;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 29;
|
||||
}
|
||||
|
||||
namespace triangle_strip {
|
||||
namespace mask {
|
||||
constexpr uint32_t t0 = 0b100000 << 25;
|
||||
constexpr uint32_t t1 = 0b010000 << 25;
|
||||
constexpr uint32_t t2 = 0b001000 << 25;
|
||||
constexpr uint32_t t3 = 0b000100 << 25;
|
||||
constexpr uint32_t t4 = 0b000010 << 25;
|
||||
constexpr uint32_t t5 = 0b000001 << 25;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3f << 25;
|
||||
}
|
||||
|
||||
constexpr uint32_t shadow = 1 << 24;
|
||||
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 21; }
|
||||
constexpr uint32_t start(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
namespace triangle_array {
|
||||
constexpr uint32_t number_of_triangles(uint32_t num) { return (num & 0xf) << 25; }
|
||||
constexpr uint32_t shadow = 1 << 24;
|
||||
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 21; }
|
||||
constexpr uint32_t start(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
namespace quad_array {
|
||||
constexpr uint32_t number_of_quads(uint32_t num) { return (num & 0xf) << 25; }
|
||||
constexpr uint32_t shadow = 1 << 24;
|
||||
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 21; }
|
||||
constexpr uint32_t start(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
namespace object_pointer_block_link {
|
||||
constexpr uint32_t end_of_list = 1 << 28;
|
||||
constexpr uint32_t next_pointer_block(uint32_t num) { return (num & 0xfffffc) << 0; }
|
||||
}
|
||||
|
||||
}
|
144
dreamcast2/holly/core/parameter.hpp
Normal file
144
dreamcast2/holly/core/parameter.hpp
Normal file
@ -0,0 +1,144 @@
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly::core::parameter {
|
||||
|
||||
enum struct volume_sel {
|
||||
one_volume,
|
||||
two_volumes
|
||||
};
|
||||
|
||||
using volume_sel::one_volume;
|
||||
using volume_sel::two_volumes;
|
||||
|
||||
enum struct offset_sel {
|
||||
offset,
|
||||
non_offset
|
||||
};
|
||||
|
||||
using offset_sel::offset;
|
||||
using offset_sel::non_offset;
|
||||
|
||||
enum struct texture_sel {
|
||||
texture,
|
||||
non_texture
|
||||
};
|
||||
|
||||
using texture_sel::texture;
|
||||
using texture_sel::non_texture;
|
||||
|
||||
template <texture_sel T, volume_sel V, offset_sel O>
|
||||
struct vertex;
|
||||
|
||||
template <>
|
||||
struct vertex<non_texture, one_volume, non_offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32_t base_color;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<non_texture, two_volumes, non_offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
struct {
|
||||
uint32_t base_color;
|
||||
} volume[2];
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<non_texture, one_volume, offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32_t base_color;
|
||||
uint32_t offset_color;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<non_texture, two_volumes, offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
struct {
|
||||
uint32_t base_color;
|
||||
uint32_t offset_color;
|
||||
} volume[2];
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<texture, one_volume, non_offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float u;
|
||||
float v;
|
||||
uint32_t base_color;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<texture, two_volumes, non_offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
struct {
|
||||
float u;
|
||||
float v;
|
||||
uint32_t base_color;
|
||||
} volume[2];
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<texture, one_volume, offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float u;
|
||||
float v;
|
||||
uint32_t base_color;
|
||||
uint32_t offset_color;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex<texture, two_volumes, offset> {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
struct {
|
||||
float u;
|
||||
float v;
|
||||
uint32_t base_color;
|
||||
uint32_t offset_color;
|
||||
} volume[2];
|
||||
};
|
||||
|
||||
template <int N, texture_sel T=non_texture, volume_sel V=one_volume, offset_sel O=non_offset>
|
||||
struct isp_tsp_parameter;
|
||||
|
||||
template <int N, texture_sel T, offset_sel O>
|
||||
struct isp_tsp_parameter<N, T, one_volume, O> {
|
||||
uint32_t isp_tsp_instruction_word;
|
||||
uint32_t tsp_instruction_word;
|
||||
uint32_t texture_control_word;
|
||||
struct vertex<T, one_volume, O> vertex[N];
|
||||
};
|
||||
|
||||
template <int N, texture_sel T, offset_sel O>
|
||||
struct isp_tsp_parameter<N, T, two_volumes, O> {
|
||||
uint32_t isp_tsp_instruction_word;
|
||||
struct {
|
||||
uint32_t tsp_instruction_word;
|
||||
uint32_t texture_control_word;
|
||||
} volume[2];
|
||||
struct vertex<T, two_volumes, O> vertex[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (isp_tsp_parameter<1>)) == 28);
|
||||
static_assert((sizeof (isp_tsp_parameter<1, texture>)) == 36);
|
||||
static_assert((sizeof (isp_tsp_parameter<1, texture, two_volumes>)) == 56);
|
||||
static_assert((sizeof (isp_tsp_parameter<1, texture, two_volumes, offset>)) == 64);
|
||||
|
||||
static_assert((sizeof (isp_tsp_parameter<1, non_texture, two_volumes>)) == 40);
|
||||
static_assert((sizeof (isp_tsp_parameter<1, non_texture, two_volumes, offset>)) == 48);
|
||||
}
|
195
dreamcast2/holly/core/parameter_bits.hpp
Normal file
195
dreamcast2/holly/core/parameter_bits.hpp
Normal file
@ -0,0 +1,195 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly::core::parameter {
|
||||
namespace isp_tsp_instruction_word {
|
||||
namespace depth_compare_mode {
|
||||
constexpr uint32_t never = 0 << 29;
|
||||
constexpr uint32_t less = 1 << 29;
|
||||
constexpr uint32_t equal = 2 << 29;
|
||||
constexpr uint32_t less_or_equal = 3 << 29;
|
||||
constexpr uint32_t greater = 4 << 29;
|
||||
constexpr uint32_t greater_or_equal = 5 << 29;
|
||||
constexpr uint32_t not_equal = 6 << 29;
|
||||
constexpr uint32_t always = 7 << 29;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 29;
|
||||
}
|
||||
|
||||
namespace volume_instruction {
|
||||
constexpr uint32_t normal_polygon = 0 << 29;
|
||||
constexpr uint32_t inside_last_polygon = 1 << 29;
|
||||
constexpr uint32_t outside_last_polygon = 2 << 29;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 29;
|
||||
}
|
||||
|
||||
namespace culling_mode {
|
||||
constexpr uint32_t no_culling = 0 << 27;
|
||||
constexpr uint32_t cull_if_small = 1 << 27;
|
||||
constexpr uint32_t cull_if_negative = 2 << 27;
|
||||
constexpr uint32_t cull_if_positive = 3 << 27;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3 << 27;
|
||||
}
|
||||
|
||||
constexpr uint32_t z_write_disable = 1 << 26;
|
||||
constexpr uint32_t texture = 1 << 25;
|
||||
constexpr uint32_t offset = 1 << 24;
|
||||
constexpr uint32_t gouraud_shading = 1 << 23;
|
||||
constexpr uint32_t _16bit_uv = 1 << 22;
|
||||
constexpr uint32_t cache_bypass = 1 << 21;
|
||||
constexpr uint32_t dcalc_ctrl = 1 << 20;
|
||||
}
|
||||
|
||||
namespace tsp_instruction_word {
|
||||
namespace src_alpha_instr {
|
||||
constexpr uint32_t zero = 0 << 29;
|
||||
constexpr uint32_t one = 1 << 29;
|
||||
constexpr uint32_t other_color = 2 << 29;
|
||||
constexpr uint32_t inverse_other_color = 3 << 29;
|
||||
constexpr uint32_t src_alpha = 4 << 29;
|
||||
constexpr uint32_t inverse_src_alpha = 5 << 29;
|
||||
constexpr uint32_t dst_alpha = 6 << 29;
|
||||
constexpr uint32_t inverse_dst_alpha = 7 << 29;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 29;
|
||||
}
|
||||
|
||||
namespace dst_alpha_instr {
|
||||
constexpr uint32_t zero = 0 << 26;
|
||||
constexpr uint32_t one = 1 << 26;
|
||||
constexpr uint32_t other_color = 2 << 26;
|
||||
constexpr uint32_t inverse_other_color = 3 << 26;
|
||||
constexpr uint32_t src_alpha = 4 << 26;
|
||||
constexpr uint32_t inverse_src_alpha = 5 << 26;
|
||||
constexpr uint32_t dst_alpha = 6 << 26;
|
||||
constexpr uint32_t inverse_dst_alpha = 7 << 26;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 26;
|
||||
}
|
||||
|
||||
namespace src_select {
|
||||
constexpr uint32_t primary_accumulation_buffer = 0 << 25;
|
||||
constexpr uint32_t secondary_accumulation_buffer = 1 << 25;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x1 << 25;
|
||||
}
|
||||
|
||||
namespace dst_select {
|
||||
constexpr uint32_t primary_accumulation_buffer = 0 << 24;
|
||||
constexpr uint32_t secondary_accumulation_buffer = 1 << 24;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x1 << 24;
|
||||
}
|
||||
|
||||
namespace fog_control {
|
||||
constexpr uint32_t look_up_table = 0b00 << 22;
|
||||
constexpr uint32_t per_vertex = 0b01 << 22;
|
||||
constexpr uint32_t no_fog = 0b10 << 22;
|
||||
constexpr uint32_t look_up_table_mode_2 = 0b11 << 22;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3 << 22;
|
||||
}
|
||||
|
||||
constexpr uint32_t color_clamp = 1 << 21;
|
||||
constexpr uint32_t use_alpha = 1 << 20;
|
||||
constexpr uint32_t ignore_texture_alpha = 1 << 19;
|
||||
|
||||
namespace flip_uv {
|
||||
constexpr uint32_t none = 0 << 17;
|
||||
constexpr uint32_t v = 1 << 17;
|
||||
constexpr uint32_t u = 2 << 17;
|
||||
constexpr uint32_t uv = 3 << 17;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3 << 17;
|
||||
}
|
||||
|
||||
namespace clamp_uv {
|
||||
constexpr uint32_t none = 0 << 15;
|
||||
constexpr uint32_t v = 1 << 15;
|
||||
constexpr uint32_t u = 2 << 15;
|
||||
constexpr uint32_t uv = 3 << 15;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3 << 15;
|
||||
}
|
||||
|
||||
namespace filter_mode {
|
||||
constexpr uint32_t point_sampled = 0b00 << 13;
|
||||
constexpr uint32_t bilinear_filter = 0b01 << 13;
|
||||
constexpr uint32_t trilinear_pass_a = 0b10 << 13;
|
||||
constexpr uint32_t trilinear_pass_b = 0b11 << 13;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3 << 13;
|
||||
}
|
||||
|
||||
constexpr uint32_t super_sample_texture = 1 << 12;
|
||||
constexpr uint32_t mip_map_d_adjust(uint32_t num) { return (num & 0xf) << 8; }
|
||||
|
||||
namespace texture_shading_instruction {
|
||||
constexpr uint32_t decal = 0 << 6;
|
||||
constexpr uint32_t modulate = 1 << 6;
|
||||
constexpr uint32_t decal_alpha = 2 << 6;
|
||||
constexpr uint32_t modulate_alpha = 3 << 6;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3 << 6;
|
||||
}
|
||||
|
||||
namespace texture_u_size {
|
||||
constexpr uint32_t _8 = 0 << 3;
|
||||
constexpr uint32_t _16 = 1 << 3;
|
||||
constexpr uint32_t _32 = 2 << 3;
|
||||
constexpr uint32_t _64 = 3 << 3;
|
||||
constexpr uint32_t _128 = 4 << 3;
|
||||
constexpr uint32_t _256 = 5 << 3;
|
||||
constexpr uint32_t _512 = 6 << 3;
|
||||
constexpr uint32_t _1024 = 7 << 3;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 3;
|
||||
}
|
||||
|
||||
namespace texture_v_size {
|
||||
constexpr uint32_t _8 = 0 << 0;
|
||||
constexpr uint32_t _16 = 1 << 0;
|
||||
constexpr uint32_t _32 = 2 << 0;
|
||||
constexpr uint32_t _64 = 3 << 0;
|
||||
constexpr uint32_t _128 = 4 << 0;
|
||||
constexpr uint32_t _256 = 5 << 0;
|
||||
constexpr uint32_t _512 = 6 << 0;
|
||||
constexpr uint32_t _1024 = 7 << 0;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace texture_control_word {
|
||||
constexpr uint32_t mip_mapped = 1 << 31;
|
||||
constexpr uint32_t vq_compressed = 1 << 30;
|
||||
|
||||
namespace pixel_format {
|
||||
constexpr uint32_t argb1555 = 0 << 27;
|
||||
constexpr uint32_t rgb565 = 1 << 27;
|
||||
constexpr uint32_t argb4444 = 2 << 27;
|
||||
constexpr uint32_t yuv422 = 3 << 27;
|
||||
constexpr uint32_t bump_map = 4 << 27;
|
||||
constexpr uint32_t palette_4bpp = 5 << 27;
|
||||
constexpr uint32_t palette_8bpp = 6 << 27;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 27;
|
||||
}
|
||||
|
||||
namespace scan_order {
|
||||
constexpr uint32_t twiddled = 0 << 26;
|
||||
constexpr uint32_t non_twiddled = 1 << 26;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x1 << 26;
|
||||
}
|
||||
|
||||
constexpr uint32_t palette_selector4(uint32_t num) { return (num & 0x3f) << 21; }
|
||||
constexpr uint32_t palette_selector8(uint32_t num) { return (num & 0x3) << 25; }
|
||||
constexpr uint32_t stride_select(uint32_t reg) { return (reg >> 25) & 0x1; }
|
||||
constexpr uint32_t texture_address(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
}
|
77
dreamcast2/holly/core/region_array.cpp
Normal file
77
dreamcast2/holly/core/region_array.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "holly/core/region_array.hpp"
|
||||
#include "holly/core/region_array_bits.hpp"
|
||||
|
||||
#include "sh7091/store_queue_transfer.hpp"
|
||||
|
||||
#include "systembus/systembus.hpp"
|
||||
|
||||
namespace holly::core::region_array {
|
||||
void transfer(const int tile_width,
|
||||
const int tile_height,
|
||||
const list_block_size& list_block_size,
|
||||
const uint32_t region_array_start,
|
||||
const uint32_t object_list_start)
|
||||
{
|
||||
const uint32_t ol_base = object_list_start;
|
||||
const uint32_t num_tiles = tile_width * tile_height;
|
||||
//region_array_entry region_array[num_tiles];
|
||||
volatile region_array_entry * region_array = (volatile region_array_entry * )&texture_memory32[region_array_start];
|
||||
|
||||
int ix = 0;
|
||||
|
||||
for (int y = 0; y < tile_height; y++) {
|
||||
for (int x = 0; x < tile_width; x++) {
|
||||
region_array[ix].tile = tile::y_position(y)
|
||||
| tile::x_position(x);
|
||||
|
||||
if (y == (tile_height - 1) && x == (tile_width - 1))
|
||||
region_array[ix].tile |= tile::last_region;
|
||||
|
||||
region_array[ix].list_pointer.opaque = (list_block_size.opaque == 0) ? list_pointer::empty :
|
||||
(ol_base + (list_block_size.opaque * ix)
|
||||
);
|
||||
|
||||
region_array[ix].list_pointer.opaque_modifier_volume = (list_block_size.opaque_modifier_volume == 0) ? list_pointer::empty :
|
||||
(ol_base + num_tiles * ( list_block_size.opaque
|
||||
)
|
||||
+ (list_block_size.opaque_modifier_volume * ix)
|
||||
);
|
||||
|
||||
region_array[ix].list_pointer.translucent = (list_block_size.translucent == 0) ? list_pointer::empty :
|
||||
(ol_base + num_tiles * ( list_block_size.opaque
|
||||
+ list_block_size.opaque_modifier_volume
|
||||
)
|
||||
+ (list_block_size.translucent * ix)
|
||||
);
|
||||
region_array[ix].list_pointer.translucent_modifier_volume = (list_block_size.translucent_modifier_volume == 0) ? list_pointer::empty :
|
||||
(ol_base + num_tiles * ( list_block_size.opaque
|
||||
+ list_block_size.opaque_modifier_volume
|
||||
+ list_block_size.translucent
|
||||
)
|
||||
+ (list_block_size.translucent_modifier_volume * ix)
|
||||
);
|
||||
region_array[ix].list_pointer.punch_through = (list_block_size.punch_through == 0) ? list_pointer::empty :
|
||||
(ol_base + num_tiles * ( list_block_size.opaque
|
||||
+ list_block_size.opaque_modifier_volume
|
||||
+ list_block_size.translucent
|
||||
+ list_block_size.translucent_modifier_volume
|
||||
)
|
||||
+ (list_block_size.punch_through * ix)
|
||||
);
|
||||
|
||||
ix += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
using systembus::systembus;
|
||||
|
||||
systembus.LMMODE0 = 1; // 32-bit address space
|
||||
systembus.LMMODE1 = 1; // 32-bit address space
|
||||
|
||||
void * dst = (void *)(&ta_fifo_texture_memory[region_array_start]);
|
||||
void * src = (void *)(region_array);
|
||||
sh7091::store_queue_transfer::copy(dst, src, (sizeof (region_array_entry)) * num_tiles);
|
||||
*/
|
||||
}
|
||||
}
|
39
dreamcast2/holly/core/region_array.hpp
Normal file
39
dreamcast2/holly/core/region_array.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly::core::region_array {
|
||||
struct region_array_entry {
|
||||
uint32_t tile;
|
||||
struct {
|
||||
uint32_t opaque;
|
||||
uint32_t opaque_modifier_volume;
|
||||
uint32_t translucent;
|
||||
uint32_t translucent_modifier_volume;
|
||||
uint32_t punch_through;
|
||||
} list_pointer;
|
||||
};
|
||||
|
||||
struct list_block_size {
|
||||
uint32_t opaque;
|
||||
uint32_t opaque_modifier_volume;
|
||||
uint32_t translucent;
|
||||
uint32_t translucent_modifier_volume;
|
||||
uint32_t punch_through;
|
||||
|
||||
uint32_t total() const
|
||||
{
|
||||
return opaque
|
||||
+ opaque_modifier_volume
|
||||
+ translucent
|
||||
+ translucent_modifier_volume
|
||||
+ punch_through;
|
||||
}
|
||||
};
|
||||
|
||||
void transfer(const int tile_width,
|
||||
const int tile_height,
|
||||
const list_block_size& list_block_size,
|
||||
const uint32_t region_array_start,
|
||||
const uint32_t object_list_start);
|
||||
}
|
20
dreamcast2/holly/core/region_array_bits.hpp
Normal file
20
dreamcast2/holly/core/region_array_bits.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly::core::region_array {
|
||||
namespace tile {
|
||||
constexpr uint32_t last_region = 1 << 31;
|
||||
constexpr uint32_t z_clear = 1 << 30;
|
||||
constexpr uint32_t pre_sort = 1 << 29;
|
||||
constexpr uint32_t flush_accumulate = 1 << 28;
|
||||
constexpr uint32_t y_position(uint32_t num) { return (num & 0x3f) << 8; }
|
||||
constexpr uint32_t x_position(uint32_t num) { return (num & 0x3f) << 2; }
|
||||
}
|
||||
|
||||
namespace list_pointer {
|
||||
constexpr uint32_t empty = 1 << 31;
|
||||
constexpr uint32_t object_list(uint32_t num) { return (num & 0xfffffc) << 0; }
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly {
|
||||
namespace object_list {
|
||||
namespace pointer_type {
|
||||
constexpr uint32_t triangle_strip = 0b000 << 29;
|
||||
constexpr uint32_t triangle_array = 0b100 << 29;
|
||||
constexpr uint32_t quad_array = 0b101 << 29;
|
||||
constexpr uint32_t object_pointer_block_link = 0b111 << 29;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x7 << 29;
|
||||
}
|
||||
|
||||
namespace triangle_strip {
|
||||
namespace mask {
|
||||
constexpr uint32_t t0 = 0b100000 << 25;
|
||||
constexpr uint32_t t1 = 0b010000 << 25;
|
||||
constexpr uint32_t t2 = 0b001000 << 25;
|
||||
constexpr uint32_t t3 = 0b000100 << 25;
|
||||
constexpr uint32_t t4 = 0b000010 << 25;
|
||||
constexpr uint32_t t5 = 0b000001 << 25;
|
||||
|
||||
constexpr uint32_t bit_mask = 0x3f << 25;
|
||||
}
|
||||
|
||||
constexpr uint32_t shadow = 1 << 24;
|
||||
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 21; }
|
||||
constexpr uint32_t start(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
namespace triangle_array {
|
||||
constexpr uint32_t number_of_triangles(uint32_t num) { return (num & 0xf) << 25; }
|
||||
constexpr uint32_t shadow = 1 << 24;
|
||||
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 21; }
|
||||
constexpr uint32_t start(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
namespace quad_array {
|
||||
constexpr uint32_t number_of_quads(uint32_t num) { return (num & 0xf) << 25; }
|
||||
constexpr uint32_t shadow = 1 << 24;
|
||||
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 21; }
|
||||
constexpr uint32_t start(uint32_t num) { return (num & 0x1fffff) << 0; }
|
||||
}
|
||||
|
||||
namespace object_pointer_block_link {
|
||||
constexpr uint32_t end_of_list = 1 << 28;
|
||||
constexpr uint32_t next_pointer_block(uint32_t num) { return (num & 0xfffffc) << 0; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
#include "holly/region_array.hpp"
|
||||
#include "holly/region_array_bits.hpp"
|
||||
|
||||
#incllude "sh7091/store_queue_transfer.hpp"
|
||||
|
||||
namespace holly::region_array {
|
||||
|
||||
void transfer_region_array(const int tile_width,
|
||||
const int tile_height,
|
||||
const list_block_size& list_block_size,
|
||||
const uint32_t region_array_start,
|
||||
const uint32_t object_list_start);
|
||||
{
|
||||
const uint32_t ol_base = object_list_start;
|
||||
const uint32_t num_tiles = width * height;
|
||||
region_array_entry region_array[num_tiles];
|
||||
|
||||
int ix = 0;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
region_array[ix].tile = tile::y_position(y)
|
||||
| tile::x_position(x);
|
||||
|
||||
if (y == (height - 1) && x == (width - 1))
|
||||
region_array[ix].tile |= tile::last_region;
|
||||
|
||||
region_array[ix].list_pointer.opaque = (opb_size.opaque == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
|
||||
(ol_base + (opb_size.opaque * ix)
|
||||
);
|
||||
|
||||
region_array[ix].list_pointer.opaque_modifier_volume = (opb_size.opaque_modifier == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
|
||||
(ol_base + num_tiles * ( opb_size.opaque
|
||||
)
|
||||
+ (opb_size.opaque_modifier_volume * ix)
|
||||
);
|
||||
|
||||
region_array[ix].list_pointer.translucent = (opb_size.translucent == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
|
||||
(ol_base + num_tiles * ( opb_size.opaque
|
||||
+ opb_size.opaque_modifier_volume
|
||||
)
|
||||
+ (opb_size.translucent * ix)
|
||||
);
|
||||
region_array[ix].list_pointer.translucent_modifier_volume = (opb_size.translucent_modifier == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
|
||||
(ol_base + num_tiles * ( opb_size.opaque
|
||||
+ opb_size.opaque_modifier_volume
|
||||
+ opb_size.translucent
|
||||
)
|
||||
+ (opb_size.translucent_modifier_volume * ix)
|
||||
);
|
||||
region_array[ix].list_pointer.punch_through = (opb_size.punch_through == 0) ? REGION_ARRAY__LIST_POINTER__EMPTY :
|
||||
(ol_base + num_tiles * ( opb_size.opaque
|
||||
+ opb_size.opaque_modifier_volume
|
||||
+ opb_size.translucent
|
||||
+ opb_size.translucent_modifier_volume
|
||||
)
|
||||
+ (opb_size.punch_through * ix)
|
||||
);
|
||||
|
||||
ix += 1;
|
||||
}
|
||||
}
|
||||
|
||||
system.LMMODE0 = 1; // 32-bit address space
|
||||
system.LMMODE1 = 1; // 32-bit address space
|
||||
|
||||
void * dst = (void *)(&ta_fifo_texture_memory[region_array_start]);
|
||||
void * src = (void *)(region_array);
|
||||
sh7091::store_queue_transfer::copy(dst, src, (sizeof (region_array_entry)) * num_tiles);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly {
|
||||
namespace region_array {
|
||||
struct region_array_entry {
|
||||
uint32_t tile;
|
||||
struct {
|
||||
uint32_t opaque;
|
||||
uint32_t opaque_modifier_volume;
|
||||
uint32_t translucent;
|
||||
uint32_t translucent_modifier_volume;
|
||||
uint32_t punch_through;
|
||||
} list_pointer;
|
||||
};
|
||||
|
||||
struct list_block_size {
|
||||
uint32_t opaque;
|
||||
uint32_t opaque_modifier_volume;
|
||||
uint32_t translucent;
|
||||
uint32_t translucent_modifier_volume;
|
||||
uint32_t punch_through;
|
||||
|
||||
uint32_t total() const
|
||||
{
|
||||
return opaque
|
||||
+ opaque_modifier_volume
|
||||
+ translucent
|
||||
+ translucent_modifier_volume
|
||||
+ punch_through;
|
||||
}
|
||||
};
|
||||
|
||||
void transfer_region_array(const int tile_width,
|
||||
const int tile_height,
|
||||
const list_block_size& list_block_size,
|
||||
const uint32_t region_array_start,
|
||||
const uint32_t object_list_start);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace holly {
|
||||
namespace region_array {
|
||||
namespace tile {
|
||||
constexpr uint32_t last_region = 1 << 31;
|
||||
constexpr uint32_t z_clear = 1 << 30;
|
||||
constexpr uint32_t pre_sort = 1 << 29;
|
||||
constexpr uint32_t flush_accumulate = 1 << 28;
|
||||
constexpr uint32_t y_position(uint32_t num) { return (num & 0x3f) << 8; }
|
||||
constexpr uint32_t x_position(uint32_t num) { return (num & 0x3f) << 2; }
|
||||
}
|
||||
|
||||
namespace list_pointer {
|
||||
constexpr uint32_t empty = 1 << 31;
|
||||
constexpr uint32_t object_list(uint32_t num) { return (num & 0xfffffc) << 0; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
#include <cstdint>
|
||||
|
||||
extern volatile uint8_t system_boot_rom[0x200000] __asm("system_boot_rom");
|
||||
extern volatile uint8_t aica_wave_memory[0x200000] __asm("aica_wave_memory");
|
||||
extern volatile uint8_t texture_memory64[0x800000] __asm("texture_memory64");
|
||||
extern volatile uint8_t texture_memory32[0x800000] __asm("texture_memory32");
|
||||
extern volatile uint8_t system_memory[0x1000000] __asm("system_memory");
|
||||
extern volatile uint8_t ta_fifo_polygon_converter[0x800000] __asm("ta_fifo_polygon_converter");
|
||||
extern volatile uint8_t ta_fifo_yuv_converter[0x800000] __asm("ta_fifo_yuv_converter");
|
||||
extern volatile uint8_t ta_fifo_texture_memory[0x800000] __asm("ta_fifo_texture_memory");
|
||||
extern volatile uint8_t ta_fifo_polygon_converter_mirror[0x800000] __asm("ta_fifo_polygon_converter_mirror");
|
||||
extern volatile uint8_t ta_fifo_yuv_converter_mirror[0x800000] __asm("ta_fifo_yuv_converter_mirror");
|
||||
extern volatile uint8_t ta_fifo_texture_memory_mirror[0x800000] __asm("ta_fifo_texture_memory_mirror");
|
||||
extern volatile uint8_t store_queue[0x4000000] __asm("store_queue");
|
||||
extern volatile uint8_t sh7091_oc_d[0x1000] __asm("sh7091_oc_d");
|
||||
extern volatile uint8_t system_boot_rom[0x200000] __asm("system_boot_rom") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t aica_wave_memory[0x200000] __asm("aica_wave_memory") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t texture_memory64[0x800000] __asm("texture_memory64") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t texture_memory32[0x800000] __asm("texture_memory32") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t system_memory[0x1000000] __asm("system_memory") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t ta_fifo_polygon_converter[0x800000] __asm("ta_fifo_polygon_converter") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t ta_fifo_yuv_converter[0x800000] __asm("ta_fifo_yuv_converter") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t ta_fifo_texture_memory[0x800000] __asm("ta_fifo_texture_memory") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t ta_fifo_polygon_converter_mirror[0x800000] __asm("ta_fifo_polygon_converter_mirror") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t ta_fifo_yuv_converter_mirror[0x800000] __asm("ta_fifo_yuv_converter_mirror") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t ta_fifo_texture_memory_mirror[0x800000] __asm("ta_fifo_texture_memory_mirror") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t store_queue[0x4000000] __asm("store_queue") __attribute__((aligned(32)));
|
||||
extern volatile uint8_t sh7091_oc_d[0x1000] __asm("sh7091_oc_d") __attribute__((aligned(32)));
|
||||
|
@ -10,11 +10,14 @@ holly/holly.hpp: regs/holly/holly.csv regs/render_block_regs.py
|
||||
holly/holly_bits.hpp: regs/holly/holly_bits.csv regs/render_bits.py
|
||||
python regs/render_bits.py $< holly > $@
|
||||
|
||||
holly/region_array_bits.hpp: regs/holly/region_array_bits.csv regs/render_bits.py
|
||||
python regs/render_bits.py $< holly region_array > $@
|
||||
holly/core/region_array_bits.hpp: regs/holly/core/region_array_bits.csv regs/render_bits.py
|
||||
python regs/render_bits.py $< holly::core::region_array > $@
|
||||
|
||||
holly/object_list_bits.hpp:regs/holly/object_list_bits.csv regs/render_bits.py
|
||||
python regs/render_bits.py $< holly object_list > $@
|
||||
holly/core/object_list_bits.hpp:regs/holly/core/object_list_bits.csv regs/render_bits.py
|
||||
python regs/render_bits.py $< holly::core::object_list > $@
|
||||
|
||||
holly/core/parameter_bits.hpp:regs/holly/core/parameter_bits.csv regs/render_bits.py
|
||||
python regs/render_bits.py $< holly::core::parameter > $@
|
||||
|
||||
# SH7091
|
||||
|
||||
|
BIN
dreamcast2/regs/holly/core/parameter_bits.ods
Normal file
BIN
dreamcast2/regs/holly/core/parameter_bits.ods
Normal file
Binary file not shown.
@ -47,8 +47,11 @@ def aggregate_enums(aggregated_rows):
|
||||
|
||||
def assert_unique_ordered(bits, row):
|
||||
nonlocal all_bits
|
||||
assert all(bit not in all_bits for bit in bits), (bits, row)
|
||||
assert max(all_bits, default=32) > max(bits), (all_bits, bits)
|
||||
#assert all(bit not in all_bits for bit in bits), (bits, row)
|
||||
if not all(bit not in all_bits for bit in bits):
|
||||
print("bit overlap", row, file=sys.stderr)
|
||||
else:
|
||||
assert max(all_bits, default=32) > max(bits), (all_bits, bits)
|
||||
all_bits |= bits
|
||||
|
||||
for row in aggregated_rows:
|
||||
|
@ -51,9 +51,3 @@ void runtime_init()
|
||||
((init_t *)(*ctors_start++))();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void foo()
|
||||
{
|
||||
runtime_init();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user