1
2 /*
3 * O2EM Free Odyssey2 / Videopac+ Emulator
4 *
5 * Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
6 *
7 * Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
8 *
9 * http://o2em.sourceforge.net
10 *
11 *
12 *
13 * Main O2 machine emulation
14 */
15
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <time.h>
20 #include "audio.h"
21 #include "types.h"
22 #include "cpu.h"
23 #include "keyboard.h"
24 #include "config.h"
25 #include "debug.h"
26 #include "vdc.h"
27 #include "vpp.h"
28 #include "timefunc.h"
29 #include "voice.h"
30 #include "vmachine.h"
31 #include "allegro.h"
32
33
34 static Byte x_latch,y_latch;
35 static int romlatch=0;
36 static Byte line_count;
37 static int fps=FPS_NTSC;
38
39 static Byte snapedlines[MAXLINES+2*MAXSNAP][256][2];
40
41 int evblclk=EVBLCLK_NTSC;
42
43 struct resource app_data;
44 int frame=0;
45 Byte dbstick1,dbstick2;
46
47 int int_clk; /* counter for length of /INT pulses */
48 int master_clk; /* Master clock */
49 int h_clk; /* horizontal clock */
50 unsigned long clk_counter;
51 int last_line;
52 int key2vcnt=0;
53 int mstate;
54
55 int pendirq=0;
56 int enahirq=1;
57 int useforen=0;
58 long regionoff=0xffff;
59 int mxsnap=2;
60 int sproff=0;
61 int tweakedaudio=0;
62
63 Byte rom_table[8][4096];
64
65 Byte intRAM[64];
66 Byte extRAM[256];
67 Byte extROM[1024];
68 Byte VDCwrite[256];
69 Byte ColorVector[MAXLINES];
70 Byte AudioVector[MAXLINES];
71 Byte *rom;
72
73 int key2[128];
74
75
76 static unsigned int key_map[6][8]= {
77 {KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7},
78 {KEY_8,KEY_9,0,0,KEY_SPACE,KEY_SLASH,KEY_L,KEY_P},
79 {KEY_PLUS_PAD,KEY_W,KEY_E,KEY_R,KEY_T,KEY_U,KEY_I,KEY_O},
80 {KEY_Q,KEY_S,KEY_D,KEY_F,KEY_G,KEY_H,KEY_J,KEY_K},
81 {KEY_A,KEY_Z,KEY_X,KEY_C,KEY_V,KEY_B,KEY_M,KEY_STOP},
82 {KEY_MINUS,KEY_ASTERISK,KEY_SLASH_PAD,KEY_EQUALS,KEY_Y,KEY_N,KEY_DEL,KEY_ENTER}
83 };
84
85
86 static void do_kluges(void);
87 static void setvideomode(int t);
88
run(void)89 void run(void){
90 while(!key_done) {
91
92 if (key_debug) {
93 app_data.debug=1;
94 set_textmode();
95 mute_audio();
96 mute_voice();
97 debug();
98 grmode();
99 app_data.debug=0;
100 init_keyboard();
101 init_sound_stream();
102 }
103
104 cpu_exec();
105
106 }
107 close_audio();
108 close_voice();
109 close_display();
110 }
111
112
handle_vbl(void)113 void handle_vbl(void){
114 if (!app_data.debug) {
115 handle_key();
116 update_audio();
117 update_voice();
118 }
119 draw_region();
120 ext_IRQ();
121 mstate = 1;
122 }
123
124
handle_evbl(void)125 void handle_evbl(void){
126 static long last=0;
127 static int rest_cnt=0;
128 int i;
129
130 #ifndef ALLEGRO_DOS
131 yield_timeslice();
132 #endif
133 i = (15*app_data.speed/100);
134 rest_cnt = (rest_cnt+1)%(i<5?5:i);
135 #ifdef ALLEGRO_WINDOWS
136 if (rest_cnt==0) rest(1);
137 #endif
138 last_line=0;
139 master_clk -= evblclk;
140 frame++;
141 if (!app_data.debug) {
142 finish_display();
143 }
144
145 for (i=0; i<MAXLINES; i++) {
146 ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80);
147 AudioVector[i] = VDCwrite[0xAA];
148 }
149
150 if (key2vcnt++ > 10) {
151 key2vcnt=0;
152 for (i=0; i<128; i++) key2[i] = 0;
153 dbstick1 = dbstick2 = 0;
154 }
155 if (app_data.limit) {
156 long d,f;
157 d = (TICKSPERSEC*100)/(app_data.speed*fps);
158 f = ((d-gettimeticks()+last)*1000)/TICKSPERSEC;
159 if (f>0) {
160 #ifdef ALLEGRO_WINDOWS
161 f = f-(f%10);
162 if (f>5) rest(f-5);
163 #else
164 #ifndef ALLEGRO_DOS
165 yield_timeslice();
166 #endif
167 #endif
168 }
169 while (gettimeticks() - last < d);
170 last = gettimeticks();
171 }
172 mstate=0;
173 }
174
175
init_system(void)176 void init_system(void){
177 int i,j,k;
178
179 last_line=0;
180 dbstick1=0x00;
181 dbstick2=0x00;
182 mstate=0;
183 master_clk=0;
184 h_clk=0;
185 line_count=0;
186 itimer=0;
187 clk_counter=0;
188 init_roms();
189 for(i=0; i<256; i++) {
190 VDCwrite[i]=0;
191 extRAM[i]=0;
192 }
193 for(i=0; i<64; i++) {
194 intRAM[i]=0;
195 }
196 for (i=0; i<MAXLINES; i++) AudioVector[i] = ColorVector[i] = 0;
197
198 for (i=0; i<MAXLINES+2*MAXSNAP; i++)
199 for (j=0; j<256; j++)
200 for (k=0; k<2; k++)
201 snapedlines[i][j][k]=0;
202
203 if (app_data.stick[0] == 2 || app_data.stick[1] == 2) {
204 i = install_joystick(JOY_TYPE_AUTODETECT);
205 if (i || (num_joysticks<1)) {
206 fprintf(stderr,"Error: no joystick detected\n");
207 exit(EXIT_FAILURE);
208 }
209 }
210 for (i=0; i<128; i++) key2[i] = 0;
211 key2vcnt=0;
212 if (app_data.euro)
213 setvideomode(1);
214 else
215 setvideomode(0);
216 do_kluges();
217 init_vpp();
218 clear_collision();
219 }
220
221
init_roms(void)222 void init_roms(void){
223 rom=rom_table[0];
224 romlatch=0;
225 }
226
227
read_t1(void)228 Byte read_t1(void){
229 if ((h_clk > 16) || (master_clk > VBLCLK))
230 return 1;
231 else
232 return 0;
233 }
234
235
write_p1(Byte d)236 void write_p1(Byte d){
237 if ((d & 0x80) != (p1 & 0x80)) {
238 int i,l;
239 l = snapline((int)((float)master_clk/22.0+0.1), VDCwrite[0xA3], 1);
240 for (i=l; i<MAXLINES; i++) ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (d & 0x80);
241 }
242 p1 = d;
243 if (app_data.bank == 2) {
244 rom=rom_table[~p1 & 0x01];
245 } else if (app_data.bank == 3) {
246 rom=rom_table[~p1 & 0x03];
247 } else if (app_data.bank == 4) {
248 rom=rom_table[(p1 & 1)?0:romlatch];
249 }
250 }
251
252
read_P2(void)253 Byte read_P2(void){
254 int i,si,so,km;
255
256 if (NeedsPoll) poll_keyboard();
257
258 if (!(p1 & 0x04)) {
259 si = (p2 & 7);
260 so=0xff;
261 if (si<6) {
262 for (i=0; i<8; i++) {
263 km = key_map[si][i];
264 if ((key[km] && ((!joykeystab[km]) || (key_shifts & KB_CAPSLOCK_FLAG))) || (key2[km])) {
265 so = i ^ 0x07;
266 }
267 }
268 }
269 if (so != 0xff) {
270 p2 = p2 & 0x0F;
271 p2 = p2 | (so << 5);
272 } else {
273 p2 = p2 | 0xF0;
274 }
275 } else {
276 p2 = p2 | 0xF0;
277 }
278 return(p2);
279
280 }
281
282
ext_read(ADDRESS adr)283 Byte ext_read(ADDRESS adr){
284 Byte d;
285 Byte si;
286 Byte m;
287 int i;
288
289 if (!(p1 & 0x08) && !(p1 & 0x40)) {
290 /* Handle VDC Read */
291 switch(adr) {
292 case 0xA1:
293 d = VDCwrite[0xA0] & 0x02;
294 if (master_clk > VBLCLK) d = d | 0x08;
295 if (h_clk < (LINECNT-7)) d = d | 0x01;
296 if (sound_IRQ) d = d | 0x04;
297 sound_IRQ=0;
298 return d;
299 case 0xA2:
300 si = VDCwrite[0xA2];
301 m=0x01;
302 d=0;
303 for(i=0; i<8; i++) {
304 if (si & m) {
305 if (coltab[1] & m) d = d | (coltab[1] & (m ^ 0xFF));
306 if (coltab[2] & m) d = d | (coltab[2] & (m ^ 0xFF));
307 if (coltab[4] & m) d = d | (coltab[4] & (m ^ 0xFF));
308 if (coltab[8] & m) d = d | (coltab[8] & (m ^ 0xFF));
309 if (coltab[0x10] & m) d = d | (coltab[0x10] & (m ^ 0xFF));
310 if (coltab[0x20] & m) d = d | (coltab[0x20] & (m ^ 0xFF));
311 if (coltab[0x80] & m) d = d | (coltab[0x80] & (m ^ 0xFF));
312 }
313 m = m << 1;
314 }
315 clear_collision();
316 return d;
317 case 0xA5:
318 if (!(VDCwrite[0xA0] & 0x02)) {
319 return x_latch;
320 }
321 else {
322 x_latch = h_clk * 12;
323 return x_latch;
324 }
325 case 0xA4:
326 if (!(VDCwrite[0xA0] & 0x02)) {
327 return y_latch;
328 }
329 else {
330 y_latch = master_clk/22;
331 if (y_latch > 241) y_latch=0xFF;
332 return y_latch;
333 }
334 default:
335 return VDCwrite[adr];
336 }
337 } else if (!(p1 & 0x10)) {
338 /* Handle ext RAM Read */
339 return extRAM[adr & 0xFF];
340 } else if (!(p1 & 0x20)) {
341 /* Read a Videopac+ register */
342 return vpp_read(adr);
343 } else if (app_data.exrom && (p1 & 0x02)) {
344 /* Handle read from exrom */
345 return extROM[(p2 << 8) | (adr & 0xFF)];
346 }
347
348 return 0;
349 }
350
351
in_bus(void)352 Byte in_bus(void){
353 Byte si=0,d=0,mode=0,jn=0;
354
355 if ((p1 & 0x08) && (p1 & 0x10)) {
356 /* Handle joystick read */
357 if (!(p1 & 0x04)) {
358 si = (p2 & 7);
359 }
360 d=0xFF;
361 if (si == 1) {
362 mode = app_data.stick[0];
363 jn = 0;
364 } else {
365 mode = app_data.stick[1];
366 jn = 1;
367 }
368 switch(mode) {
369 case 1:
370 d = keyjoy(jn);
371 break;
372 case 2:
373 poll_joystick();
374 if (joy_up) d &= 0xFE;
375 if (joy_right) d &= 0xFD;
376 if (joy_down) d &= 0xFB;
377 if (joy_left) d &= 0xF7;
378 if (joy_b1) d &= 0xEF;
379 break;
380 }
381 if (si == 1) {
382 if (dbstick1) d = dbstick1;
383 } else {
384 if (dbstick2) d = dbstick2;
385 }
386 }
387 return d;
388 }
389
390
ext_write(Byte dat,ADDRESS adr)391 void ext_write(Byte dat, ADDRESS adr){
392 int i;
393
394 if (!(p1 & 0x08)) {
395 /* Handle VDC Write */
396 if (adr == 0xA0){
397 if ((VDCwrite[0xA0] & 0x02) && !(dat & 0x02)) {
398 y_latch = master_clk/22;
399 x_latch = h_clk * 12;
400 if (y_latch > 241) y_latch=0xFF;
401 }
402 if ((master_clk <= VBLCLK) && (VDCwrite[0xA0] != dat)) {
403 draw_region();
404 }
405 } else if (adr == 0xA3){
406 int l;
407 l = snapline((int)((float)master_clk/22.0+0.5), dat, 1);
408 for (i=l; i<MAXLINES; i++) ColorVector[i] = (dat & 0x7f) | (p1 & 0x80);
409 } else if (adr == 0xAA) {
410 for (i=master_clk/22; i<MAXLINES; i++) AudioVector[i]=dat;
411 }
412 VDCwrite[adr]=dat;
413 } else if (!(p1 & 0x10) && !(p1 & 0x40)) {
414 adr = adr & 0xFF;
415 if (adr < 0x80) {
416 /* Handle ext RAM Write */
417 extRAM[adr] = dat;
418 } else {
419
420 if (app_data.bank == 4) {
421 romlatch = (~dat) & 7;
422 rom=rom_table[(p1 & 1)?0:romlatch];
423 }
424
425 /* Handle The Voice */
426 if (!(dat & 0x20))
427 reset_voice();
428 else {
429 if (adr == 0xE4)
430 set_voice_bank(0);
431 else if ((adr >= 0xE8) && (adr <= 0xEF))
432 set_voice_bank(adr-0xE7);
433 else if (((adr >= 0x80) && (adr <= 0xDF)) || ((adr >= 0xF0) && (adr <= 0xFF)))
434 trigger_voice(adr);
435 }
436 }
437 } else if (!(p1 & 0x20)) {
438 /* Write to a Videopac+ register */
439 vpp_write(dat,adr);
440 }
441 }
442
443
do_kluges(void)444 static void do_kluges(void){
445 if (app_data.crc == 0xA7344D1F) pendirq=1; /* Atlantis */
446 if (app_data.crc == 0xFB83171E) pendirq=1; /* Blockout */
447 if (app_data.crc == 0xD38153F6) pendirq=1; /* Blockout (french) */
448 if (app_data.crc == 0x881CEAE4) pendirq=1; /* Wall Street */
449
450 if (app_data.crc == 0x9E42E766) useforen=1; /* Turtles */
451 if (app_data.crc == 0x1C750349) useforen=1; /* Turtles (European version) */
452 if (app_data.crc == 0x202F2749) useforen=1; /* Q*bert */
453 if (app_data.crc == 0x06861A9C) useforen=1; /* Flashpoint 5 (Videopac adaption) */
454
455 if (app_data.crc == 0xFB83171E) enahirq=0; /* Blockout*/
456 if (app_data.crc == 0xD38153F6) enahirq=0; /* Blockout (french) */
457
458 if (app_data.crc == 0xFB83171E) regionoff=1; /* Blockout*/
459 if (app_data.crc == 0xD38153F6) regionoff=1; /* Blockout (french) */
460 if (app_data.crc == 0x202F2749) regionoff=0; /* Q*bert */
461 if (app_data.crc == 0x5216771A) regionoff=1; /* Popeye */
462 if (app_data.crc == 0x0C2E4811) regionoff=11; /* Out of this World! / Helicopter Rescue! */
463 if (app_data.crc == 0x67069924) regionoff=11; /* Smithereens! */
464 if (app_data.crc == 0x44D1A8A5) regionoff=11; /* Smithereens! (European version) */
465 if (app_data.crc == 0x2391C2FB) regionoff=11; /* Smithereens! + */
466 if (app_data.crc == 0xBB4AD548) regionoff=11; /* Smithereens! modified 1 */
467 if (app_data.crc == 0x25057C11) regionoff=11; /* Smithereens! modified 2 */
468 if (app_data.crc == 0xB936BD78) regionoff=12; /* Type & Tell */
469 if (app_data.crc == 0xAD8B9AE0) regionoff=2; /* Type & Tell modified 1 */
470 if (app_data.crc == 0x5C02BEE6) regionoff=2; /* Type & Tell modified 2 */
471 if (app_data.crc == 0xDC30AD3D) regionoff=10; /* Dynasty! */
472 if (app_data.crc == 0x7810BAD5) regionoff=8; /* Dynasty! (European) */
473 if (app_data.crc == 0xA7344D1F) regionoff=0; /* Atlantis */
474 if (app_data.crc == 0xD0BC4EE6) regionoff=12; /* Frogger */
475 if (app_data.crc == 0xA57D84F3) regionoff=8; /* Frogger BR */
476 if (app_data.crc == 0x825976A9) regionoff=0; /* Mousing Cat 8kb */
477 if (app_data.crc == 0xF390BFEC) regionoff=0; /* Mousing Cat 4kb */
478 if (app_data.crc == 0x61A350E6) regionoff=0; /* Mousing Cat (french) */
479 if (app_data.crc == 0x3BFEF56B) regionoff=1; /* Four in 1 Row! */
480 if (app_data.crc == 0x7C747245) regionoff=1; /* Four in 1 Row! modified */
481 if (app_data.crc == 0x9B5E9356) regionoff=1; /* Four in 1 Row! (french) */
482
483 if (app_data.crc == 0x6CEBAB74) regionoff=12; /* P.T. Barnum's Acrobats! (European version) */
484 if (app_data.crc == 0xE7B26A56) regionoff=12; /* P.T. Barnum's Acrobats! (European version - Extra keys) */
485
486 if (app_data.crc == 0xFB83171E) mxsnap=3; /* Blockout*/
487 if (app_data.crc == 0xD38153F6) mxsnap=3; /* Blockout (french) */
488 if (app_data.crc == 0xA57E1724) mxsnap=12; /* Catch the Ball / Noughts and Crosses */
489 if (app_data.crc == 0xBE4FF48E) mxsnap=12; /* Catch the Ball / Noughts and Crosses modified */
490 if (app_data.crc == 0xFD179F6D) mxsnap=3; /* Clay Pigeon! */
491 if (app_data.crc == 0x9C9DDDF9) mxsnap=3; /* Verkehr */
492 if (app_data.crc == 0x95936B07) mxsnap=3; /* Super Cobra */
493 if (app_data.crc == 0x881CEAE4) mxsnap=3; /* Wall Street */
494 if (app_data.crc == 0x9E42E766) mxsnap=0; /* Turtles */
495 if (app_data.crc == 0x1C750349) mxsnap=0; /* Turtles (European version) */
496 if (app_data.crc == 0xD0BC4EE6) mxsnap=3; /* Frogger */
497 if (app_data.crc == 0xA57D84F3) mxsnap=3; /* Frogger BR */
498 if (app_data.crc == 0x3BFEF56B) mxsnap=6; /* Four in 1 Row! */
499 if (app_data.crc == 0x9B5E9356) mxsnap=6; /* Four in 1 Row! (french) */
500 if (app_data.crc == 0x7C747245) mxsnap=6; /* Four in 1 Row! modified */
501
502 if (app_data.crc == 0xA7344D1F) setvideomode(1); /* Atlantis */
503 if (app_data.crc == 0x39E31BF0) setvideomode(1); /* Jake */
504 if (app_data.crc == 0x92D0177B) setvideomode(1); /* Jake (hack) */
505 if (app_data.crc == 0x3351FEDA) setvideomode(1); /* Power Lords */
506 if (app_data.crc == 0x40AE062D) setvideomode(1); /* Power Lords (alternate) */
507 if (app_data.crc == 0xD158EEBA) setvideomode(1); /* Labirinth */
508 if (app_data.crc == 0x26B0FF5B) setvideomode(1); /* Nightmare */
509 if (app_data.crc == 0xDF36683F) setvideomode(1); /* Shark Hunter */
510 if (app_data.crc == 0xAF307559) setvideomode(1); /* Super Bee 8Kb */
511 if (app_data.crc == 0x9585D511) setvideomode(1); /* Super Bee 4Kb */
512 if (app_data.crc == 0x58FA6766) setvideomode(1); /* War of the Nerves */
513 if (app_data.crc == 0x58FA6766) setvideomode(1); /* War of the Nerves */
514 if (app_data.crc == 0x39989464) setvideomode(1); /* Hockey! / Soccer! */
515 if (app_data.crc == 0x3BFEF56B) setvideomode(1); /* Four in 1 Row! */
516 if (app_data.crc == 0x9B5E9356) setvideomode(1); /* Four in 1 Row! (french) */
517 if (app_data.crc == 0x7C747245) setvideomode(1); /* Four in 1 Row! modified */
518 if (app_data.crc == 0x68560DC7) setvideomode(1); /* Jopac Moto Crash */
519 if (app_data.crc == 0x020FCA15) setvideomode(1); /* Jopac Moto Crash modified (non VP+) */
520 if (app_data.crc == 0xC4134DF8) setvideomode(1); /* Helicopter Rescue + */
521 if (app_data.crc == 0x0D2D721D) setvideomode(1); /* Trans American Rally + */
522 if (app_data.crc == 0x9D72D4E9) setvideomode(1); /* Blobbers */
523 if (app_data.crc == 0xB2F0F0B4) setvideomode(1); /* Le Tresor Englouti + */
524 if (app_data.crc == 0x0B2DEB61) setvideomode(1); /* Tutankham */
525 if (app_data.crc == 0x313547EB) setvideomode(1); /* VP53 */
526 if (app_data.crc == 0x06861A9C) setvideomode(1); /* Flashpoint 5 (Videopac adaption) */
527 if (app_data.crc == 0xA57E1724) setvideomode(0); /* Catch the Ball / Noughts and Crosses */
528 if (app_data.crc == 0xBE4FF48E) setvideomode(0); /* Catch the Ball / Noughts and Crosses modified */
529 if (app_data.crc == 0xFB83171E) setvideomode(0); /* Blockout*/
530 if (app_data.crc == 0xD38153F6) setvideomode(0); /* Blockout (french) */
531 if (app_data.crc == 0x9BFC3E01) setvideomode(0); /* Demon Attack */
532 if (app_data.crc == 0x50AF9D45) setvideomode(0); /* Demon Attack + */
533 if (app_data.crc == 0x9884EF36) setvideomode(0); /* Demon Attack + modified */
534 if (app_data.crc == 0x4A578DFE) setvideomode(0); /* Restaurant ntsc */
535 if (app_data.crc == 0x863D5E2D) setvideomode(0); /* Shark Hunter ntsc */
536
537 if (app_data.crc == 0xD62814A3) evblclk=12000; /* Pick Axe Pete */
538 if (app_data.crc == 0xB2FFB353) evblclk=12000; /* Pick Axe Pete + */
539 if (app_data.crc == 0x81C20196) evblclk=12000; /* Pick Axe Pete + (modified) */
540
541 if ((app_data.crc == 0xF390BFEC) || (app_data.crc == 0x825976A9) || (app_data.crc == 0x61A350E6)){ /* Mousing Cat */
542 setvideomode(1);
543 evblclk=7642;
544 }
545 if (app_data.crc == 0xD0BC4EE6) { /* Frogger */
546 setvideomode(1);
547 evblclk=7642;
548 }
549 if ((app_data.crc == 0x2DCB77F0) || (app_data.crc == 0xF6882734)) { /* Depth Charge / Marksman */
550 setvideomode(1);
551 evblclk=8000;
552 }
553 if (app_data.crc == 0x881CEAE4) { /* Wall Street */
554 setvideomode(1);
555 evblclk=6100;
556 }
557
558 if (app_data.crc == 0xD0BC4EE6) tweakedaudio=1; /* Frogger */
559 if (app_data.crc == 0xA57D84F3) tweakedaudio=1; /* Frogger BR */
560 if (app_data.crc == 0x5216771A) tweakedaudio=1; /* Popeye */
561 if (app_data.crc == 0xAFB23F89) tweakedaudio=1; /* Musician */
562 if (app_data.crc == 0xC4134DF8) tweakedaudio=1; /* Helicopter Rescue + */
563 if (app_data.crc == 0x0D2D721D) tweakedaudio=1; /* Trans American Rally + */
564
565 if (app_data.crc == 0xD3B09FEC) sproff=1; /* Volleyball! */
566 if (app_data.crc == 0x551E38A2) sproff=1; /* Volleyball! (french) */
567
568 }
569
570
snapline(int pos,Byte reg,int t)571 int snapline(int pos, Byte reg, int t){
572 int i;
573 if (pos<MAXLINES+MAXSNAP+MAXSNAP) {
574 for (i=0; i<mxsnap; i++){
575 if (snapedlines[pos+MAXSNAP-i][reg][t]) return pos-i;
576 if (snapedlines[pos+MAXSNAP+i][reg][t]) return pos+i;
577 }
578 snapedlines[pos+MAXSNAP][reg][t]=1;
579 }
580 return pos;
581 }
582
583
setvideomode(int t)584 static void setvideomode(int t){
585 if (t) {
586 evblclk = EVBLCLK_PAL;
587 fps = FPS_PAL;
588 } else {
589 evblclk = EVBLCLK_NTSC;
590 fps = FPS_NTSC;
591 }
592 }
593
594
595