MOD playback works

This commit is contained in:
ABelliqueux 2021-10-28 18:28:04 +02:00
parent 097597d75e
commit fd9e8f0461
19 changed files with 194 additions and 163 deletions

BIN
HIT/shin1.mod Normal file

Binary file not shown.

View File

@ -12,6 +12,6 @@ SRCS = hello_str.c \
src/str.c \
src/mod.c \
src/modplayer.c \
HIT/shine.hit \
HIT/SHIN1.HIT \
include common.mk

View File

@ -1,5 +1,5 @@
Avi2strMdecV(
.\idle_loop_mc.avi,
.\render\idle_loop_mc.avi,
.\idle_loop_mc.str,
x2, # CD-ROM speed
15fps, # Frame rate
@ -9,7 +9,7 @@ Avi2strMdecV(
);
Avi2strMdecV(
.\transition_mc.avi,
.\render\transition_mc.avi,
.\transition_mc.str,
x2, # CD-ROM speed
15fps, # Frame rate
@ -18,9 +18,31 @@ Avi2strMdecV(
FALSE # Leap sector
);
Avi2strMdecV(
.\render\transition_reverse_mc.avi,
.\transition_reverse_mc.str,
x2, # CD-ROM speed
15fps, # Frame rate
2, # Number of channels
2, # MDEC version
FALSE # Leap sector
);
#Avi2strMdecC(
#.\empty_mc.avi,
#.\empty_mc.str,
#2048bytes,
#VariableFrameSize,
#2
#);
Pack2ch(
.\menu.str, FALSE, # Output file name(Fn), Subheader(Sub)
.\idle_loop_mc.str, FALSE, 0, 0, # ch0; Fn,sub,TermType,TermLength
.\transition_mc.str, FALSE, 0, 0 # ch1; Fn sub,TermType,TermLength
.\menu.str, FALSE, # Output file name(Fn), Subheader(Sub)
.\idle_loop_mc.str, FALSE, 0, 0, # ch0; Fn,sub,TermType,TermLength
.\transition_mc.str, FALSE, 0, 0 # ch1; Fn sub,TermType,TermLength
);
Pack2ch(
.\menu1.str, FALSE, # Output file name(Fn), Subheader(Sub)
.\idle_loop_mc.str, FALSE, 0, 0, # ch0; Fn,sub,TermType,TermLength
.\transition_reverse_mc.str, FALSE, 0, 0 # ch1; Fn sub,TermType,TermLength
);

View File

@ -1,38 +1,46 @@
#!/bin/bash
SOURCE_DIR="./sources"
RENDER_DIR="./render"
# Render blender files
if [ "$1" == "-b" ] || [ "$1" == "-a" ]; then
echo "Rendering blender files..."
prime-run blender29 -b ../sources/nolibgsdemo-idle_loop.blend -a --cycles-device CUDA+CPU
prime-run blender29 -b ../sources/nolibgsdemo-trans.blend -a --cycles-device CUDA+CPU
# unused
# prime-run blender29 -b ../sources/nolibgsdemo-trans_alpha.blend -a --cycles-device CUDA+CPU
# prime-run blender29 -b ../sources/nolibgsdemo-bg_only.blend -a --cycles-device CUDA+CPU
if [ ! -d $SOURCE_DIR ]; then
mkdir $SOURCE_DIR
fi
if [ ! -d $RENDER_DIR ]; then
mkdir $RENDER_DIR
fi
prime-run blender29 -b "$SOURCE_DIR"/nolibgsdemo-idle_loop.blend -o "$RENDER_DIR"/idle_loop/idle_####.png -a
prime-run blender29 -b "$SOURCE_DIR"/nolibgsdemo-trans.blend -o "$RENDER_DIR"/trans/trans_####.png -a
prime-run blender29 -b "$SOURCE_DIR"/nolibgsdemo-trans_reverse.blend -o "$RENDER_DIR"/trans_reverse/trans_reverse_####.png -a
fi
# Convert PNGs to AVI
if [ "$1" == "-v" ] || [ "$1" == "-a" ]; then
if [ ! -d $RENDER_DIR ]; then
echo "Nothing to render !"
break
fi
echo "Converting png to avi..."
# idle loop
ffmpeg -r 15 -f image2 -s 320x240 -i idle_loop/idle_loop%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=256:240,setsar=1:1,vflip -an -r 15 idle_loop.avi -y
ffmpeg -r 15 -f image2 -s 320x240 -i "$RENDER_DIR"/idle_loop/idle_%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=256:240,setsar=1:1,vflip -an -r 15 "$RENDER_DIR"/idle_loop.avi -y
# transition
ffmpeg -r 15 -f image2 -s 320x240 -i trans/trans%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=256:240,setsar=1:1,vflip -an -r 15 transition.avi -y
# unused
# upper part
# ffmpeg -r 15 -f image2 -s 320x240 -i idle_loop/idle_loop%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=256:240,setsar=1:1,crop=320:144:0:0,vflip -an -r 15 idle_loop_up.avi -y
# down part idle
# ffmpeg -r 15 -f image2 -s 320x240 -i idle_loop/idle_loop%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=320:240,setsar=1:1,crop=320:96:0:144,vflip -an -r 15 idle_loop_down.avi -y
# down part trans-aplpha
# ffmpeg -r 15 -f image2 -s 320x240 -i trans_alpha/trans_alpha%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=320:240,setsar=1:1,crop=320:96:0:140,vflip -an -r 15 trans_alpha_down.avi -y
# bg_only
# ffmpeg -r 15 -f image2 -s 320x240 -i bg_only/bg_only%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=320:240,setsar=1:1,vflip -an -r 15 bg_only.avi -y
ffmpeg -r 15 -f image2 -s 320x240 -i "$RENDER_DIR"/trans/trans_%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=256:240,setsar=1:1,vflip -an -r 15 "$RENDER_DIR"/transition.avi -y
# transition
ffmpeg -r 15 -f image2 -s 320x240 -i "$RENDER_DIR"/trans_reverse/trans_reverse_%04d.png -vcodec rawvideo -pix_fmt bgr24 -vf scale=256:240,setsar=1:1,vflip -an -r 15 "$RENDER_DIR"/transition_reverse.avi -y
# Fix AVI files with mencoder
# mencoder -force-avi-aspect 1.33
rm *_mc.avi
for vid in *.avi;
do mencoder $vid -ovc copy -o ${vid%%.*}_mc.avi;
rm -f "$RENDER_DIR"/*_mc.avi
for vid in "$RENDER_DIR"/*.avi;
#~ do echo ${$(basename $vid)%%.*}
do
base=${vid##*/}
echo ${base%%.*}
mencoder $vid -ovc copy -o "$RENDER_DIR"/${base%%.*}_mc.avi;
done
fi
# Convert AVI to STR

BIN
STR/sources/flare-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
STR/sources/flare-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
VAG/selectd.wav Normal file

Binary file not shown.

BIN
VAG/switchs.wav Normal file

Binary file not shown.

View File

@ -53,6 +53,6 @@ endef
$(call OBJCOPYME)
# convert HIT to bin
%.o: %.hit
%.o: %.HIT
$(call OBJCOPYME)

View File

@ -34,9 +34,11 @@ char primbuff[2][32768]; // double primitive buffer of length 32768 * 8 = 2
char *nextpri = primbuff[0]; // pointer to the next primitive in primbuff. Initially, points to the first bit of primbuff[0]
short db = 1; // index of which buffer is used, values 0, 1
STR menu[2] = {
STR menu[4] = {
{ "\\MENU.STR;1", 256, 240, 30, 0, 0 },
{ "\\MENU.STR;1", 256, 240, 30, 1, 0 },
{ "\\MENU1.STR;1", 256, 240, 30, 0, 0 },
{ "\\MENU1.STR;1", 256, 240, 30, 1, 0 },
};
STR * curStr;
StHEADER * sectorHeader;
@ -157,24 +159,54 @@ void drawBG(void)
}
void checkPad(void)
{
u_short pad;
u_short pad = 0;
static u_short oldPad;
pad = PadRead(0);
if ( pad & PADLleft && !(oldPad & PADLleft) )
{
// Channel 1 is transition anim, only take input when !transition
if(curStr->channel != 1)
if ( curStr == &menu[IDLE] )
{
ramsyscall_printf("Left: change channel\n");
switchStrCh(&curStr);
oldPad = pad;
ramsyscall_printf("Left\n");
// Switch sound
MOD_PlayNote(23, 12, 15, 63);
switchStr(&curStr, LEFT);
}
oldPad = pad;
}
if ( !(pad & PADLleft) && oldPad & PADLleft )
{
oldPad = pad;
}
// Right
if ( pad & PADLright && !(oldPad & PADLright) )
{
// Channel 1 is transition anim, only take input when !transition
if( curStr == &menu[IDLE] )
{
ramsyscall_printf("Right\n");
// Switch sound
MOD_PlayNote(23, 12, 15, 63);
switchStr(&curStr, RIGHT);
}
oldPad = pad;
}
if ( !(pad & PADLright) && oldPad & PADLright )
{
oldPad = pad;
}
// Cross button
if ( pad & PADRdown && !(oldPad & PADRdown) )
{
// Select sound
MOD_PlayNote(22, 7, 15, 63);
oldPad = pad;
}
if ( !(pad & PADRdown) && oldPad & PADRdown )
{
oldPad = pad;
}
}
int main() {
curStr = &(menu[0]);
@ -191,26 +223,12 @@ int main() {
initSTR(curStr);
// Set Channel
StSetChannel( curStr->channel );
// Mod Playback
loadMod();
startMusic();
// Main loop
//~ loadMod();
printf("Loading MOD:\'%s\'\n", HITFILE);
// We are going to use timer1 and its hblank counter to tell us when
// we need to call MOD_Poll again. For this, we need timer1 to be
// counting hblanks instead of the system clock.
COUNTERS[1].mode = 0x0100;
MOD_Load((struct MODFileFormat*)HITFILE);
printf("%02d Channels, %02d Orders\n", MOD_Channels, MOD_SongLength);
unsigned row = 0xffffffff;
unsigned order = 0xffffffff;
unsigned pattern = 0xffffffff;
//~ uint16_t s_nextCounter = 0;
// Giving our initial counter a proper value.
s_nextCounter = COUNTERS[1].value + MOD_hblanks;
while (1)
//~ while (VSync(-1))
{
playMod(row, order, pattern);
checkMusic();
// Only display background STR if drawMenu is set
if (drawMenu)
{
@ -240,9 +258,8 @@ int main() {
}
}
}
//~ playMod(row, order, pattern);
//~ waitVSync();
display();
}
return 0;
}
}

View File

@ -87,6 +87,7 @@
<file name="system.cnf" type="data" source="system.cnf"/>
<file name="SCES_313.37" type="data" source="hello_str.ps-exe"/>
<file name="MENU.STR" type="str" source="STR/menu.str"/>
<file name="MENU1.STR" type="str" source="STR/menu1.str"/>
<dummy sectors="1024"/>

130
src/mod.c
View File

@ -1,91 +1,57 @@
/*
MIT License
Copyright (c) 2021 PCSX-Redux authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "mod.h"
uint16_t s_nextCounter = 0;
long musicEvent;
typedef struct SpuVoiceVolume {
short volL, volR;
} SpuVoiceVolume;
// Function to call periodically if we can't use interrupts for some reason.
// If the code is running slower than the normal vsync speed, then you should
// call this during your frame computation code, in order to make sure you're
// not missing any tick.
void checkMusic() {
if (((int16_t)(s_nextCounter - COUNTERS[1].value)) <= 0) {
printf("cnt: %d\n", s_nextCounter);
MOD_Poll();
s_nextCounter += MOD_hblanks;
}
SpuVoiceVolume volumeState[24] = {0};
// Playing a sound effect (aka mod note): https://discord.com/channels/642647820683444236/642848592754901033/898249196174458900
// Code by NicolasNoble : https://discord.com/channels/642647820683444236/663664210525290507/902624952715452436
void loadMod() {
printf("Loading MOD:\'%s\'\n", HITFILE);
MOD_Load((struct MODFileFormat*)HITFILE);
printf("%02d Channels, %02d Orders\n", MOD_Channels, MOD_SongLength);
}
void waitVSync() {
int wasLocked = enterCriticalSection();
uint32_t imask = IMASK;
IMASK = imask | IRQ_VBLANK;
while ((IREG & IRQ_VBLANK) == 0) {
// Since our vsync is a kludge, we can't use the root counter IRQ
// mechanism to call MOD_Poll, and so we have to poll here, during
// vsync, for when our timer has passed the target value manually.
// We *could* set up the timer properly using the target value system,
// but this might make a few emulators sad. Beside, this is a perfectly
// valid and common solution.
checkMusic();
}
IREG &= ~IRQ_VBLANK;
IMASK = imask;
if (!wasLocked) leaveCriticalSection();
void startMusic() {
ResetRCnt(RCntCNT1);
SetRCnt(RCntCNT1, MOD_hblanks, RCntMdINTR);
StartRCnt(RCntCNT1);
musicEvent = OpenEvent(RCntCNT1, EvSpINT, EvMdINTR, processMusic);
EnableEvent(musicEvent);
}
void playMod(unsigned row, unsigned order, unsigned pattern)
{
if (row != MOD_CurrentRow || order != MOD_CurrentOrder || pattern != MOD_CurrentPattern) {
row = MOD_CurrentRow;
order = MOD_CurrentOrder;
pattern = MOD_CurrentPattern;
printf("Row: %02d, Order: %02d, Pattern: %02d\n", row, order, pattern);
}
long processMusic() {
uint32_t old_hblanks = MOD_hblanks;
MOD_Poll();
uint32_t new_hblanks = MOD_hblanks;
if (old_hblanks != new_hblanks) SetRCnt(RCntCNT1, new_hblanks, RCntMdINTR);
return MOD_hblanks;
}
//~ void loadMod() {
//~ printf("Loading MOD:\'%s\'\n", HITFILE);
//~ // We are going to use timer1 and its hblank counter to tell us when
//~ // we need to call MOD_Poll again. For this, we need timer1 to be
//~ // counting hblanks instead of the system clock.
//~ COUNTERS[1].mode = 0x0100;
//~ MOD_Load((struct MODFileFormat*)HITFILE);
//~ printf("%02d Channels, %02d Orders\n", MOD_Channels, MOD_SongLength);
//~ unsigned row = 0xffffffff;
//~ unsigned order = 0xffffffff;
//~ unsigned pattern = 0xffffffff;
//~ // Giving our initial counter a proper value.
//~ s_nextCounter = COUNTERS[1].value + MOD_hblanks;
//~ while (1) {
//~ playMod(row, order, pattern);
//~ waitVSync();
//~ }
//~ }
void pauseMusic() {
for (unsigned i = 0; i < 24; i++) {
// Store current volume
SpuGetVoiceVolume(i, &(volumeState[i].volL), &(volumeState[i].volR) );
// Mute
SpuSetVoiceVolume(i, 0, 0);
}
DisableEvent(musicEvent);
}
void resumeMusic() {
for (unsigned i = 0; i < 24; i++) {
// Restore volume
SpuSetVoiceVolume(i, volumeState[i].volL, volumeState[i].volR );
}
EnableEvent(musicEvent);
}
void stopMusic() {
MOD_Silence();
StopRCnt(RCntCNT1);
DisableEvent(musicEvent);
CloseEvent(musicEvent);
}

View File

@ -1,15 +1,19 @@
#pragma once
#include <libapi.h>
#include <libspu.h>
#include "../../nugget/common/hardware/hwregs.h"
#include "../../nugget/common/hardware/irq.h"
#include "../../nugget/common/syscalls/syscalls.h"
#include "modplayer.h"
extern const uint8_t _binary_HIT_shine_hit_start[];
#define HITFILE _binary_HIT_shine_hit_start
extern const uint8_t _binary_HIT_SHIN1_HIT_start[];
#define HITFILE _binary_HIT_SHIN1_HIT_start
#define printf ramsyscall_printf
extern uint16_t s_nextCounter;
void checkMusic();
void waitVSync();
extern long musicEvent;
void loadMod();
void playMod();
long processMusic();
void startMusic();
void pauseMusic();
void resumeMusic();
void stopMusic();

View File

@ -214,7 +214,7 @@ static void MOD_SetBPM(unsigned bpm) {
MOD_hblanks = base / bpm;
}
static struct SPUChannelData s_channelData[24];
struct SPUChannelData s_channelData[24];
uint32_t MOD_Load(const struct MODFileFormat* module) {
SPUInit();

View File

@ -1,6 +1,7 @@
#include "str.h"
CdlFILE STRfile;
// Parameter we want to set the CDROM with
u_char param = CdlModeSpeed;
// Buffers total ~110KB in memory
@ -15,39 +16,44 @@ u_short ImgBuff[ 16 * SCREENYRES];
u_long * curVLCptr = &VlcBuff[0];
u_short * curIMGptr = &ImgBuff[0];
void initSTR(STR * str)
void loadCdFile(STR * str)
{
DecDCTReset(0);
StSetRing(RingBuff, RING_SIZE);
StSetStream(0, 1, str->length, 0, 0);
if ( CdSearchFile(&STRfile, str->name) == 0 ) {
FntPrint("File not found :%s\n", str->name);
}
CdControl(CdlSetloc, (u_char *)&STRfile.pos, 0);
//CdControl(CdlSetmode, &param, 0);
CdRead2(CdlModeStream|CdlModeSpeed);
}
void initSTR(STR * str)
{
DecDCTReset(0);
StSetRing(RingBuff, RING_SIZE);
StSetStream(0, 1, str->length, 0, 0);
// Set CD mode to CdlModeSpeed
CdControl(CdlSetmode, &param, 0);
loadCdFile(str);
}
void resetSTR(STR * str)
{
u_long * curVLCptr = &VlcBuff[0];
u_short * curIMGptr = &ImgBuff[0];
// Set the seek target position
CdControl(CdlSetloc, (u_char *)&STRfile.pos, 0);
// Set CD mode to CdlModeSpeed
CdControl(CdlSetmode, &param, 0);
// Read from CD at position &STRfile.pos
// Enable streaming, double speed and ADPCM playback
CdRead2(CdlModeStream|CdlModeSpeed|CdlModeRT);
loadCdFile(str);
//~ // Set the seek target position
//~ CdControl(CdlSetloc, (u_char *)&STRfile.pos, 0);
//~ // Read from CD at position &STRfile.pos
//~ // Enable streaming, double speed
//~ CdRead2(CdlModeStream|CdlModeSpeed);
str->endPlayback = 0;
}
void switchStrCh(STR ** str)
void switchStr(STR ** str, int strID)
{
// Switch current STR channel
// Switch current STR
printf("p0: %p - %d - ", *str, (*str)->channel);
sectorHeader->frameCount = 0;
*str = &menu[!((*str)->channel)];
*str = &menu[strID];
printf("p1: %p\n", *str);
StSetChannel( (*str)->channel );
(*str)->endPlayback = 1;
@ -129,7 +135,7 @@ void playSTR(STR ** str)
// If on channel 1, go back to channel 0 after 30 frames
if ((*str)->channel)
{
switchStrCh(str);
switchStr(str, IDLE);
} else {
// if on channel 0, set end flag for loop
(*str)->endPlayback = 1;

View File

@ -17,7 +17,7 @@
#define STR_POS_X SCREENXRES
#define STR_POS_Y 0
// Ring Buffer size (reduce if flickering occurs)
#define RING_SIZE 24
#define RING_SIZE 32
#define PPW 1
#define DCT_MODE 2
typedef struct STR {
@ -27,7 +27,7 @@ typedef struct STR {
uint8_t channel, endPlayback;
} STR;
// 2 channels STR: ch0 = idle loop, ch1 = transition anim
extern STR menu[2];
extern STR menu[4];
// CD File descriptor
extern CdlFILE STRfile;
extern StHEADER * sectorHeader;
@ -46,10 +46,17 @@ extern u_short * curIMGptr;
extern u_long * nextFrame;
// Ring buffer frame address
extern u_long * frameAddr;
extern uint8_t drawMenu;
enum MENU_STATE
{
IDLE = 0,
LEFT = 1,
RIGHT = 3,
};
void loadCdFile(STR * str);
void initSTR(STR * str);
void resetSTR(STR * str);
void playSTR(STR ** str);
void switchStrCh(STR ** curStr);
void switchStr(STR ** curStr, int strID);