Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/octoshock/test/miniclient/miniclient.cpp
2 views
1
#include <stdio.h>
2
3
#include "octoshock.h"
4
#include "psx/psx.h"
5
6
// lookup table for crc calculation
7
static uint16 subq_crctab[256] =
8
{
9
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
10
0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
11
0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
12
0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
13
0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
14
0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
15
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
16
0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
17
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
18
0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
19
0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
20
0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
21
0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
22
0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
23
0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
24
0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
25
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
26
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
27
0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
28
0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
29
0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
30
0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
31
0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
32
0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
33
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
34
0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
35
0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
36
0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
37
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
38
};
39
40
#ifndef __PACKED
41
#ifdef __GNUC__
42
#define __PACKED __attribute__((__packed__))
43
#else
44
#define __PACKED
45
#endif
46
#endif
47
48
#ifndef __GNUC__
49
#pragma pack(push, 1)
50
#pragma warning(disable : 4103)
51
#endif
52
struct bmpimgheader_struct
53
{
54
u32 size;
55
s32 width;
56
s32 height;
57
u16 planes;
58
u16 bpp;
59
u32 cmptype;
60
u32 imgsize;
61
s32 hppm;
62
s32 vppm;
63
u32 numcol;
64
u32 numimpcol;
65
} ;
66
struct bmpfileheader_struct
67
{
68
u16 id __PACKED;
69
u32 size __PACKED;
70
u16 reserved1 __PACKED;
71
u16 reserved2 __PACKED;
72
u32 imgoffset __PACKED;
73
};
74
#ifndef __GNUC__
75
#pragma pack(pop)
76
#endif
77
78
int WriteBMP32(int width, int height, const void* buf, const char *filename)
79
{
80
bmpfileheader_struct fileheader;
81
bmpimgheader_struct imageheader;
82
FILE *file;
83
size_t elems_written = 0;
84
memset(&fileheader, 0, sizeof(fileheader));
85
fileheader.size = sizeof(fileheader);
86
fileheader.id = 'B' | ('M' << 8);
87
fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
88
89
memset(&imageheader, 0, sizeof(imageheader));
90
imageheader.size = sizeof(imageheader);
91
imageheader.width = width;
92
imageheader.height = height;
93
imageheader.planes = 1;
94
imageheader.bpp = 32;
95
imageheader.cmptype = 0; // None
96
imageheader.imgsize = imageheader.width * imageheader.height * 4;
97
98
if ((file = fopen(filename,"wb")) == NULL)
99
return 0;
100
101
elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
102
elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
103
104
for(int i=0;i<height;i++)
105
for(int x=0;x<width;x++)
106
{
107
u8* pixel = (u8*)buf + (height-i-1)*width*4;
108
pixel += (x*4);
109
elems_written += fwrite(pixel+2,1,1,file);
110
elems_written += fwrite(pixel+1,1,1,file);
111
elems_written += fwrite(pixel+0,1,1,file);
112
elems_written += fwrite(pixel+3,1,1,file);
113
}
114
fclose(file);
115
116
return 1;
117
}
118
119
class BinReader2352
120
{
121
public:
122
BinReader2352(const char* path)
123
{
124
inf = fopen(path,"rb");
125
fseek(inf,0,SEEK_END);
126
size_t sz = ftell(inf);
127
fseek(inf,0,SEEK_SET);
128
lbaCount = (int)(sz/2352);
129
130
shock_CreateDisc(&disc,this,lbaCount,s_ReadTOC,s_ReadLBA2448,false);
131
}
132
133
ShockDiscRef* disc;
134
135
static s32 s_ReadTOC(void* opaque, ShockTOC *read_target, ShockTOCTrack tracks[100 + 1]) { return ((BinReader2352*)opaque)->ReadTOC(read_target, tracks); }
136
static s32 s_ReadLBA2448(void* opaque, s32 lba, void* dst) { return ((BinReader2352*)opaque)->ReadLBA2448(lba,dst); }
137
138
~BinReader2352()
139
{
140
fclose(inf);
141
shock_DestroyDisc(disc);
142
}
143
144
private:
145
int lbaCount;
146
FILE* inf;
147
148
149
union Sector {
150
struct {
151
u8 sync[12];
152
u8 adr[3];
153
u8 mode;
154
union {
155
struct {
156
u8 data2048[2048];
157
u8 ecc[4];
158
u8 reserved[8];
159
u8 ecm[276];
160
};
161
u8 data2336[2336];
162
};
163
};
164
u8 buf[2352];
165
};
166
167
union XASector {
168
struct {
169
u8 sync[12];
170
u8 adr[3];
171
u8 mode;
172
u8 subheader[8];
173
union {
174
u8 data2048[2048];
175
u8 ecc[4];
176
u8 ecm[276];
177
} form1;
178
union {
179
u8 data2334[2334];
180
u8 ecc[4];
181
} form2;
182
};
183
u8 buf[2352];
184
};
185
186
union {
187
XASector xasector;
188
Sector sector;
189
};
190
191
192
s32 ReadTOC( ShockTOC *read_target, ShockTOCTrack tracks[100 + 1])
193
{
194
memset(read_target,0,sizeof(*read_target));
195
read_target->disc_type = 0;
196
read_target->first_track = 1;
197
read_target->last_track = 1;
198
tracks[1].adr = 1;
199
tracks[1].lba = 0;
200
tracks[1].control = 4;
201
tracks[2].adr = 1;
202
tracks[2].lba = lbaCount;
203
tracks[2].control = 0;
204
tracks[100].adr = 1;
205
tracks[100].lba = lbaCount;
206
tracks[100].control = 0;
207
return SHOCK_OK;
208
}
209
210
s32 ReadLBA2448(s32 lba, void* dst)
211
{
212
fseek(inf,lba*2352,SEEK_SET);
213
fread(dst,1,2352,inf);
214
//do something for subcode I guess
215
memset((u8*)dst+2352,0,96);
216
hacky_MakeSubPQ(lba,(u8*)dst+2352,1,0);
217
218
//not the right thing to do
219
//return ((Sector*)dst)->mode;
220
221
return SHOCK_OK;
222
}
223
224
uint8 U8_to_BCD(uint8 num)
225
{
226
return( ((num / 10) << 4) + (num % 10) );
227
}
228
229
void subq_generate_checksum(uint8 *buf)
230
{
231
uint16 crc = 0;
232
233
for(int i = 0; i < 0xA; i++)
234
crc = subq_crctab[(crc >> 8) ^ buf[i]] ^ (crc << 8);
235
236
// Checksum
237
buf[0xa] = ~(crc >> 8);
238
buf[0xb] = ~(crc);
239
}
240
void hacky_MakeSubPQ(int lba, u8* SubPWBuf, int track, int track_start)
241
{
242
uint8 buf[0xC];
243
uint32 lba_relative;
244
uint32 ma, sa, fa;
245
uint32 m, s, f;
246
uint8 pause_or = 0x00;
247
248
lba_relative = abs((int32)lba - track_start);
249
250
f = (lba_relative % 75);
251
s = ((lba_relative / 75) % 60);
252
m = (lba_relative / 75 / 60);
253
254
fa = (lba + 150) % 75;
255
sa = ((lba + 150) / 75) % 60;
256
ma = ((lba + 150) / 75 / 60);
257
258
uint8 adr = 0x1; // Q channel data encodes position
259
260
memset(buf, 0, 0xC);
261
buf[0] = (adr << 0) | (0x04 << 4);
262
buf[1] = U8_to_BCD(track);
263
264
buf[2] = U8_to_BCD(0x01);
265
266
// Track relative MSF address
267
buf[3] = U8_to_BCD(m);
268
buf[4] = U8_to_BCD(s);
269
buf[5] = U8_to_BCD(f);
270
271
buf[6] = 0; // Zerroooo
272
273
// Absolute MSF address
274
buf[7] = U8_to_BCD(ma);
275
buf[8] = U8_to_BCD(sa);
276
buf[9] = U8_to_BCD(fa);
277
278
subq_generate_checksum(buf);
279
280
for(int i = 0; i < 96; i++)
281
SubPWBuf[i] |= (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | pause_or;
282
}
283
284
285
};
286
287
int main(int argc, char **argv)
288
{
289
const char* fwpath = argv[1];
290
const char* discpath = argv[2];
291
const char* outdir = argv[3];
292
293
FILE* inf;
294
295
//load up the firmware
296
char firmware[512*1024];
297
inf = fopen(fwpath,"rb");
298
fread(firmware,1,512*1024,inf);
299
fclose(inf);
300
301
BinReader2352 bin(discpath);
302
ShockDiscInfo info;
303
shock_AnalyzeDisc(bin.disc, &info);
304
printf("disc id: %s\n",info.id);
305
306
//placeholder for instance
307
void* psx = NULL;
308
309
shock_Create(&psx, REGION_NA, firmware);
310
shock_OpenTray(psx);
311
shock_SetDisc(psx,bin.disc);
312
shock_CloseTray(psx);
313
shock_Peripheral_Connect(psx,0x01,ePeripheralType_DualShock);
314
shock_PowerOn(psx);
315
316
int framectr = 0;
317
for(;;)
318
{
319
printf("frame %d\n",framectr);
320
shock_Step(psx,eShockStep_Frame);
321
if(framectr%60==0)
322
{
323
//dump a screen grab
324
ShockFramebufferInfo fbinfo;
325
static u32 buf[1024*1024];
326
fbinfo.ptr = buf;
327
fbinfo.flags = eShockFramebufferFlags_Normalize;
328
shock_GetFramebuffer(psx,&fbinfo);
329
char fname[128];
330
sprintf(fname,"%s\\test%03d.bmp",outdir,framectr/60);
331
WriteBMP32(fbinfo.width,fbinfo.height,buf,fname); //rgb is backwards
332
}
333
334
framectr++;
335
}
336
}
337