diff --git a/cover/moonmountains.data b/cover/moonmountains.data new file mode 100644 index 0000000..404e429 Binary files /dev/null and b/cover/moonmountains.data differ diff --git a/cover/moonmountains.data.h b/cover/moonmountains.data.h new file mode 100644 index 0000000..3f930df --- /dev/null +++ b/cover/moonmountains.data.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#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 diff --git a/cover/moonmountains.png b/cover/moonmountains.png new file mode 100644 index 0000000..151378e Binary files /dev/null and b/cover/moonmountains.png differ diff --git a/src/graphics.cpp b/src/graphics.cpp index 37846db..aa7399b 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -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, diff --git a/src/graphics.hpp b/src/graphics.hpp index 781acf1..8c90867 100644 --- a/src/graphics.hpp +++ b/src/graphics.hpp @@ -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); diff --git a/src/main.cpp b/src/main.cpp index 5ef4f2d..18387d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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(); diff --git a/src/playlist.cpp b/src/playlist.cpp index db57abf..7836082 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -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, }, }; diff --git a/src/scene/emulator/scene.cpp b/src/scene/emulator/scene.cpp index 4673e91..c1f9217 100644 --- a/src/scene/emulator/scene.cpp +++ b/src/scene/emulator/scene.cpp @@ -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; diff --git a/src/scene/emulator/scene.hpp b/src/scene/emulator/scene.hpp index 93ad91a..8817476 100644 --- a/src/scene/emulator/scene.hpp +++ b/src/scene/emulator/scene.hpp @@ -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); diff --git a/src/scene/logo/scene.cpp b/src/scene/logo/scene.cpp index fc3c10c..c6dc234 100644 --- a/src/scene/logo/scene.cpp +++ b/src/scene/logo/scene.cpp @@ -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; diff --git a/src/scene/tracker/cover.cpp b/src/scene/tracker/cover.cpp index aecba52..9fc9a05 100644 --- a/src/scene/tracker/cover.cpp +++ b/src/scene/tracker/cover.cpp @@ -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, diff --git a/src/scene/tracker/cover.hpp b/src/scene/tracker/cover.hpp index 0274f85..13aac6c 100644 --- a/src/scene/tracker/cover.hpp +++ b/src/scene/tracker/cover.hpp @@ -13,6 +13,7 @@ namespace scene::tracker::cover { mossycottage, clocks, tree, + moonmountains, }; void draw(ta_multiwriter& multi, float x, float y, bool zoom); diff --git a/src/texture.cpp b/src/texture.cpp index 90f690a..3ee7122 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -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(&_binary_cover_tree_data_size), .offset = offset::tree, }, + { + .start = reinterpret_cast(&_binary_cover_moonmountains_data_start), + .size = reinterpret_cast(&_binary_cover_moonmountains_data_size), + .offset = offset::moonmountains, + }, }; const int textures_length = (sizeof (textures)) / (sizeof (textures[0])); diff --git a/src/texture.hpp b/src/texture.hpp index 2958650..b44d46e 100644 --- a/src/texture.hpp +++ b/src/texture.hpp @@ -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[]; diff --git a/xm_player.mk b/xm_player.mk index c026bd5..ab3eb55 100644 --- a/xm_player.mk +++ b/xm_player.mk @@ -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 \