summaryrefslogtreecommitdiff
path: root/src/m_Do/m_Do_DVDError.cpp
blob: 686b62dd7a145e046f288b12eb81648e027fb630 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
 * m_Do_DVDError.cpp
 * DVD Error Handling
 */

#include "m_Do/machine.h" // IWYU pragma: keep

#include "m_Do/m_Do_DVDError.h"
#include "JSystem/JKernel/JKRAssertHeap.h"
#include "JSystem/JKernel/JKRThread.h"
#include <os.h>
#include "m_Do/m_Do_dvd_thread.h"
#include "m_Do/m_Do_ext.h"
#include "m_Do/m_Do_Reset.h"

#if PLATFORM_GCN
const int stack_size = 3072;
#else
const int stack_size = 8192;
#endif


bool mDoDvdErr_initialized;

static OSThread DvdErr_thread;

#pragma push
#pragma force_active on
static u8 DvdErr_stack[stack_size] ATTRIBUTE_ALIGN(16);
#pragma pop

static OSAlarm Alarm;

void mDoDvdErr_ThdInit() {
    if (mDoDvdErr_initialized) {
        return;
    }

    OSTime time = OSGetTime();

    OSCreateThread(&DvdErr_thread, (void*(*)(void*))mDoDvdErr_Watch, NULL, DvdErr_stack + sizeof(DvdErr_stack),
                    sizeof(DvdErr_stack), OSGetThreadPriority(OSGetCurrentThread()) - 3, 1);
    OSResumeThread(&DvdErr_thread);
    OSCreateAlarm(&Alarm);
    OSSetPeriodicAlarm(&Alarm, time, OS_BUS_CLOCK / 4, AlarmHandler);

    mDoDvdErr_initialized = true;
}

void mDoDvdErr_ThdCleanup() {
    if (mDoDvdErr_initialized) {
        OSCancelThread(&DvdErr_thread);
        OSCancelAlarm(&Alarm);
        mDoDvdErr_initialized = false;
    }
}

static void mDoDvdErr_Watch(void*) {
#if PLATFORM_GCN
    OSDisableInterrupts();
#endif
    JKRThread(OSGetCurrentThread(), 0);

    JKRSetCurrentHeap(mDoExt_getAssertHeap());

    s32 status;
    do {
        status = DVDGetDriveStatus();
        if (status == DVD_STATE_FATAL_ERROR) {
            mDoDvdThd::suspend();
        }
        OSSuspendThread(&DvdErr_thread);
    } while (true);
}

static void AlarmHandler(OSAlarm*, OSContext*) {
    OSResumeThread(&DvdErr_thread);
}