adb4b2c6 |
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include "gpu.h" |
5 | |
6 | static inline unsigned int pcnt_get(void) |
7 | { |
8 | unsigned int val; |
9 | #ifdef __ARM_ARCH_7A__ |
10 | asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(val)); |
11 | #else |
12 | val = 0; |
13 | #endif |
14 | return val; |
15 | } |
16 | |
17 | static inline void pcnt_init(void) |
18 | { |
19 | #ifdef __ARM_ARCH_7A__ |
20 | int v; |
21 | asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(v)); |
22 | v |= 5; // master enable, ccnt reset |
23 | v &= ~8; // ccnt divider 0 |
24 | asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(v)); |
25 | // enable cycle counter |
26 | asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(1<<31)); |
27 | #endif |
28 | } |
29 | |
30 | const unsigned char cmd_lengths[256] = |
31 | { |
32 | 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
33 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
34 | 3, 3, 3, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, // 20 |
35 | 5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7, 11, 11, 11, 11, |
36 | 2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, // 40 |
37 | 3, 3, 3, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, |
38 | 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, // 60 |
39 | 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, |
40 | 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80 |
41 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
42 | 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a0 |
43 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
44 | 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c0 |
45 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e0 |
47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
48 | }; |
49 | |
50 | struct psx_gpu gpu __attribute__((aligned(64))); |
51 | |
52 | typedef struct |
53 | { |
54 | uint16_t vram[1024 * 512]; |
55 | uint32_t gpu_register[15]; |
56 | uint32_t status; |
57 | } gpu_dump_struct; |
58 | |
59 | static gpu_dump_struct state; |
60 | |
61 | int main(int argc, char *argv[]) |
62 | { |
63 | unsigned int start_cycles; |
64 | uint32_t *list; |
2e6189bc |
65 | int size, dummy; |
adb4b2c6 |
66 | FILE *state_file; |
67 | FILE *list_file; |
68 | FILE *out_file; |
69 | |
70 | if (argc != 3 && argc != 4) |
71 | { |
72 | printf("usage:\n%s <state> <list> [vram_out]\n", argv[0]); |
73 | return 1; |
74 | } |
75 | |
76 | state_file = fopen(argv[1], "rb"); |
77 | fread(&state, 1, sizeof(gpu_dump_struct), state_file); |
78 | fclose(state_file); |
79 | |
80 | list_file = fopen(argv[2], "rb"); |
81 | fseek(list_file, 0, SEEK_END); |
82 | size = ftell(list_file); |
83 | fseek(list_file, 0, SEEK_SET); |
84 | |
85 | list = (uint32_t *)malloc(size); |
86 | fread(list, 1, size, list_file); |
87 | fclose(list_file); |
88 | |
89 | pcnt_init(); |
90 | renderer_init(); |
91 | memcpy(gpu.vram, state.vram, sizeof(gpu.vram)); |
5440b88e |
92 | if ((state.gpu_register[8] & 0x24) == 0x24) |
93 | renderer_set_interlace(1, !(state.status >> 31)); |
adb4b2c6 |
94 | |
95 | start_cycles = pcnt_get(); |
96 | |
2e6189bc |
97 | do_cmd_list(list, size / 4, &dummy); |
adb4b2c6 |
98 | renderer_flush_queues(); |
99 | |
100 | printf("%u\n", pcnt_get() - start_cycles); |
101 | |
102 | if (argc >= 4) { |
103 | out_file = fopen(argv[3], "wb"); |
104 | fwrite(gpu.vram, 1, sizeof(gpu.vram), out_file); |
105 | fclose(out_file); |
106 | } |
107 | |
108 | return 0; |
109 | } |