@@ -31,6 +31,11 @@ SOFTWARE.
31
31
32
32
#include " EASTL/internal/function.h"
33
33
#include " common/syscalls/syscalls.h"
34
+ #include " psyqo/fragment-concept.hh"
35
+ extern " C" {
36
+ #include " modplayer/modplayer.h"
37
+ }
38
+ #include " psyqo/advancedpad.hh"
34
39
#include " psyqo/application.hh"
35
40
#include " psyqo/fixed-point.hh"
36
41
#include " psyqo/font.hh"
@@ -47,7 +52,6 @@ SOFTWARE.
47
52
#include " psyqo/primitives/rectangles.hh"
48
53
#include " psyqo/primitives/sprites.hh"
49
54
#include " psyqo/scene.hh"
50
- #include " psyqo/simplepad.hh"
51
55
#include " psyqo/soft-math.hh"
52
56
#include " psyqo/trigonometry.hh"
53
57
#include " psyqo/vector.hh"
@@ -56,6 +60,8 @@ using namespace psyqo::fixed_point_literals;
56
60
using namespace psyqo ::timer_literals;
57
61
using namespace psyqo ::trig_literals;
58
62
63
+ extern const struct MODFileFormat _binary_LittleCottonPillow_v260_hit_start;
64
+
59
65
namespace {
60
66
61
67
// We're going to use the scratchpad to store the color lookup tables.
@@ -66,11 +72,11 @@ constexpr psyqo::Color c_backgroundColor{{.r = 0x34, .g = 0x58, .b = 0x6c}};
66
72
// This is for debugging purposes only.
67
73
template <typename T>
68
74
void printVec (const T& v) {
69
- ramsyscall_printf (" x: " );
75
+ syscall_puts (" x: " );
70
76
v.x .print ([](char c) { syscall_putchar (c); });
71
- ramsyscall_printf (" , y: " );
77
+ syscall_puts (" , y: " );
72
78
v.y .print ([](char c) { syscall_putchar (c); });
73
- ramsyscall_printf (" , z: " );
79
+ syscall_puts (" , z: " );
74
80
v.z .print ([](char c) { syscall_putchar (c); });
75
81
syscall_putchar (' \n ' );
76
82
}
@@ -82,7 +88,8 @@ class TorusDemo final : public psyqo::Application {
82
88
public:
83
89
psyqo::Font<2 > m_font;
84
90
psyqo::Trig<> m_trig;
85
- psyqo::SimplePad m_input;
91
+ psyqo::AdvancedPad m_input;
92
+ unsigned m_musicTimer;
86
93
};
87
94
88
95
TorusDemo torusDemo;
@@ -146,10 +153,10 @@ struct TorusTemplate {
146
153
psyqo::GTE::write<psyqo::GTE::Register::IR3, psyqo::GTE::Safe>(reinterpret_cast <uint32_t *>(&t.z .value ));
147
154
psyqo::GTE::Kernels::cp ();
148
155
// The result is stored in the LV register, so first we simply read it.
149
- psyqo::GTE::read<psyqo::GTE::PseudoRegister::LV>(& cp);
156
+ psyqo::GTE::read<psyqo::GTE::PseudoRegister::LV>(cp);
150
157
// Then we square LV to get the square of the length of the normal.
151
158
psyqo::GTE::Kernels::sqr ();
152
- psyqo::GTE::read<psyqo::GTE::PseudoRegister::LV>(& sq);
159
+ psyqo::GTE::read<psyqo::GTE::PseudoRegister::LV>(sq);
153
160
// We still need to add the three components of the square.
154
161
auto square = sq.x + sq.y + sq.z ;
155
162
// Finally, we compute the square root of the square of the length of the normal.
@@ -323,12 +330,12 @@ class TorusScene final : public psyqo::Scene {
323
330
// The generator finished, our scene starts. We set the proper context.
324
331
m_lastFrameCounter = gpu ().getFrameCount ();
325
332
m_sequenceStartTime = gpu ().now ();
326
- torusDemo.m_input .setOnEvent ([this ](const psyqo::SimplePad ::Event& event) {
327
- if (event.type != psyqo::SimplePad ::Event::ButtonReleased) return ;
328
- if (event.button == psyqo::SimplePad ::Button::Triangle) {
333
+ torusDemo.m_input .setOnEvent ([this ](const psyqo::AdvancedPad ::Event& event) {
334
+ if (event.type != psyqo::AdvancedPad ::Event::ButtonReleased) return ;
335
+ if (event.button == psyqo::AdvancedPad ::Button::Triangle) {
329
336
m_lutIndex = (m_lutIndex + 1 ) % 3 ;
330
337
}
331
- if (event.button == psyqo::SimplePad ::Button::Cross) {
338
+ if (event.button == psyqo::AdvancedPad ::Button::Cross) {
332
339
m_lutInverted = !m_lutInverted;
333
340
}
334
341
const psyqo::Color* lut = nullptr ;
@@ -448,12 +455,12 @@ class TorusScene final : public psyqo::Scene {
448
455
constexpr psyqo::Angle rippleIncrement = 1 .0_pi / Count;
449
456
psyqo::Angle ripple = rippleIncrement * torusIndex;
450
457
auto & torus = m_tori[torusIndex];
451
- ramsyscall_printf (" Generating torus %u\n " , torusIndex);
458
+ // ramsyscall_printf("Generating torus %u\n", torusIndex);
452
459
453
460
auto amplitude = torusDemo.m_trig .sin (ripple) * 0 .6_fp;
454
461
unsigned index = 0 ;
455
462
for (psyqo::Angle outside = 0 ; outside < 2 .0_pi; outside += incrementOutside) {
456
- auto rot = psyqo::SoftMath::generateRotationMatrix33 (outside, psyqo::SoftMath::Axis::Z, & torusDemo.m_trig );
463
+ auto rot = psyqo::SoftMath::generateRotationMatrix33 (outside, psyqo::SoftMath::Axis::Z, torusDemo.m_trig );
457
464
psyqo::GTE::writeUnsafe<psyqo::GTE::PseudoRegister::Rotation>(rot);
458
465
psyqo::FixedPoint<> rippleAmplitude = amplitude * torusDemo.m_trig .sin (outside * 5 + ripple * 8 ) + 1 .5_fp;
459
466
for (psyqo::Angle inside = 0 ; inside < 2 .0_pi; inside += incrementInside) {
@@ -548,12 +555,20 @@ TorusScene::SequenceItem TorusScene::sequence[] = {
548
555
{3 .0_s, " " },
549
556
{2 .0_s, " Yep." },
550
557
{2 .0_s, " Yep. That's projected shadows." },
551
- {2 .0_s, " " },
558
+ {5 .0_s, " " },
552
559
{3 .0_s, " By the way..." },
553
560
{2 .0_s, " ... it's interactive..." },
554
561
{2 .0_s, " " },
555
562
{2 .0_s, " Try pressing buttons." },
556
563
{4 .0_s, " " },
564
+ {0 .5_s, " Credits." },
565
+ {0 .5_s, " Credits.." },
566
+ {4 .0_s, " Credits..." },
567
+ {4 .0_s, " Torus Code & Design: Pixel" },
568
+ {4 .0_s, " Music: Sicklebrick" },
569
+ {4 .0_s, " Splash screen: Smidgens" },
570
+ {4 .0_s, " Fonts: Zingot Games" },
571
+ {5 .0_s, " " },
557
572
{2 .0_s, " And that's it." },
558
573
{2 .0_s, " " },
559
574
{3 .0_s, " Thanks for watching." },
@@ -581,25 +596,43 @@ class TorusGeneratorScene final : public psyqo::Scene {
581
596
void frame () override ;
582
597
unsigned m_generationFrame = 0 ;
583
598
uint32_t m_startTimestamp = 0 ;
599
+ struct Splash {
600
+ psyqo::Prim::TPage tpage1;
601
+ psyqo::Prim::Sprite splash1;
602
+ psyqo::Prim::TPage tpage2;
603
+ psyqo::Prim::Sprite splash2;
604
+ };
605
+ psyqo::Fragments::SimpleFragment<Splash> m_splashFragment;
584
606
// Our generator scene won't try to double buffer, so we only need one set of primitives.
585
607
struct ProgressBar {
586
608
psyqo::Prim::PolyLine<4 > line;
587
609
psyqo::Prim::Rectangle rect;
588
- } m_progressBar;
610
+ };
611
+ psyqo::Fragments::SimpleFragment<ProgressBar> m_progressBarFragment;
589
612
uint8_t computePixel (uint8_t x, uint8_t y);
590
613
591
614
public:
592
615
TorusGeneratorScene () {
593
616
// Preparing the progress bar drawing calls.
594
- m_progressBar.line .setColor ({{.r = 255 , .g = 255 , .b = 255 }});
595
- m_progressBar.line .points [0 ] = {{.x = 30 , .y = 118 }};
596
- m_progressBar.line .points [1 ] = {{.x = 30 , .y = 138 }};
597
- m_progressBar.line .points [2 ] = {{.x = 290 , .y = 138 }};
598
- m_progressBar.line .points [3 ] = {{.x = 290 , .y = 118 }};
599
- m_progressBar.line .points [4 ] = {{.x = 30 , .y = 118 }};
600
- m_progressBar.rect .position = {{.x = 32 , .y = 120 }};
601
- m_progressBar.rect .size = {{.w = 0 , .h = 17 }};
602
- m_progressBar.rect .setColor ({{.r = 255 , .g = 255 , .b = 255 }});
617
+ m_progressBarFragment.primitive .line .setColor ({{.r = 255 , .g = 255 , .b = 255 }});
618
+ m_progressBarFragment.primitive .line .points [0 ] = {{.x = 30 , .y = 118 }};
619
+ m_progressBarFragment.primitive .line .points [1 ] = {{.x = 30 , .y = 138 }};
620
+ m_progressBarFragment.primitive .line .points [2 ] = {{.x = 290 , .y = 138 }};
621
+ m_progressBarFragment.primitive .line .points [3 ] = {{.x = 290 , .y = 118 }};
622
+ m_progressBarFragment.primitive .line .points [4 ] = {{.x = 30 , .y = 118 }};
623
+ m_progressBarFragment.primitive .rect .position = {{.x = 32 , .y = 120 }};
624
+ m_progressBarFragment.primitive .rect .size = {{.w = 0 , .h = 17 }};
625
+ m_progressBarFragment.primitive .rect .setColor ({{.r = 255 , .g = 255 , .b = 255 }});
626
+ m_splashFragment.primitive .tpage1 .attr .setPageX (8 ).setPageY (1 ).enableDisplayArea ().setDithering (false ).set (
627
+ psyqo::Prim::TPageAttr::Tex16Bits);
628
+ m_splashFragment.primitive .splash1 .setColor ({{.r = 128 , .g = 128 , .b = 128 }});
629
+ m_splashFragment.primitive .splash1 .position = {{.x = 0 , .y = 0 }};
630
+ m_splashFragment.primitive .splash1 .size = {{.w = 256 , .h = 240 }};
631
+ m_splashFragment.primitive .tpage2 .attr .setPageX (12 ).setPageY (1 ).enableDisplayArea ().setDithering (false ).set (
632
+ psyqo::Prim::TPageAttr::Tex16Bits);
633
+ m_splashFragment.primitive .splash2 .setColor ({{.r = 128 , .g = 128 , .b = 128 }});
634
+ m_splashFragment.primitive .splash2 .position = {{.x = 256 , .y = 0 }};
635
+ m_splashFragment.primitive .splash2 .size = {{.w = 64 , .h = 240 }};
603
636
}
604
637
};
605
638
@@ -615,11 +648,16 @@ void TorusDemo::prepare() {
615
648
.set (psyqo::GPU::Interlace::PROGRESSIVE)
616
649
.set (psyqo::GPU::MiscSetting::KEEP_VRAM);
617
650
gpu ().initialize (config);
651
+ m_input.initialize ();
618
652
}
619
653
620
654
void TorusDemo::createScene () {
655
+ MOD_LoadEx (&_binary_LittleCottonPillow_v260_hit_start, NULL );
656
+ m_musicTimer = gpu ().armPeriodicTimer (MOD_hblanks * psyqo::GPU::US_PER_HBLANK, [this ](uint32_t ) {
657
+ MOD_Poll ();
658
+ gpu ().changeTimerPeriod (m_musicTimer, MOD_hblanks * psyqo::GPU::US_PER_HBLANK);
659
+ });
621
660
m_font.uploadSystemFont (gpu ());
622
- m_input.initialize ();
623
661
pushScene (&torusGeneratorScene);
624
662
}
625
663
@@ -674,11 +712,12 @@ void TorusGeneratorScene::frame() {
674
712
psyqo::Prim::FlushCache fc;
675
713
gpu ().sendPrimitive (fc);
676
714
pushScene (&torusScene);
715
+ return ;
677
716
}
678
717
m_generationFrame++;
679
718
uint32_t elapsed = (gpu ().now () - m_startTimestamp) / 1000 ;
680
719
int32_t eta = (elapsed * eastl::max (TorusScene::Count, size_t (256 ))) / m_generationFrame - elapsed;
681
- gpu ().clear (c_backgroundColor );
720
+ gpu ().sendFragment (m_splashFragment );
682
721
if (m_generationFrame < 128 ) {
683
722
torusDemo.m_font .print (gpu (), " Generating animation..." , {{.x = 60 , .y = 80 }},
684
723
{{.r = 255 , .g = 255 , .b = 255 }});
@@ -692,8 +731,8 @@ void TorusGeneratorScene::frame() {
692
731
torusDemo.m_font .printf (gpu (), {{.x = 60 , .y = 160 }}, {{.r = 255 , .g = 255 , .b = 255 }}, " Elapsed: %us, ETA: %us" ,
693
732
elapsed / 1000 , eastl::max (eta, int32_t (0 )) / 1000 );
694
733
// This is the only dynamic part of the progress bar, so that's the only write to our draw calls we're doing.
695
- m_progressBar .rect .size .w = int16_t (m_generationFrame);
696
- gpu ().sendPrimitive (m_progressBar );
734
+ m_progressBarFragment. primitive .rect .size .w = int16_t (m_generationFrame);
735
+ gpu ().sendFragment (m_progressBarFragment );
697
736
}
698
737
699
738
void TorusScene::checkSequence (uint32_t currentTime) {
@@ -772,11 +811,11 @@ void TorusScene::frame() {
772
811
// These matrix multiplications are done in software, and they're not particularly fast, but it's done only once per
773
812
// frame, so it's not really a problem. The computation could be accelerated using the GTE however, but we're not
774
813
// starving for CPU at this point, so it's all good.
775
- auto transform = psyqo::SoftMath::generateRotationMatrix33 (m_angleX, psyqo::SoftMath::Axis::X, & torusDemo.m_trig );
776
- auto rot = psyqo::SoftMath::generateRotationMatrix33 (m_angleY, psyqo::SoftMath::Axis::Y, & torusDemo.m_trig );
777
- psyqo::SoftMath::multiplyMatrix33 (& transform, & rot, &transform);
778
- psyqo::SoftMath::generateRotationMatrix33 (&rot, m_angleZ, psyqo::SoftMath::Axis::Z, & torusDemo.m_trig );
779
- psyqo::SoftMath::multiplyMatrix33 (& transform, & rot, &transform);
814
+ auto transform = psyqo::SoftMath::generateRotationMatrix33 (m_angleX, psyqo::SoftMath::Axis::X, torusDemo.m_trig );
815
+ auto rot = psyqo::SoftMath::generateRotationMatrix33 (m_angleY, psyqo::SoftMath::Axis::Y, torusDemo.m_trig );
816
+ psyqo::SoftMath::multiplyMatrix33 (transform, rot, &transform);
817
+ psyqo::SoftMath::generateRotationMatrix33 (&rot, m_angleZ, psyqo::SoftMath::Axis::Z, torusDemo.m_trig );
818
+ psyqo::SoftMath::multiplyMatrix33 (transform, rot, &transform);
780
819
psyqo::GTE::writeUnsafe<psyqo::GTE::PseudoRegister::Rotation>(transform);
781
820
782
821
// All these will be reused multiple times over the course of the frame.
@@ -876,8 +915,8 @@ void TorusScene::frame() {
876
915
// shadow texture, and we multiply it by a 90 degree rotation around the X axis, as the platform is going to be
877
916
// rendered visually underneath the torus. This will make the appearance that everything has been projected
878
917
// properly, but it's all just a visual trick.
879
- psyqo::SoftMath::generateRotationMatrix33 (&rot, 0 .5_pi, psyqo::SoftMath::Axis::X, & torusDemo.m_trig );
880
- psyqo::SoftMath::multiplyMatrix33 (& transform, & rot, &transform);
918
+ psyqo::SoftMath::generateRotationMatrix33 (&rot, 0 .5_pi, psyqo::SoftMath::Axis::X, torusDemo.m_trig );
919
+ psyqo::SoftMath::multiplyMatrix33 (transform, rot, &transform);
881
920
psyqo::GTE::writeUnsafe<psyqo::GTE::PseudoRegister::Rotation>(transform);
882
921
883
922
// At this point, our background DMA chain has most likely finished. At some point, we want to send
@@ -917,13 +956,13 @@ void TorusScene::frame() {
917
956
psyqo::Vec3 v1 = m_tori[animationIndex].normals [i + 1 ];
918
957
psyqo::Vec3 v2 = m_tori[animationIndex].normals [i + 2 ];
919
958
psyqo::GTE::Kernels::rtpt ();
920
- auto sz = -psyqo::SoftMath::matrixVecMul3z (& transform, & v0);
959
+ auto sz = -psyqo::SoftMath::matrixVecMul3z (transform, v0);
921
960
int32_t z = sz.integer <256 >() - 1 ;
922
961
zNormal[i + 0 ] = eastl::clamp (z, int32_t (0 ), int32_t (255 ));
923
- sz = -psyqo::SoftMath::matrixVecMul3z (& transform, & v1);
962
+ sz = -psyqo::SoftMath::matrixVecMul3z (transform, v1);
924
963
z = sz.integer <256 >() - 1 ;
925
964
zNormal[i + 1 ] = eastl::clamp (z, int32_t (0 ), int32_t (255 ));
926
- sz = -psyqo::SoftMath::matrixVecMul3z (& transform, & v2);
965
+ sz = -psyqo::SoftMath::matrixVecMul3z (transform, v2);
927
966
z = sz.integer <256 >() - 1 ;
928
967
zNormal[i + 2 ] = eastl::clamp (z, int32_t (0 ), int32_t (255 ));
929
968
psyqo::GTE::read<psyqo::GTE::Register::SXY0>(&projected[i + 0 ].packed );
@@ -937,7 +976,7 @@ void TorusScene::frame() {
937
976
psyqo::GTE::writeUnsafe<psyqo::GTE::PseudoRegister::V0>(m_tori[animationIndex].vertices [i]);
938
977
psyqo::Vec3 v = m_tori[animationIndex].normals [i];
939
978
psyqo::GTE::Kernels::rtps ();
940
- auto sz = -psyqo::SoftMath::matrixVecMul3z (& transform, & v);
979
+ auto sz = -psyqo::SoftMath::matrixVecMul3z (transform, v);
941
980
int32_t z = sz.integer <256 >() - 1 ;
942
981
zNormal[i] = eastl::clamp (z, int32_t (0 ), int32_t (255 ));
943
982
psyqo::GTE::read<psyqo::GTE::Register::SXY2>(&projected[i].packed );
@@ -1038,4 +1077,8 @@ void TorusScene::frame() {
1038
1077
}
1039
1078
}
1040
1079
1041
- int main () { return torusDemo.run (); }
1080
+ int main () {
1081
+ *((volatile uint8_t *)0x23 ) = 0 ;
1082
+ psyqo::Kernel::takeOverKernel ();
1083
+ return torusDemo.run ();
1084
+ }
0 commit comments