add moonmountains

This commit is contained in:
Zack Buhman 2025-07-04 21:02:43 -05:00
parent aafab6c31c
commit de6c8f31fe
15 changed files with 198 additions and 47 deletions

BIN
cover/moonmountains.data Normal file

Binary file not shown.

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_cover_moonmountains_data_start __asm("_binary_cover_moonmountains_data_start");
extern uint32_t _binary_cover_moonmountains_data_end __asm("_binary_cover_moonmountains_data_end");
extern uint32_t _binary_cover_moonmountains_data_size __asm("_binary_cover_moonmountains_data_size");
#ifdef __cplusplus
}
#endif

BIN
cover/moonmountains.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -27,7 +27,9 @@
#include "cursor.hpp"
#include "ta_parameter.hpp"
#include "dve.hpp"
#include "sh7091/sh7091.hpp"
#include "aica/aica.hpp"
static volatile int ta_in_use = 0;
static volatile int core_in_use = 0;
@ -35,9 +37,6 @@ volatile int next_frame = 0;
static volatile int framebuffer_ix = 0;
static volatile int next_frame_ix = 0;
static void * pt_buf = nullptr;
static int pt_offset = 0;
static void * op_buf = nullptr;
static int op_offset = 0;
@ -48,6 +47,7 @@ void graphics_interrupt(uint32_t istnrm)
next_frame = 1;
holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[next_frame_ix].start;
holly.FB_R_SOF2 = texture_memory_alloc.framebuffer[next_frame_ix].start;
}
if (istnrm & istnrm::end_of_render_tsp) {
@ -123,7 +123,41 @@ static inline void zeroize_ta_fifo_texture_memory_32byte(void * dst, int length)
}
}
void graphics_init()
void set_mode_by_cable_type(uint32_t cable_type, bool emulator)
{
if (emulator)
goto vga;
switch (cable_type) {
case pdtra::cable_type::vga:
vga:
printf("vga\n");
spg_set_mode_640x480();
framebuffer.px_width = 640;
framebuffer.px_height = 480;
aica_sound.common.VREG(vreg::output_mode::vga);
break;
case pdtra::cable_type::rgb:
printf("rgb\n");
video_output::set_mode(video_output::ntsc_ni);
framebuffer.px_width = 320;
framebuffer.px_height = 240;
aica_sound.common.VREG(vreg::output_mode::rgb);
break;
case pdtra::cable_type::cvbs_yc:
printf("cvbs\n");
video_output::set_mode(video_output::ntsc_ni);
framebuffer.px_width = 320;
framebuffer.px_height = 240;
aica_sound.common.VREG(vreg::output_mode::cvbs_yc);
break;
default:
assert(false);
break;
}
}
void graphics_init(bool emulator)
{
holly.SOFTRESET = softreset::pipeline_soft_reset
| softreset::ta_soft_reset;
@ -140,7 +174,10 @@ void graphics_init()
scaler_init();
core_init();
core_param_init();
spg_set_mode_640x480();
uint32_t cable_type = video_output::get_cable_type();
set_mode_by_cable_type(cable_type, emulator);
framebuffer_init();
background_parameter2(texture_memory_alloc.background[1].start,

View File

@ -10,6 +10,6 @@ constexpr int ta_cont_count = 1;
extern volatile int next_frame;
void graphics_interrupt(uint32_t istnrm);
void graphics_init();
void graphics_init(bool emulator);
void graphics_event(ta_multiwriter& multi);
void graphics_scene_init(const opb_size * opb_size);

View File

@ -6,10 +6,14 @@
#include "sound.hpp"
#include "scene/scene.hpp"
#include "scene/logo/sound.hpp"
#include "scene/emulator/scene.hpp"
#include "scene/emulator/sound.hpp"
#include "cursor.hpp"
#include "input.hpp"
#include "dve.hpp"
#include "holly/video_output.hpp"
#include "detect_emulator.hpp"
void vbr100()
@ -106,18 +110,29 @@ void main()
{
serial::init(0);
sound::init();
//bool emulator = detect_emulator();
//printf("emulator %d\n", emulator);
bool emulator = detect_emulator();
printf("emulator %d\n", emulator);
printf("graphics_init\n");
graphics_init();
//scene::scene_init(scene::id::logo);
printf("scene_init\n");
scene::scene_init(scene::id::tracker);
printf("state_init\n");
graphics_init(emulator);
//scene::scene_init(scene::id::tracker);
//printf("state_init\n");
for (int i = 0; i < 10000000; i++) {
asm volatile ("nop");
}
sound::init();
input::state_init();
cursor::init();
if (emulator) {
scene::emulator::current_message_id = scene::emulator::counterfeit;
//scene::scene_init(scene::id::emulator);
scene::scene_init(scene::id::tracker);
} else {
scene::scene_init(scene::id::logo);
}
//test_pattern();
interrupt_init();

View File

@ -46,7 +46,7 @@ namespace playlist {
.artist = "Cai",
.title = "SummerDreamsDemov4",
.start = (int)&_binary_xm_SummerDreamsDemoTrackv4_xm_start,
.cover_ix = scene::tracker::cover::tree,
.cover_ix = scene::tracker::cover::moonmountains,
},
};

View File

@ -33,32 +33,81 @@ namespace scene::emulator {
static float intensity = 0.0;
struct message {
const char * title;
const int title_length;
const char ** paragraph;
const int paragraph_length;
};
const char * counterfeit_title = "Counterfeit Dreamcast Detected";
const int counterfeit_title_length = 30;
const char * counterfeit_paragraph[] = {
"Your counterfeit Dreamcast failed a CORE",
"rasterization test.",
"",
"Dreamcast emulator behavior is highly divergent",
"from a genuine Sega Dreamcast. Some emulator",
"authors deliberately choose to forgo accuracy,",
"and instead are developing a distinct and",
"unrelated fantasy-platform.",
"",
"This program only supports genuine Sega",
"Dreamcasts. Other fantasy-platforms and emulators",
"are not supported."
};
const int counterfeit_paragraph_length = (sizeof (counterfeit_paragraph)) / (sizeof (counterfeit_paragraph[0]));
const char * cvbs_title = "CVBS unsupported";
const int cvbs_title_length = 16;
const char * cvbs_paragraph[] = {
"Drawing the UI at",
"320x240 would require a",
"complete redesign."
"",
"Please switch to VGA."
};
const int cvbs_paragraph_length = (sizeof (cvbs_paragraph)) / (sizeof (cvbs_paragraph[0]));
const char * scart_title = "SCART unsupported";
const int scart_title_length = 17;
const message messages[] = {
[counterfeit] = {
counterfeit_title,
counterfeit_title_length,
counterfeit_paragraph,
counterfeit_paragraph_length,
},
[cvbs] = {
cvbs_title,
cvbs_title_length,
cvbs_paragraph,
cvbs_paragraph_length,
},
[scart] = {
scart_title,
scart_title_length,
cvbs_paragraph,
cvbs_paragraph_length,
},
};
int current_message_id = 0;
void draw_title(ta_parameter_writer& writer, int color)
{
const font::font& face = font::fonts[font::font::ter_u32n];
draw_glyph_global(writer, face);
int h_center = framebuffer.px_width / 2 - (30 * face.width) / 2;
draw_string(writer, face, "Counterfeit Dreamcast Detected", h_center, 35, 0.1, color << 16);
int length = messages[current_message_id].title_length;
int h_center = framebuffer.px_width / 2 - (length * face.width) / 2;
const char * title = messages[current_message_id].title;
draw_string(writer, face, title, h_center, 35, 0.1, color << 16);
}
void draw_paragraph(ta_parameter_writer& writer, int color)
{
const char * paragraph[] = {
"Your counterfeit Dreamcast failed a CORE",
"rasterization test.",
"",
"Dreamcast emulator behavior is highly divergent",
"from a genuine Sega Dreamcast. Some emulator",
"authors deliberately choose to forgo accuracy,",
"and instead are developing a distinct and",
"unrelated fantasy-platform.",
"",
"This program only supports genuine Sega",
"Dreamcasts. Other fantasy-platforms and emulators",
"are not supported."
};
const int paragraph_length = (sizeof (paragraph)) / (sizeof (paragraph[0]));
const font::font& face = font::fonts[font::font::ter_u24n];
draw_glyph_global(writer, face);
@ -68,7 +117,9 @@ namespace scene::emulator {
int base_color = (color << 16) | (color << 8) | (color << 0);
for (int i = 0; i < paragraph_length; i++) {
int length = messages[current_message_id].paragraph_length;
const char ** paragraph = messages[current_message_id].paragraph;
for (int i = 0; i < length; i++) {
const char * s = paragraph[i];
draw_string(writer, face, s, x, y, 0.1, base_color);
y += face.height;

View File

@ -5,6 +5,14 @@
namespace scene::emulator {
enum message_id {
counterfeit,
cvbs,
scart,
};
extern int current_message_id;
extern const struct scene::scene scene;
void transfer(ta_multiwriter& multi);

View File

@ -169,21 +169,21 @@ namespace scene::logo {
.rx = 0,
.ry = pi,
.s = 0.01,
.duration = 1.0 / (3.670 * 60),
.duration = 1.0 / (3.670),
},
{
.i = 1,
.rx = 0,
.ry = pi,
.s = 0.1,
.duration = 1.0 / (10.988 * 60),
.duration = 1.0 / (10.988),
},
{
.i = 1,
.rx = pi / 4,
.ry = -(pi - pi / 4),
.s = 0.7,
.duration = 1.0 / (10 * 60),
.duration = 1.0 / (10),
},
};
@ -199,9 +199,9 @@ namespace scene::logo {
return f;
}
static inline keyframe interpolate(const keyframe& a, const keyframe& b, const float dt)
static inline keyframe interpolate(const keyframe& a, const keyframe& b, const float dt, const float tick_div)
{
float ratio = clamp(dt * a.duration);
float ratio = clamp(dt * a.duration * tick_div);
float di = b.i - a.i;
float drx = b.rx - a.rx;
@ -213,7 +213,7 @@ namespace scene::logo {
.rx = a.rx + drx * ratio,
.ry = a.ry + dry * ratio,
.s = a.s + ds * ratio,
.duration = a.duration,
.duration = 0,
};
}
@ -224,15 +224,18 @@ namespace scene::logo {
static int keyframe_ix = 0;
const float tick_div = framebuffer.px_height == 480 ? (1.0 / 60.0) : (1.0 / 120.0);
const float tick_mul = framebuffer.px_height == 480 ? 60 : 120;
float dt = tick - last_tick;
if (dt * keyframes[keyframe_ix].duration >= 1) {
if (dt * keyframes[keyframe_ix].duration * tick_div >= 1) {
if (keyframe_ix < (keyframes_length - 2)) {
last_tick = tick;
dt = 0;
keyframe_ix += 1;
}
}
keyframe k = interpolate(keyframes[keyframe_ix], keyframes[keyframe_ix + 1], dt);
keyframe k = interpolate(keyframes[keyframe_ix], keyframes[keyframe_ix + 1], dt, tick_div);
mat4x4 trans
= translate(t)
@ -245,11 +248,11 @@ namespace scene::logo {
* rotate_y(k.ry)
* scale((vec3){-1, -1, 1});
bool _32_wf = tick < (10.988 * 60);
bool bit_wf = tick < (11.908 * 60);
bool jam_wf = tick < (12.825 * 60);
bool _32_wf = tick < (10.988 * tick_mul);
bool bit_wf = tick < (11.908 * tick_mul);
bool jam_wf = tick < (12.825 * tick_mul);
bool diffuse = tick >= (14.608 * 60);
bool diffuse = tick >= (14.608 * tick_mul);
render_mesh(multi.op, mesh_thirty_two, trans, k.i, _32_wf, diffuse);
if (keyframe_ix > 0) {
@ -271,7 +274,9 @@ namespace scene::logo {
int done()
{
if (tick >= (20.000 * 60)) {
float tick_mul = framebuffer.px_height == 480 ? 60 : 120;
if (tick >= (20.000 * tick_mul)) {
int scene_id = ::scene::id::tracker;
printf("scene transition to tracker %d\n", scene_id);
return scene_id;

View File

@ -105,6 +105,17 @@ namespace scene::tracker::cover {
.scale = 6,
.color = {0x0d, 0x1a, 0x0e},
},
[moonmountains] = {
.texture_offset = texture::offset::moonmountains,
.texture_size = tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(128),
.texture_width = 1.0f / 128.0f,
.texture_height = 1.0f / 128.0f,
.width = 72,
.height = 72,
.scale = 6,
.color = {0x00, 0x06, 0x1a},
},
};
constexpr inline vec3 transform_position_fs(const cover& cover,

View File

@ -13,6 +13,7 @@ namespace scene::tracker::cover {
mossycottage,
clocks,
tree,
moonmountains,
};
void draw(ta_multiwriter& multi, float x, float y, bool zoom);

View File

@ -22,6 +22,7 @@
#include "cover/silvertrees.data.h"
#include "cover/thebeach.data.h"
#include "cover/tree.data.h"
#include "cover/moonmountains.data.h"
#include "printf/printf.h"
@ -88,6 +89,11 @@ namespace texture {
.size = reinterpret_cast<int>(&_binary_cover_tree_data_size),
.offset = offset::tree,
},
{
.start = reinterpret_cast<void *>(&_binary_cover_moonmountains_data_start),
.size = reinterpret_cast<int>(&_binary_cover_moonmountains_data_size),
.offset = offset::moonmountains,
},
};
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));

View File

@ -20,6 +20,7 @@ namespace texture {
constexpr int silvertrees = redtree + 32768;
constexpr int thebeach = silvertrees + 32768;
constexpr int tree = thebeach + 32768;
constexpr int moonmountains= tree + 32768;
};
extern struct texture textures[];

View File

@ -18,7 +18,8 @@ TEXTURE_OBJ = \
cover/redtree.data.o \
cover/silvertrees.data.o \
cover/thebeach.data.o \
cover/tree.data.o
cover/tree.data.o \
cover/moonmountains.data.o
PCM_OBJ = \
pcm/start3.adpcm.o \