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
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gpu.h"
static inline unsigned int pcnt_get(void)
{
unsigned int val;
#ifdef __ARM_ARCH_7A__
asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(val));
#else
val = 0;
#endif
return val;
}
static inline void pcnt_init(void)
{
#ifdef __ARM_ARCH_7A__
int v;
asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(v));
v |= 5; // master enable, ccnt reset
v &= ~8; // ccnt divider 0
asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(v));
// enable cycle counter
asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(1<<31));
#endif
}
const unsigned char cmd_lengths[256] =
{
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3, 3, 3, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, // 20
5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7, 11, 11, 11, 11,
2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, // 40
3, 3, 3, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, // 60
1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
struct psx_gpu gpu __attribute__((aligned(64)));
typedef struct
{
uint16_t vram[1024 * 512];
uint32_t gpu_register[15];
uint32_t status;
} gpu_dump_struct;
static gpu_dump_struct state;
int main(int argc, char *argv[])
{
unsigned int start_cycles;
uint32_t *list;
int size;
FILE *state_file;
FILE *list_file;
FILE *out_file;
if (argc != 3 && argc != 4)
{
printf("usage:\n%s <state> <list> [vram_out]\n", argv[0]);
return 1;
}
state_file = fopen(argv[1], "rb");
fread(&state, 1, sizeof(gpu_dump_struct), state_file);
fclose(state_file);
list_file = fopen(argv[2], "rb");
fseek(list_file, 0, SEEK_END);
size = ftell(list_file);
fseek(list_file, 0, SEEK_SET);
list = (uint32_t *)malloc(size);
fread(list, 1, size, list_file);
fclose(list_file);
pcnt_init();
renderer_init();
memcpy(gpu.vram, state.vram, sizeof(gpu.vram));
if ((state.gpu_register[8] & 0x24) == 0x24)
renderer_set_interlace(1, !(state.status >> 31));
start_cycles = pcnt_get();
do_cmd_list(list, size / 4);
renderer_flush_queues();
printf("%u\n", pcnt_get() - start_cycles);
if (argc >= 4) {
out_file = fopen(argv[3], "wb");
fwrite(gpu.vram, 1, sizeof(gpu.vram), out_file);
fclose(out_file);
}
return 0;
}
|