Match and link THPRead

This commit is contained in:
SwareJonge 2023-08-25 23:23:06 +02:00
parent a8d640de30
commit e1d2415f6e
8 changed files with 353 additions and 150 deletions

View File

@ -642,6 +642,11 @@ src/Kaneshige/THP/THPPlayer.c:
.sbss: [0x80416850, 0x80416868]
.sdata2: [0x8041a690, 0x8041a6c0]
src/Kaneshige/THP/THPRead.c:
.text: [0x801dc4d4, 0x801dc7f0]
.bss: [0x803cd618, 0x803cea08]
.sbss: [0x80416870, 0x80416878]
src/Osako/clock.cpp:
.text: [0x801f6e04, 0x801f6e9c]
.sbss: [0x804168c8, 0x804168d8]

View File

@ -609,6 +609,11 @@ src/Kaneshige/THP/THPPlayer.c:
.sbss: [0x803d5ab8, 0x803d5ad0]
.sdata2: [0x803d8ea0, 0x803d8ec0]
src/Kaneshige/THP/THPRead.c:
.text: [0x801b41dc, 0x801b44f8]
.bss: [0x8038d118, 0x8038e508]
.sbss: [0x803d5ad8, 0x803d5ae0]
src/Osako/clock.cpp:
.text: [0x801cbe60, 0x801cbef8]
.sbss: [0x803d5b30, 0x803d5b40]

View File

@ -12,7 +12,12 @@ BOOL CreateReadThread(OSPriority prio);
void ReadThreadStart();
void ReadThreadCancel();
void PushFreeReadBuffer(OSMessage msg);
void *PopReadedBuffer();
void *PopFreeReadBuffer();
void *PopReadedBuffer2();
void *PushReadedBuffer(void *buffer);
void PushFreeReadBuffer(void *buffer);
void PushReadedBuffer2(void *buffer);
#ifdef __cplusplus
}

View File

@ -8,75 +8,80 @@ extern "C"
#include <dolphin/os/OSContext.h>
typedef struct OSThread OSThread;
typedef struct OSThreadQueue OSThreadQueue;
typedef struct OSThreadLink OSThreadLink;
typedef s32 OSPriority; // 0 highest, 31 lowest
#define OS_THREAD_SPECIFIC_MAX 2
typedef struct OSMutex OSMutex;
typedef struct OSMutexQueue OSMutexQueue;
typedef struct OSMutexLink OSMutexLink;
typedef struct OSCond OSCond;
typedef struct OSThread OSThread;
typedef struct OSThreadQueue OSThreadQueue;
typedef struct OSThreadLink OSThreadLink;
typedef s32 OSPriority; // 0 highest, 31 lowest
typedef void (*OSIdleFunction)(void *param);
typedef struct OSMutex OSMutex;
typedef struct OSMutexQueue OSMutexQueue;
typedef struct OSMutexLink OSMutexLink;
typedef struct OSCond OSCond;
struct OSThreadQueue
{
OSThread *head;
OSThread *tail;
};
typedef void (*OSIdleFunction)(void *param);
typedef void *(*OSThreadFunc)(void *arg);
struct OSThreadLink
{
OSThread *next;
OSThread *prev;
};
struct OSThreadQueue
{
OSThread *head;
OSThread *tail;
};
struct OSMutexQueue
{
OSMutex *head;
OSMutex *tail;
};
struct OSThreadLink
{
OSThread *next;
OSThread *prev;
};
struct OSMutexLink
{
OSMutex *next;
OSMutex *prev;
};
struct OSMutexQueue
{
OSMutex *head;
OSMutex *tail;
};
struct OSThread
{
OSContext context; // register context
struct OSMutexLink
{
OSMutex *next;
OSMutex *prev;
};
u16 state; // OS_THREAD_STATE_*
u16 attr; // OS_THREAD_ATTR_*
s32 suspend; // suspended if the count is greater than zero
OSPriority priority; // effective scheduling priority
OSPriority base; // base scheduling priority
void *val; // exit value
struct OSThread
{
OSContext context; // register context
OSThreadQueue *queue; // queue thread is on
OSThreadLink link; // queue link
u16 state; // OS_THREAD_STATE_*
u16 attr; // OS_THREAD_ATTR_*
s32 suspend; // suspended if the count is greater than zero
OSPriority priority; // effective scheduling priority
OSPriority base; // base scheduling priority
void *val; // exit value
OSThreadQueue queueJoin; // list of threads waiting for termination (join)
OSThreadQueue *queue; // queue thread is on
OSThreadLink link; // queue link
OSMutex *mutex; // mutex trying to lock
OSMutexQueue queueMutex; // list of mutexes owned
OSThreadQueue queueJoin; // list of threads waiting for termination (join)
OSThreadLink linkActive; // link of all threads for debugging
OSMutex *mutex; // mutex trying to lock
OSMutexQueue queueMutex; // list of mutexes owned
u8 *stackBase; // the thread's designated stack (high address)
u32 *stackEnd; // last word of stack (low address)
};
OSThreadLink linkActive; // link of all threads for debugging
// Thread states
enum OS_THREAD_STATE
{
OS_THREAD_STATE_READY = 1,
OS_THREAD_STATE_RUNNING = 2,
OS_THREAD_STATE_WAITING = 4,
OS_THREAD_STATE_MORIBUND = 8
};
u8 *stackBase; // the thread's designated stack (high address)
u32 *stackEnd; // last word of stack (low address)
s32 error;
void *specific[OS_THREAD_SPECIFIC_MAX];
};
// Thread states
enum OS_THREAD_STATE
{
OS_THREAD_STATE_READY = 1,
OS_THREAD_STATE_RUNNING = 2,
OS_THREAD_STATE_WAITING = 4,
OS_THREAD_STATE_MORIBUND = 8
};
// Thread priorities
#define OS_PRIORITY_MIN 0 // highest
@ -96,13 +101,8 @@ BOOL OSIsThreadTerminated(OSThread *thread);
s32 OSDisableScheduler(void);
s32 OSEnableScheduler(void);
void OSYieldThread(void);
BOOL OSCreateThread(OSThread *thread,
void *(*func)(void *),
void *param,
void *stack,
u32 stackSize,
OSPriority priority,
u16 attr);
BOOL OSCreateThread(OSThread *thread, OSThreadFunc func, void *funcArg,
void *stackBegin, u32 stackSize, OSPriority prio, u16 flags);
void OSExitThread(void *val);
void OSCancelThread(OSThread *thread);
BOOL OSJoinThread(OSThread *thread, void **val);
@ -115,9 +115,9 @@ void OSSleepThread(OSThreadQueue *queue);
void OSWakeupThread(OSThreadQueue *queue);
OSThread *OSSetIdleFunction(OSIdleFunction idleFunction,
void *param,
void *stack,
u32 stackSize);
void *param,
void *stack,
u32 stackSize);
OSThread *OSGetIdleFunction(void);
long OSCheckActiveThreads(void);

View File

@ -71,7 +71,7 @@ void JKRThread::setCommon_mesgQueue(JKRHeap* heap, int msgCount)
mMesgBuffer = (OSMessage*)JKRHeap::alloc(mMessageCount << 2, 0, heap);
JUT_ASSERT(mMesgBuffer);
OSInitMessageQueue(&mMessageQueue, (void**)mMesgBuffer, mMessageCount);
OSInitMessageQueue(&mMessageQueue, mMesgBuffer, mMessageCount);
JKRThread::sThreadList.append(&mThreadListLink);
mCurrentHeap = nullptr;
mCurrentHeapError = nullptr;
@ -85,8 +85,8 @@ BOOL JKRThread::setCommon_heapSpecified(JKRHeap* heap, unsigned long stackSize,
mStackMemory = JKRHeap::alloc(mStackSize, 0x20, mHeap);
JUT_ASSERT(mStackMemory);
// maybe a custom struct is used here, investigate someday
mThreadRecord = (OSThread*)JKRHeap::alloc(sizeof(OSThread) + 8, 0x20, mHeap);
#line 167
mThreadRecord = (OSThread*)JKRHeap::alloc(sizeof(OSThread), 0x20, mHeap);
JUT_ASSERT(mThreadRecord);
return OSCreateThread(mThreadRecord, &JKRThread::start, this, (void*)((u32)mStackMemory + mStackSize), mStackSize, threadPriority, 1);
}

View File

@ -51,7 +51,7 @@ u16 VolumeTable[128] = {
};
// clang-format on
// static functions definitions
// static function definitions
static s16 *audioCallback(s32 p1);
static void MixAudio(s16 *, u32);
static void *PopUsedTextureSet();
@ -89,7 +89,6 @@ static void quitAudio()
BOOL THPPlayerInit()
{
memset(&ActivePlayer, 0, sizeof(THPPlayer));
LCEnable();
OSInitMessageQueue(&UsedTextureSetQueue, UsedTextureSetMessage, 3);
@ -121,7 +120,7 @@ void THPPlayerQuit()
BOOL THPPlayerOpen(const char *fileName, BOOL onMemory)
{
u32 readOffset;
int i;
s32 i;
if (Initialized == FALSE)
{
@ -247,14 +246,16 @@ BOOL THPPlayerClose()
u32 THPPlayerCalcNeedMemory()
{
if(ActivePlayer.open) {
if (ActivePlayer.open)
{
u32 size = ActivePlayer.onMemory ? ALIGN_NEXT(ActivePlayer.header.movieDataSize, 32) : ALIGN_NEXT(ActivePlayer.header.bufsize, 32) * 10;
size += ALIGN_NEXT(ActivePlayer.videoInfo.xSize * ActivePlayer.videoInfo.ySize, 32) * 3;
size += ALIGN_NEXT(ActivePlayer.videoInfo.xSize * ActivePlayer.videoInfo.ySize / 4, 32) * 3;
size += ALIGN_NEXT(ActivePlayer.videoInfo.xSize * ActivePlayer.videoInfo.ySize / 4, 32) * 3;
if(ActivePlayer.audioExist) {
if (ActivePlayer.audioExist)
{
size += ALIGN_NEXT(ActivePlayer.header.audioMaxSamples * 4, 32) * 6;
}
return size + 0x1000;
@ -268,13 +269,16 @@ BOOL THPPlayerSetBuffer(u8 *data)
u32 ySampleSize;
u32 uvSampleSize;
s32 i;
if(ActivePlayer.open && ActivePlayer.state == 0) {
if (ActivePlayer.open && ActivePlayer.state == 0)
{
u8 *workPtr = data;
if(ActivePlayer.onMemory) {
if (ActivePlayer.onMemory)
{
ActivePlayer.movieData = data;
workPtr += ActivePlayer.header.movieDataSize;
}
else {
else
{
for (i = 0; i < ARRAY_SIZE(ActivePlayer.readBuffer); i++)
{
ActivePlayer.readBuffer[i].ptr = workPtr;
@ -295,14 +299,16 @@ BOOL THPPlayerSetBuffer(u8 *data)
ActivePlayer.textureSet[i].utexture = workPtr;
DCInvalidateRange(workPtr, uvSampleSize);
workPtr += uvSampleSize;
ActivePlayer.textureSet[i].vtexture = workPtr;
DCInvalidateRange(workPtr, uvSampleSize);
workPtr += uvSampleSize;
}
if(ActivePlayer.audioExist) {
for(i = 0; i < ARRAY_SIZE(ActivePlayer.audioBuffer); i++) {
if (ActivePlayer.audioExist)
{
for (i = 0; i < ARRAY_SIZE(ActivePlayer.audioBuffer); i++)
{
ActivePlayer.audioBuffer[i].buffer = (s16 *)workPtr;
ActivePlayer.audioBuffer[i].curPtr = (s16 *)workPtr;
ActivePlayer.audioBuffer[i].validSample = 0;
@ -317,40 +323,58 @@ BOOL THPPlayerSetBuffer(u8 *data)
return FALSE;
}
static void InitAllMessageQueue() {
if(ActivePlayer.onMemory == FALSE) {
for(int i = 0; i < 10; i++) {
static void InitAllMessageQueue()
{
s32 i;
if (ActivePlayer.onMemory == FALSE)
{
for (i = 0; i < 10; i++)
{
PushFreeReadBuffer(&ActivePlayer.readBuffer[i]);
}
}
for (int i = 0; i < 3; i++)
for (i = 0; i < 3; i++)
{
PushFreeTextureSet(&ActivePlayer.textureSet[i]);
}
if(ActivePlayer.audioExist) {
for (int i = 0; i < 6; i++) {
if (ActivePlayer.audioExist)
{
for (i = 0; i < 6; i++)
{
PushFreeAudioBuffer(&ActivePlayer.audioBuffer[i]);
}
}
OSInitMessageQueue(&PrepareReadyQueue, &PrepareReadyMessage, 1);
}
static BOOL WaitUntilPrepare() {
s32 msg;
OSReceiveMessage(&PrepareReadyQueue, (OSMessage*)&msg, 1);
return msg ? TRUE : FALSE;
static BOOL WaitUntilPrepare()
{
OSMessage msg;
OSReceiveMessage(&PrepareReadyQueue, &msg, OS_MESSAGE_BLOCK);
if ((BOOL)msg)
{
return TRUE;
}
else
{
return FALSE;
}
}
void PrepareReady(int msg)
void PrepareReady(BOOL msg)
{
OSSendMessage(&PrepareReadyQueue, (OSMessage)msg, OS_MESSAGE_BLOCK);
}
BOOL THPPlayerPrepare(s32 frame, u8 flag, s32 audioTrack)
{
if (ActivePlayer.open && ActivePlayer.state == 0) {
u8 *threadData;
if (ActivePlayer.open && ActivePlayer.state == 0)
{
if (frame > 0)
{
if (ActivePlayer.header.offsetDataOffsets == 0)
@ -365,18 +389,21 @@ BOOL THPPlayerPrepare(s32 frame, u8 flag, s32 audioTrack)
ActivePlayer.initReadSize = WorkBuffer[1] - WorkBuffer[0];
ActivePlayer.initReadFrame = frame;
}
else {
else
{
return FALSE;
}
}
else {
else
{
ActivePlayer.initOffset = ActivePlayer.header.movieDataOffsets;
ActivePlayer.initReadSize = ActivePlayer.header.firstFrameSize;
ActivePlayer.initReadFrame = frame;
}
if (ActivePlayer.audioExist) {
if (ActivePlayer.audioExist)
{
if (audioTrack < 0 || audioTrack >= ActivePlayer.audioInfo.sndNumTracks)
return FALSE;
ActivePlayer.curAudioTrack = audioTrack;
@ -385,18 +412,21 @@ BOOL THPPlayerPrepare(s32 frame, u8 flag, s32 audioTrack)
ActivePlayer.playFlag = flag & 1;
ActivePlayer.videoDecodeCount = 0;
if(ActivePlayer.onMemory) {
if (DVDReadPrio(&ActivePlayer.fileInfo, ActivePlayer.movieData, ActivePlayer.header.movieDataSize, ActivePlayer.header.movieDataOffsets, 2) < 0) {
if (ActivePlayer.onMemory)
{
if (DVDReadPrio(&ActivePlayer.fileInfo, ActivePlayer.movieData, ActivePlayer.header.movieDataSize, ActivePlayer.header.movieDataOffsets, 2) < 0)
{
return FALSE;
}
u8 *threadData = ActivePlayer.movieData + ActivePlayer.initOffset - ActivePlayer.header.movieDataOffsets;
threadData = ActivePlayer.movieData + ActivePlayer.initOffset - ActivePlayer.header.movieDataOffsets;
CreateVideoDecodeThread(22, threadData);
if (ActivePlayer.audioExist)
CreateAudioDecodeThread(21, threadData);
}
else {
else
{
CreateVideoDecodeThread(22, 0);
if (ActivePlayer.audioExist)
CreateAudioDecodeThread(21, NULL);
@ -405,7 +435,7 @@ BOOL THPPlayerPrepare(s32 frame, u8 flag, s32 audioTrack)
ActivePlayer.curVideoNumber = -1;
ActivePlayer.curAudioNumber = 0;
InitAllMessageQueue();
VideoDecodeThreadStart();
@ -431,7 +461,7 @@ BOOL THPPlayerPrepare(s32 frame, u8 flag, s32 audioTrack)
return TRUE;
}
return FALSE;
}
@ -450,7 +480,8 @@ BOOL THPPlayerPlay()
void THPPlayerStop()
{
if(ActivePlayer.open && ActivePlayer.state != 0) {
if (ActivePlayer.open && ActivePlayer.state != 0)
{
ActivePlayer.internalState = 0;
ActivePlayer.state = 0;
VISetPostRetraceCallback(OldVIPostCallback);
@ -461,12 +492,15 @@ void THPPlayerStop()
}
VideoDecodeThreadCancel();
if(ActivePlayer.audioExist) {
if (ActivePlayer.audioExist)
{
AudioDecodeThreadCancel();
quitAudio();
}
while(PopUsedTextureSet() != 0) {}
while (PopUsedTextureSet() != 0)
{
}
ActivePlayer.rampCount = 0;
ActivePlayer.curVolume = ActivePlayer.targetVolume;
@ -486,25 +520,31 @@ BOOL THPPlayerPause()
return FALSE;
}
static void PlayControl(u32 retraceCnt) {
static void PlayControl(u32 retraceCnt)
{
THPTextureSet *decodedTexture;
if (OldVIPostCallback != NULL)
OldVIPostCallback(retraceCnt);
THPTextureSet *decodedTexture = (THPTextureSet *)-1;
decodedTexture = (THPTextureSet *)-1;
if (ActivePlayer.open && ActivePlayer.state == 2)
{
if (ActivePlayer.dvdError || ActivePlayer.videoError) {
if (ActivePlayer.dvdError || ActivePlayer.videoError)
{
ActivePlayer.state = 5;
ActivePlayer.internalState = 5;
return;
}
if (++ActivePlayer.retaceCount == 0)
{
if(ProperTimingForStart()) {
if (ActivePlayer.audioExist) {
if (ActivePlayer.curVideoNumber - ActivePlayer.curAudioNumber <= 1) {
if (ProperTimingForStart())
{
if (ActivePlayer.audioExist)
{
if (ActivePlayer.curVideoNumber - ActivePlayer.curAudioNumber <= 1)
{
decodedTexture = (THPTextureSet *)PopDecodedTextureSet(NULL);
ActivePlayer.curVideoNumber++;
@ -514,11 +554,13 @@ static void PlayControl(u32 retraceCnt) {
ActivePlayer.curField ^= 1;
}
}
else {
else
{
ActivePlayer.internalState = 2;
}
}
}
else {
else
{
decodedTexture = (THPTextureSet *)PopDecodedTextureSet(NULL);
if (ActivePlayer.videoInfo.videoType != 0 &&
(ActivePlayer.header.frameRate == 59.94f || ActivePlayer.header.frameRate == 50.0f))
@ -527,17 +569,20 @@ static void PlayControl(u32 retraceCnt) {
}
}
}
else {
else
{
ActivePlayer.retaceCount = -1;
}
}
else {
else
{
if (ActivePlayer.retaceCount == 1)
{
ActivePlayer.internalState = 2;
}
if(ProperTimingForGettingNextFrame()) {
if (ProperTimingForGettingNextFrame())
{
if (ActivePlayer.audioExist)
{
if (ActivePlayer.curVideoNumber - ActivePlayer.curAudioNumber <= 1)
@ -570,9 +615,9 @@ static void PlayControl(u32 retraceCnt) {
PushUsedTextureSet(ActivePlayer.dispTextureSet);
ActivePlayer.dispTextureSet = decodedTexture;
}
if ((ActivePlayer.playFlag & 1) == 0) {
if ((ActivePlayer.playFlag & 1) == 0)
{
if (ActivePlayer.audioExist)
{
s32 audioFrame = ActivePlayer.curAudioNumber + ActivePlayer.initReadFrame;
@ -582,9 +627,11 @@ static void PlayControl(u32 retraceCnt) {
ActivePlayer.state = 3;
}
}
else {
else
{
s32 curFrame = ActivePlayer.dispTextureSet != NULL ? ActivePlayer.dispTextureSet->frameNumber + ActivePlayer.initReadFrame : ActivePlayer.initReadFrame - 1;
if (curFrame == ActivePlayer.header.numFrames - 1 && decodedTexture == NULL) {
if (curFrame == ActivePlayer.header.numFrames - 1 && decodedTexture == NULL)
{
ActivePlayer.internalState = 3;
ActivePlayer.state = 3;
}
@ -606,10 +653,12 @@ static BOOL ProperTimingForGettingNextFrame()
if (ActivePlayer.videoInfo.videoType == 0)
{
s32 rate = ActivePlayer.header.frameRate * 100.0f;
if(VIGetTvFormat() == VI_PAL) {
if (VIGetTvFormat() == VI_PAL)
{
ActivePlayer.curCount = ActivePlayer.retaceCount * rate / 5000;
}
else {
else
{
ActivePlayer.curCount = ActivePlayer.retaceCount * rate / 5994;
}
@ -617,9 +666,10 @@ static BOOL ProperTimingForGettingNextFrame()
{
ActivePlayer.prevCount = ActivePlayer.curCount;
return TRUE;
}
}
}
else {
else
{
if (ActivePlayer.curField == VIGetNextField())
{
return TRUE;
@ -659,10 +709,9 @@ BOOL THPPlayerGetVideoInfo(void *dst)
u32 THPPlayerGetTotalFrame()
{
if (ActivePlayer.open != 0)
{
if (ActivePlayer.open)
return ActivePlayer.header.numFrames;
}
return 0;
}
@ -679,23 +728,26 @@ static void PushUsedTextureSet(OSMessage msg)
static OSMessage PopUsedTextureSet()
{
OSMessage msg; // TODO: correct type
if(OSReceiveMessage(&UsedTextureSetQueue, &msg, OS_MESSAGE_NOBLOCK) == 1) {
if (OSReceiveMessage(&UsedTextureSetQueue, &msg, OS_MESSAGE_NOBLOCK) == 1)
return msg;
}
return NULL;
}
void THPPlayerPostDrawDone() {
if(Initialized) {
void THPPlayerPostDrawDone()
{
if (Initialized)
{
OSMessage msg;
while(TRUE)
while (TRUE)
{
msg = PopUsedTextureSet();
if(msg == NULL) {
if (msg == NULL)
{
break;
}
PushFreeTextureSet(msg);
}
PushFreeTextureSet(msg);
}
}
}
@ -709,6 +761,10 @@ static void MixAudio(s16 *buf, u32 n)
s16 *aBuf;
n2 = n;
aBuf = buf;
s16 *curPtr;
s32 vol2, vol1;
u16 volFromTable;
do
{
do
@ -730,7 +786,7 @@ static void MixAudio(s16 *buf, u32 n)
lastSample = n2;
}
s16 *curPtr = ActivePlayer.playAudioBuffer->curPtr;
curPtr = ActivePlayer.playAudioBuffer->curPtr;
for (i = 0; i < lastSample; i++)
{
@ -743,8 +799,8 @@ static void MixAudio(s16 *buf, u32 n)
{
ActivePlayer.curVolume = ActivePlayer.targetVolume;
}
s32 vol2, vol1;
u16 volFromTable = VolumeTable[(s32)ActivePlayer.curVolume];
volFromTable = VolumeTable[(s32)ActivePlayer.curVolume];
vol1 = volFromTable * curPtr[0] >> 15;
// clamp volume
@ -797,36 +853,40 @@ static void MixAudio(s16 *buf, u32 n)
BOOL THPPlayerSetVolume(s32 vol, s32 duration)
{
if(ActivePlayer.open && ActivePlayer.audioExist) {
u32 numSamples = AIGetDSPSampleRate() == 0 ? 32 : 48;
u32 numSamples;
BOOL interrupt;
if (ActivePlayer.open && ActivePlayer.audioExist)
{
numSamples = AIGetDSPSampleRate() == 0 ? 32 : 48;
// clamp volume
if (vol > 127)
vol = 127;
if(vol < 0)
if (vol < 0)
vol = 0;
// clamp duration
if(duration > 60000)
if (duration > 60000)
duration = 60000;
if (duration < 0)
duration = 0;
BOOL interrupt = OSDisableInterrupts();
interrupt = OSDisableInterrupts();
ActivePlayer.targetVolume = vol;
if(duration != 0) {
if (duration != 0)
{
ActivePlayer.rampCount = numSamples * duration;
ActivePlayer.deltaVolume = (ActivePlayer.targetVolume - ActivePlayer.curVolume) / ActivePlayer.rampCount;
}
else {
else
{
ActivePlayer.rampCount = 0;
ActivePlayer.curVolume = ActivePlayer.targetVolume;
}
OSRestoreInterrupts(interrupt);
return TRUE;
}
}
return FALSE;
}

128
src/Kaneshige/THP/THPRead.c Normal file
View File

@ -0,0 +1,128 @@
#include "Kaneshige/THP/THPRead.h"
#include "Kaneshige/THP/THPPlayer.h"
#include "ppcdis.h"
#define STACK_SIZE 4096
#define MESSAGE_COUNT 10
static OSMessageQueue FreeReadBufferQueue;
static OSMessageQueue ReadedBufferQueue;
static OSMessageQueue ReadedBufferQueue2;
static OSMessage FreeReadBufferMessage[MESSAGE_COUNT];
static OSMessage ReadedBufferMessage[MESSAGE_COUNT];
static OSMessage ReadedBufferMessage2[MESSAGE_COUNT];
static OSThread ReadThread;
static u8 ReadThreadStack[STACK_SIZE];
static void *Reader(void *arg);
static BOOL ReadThreadCreated;
BOOL CreateReadThread(OSPriority prio)
{
if (OSCreateThread(&ReadThread, Reader, NULL, ReadThreadStack + STACK_SIZE, STACK_SIZE, prio, 1) == FALSE)
return FALSE;
OSInitMessageQueue(&FreeReadBufferQueue, FreeReadBufferMessage, MESSAGE_COUNT);
OSInitMessageQueue(&ReadedBufferQueue, ReadedBufferMessage, MESSAGE_COUNT);
OSInitMessageQueue(&ReadedBufferQueue2, ReadedBufferMessage2, MESSAGE_COUNT);
ReadThreadCreated = TRUE;
return TRUE;
}
void ReadThreadStart()
{
if (ReadThreadCreated)
OSResumeThread(&ReadThread);
}
void ReadThreadCancel()
{
if (ReadThreadCreated)
{
OSCancelThread(&ReadThread);
ReadThreadCreated = FALSE;
}
}
static void *Reader(void *arg)
{
THPReadBuffer *buf;
s32 curFrame;
s32 status;
s32 offset = ActivePlayer.initOffset;
s32 initReadSize = ActivePlayer.initReadSize;
s32 frame = 0;
while (TRUE)
{
buf = (THPReadBuffer *)PopFreeReadBuffer();
status = DVDReadPrio(&ActivePlayer.fileInfo, buf->ptr, initReadSize, offset, 2);
if (status != initReadSize)
{
if (status == -1)
ActivePlayer.dvdError = -1;
if (frame == 0)
PrepareReady(FALSE);
OSSuspendThread(&ReadThread);
}
buf->frameNumber = frame;
PushReadedBuffer(buf);
offset += initReadSize;
initReadSize = *(s32*)buf->ptr;
curFrame = (frame + ActivePlayer.initReadFrame) % ActivePlayer.header.numFrames;
if (curFrame == ActivePlayer.header.numFrames - 1)
{
if ((ActivePlayer.playFlag & 1))
offset = ActivePlayer.header.movieDataOffsets;
else
OSSuspendThread(&ReadThread);
}
frame++;
}
}
void *PopReadedBuffer()
{
void *buffer;
OSReceiveMessage(&ReadedBufferQueue, &buffer, OS_MESSAGE_BLOCK);
return buffer;
}
void *PushReadedBuffer(void *buffer)
{
OSSendMessage(&ReadedBufferQueue, buffer, 1);
}
void *PopFreeReadBuffer()
{
void *buffer;
OSReceiveMessage(&FreeReadBufferQueue, &buffer, OS_MESSAGE_BLOCK);
return buffer;
}
void PushFreeReadBuffer(void *buffer)
{
OSSendMessage(&FreeReadBufferQueue, buffer, 1);
}
void *PopReadedBuffer2()
{
void *buffer;
OSReceiveMessage(&ReadedBufferQueue2, &buffer, OS_MESSAGE_BLOCK);
return buffer;
}
void PushReadedBuffer2(void *buffer)
{
OSSendMessage(&ReadedBufferQueue2, buffer, 1);
}