summaryrefslogtreecommitdiff
path: root/libs/revolution/src/exi/EXICommon.c
blob: e53525fbba07bffb8f4089f895ab36e73936908c (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <revolution/types.h>
#include <revolution/os.h>
#include <revolution/exi.h>

const u32 __EXIFreq = 4;

s32 EXIGetConsoleType(void) {
    return 1;
}

void EXIWait(void) {
    while (__OSDeviceCode == 0) {}
}

static u32 __EXISwap32(u32 val) {
    return val >> 24 & 0x000000FF | val >> 8 & 0x0000FF00 | val << 8 & 0x00FF0000 | val << 24 & 0xFF000000;
}

BOOL EXIWriteReg(s32 chan, u32 dev, u32 exiCmd, void* reg, s32 size) {
    BOOL ret = FALSE;
    u32 reg32;

    switch (size) {
    case 1:
        reg32 = (u32)((*((u8*)reg) & 0xFF) << 24);
        break;
    case 2:
        reg32 = (u32)(((*((u16*)reg) & 0xFF) << 24) | ((*((u16*)reg) & 0xFF00) << 8));
        break;
    default:
        reg32 = __EXISwap32(*((u32*)reg));
        break;
    }

    ret |= !EXILock(chan, dev, 0);

    if (ret) {
        return FALSE;
    }

    ret |= !EXISelect(chan, dev, 4);

    if (ret) {
        EXIUnlock(chan);
        return FALSE;
    }

    ret |= !EXIImm(chan, &exiCmd, 4, 1, NULL);
    ret |= !EXISync(chan);
    ret |= !EXIImm(chan, &reg32, 4, 1, NULL);
    ret |= !EXISync(chan);
    ret |= !EXIDeselect(chan);
    ret |= !EXIUnlock(chan);
    return !ret;
}

BOOL EXIReadRam(s32 chan, u32 dev, u32 exiCmd, void* buffer, s32 size, EXICallback callback) {
    BOOL ret = FALSE;

    ret |= !EXILock(chan, dev, NULL);

    if (ret) {
        return FALSE;
    }

    ret |= !EXISelect(chan, dev, 4);

    if (ret) {
        EXIUnlock(chan);
        return FALSE;
    }

    ret |= !EXIImm(chan, &exiCmd, 4, 1, NULL);
    ret |= !EXISync(chan);
    ret |= !EXIDma(chan, buffer, size, EXI_READ, callback);

    if (callback == NULL) {
        ret |= !EXISync(chan);
        ret |= !EXIDeselect(chan);
        ret |= !EXIUnlock(chan);
    }
    
    return !ret;
}

BOOL EXIWriteRam(s32 chan, u32 dev, u32 exiCmd, void* buffer, s32 size, EXICallback callback) {
    BOOL ret = FALSE;

    ret |= !EXILock(chan, dev, NULL);

    if (ret) {
        return FALSE;
    }

    ret |= !EXISelect(chan, dev, 4);

    if (ret) {
        EXIUnlock(chan);
        return FALSE;
    }

    ret |= !EXIImm(chan, &exiCmd, 4, 1, NULL);
    ret |= !EXISync(chan);
    ret |= !EXIDma(chan, buffer, size, EXI_WRITE, callback);

    if (callback == NULL) {
        ret |= !EXISync(chan);
        ret |= !EXIDeselect(chan);
        ret |= !EXIUnlock(chan);
    }
    
    return !ret;
}