1
2 static uae_u8 *inprec_buffer, *inprec_p;
3 static struct zfile *inprec_zf;
4 static int inprec_size;
5 int input_recording = 0;
6 static uae_u8 *inprec_plast, *inprec_plastptr;
7 static int inprec_div;
8
9 static uae_u32 oldbuttons[4];
10 static uae_u16 oldjoy[2];
11
inprec_open(char * fname,int record)12 int inprec_open(char *fname, int record)
13 {
14 uae_u32 t = (uae_u32)time(0);
15 int i;
16
17 inprec_close();
18 inprec_zf = zfile_fopen(fname, record > 0 ? "wb" : "rb");
19 if (inprec_zf == NULL)
20 return 0;
21 inprec_size = 10000;
22 inprec_div = 1;
23 if (record < 0) {
24 uae_u32 id;
25 zfile_fseek (inprec_zf, 0, SEEK_END);
26 inprec_size = zfile_ftell (inprec_zf);
27 zfile_fseek (inprec_zf, 0, SEEK_SET);
28 inprec_buffer = inprec_p = (uae_u8*)xmalloc (inprec_size);
29 zfile_fread (inprec_buffer, inprec_size, 1, inprec_zf);
30 inprec_plastptr = inprec_buffer;
31 id = inprec_pu32();
32 if (id != 'UAE\0') {
33 inprec_close();
34 return 0;
35 }
36 inprec_pu32();
37 t = inprec_pu32();
38 i = inprec_pu32();
39 while (i-- > 0)
40 inprec_pu8();
41 inprec_p = inprec_plastptr;
42 oldbuttons[0] = oldbuttons[1] = oldbuttons[2] = oldbuttons[3] = 0;
43 oldjoy[0] = oldjoy[1] = 0;
44 if (record < -1)
45 inprec_div = maxvpos;
46 } else if (record > 0) {
47 inprec_buffer = inprec_p = (uae_u8*)xmalloc (inprec_size);
48 inprec_ru32('UAE\0');
49 inprec_ru8(1);
50 inprec_ru8(UAEMAJOR);
51 inprec_ru8(UAEMINOR);
52 inprec_ru8(UAESUBREV);
53 inprec_ru32(t);
54 inprec_ru32(0); // extra header size
55 } else {
56 return 0;
57 }
58 input_recording = record;
59 srand(t);
60 CIA_inprec_prepare();
61 write_log ("inprec initialized '%s', mode=%d\n", fname, input_recording);
62 return 1;
63 }
64
inprec_close(void)65 void inprec_close(void)
66 {
67 if (!inprec_zf)
68 return;
69 if (inprec_buffer && input_recording > 0) {
70 hsync_counter++;
71 inprec_rstart(INPREC_END);
72 inprec_rend();
73 hsync_counter--;
74 zfile_fwrite (inprec_buffer, inprec_p - inprec_buffer, 1, inprec_zf);
75 inprec_p = inprec_buffer;
76 }
77 zfile_fclose (inprec_zf);
78 inprec_zf = NULL;
79 xfree (inprec_buffer);
80 inprec_buffer = NULL;
81 input_recording = 0;
82 write_log ("inprec finished\n");
83 }
84
inprec_ru8(uae_u8 v)85 void inprec_ru8(uae_u8 v)
86 {
87 *inprec_p++= v;
88 }
inprec_ru16(uae_u16 v)89 void inprec_ru16(uae_u16 v)
90 {
91 inprec_ru8((uae_u8)(v >> 8));
92 inprec_ru8((uae_u8)v);
93 }
inprec_ru32(uae_u32 v)94 void inprec_ru32(uae_u32 v)
95 {
96 inprec_ru16((uae_u16)(v >> 16));
97 inprec_ru16((uae_u16)v);
98 }
inprec_rstr(const char * s)99 void inprec_rstr(const char *s)
100 {
101 while(*s) {
102 inprec_ru8(*s);
103 s++;
104 }
105 inprec_ru8(0);
106 }
inprec_rstart(uae_u8 type)107 void inprec_rstart(uae_u8 type)
108 {
109 write_log ("INPREC: %08X: %d\n", hsync_counter, type);
110 inprec_ru32(hsync_counter);
111 inprec_ru8(0);
112 inprec_plast = inprec_p;
113 inprec_ru8(0xff);
114 inprec_ru8(type);
115 }
inprec_rend(void)116 void inprec_rend(void)
117 {
118 *inprec_plast = inprec_p - (inprec_plast + 2);
119 if (inprec_p >= inprec_buffer + inprec_size - 256) {
120 zfile_fwrite (inprec_buffer, inprec_p - inprec_buffer, 1, inprec_zf);
121 inprec_p = inprec_buffer;
122 }
123 }
124
inprec_pstart(uae_u8 type)125 int inprec_pstart(uae_u8 type)
126 {
127 uae_u8 *p = inprec_p;
128 uae_u32 hc = hsync_counter;
129 static uae_u8 *lastp;
130 uae_u32 hc_orig, hc2_orig;
131
132 if (savestate_state)
133 return 0;
134 if (p[5 + 1] == INPREC_END) {
135 inprec_close();
136 return 0;
137 }
138 hc_orig = hc;
139 hc /= inprec_div;
140 hc *= inprec_div;
141 for (;;) {
142 uae_u32 hc2 = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
143 if (p > lastp) {
144 write_log ("INPREC: Next %08x (%08x=%d): %d (%d)\n", hc2, hc, hc2 - hc, p[5 + 1], p[5]);
145 lastp = p;
146 }
147 hc2_orig = hc2;
148 hc2 /= inprec_div;
149 hc2 *= inprec_div;
150 if (hc > hc2) {
151 write_log ("INPREC: %08x > %08x: %d (%d) missed!\n", hc, hc2, p[5 + 1], p[5]);
152 inprec_close();
153 return 0;
154 }
155 if (hc2 != hc) {
156 lastp = p;
157 break;
158 }
159 if (p[5 + 1] == type) {
160 write_log ("INPREC: %08x: %d (%d) (%+d)\n", hc, type, p[5], hc_orig - hc2_orig);
161 inprec_plast = p;
162 inprec_plastptr = p + 5 + 2;
163 return 1;
164 }
165 p += 5 + 2 + p[5];
166 }
167 inprec_plast = NULL;
168 return 0;
169 }
inprec_pend(void)170 void inprec_pend(void)
171 {
172 uae_u8 *p = inprec_p;
173 uae_u32 hc = hsync_counter;
174
175 if (!inprec_plast)
176 return;
177 inprec_plast[5 + 1] = 0;
178 inprec_plast = NULL;
179 inprec_plastptr = NULL;
180 hc /= inprec_div;
181 hc *= inprec_div;
182 for (;;) {
183 uae_u32 hc2 = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
184 hc2 /= inprec_div;
185 hc2 *= inprec_div;
186 if (hc2 != hc)
187 break;
188 if (p[5 + 1] != 0)
189 return;
190 p += 5 + 2 + p[5];
191 }
192 inprec_p = p;
193 if (p[5 + 1] == INPREC_END)
194 inprec_close();
195 }
196
inprec_pu8(void)197 uae_u8 inprec_pu8(void)
198 {
199 return *inprec_plastptr++;
200 }
inprec_pu16(void)201 uae_u16 inprec_pu16(void)
202 {
203 uae_u16 v = inprec_pu8() << 8;
204 v |= inprec_pu8();
205 return v;
206 }
inprec_pu32(void)207 uae_u32 inprec_pu32(void)
208 {
209 uae_u32 v = inprec_pu16() << 16;
210 v |= inprec_pu16();
211 return v;
212 }
inprec_pstr(char * s)213 int inprec_pstr(char *s)
214 {
215 int len = 0;
216 for(;;) {
217 uae_u8 v = inprec_pu8();
218 *s++ = v;
219 if (!v)
220 break;
221 len++;
222 }
223 return len;
224 }
225