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