forked from satiator/satiator-menu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jhloader.c
127 lines (107 loc) · 2.67 KB
/
jhloader.c
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* Copyright (c) 2015 James Laird-Wah
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
#include <string.h>
#include <iapetus.h>
static int emulate_bios_loadcd_init(void) {
*(uint32_t*)0x6000278 = 0;
*(uint32_t*)0x600027c = 0;
cd_abort_file();
cd_end_transfer();
cd_reset_selector_all();
cd_set_sector_size(SECT_2048);
cd_auth(); // gotta make sure that's a real disc thar
return 0;
}
static struct region_s {
uint8_t id;
const char *key;
} regions[] = {
{1, "JAPAN"},
{2, "TAIWAN and PHILIPINES"},
{4, "USA and CANADA"},
{5, "BRAZIL"},
{6, "KOREA"},
{10, "ASIA PAL area"},
{12, "EUROPE"},
{13, "LATIN AMERICA"},
{0, NULL}
};
static const char *get_region_string(void) {
// fetch SMPC region byte
smpc_wait_till_ready();
SMPC_REG_IREG(0) = 0x01;
SMPC_REG_IREG(1) = 0x00;
SMPC_REG_IREG(2) = 0xf0;
smpc_issue_command(SMPC_CMD_INTBACK);
smpc_wait_till_ready();
uint8_t region = SMPC_REG_OREG(9);
struct region_s *r;
for (r=regions; r->id; r++)
if (r->id == region)
return r->key;
return NULL;
}
static int set_image_region(u8 *base)
{
const char *str = get_region_string();
if (!str)
return -1;
// set region header
memset(base + 0x40, ' ', 0x10);
base[0x40] = str[0];
// set region footer
char *ptr = (char*)base + 0xe00;
memset(ptr, ' ', 0x20);
*(uint32_t*)ptr = 0xa00e0009;
strcpy(ptr + 4, "For ");
strcpy(ptr + 8, str);
char *end = ptr + 4 + strlen(ptr + 4);
*end = '.';
return 0;
}
static int emulate_bios_loadcd_read(void)
{
int ret, i;
// doesn't matter where
u8 *ptr = (u8*)0x6002000;
ret = cd_read_sector(ptr, 150, SECT_2048, 2048*16);
if (ret < 0)
return ret;
ret = set_image_region(ptr);
if (ret < 0)
return ret;
ret = cd_put_sector_data(0, 16);
if (ret < 0)
return ret;
while (!(CDB_REG_HIRQ & HIRQ_DRDY)) {}
for (i = 0; i < 2048 * 16; i+=4)
CDB_REG_DATATRNS = *(uint32_t*)(ptr + i);
if ((ret = cd_end_transfer()) != 0)
return ret;
while (!(CDB_REG_HIRQ & HIRQ_EHST)) {}
*(uint16_t*)0x60003a0 = 1;
return 0;
}
int boot_disc(void)
{
int ret;
#if 0
// authentic boot
ret = bios_loadcd_init();
ret = bios_loadcd_read();
#else
// region free boot
if ((ret = emulate_bios_loadcd_init()) < 0)
return ret;
if ((ret = emulate_bios_loadcd_read()) < 0)
return ret;
#endif
do {
ret = bios_loadcd_boot();
vdp_vsync();
} while (ret == 1);
return ret;
}