32x: some hacks..
[picodrive.git] / pico / 32x / memory.c
1 /*
2  * PicoDrive
3  * (C) notaz, 2009,2010,2013
4  *
5  * This work is licensed under the terms of MAME license.
6  * See COPYING file in the top-level directory.
7  *
8  * Register map:
9  * a15100 F....... R.....EA  F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
10  * a15102 ........ ......SM  ?                 4002 // intS intM
11  * a15104 ........ ......10  ........ hhhhhhhh 4004 // bk1 bk0 Hint
12  * a15106 ........ F....SDR  UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
13  * a15108           (32bit DREQ src)           4008
14  * a1510c           (32bit DREQ dst)           400c
15  * a15110          llllllll llllll00           4010 // DREQ Len
16  * a15112           (16bit FIFO reg)           4012
17  * a15114 0                  (16bit VRES clr)  4014
18  * a15116 0                  (16bit Vint clr)  4016
19  * a15118 0                  (16bit Hint clr)  4018
20  * a1511a .......? .......C  (16bit CMD clr)   401a // TV Cm
21  * a1511c 0                  (16bit PWM clr)   401c
22  * a1511e 0                  ?                 401e
23  * a15120            (16 bytes comm)           2020
24  * a15130                 (PWM)                2030
25  *
26  * SH2 addr lines:
27  * iii. .cc. ..xx *   // Internal, Cs, x
28  *
29  * sh2 map, wait/bus cycles (from docs):
30  *                             r    w
31  * rom      0000000-0003fff    1    -
32  * sys reg  0004000-00040ff    1    1
33  * vdp reg  0004100-00041ff    5    5
34  * vdp pal  0004200-00043ff    5    5
35  * cart     2000000-23fffff     6-15
36  * dram/fb  4000000-401ffff 5-12  1-3
37  * fb ovr   4020000-403ffff
38  * sdram    6000000-603ffff   12    2  (cycles)
39  * d.a.    c0000000-?
40  */
41 #include "../pico_int.h"
42 #include "../memory.h"
43 #include "../../cpu/sh2/compiler.h"
44
45 static const char str_mars[] = "MARS";
46
47 void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
48 struct Pico32xMem *Pico32xMem;
49
50 static void bank_switch(int b);
51
52 // addressing byte in 16bit reg
53 #define REG8IN16(ptr, offs) ((u8 *)ptr)[(offs) ^ 1]
54
55 // poll detection
56 #define POLL_THRESHOLD 3
57
58 static struct {
59   u32 addr, cycles;
60   int cnt;
61 } m68k_poll;
62
63 static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
64 {
65   int ret = 0;
66
67   if (a - 2 <= m68k_poll.addr && m68k_poll.addr <= a + 2
68     && cycles - m68k_poll.cycles <= 64)
69   {
70     if (m68k_poll.cnt++ > POLL_THRESHOLD) {
71       if (!(Pico32x.emu_flags & flags)) {
72         elprintf(EL_32X, "m68k poll addr %08x, cyc %u",
73           a, cycles - m68k_poll.cycles);
74         ret = 1;
75       }
76       Pico32x.emu_flags |= flags;
77     }
78   }
79   else {
80     m68k_poll.cnt = 0;
81     m68k_poll.addr = a;
82   }
83   m68k_poll.cycles = cycles;
84
85   return ret;
86 }
87
88 void p32x_m68k_poll_event(u32 flags)
89 {
90   if (Pico32x.emu_flags & flags) {
91     elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags,
92       Pico32x.emu_flags & ~flags);
93     Pico32x.emu_flags &= ~flags;
94     SekSetStop(0);
95   }
96   m68k_poll.addr = m68k_poll.cnt = 0;
97 }
98
99 static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt)
100 {
101   int cycles_left = sh2_cycles_left(sh2);
102
103   if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) {
104     if (sh2->poll_cnt++ > maxcnt) {
105       if (!(sh2->state & flags))
106         elprintf_sh2(sh2, EL_32X, "state: %02x->%02x",
107           sh2->state, sh2->state | flags);
108
109       sh2->state |= flags;
110       sh2_end_run(sh2, 1);
111       pevt_log_sh2(sh2, EVT_POLL_START);
112       return;
113     }
114   }
115   else
116     sh2->poll_cnt = 0;
117   sh2->poll_addr = a;
118   sh2->poll_cycles = cycles_left;
119 }
120
121 void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles)
122 {
123   if (sh2->state & flags) {
124     elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state,
125       sh2->state & ~flags);
126
127     if (sh2->m68krcycles_done < m68k_cycles)
128       sh2->m68krcycles_done = m68k_cycles;
129
130     pevt_log_sh2_o(sh2, EVT_POLL_END);
131   }
132
133   sh2->state &= ~flags;
134   sh2->poll_addr = sh2->poll_cycles = sh2->poll_cnt = 0;
135 }
136
137 static void sh2s_sync_on_read(SH2 *sh2)
138 {
139   int cycles;
140   if (sh2->poll_cnt != 0)
141     return;
142
143   cycles = sh2_cycles_done(sh2);
144   if (cycles > 600)
145     p32x_sync_other_sh2(sh2, sh2->m68krcycles_done + cycles / 3);
146 }
147
148 // SH2 faking
149 //#define FAKE_SH2
150 #ifdef FAKE_SH2
151 static int p32x_csum_faked;
152 static const u16 comm_fakevals[] = {
153   0x4d5f, 0x4f4b, // M_OK
154   0x535f, 0x4f4b, // S_OK
155   0x4D41, 0x5346, // MASF - Brutal Unleashed
156   0x5331, 0x4d31, // Darxide
157   0x5332, 0x4d32,
158   0x5333, 0x4d33,
159   0x0000, 0x0000, // eq for doom
160   0x0002, // Mortal Kombat
161 //  0, // pad
162 };
163
164 static u32 sh2_comm_faker(u32 a)
165 {
166   static int f = 0;
167   if (a == 0x28 && !p32x_csum_faked) {
168     p32x_csum_faked = 1;
169     return *(unsigned short *)(Pico.rom + 0x18e);
170   }
171   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
172     f = 0;
173   return comm_fakevals[f++];
174 }
175 #endif
176
177 // ------------------------------------------------------------------
178 // 68k regs
179
180 static u32 p32x_reg_read16(u32 a)
181 {
182   a &= 0x3e;
183
184 #if 0
185   if ((a & 0x30) == 0x20)
186     return sh2_comm_faker(a);
187 #else
188   if ((a & 0x30) == 0x20) {
189     static u32 dr2 = 0;
190     unsigned int cycles = SekCyclesDoneT();
191     int comreg = 1 << (a & 0x0f) / 2;
192
193     // evil X-Men proto polls in a dbra loop and expects it to expire..
194     if (SekDar(2) != dr2)
195       m68k_poll.cnt = 0;
196     dr2 = SekDar(2);
197
198     if (cycles - msh2.m68krcycles_done > 244
199         || (Pico32x.comm_dirty_68k & comreg))
200       p32x_sync_sh2s(cycles);
201
202     if (Pico32x.comm_dirty_sh2 & comreg)
203       Pico32x.comm_dirty_sh2 &= ~comreg;
204     else if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) {
205       SekSetStop(1);
206       SekEndRun(16);
207     }
208     dr2 = SekDar(2);
209     goto out;
210   }
211 #endif
212
213   if (a == 2) { // INTM, INTS
214     unsigned int cycles = SekCyclesDoneT();
215     if (cycles - msh2.m68krcycles_done > 64)
216       p32x_sync_sh2s(cycles);
217     goto out;
218   }
219
220   if ((a & 0x30) == 0x30)
221     return p32x_pwm_read16(a, NULL, SekCyclesDoneT());
222
223 out:
224   return Pico32x.regs[a / 2];
225 }
226
227 static void dreq0_write(u16 *r, u32 d)
228 {
229   if (!(r[6 / 2] & P32XS_68S)) {
230     elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
231     return; // ignored - tested
232   }
233   if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) {
234     Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d;
235     if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN)
236       r[6 / 2] |= P32XS_FULL;
237     // tested: len register decrements and 68S clears
238     // even if SH2s/DMAC aren't active..
239     r[0x10 / 2]--;
240     if (r[0x10 / 2] == 0)
241       r[6 / 2] &= ~P32XS_68S;
242
243     if ((Pico32x.dmac0_fifo_ptr & 3) == 0) {
244       p32x_sync_sh2s(SekCyclesDoneT());
245       p32x_dreq0_trigger();
246     }
247   }
248   else
249     elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!");
250 }
251
252 // writable bits tested
253 static void p32x_reg_write8(u32 a, u32 d)
254 {
255   u16 *r = Pico32x.regs;
256   a &= 0x3f;
257
258   // for things like bset on comm port
259   m68k_poll.cnt = 0;
260
261   switch (a) {
262     case 0x00: // adapter ctl: FM writable
263       REG8IN16(r, 0x00) = d & 0x80;
264       return;
265     case 0x01: // adapter ctl: RES and ADEN writable
266       if ((d ^ r[0]) & d & P32XS_nRES)
267         p32x_reset_sh2s();
268       REG8IN16(r, 0x01) &= ~(P32XS_nRES|P32XS_ADEN);
269       REG8IN16(r, 0x01) |= d & (P32XS_nRES|P32XS_ADEN);
270       return;
271     case 0x02: // ignored, always 0
272       return;
273     case 0x03: // irq ctl
274       if ((d ^ r[0x02 / 2]) & 3) {
275         int cycles = SekCyclesDoneT();
276         p32x_sync_sh2s(cycles);
277         r[0x02 / 2] = d & 3;
278         p32x_update_cmd_irq(NULL, cycles);
279       }
280       return;
281     case 0x04: // ignored, always 0
282       return;
283     case 0x05: // bank
284       d &= 3;
285       if (r[0x04 / 2] != d) {
286         r[0x04 / 2] = d;
287         bank_switch(d);
288       }
289       return;
290     case 0x06: // ignored, always 0
291       return;
292     case 0x07: // DREQ ctl
293       REG8IN16(r, 0x07) &= ~(P32XS_68S|P32XS_DMA|P32XS_RV);
294       if (!(d & P32XS_68S)) {
295         Pico32x.dmac0_fifo_ptr = 0;
296         REG8IN16(r, 0x07) &= ~P32XS_FULL;
297       }
298       REG8IN16(r, 0x07) |= d & (P32XS_68S|P32XS_DMA|P32XS_RV);
299       return;
300     case 0x08: // ignored, always 0
301       return;
302     case 0x09: // DREQ src
303       REG8IN16(r, 0x09) = d;
304       return;
305     case 0x0a:
306       REG8IN16(r, 0x0a) = d;
307       return;
308     case 0x0b:
309       REG8IN16(r, 0x0b) = d & 0xfe;
310       return;
311     case 0x0c: // ignored, always 0
312       return;
313     case 0x0d: // DREQ dest
314     case 0x0e:
315     case 0x0f:
316     case 0x10: // DREQ len
317       REG8IN16(r, a) = d;
318       return;
319     case 0x11:
320       REG8IN16(r, a) = d & 0xfc;
321       return;
322     // DREQ FIFO - writes to odd addr go to fifo
323     // do writes to even work? Reads return 0
324     case 0x12:
325       REG8IN16(r, a) = d;
326       return;
327     case 0x13:
328       d = (REG8IN16(r, 0x12) << 8) | (d & 0xff);
329       REG8IN16(r, 0x12) = 0;
330       dreq0_write(r, d);
331       return;
332     case 0x14: // ignored, always 0
333     case 0x15:
334     case 0x16:
335     case 0x17:
336     case 0x18:
337     case 0x19:
338       return;
339     case 0x1a: // what's this?
340       elprintf(EL_32X|EL_ANOMALY, "mystery w8 %02x %02x", a, d);
341       REG8IN16(r, a) = d & 0x01;
342       return;
343     case 0x1b: // TV
344       REG8IN16(r, a) = d & 0x01;
345       return;
346     case 0x1c: // ignored, always 0
347     case 0x1d:
348     case 0x1e:
349     case 0x1f:
350     case 0x30:
351       return;
352     case 0x31: // PWM control
353       REG8IN16(r, a) &= ~0x0f;
354       REG8IN16(r, a) |= d & 0x0f;
355       d = r[0x30 / 2];
356       goto pwm_write;
357     case 0x32: // PWM cycle
358       REG8IN16(r, a) = d & 0x0f;
359       d = r[0x32 / 2];
360       goto pwm_write;
361     case 0x33:
362       REG8IN16(r, a) = d;
363       d = r[0x32 / 2];
364       goto pwm_write;
365     // PWM pulse regs.. Only writes to odd address send a value
366     // to FIFO; reads are 0 (except status bits)
367     case 0x34:
368     case 0x36:
369     case 0x38:
370       REG8IN16(r, a) = d;
371       return;
372     case 0x35:
373     case 0x37:
374     case 0x39:
375       d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
376       REG8IN16(r, a ^ 1) = 0;
377       goto pwm_write;
378     case 0x3a: // ignored, always 0
379     case 0x3b:
380     case 0x3c:
381     case 0x3d:
382     case 0x3e:
383     case 0x3f:
384       return;
385     pwm_write:
386       p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDoneT());
387       return;
388   }
389
390   if ((a & 0x30) == 0x20) {
391     int cycles = SekCyclesDoneT();
392     int comreg;
393     
394     if (REG8IN16(r, a) == d)
395       return;
396
397     comreg = 1 << (a & 0x0f) / 2;
398     if (Pico32x.comm_dirty_68k & comreg)
399       p32x_sync_sh2s(cycles);
400
401     REG8IN16(r, a) = d;
402     p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
403     p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
404     Pico32x.comm_dirty_68k |= comreg;
405
406     if (cycles - (int)msh2.m68krcycles_done > 120)
407       p32x_sync_sh2s(cycles);
408     return;
409   }
410 }
411
412 static void p32x_reg_write16(u32 a, u32 d)
413 {
414   u16 *r = Pico32x.regs;
415   a &= 0x3e;
416
417   // for things like bset on comm port
418   m68k_poll.cnt = 0;
419
420   switch (a) {
421     case 0x00: // adapter ctl
422       if ((d ^ r[0]) & d & P32XS_nRES)
423         p32x_reset_sh2s();
424       r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN);
425       r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN);
426       return;
427     case 0x08: // DREQ src
428       r[a / 2] = d & 0xff;
429       return;
430     case 0x0a:
431       r[a / 2] = d & ~1;
432       return;
433     case 0x0c: // DREQ dest
434       r[a / 2] = d & 0xff;
435       return;
436     case 0x0e:
437       r[a / 2] = d;
438       return;
439     case 0x10: // DREQ len
440       r[a / 2] = d & ~3;
441       return;
442     case 0x12: // FIFO reg
443       dreq0_write(r, d);
444       return;
445     case 0x1a: // TV + mystery bit
446       r[a / 2] = d & 0x0101;
447       return;
448     case 0x30: // PWM control
449       d = (r[a / 2] & ~0x0f) | (d & 0x0f);
450       r[a / 2] = d;
451       p32x_pwm_write16(a, d, NULL, SekCyclesDoneT());
452       return;
453   }
454
455   // comm port
456   if ((a & 0x30) == 0x20) {
457     int cycles = SekCyclesDoneT();
458     int comreg;
459     
460     if (r[a / 2] == d)
461       return;
462
463     comreg = 1 << (a & 0x0f) / 2;
464     if (Pico32x.comm_dirty_68k & comreg)
465       p32x_sync_sh2s(cycles);
466
467     r[a / 2] = d;
468     p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
469     p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
470     Pico32x.comm_dirty_68k |= comreg;
471
472     if (cycles - (int)msh2.m68krcycles_done > 120)
473       p32x_sync_sh2s(cycles);
474     return;
475   }
476   // PWM
477   else if ((a & 0x30) == 0x30) {
478     p32x_pwm_write16(a, d, NULL, SekCyclesDoneT());
479     return;
480   }
481
482   p32x_reg_write8(a + 1, d);
483 }
484
485 // ------------------------------------------------------------------
486 // VDP regs
487 static u32 p32x_vdp_read16(u32 a)
488 {
489   u32 d;
490   a &= 0x0e;
491
492   d = Pico32x.vdp_regs[a / 2];
493   if (a == 0x0a) {
494     // tested: FEN seems to be randomly pulsing on hcnt 0x80-0xf0,
495     // most often at 0xb1-0xb5, even during vblank,
496     // what's the deal with that?
497     // we'll just fake it along with hblank for now
498     Pico32x.vdp_fbcr_fake++;
499     if (Pico32x.vdp_fbcr_fake & 4)
500       d |= P32XV_HBLK;
501     if ((Pico32x.vdp_fbcr_fake & 7) == 0)
502       d |= P32XV_nFEN;
503   }
504   return d;
505 }
506
507 static void p32x_vdp_write8(u32 a, u32 d)
508 {
509   u16 *r = Pico32x.vdp_regs;
510   a &= 0x0f;
511
512   // TODO: verify what's writeable
513   switch (a) {
514     case 0x01:
515       // priority inversion is handled in palette
516       if ((r[0] ^ d) & P32XV_PRI)
517         Pico32x.dirty_pal = 1;
518       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
519       break;
520     case 0x03: // shift (for pp mode)
521       r[2 / 2] = d & 1;
522       break;
523     case 0x05: // fill len
524       r[4 / 2] = d & 0xff;
525       break;
526     case 0x0b:
527       d &= 1;
528       Pico32x.pending_fb = d;
529       // if we are blanking and FS bit is changing
530       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
531         r[0x0a/2] ^= P32XV_FS;
532         Pico32xSwapDRAM(d ^ 1);
533         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
534       }
535       break;
536   }
537 }
538
539 static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2)
540 {
541   a &= 0x0e;
542   if (a == 6) { // fill start
543     Pico32x.vdp_regs[6 / 2] = d;
544     return;
545   }
546   if (a == 8) { // fill data
547     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
548     int len = Pico32x.vdp_regs[4 / 2] + 1;
549     int len1 = len;
550     a = Pico32x.vdp_regs[6 / 2];
551     while (len1--) {
552       dram[a] = d;
553       a = (a & 0xff00) | ((a + 1) & 0xff);
554     }
555     Pico32x.vdp_regs[0x06 / 2] = a;
556     Pico32x.vdp_regs[0x08 / 2] = d;
557     if (sh2 != NULL && len > 4) {
558       Pico32x.vdp_regs[0x0a / 2] |= P32XV_nFEN;
559       // supposedly takes 3 bus/6 sh2 cycles? or 3 sh2 cycles?
560       p32x_event_schedule_sh2(sh2, P32X_EVENT_FILLEND, 3 + len);
561     }
562     return;
563   }
564
565   p32x_vdp_write8(a | 1, d);
566 }
567
568 // ------------------------------------------------------------------
569 // SH2 regs
570
571 static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
572 {
573   u16 *r = Pico32x.regs;
574   a &= 0xfe; // ?
575
576   switch (a) {
577     case 0x00: // adapter/irq ctl
578       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0]
579         | Pico32x.sh2irq_mask[sh2->is_slave];
580     case 0x04: // H count (often as comm too)
581       sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
582       sh2s_sync_on_read(sh2);
583       return Pico32x.sh2_regs[4 / 2];
584     case 0x06:
585       return (r[a / 2] & ~P32XS_FULL) | 0x4000;
586     case 0x08: // DREQ src
587     case 0x0a:
588     case 0x0c: // DREQ dst
589     case 0x0e:
590     case 0x10: // DREQ len
591       return r[a / 2];
592     case 0x12: // DREQ FIFO - does this work on hw?
593       if (Pico32x.dmac0_fifo_ptr > 0) {
594         Pico32x.dmac0_fifo_ptr--;
595         r[a / 2] = Pico32x.dmac_fifo[0];
596         memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1],
597           Pico32x.dmac0_fifo_ptr * 2);
598       }
599       return r[a / 2];
600     case 0x14:
601     case 0x16:
602     case 0x18:
603     case 0x1a:
604     case 0x1c:
605       return 0; // ?
606   }
607
608   // comm port
609   if ((a & 0x30) == 0x20) {
610     int comreg = 1 << (a & 0x0f) / 2;
611     if (Pico32x.comm_dirty_68k & comreg)
612       Pico32x.comm_dirty_68k &= ~comreg;
613     else
614       sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
615     sh2s_sync_on_read(sh2);
616     return r[a / 2];
617   }
618   if ((a & 0x30) == 0x30)
619     return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2));
620
621   elprintf_sh2(sh2, EL_32X|EL_ANOMALY, 
622     "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2));
623   return 0;
624 }
625
626 static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
627 {
628   u16 *r = Pico32x.regs;
629   u32 old;
630
631   a &= 0xff;
632   sh2->poll_addr = 0;
633
634   switch (a) {
635     case 0x00: // FM
636       r[0] &= ~P32XS_FM;
637       r[0] |= (d << 8) & P32XS_FM;
638       return;
639     case 0x01: // HEN/irq masks
640       old = Pico32x.sh2irq_mask[sh2->is_slave];
641       if ((d ^ old) & 1)
642         p32x_pwm_sync_to_sh2(sh2);
643
644       Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f;
645       Pico32x.sh2_regs[0] &= ~0x80;
646       Pico32x.sh2_regs[0] |= d & 0x80;
647
648       if ((d ^ old) & 1)
649         p32x_pwm_schedule_sh2(sh2);
650       if ((old ^ d) & 2)
651         p32x_update_cmd_irq(sh2, 0);
652       if ((old ^ d) & 4)
653         p32x_schedule_hint(sh2, 0); 
654       return;
655     case 0x04: // ignored?
656       return;
657     case 0x05: // H count
658       d &= 0xff;
659       if (Pico32x.sh2_regs[4 / 2] != d) {
660         Pico32x.sh2_regs[4 / 2] = d;
661         p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
662           sh2_cycles_done_m68k(sh2));
663         sh2_end_run(sh2, 4);
664       }
665       return;
666     case 0x30:
667       REG8IN16(r, a) = d & 0x0f;
668       d = r[0x30 / 2];
669       goto pwm_write;
670     case 0x31: // PWM control
671       REG8IN16(r, a) = d & 0x8f;
672       d = r[0x30 / 2];
673       goto pwm_write;
674     case 0x32: // PWM cycle
675       REG8IN16(r, a) = d & 0x0f;
676       d = r[0x32 / 2];
677       goto pwm_write;
678     case 0x33:
679       REG8IN16(r, a) = d;
680       d = r[0x32 / 2];
681       goto pwm_write;
682     // PWM pulse regs.. Only writes to odd address send a value
683     // to FIFO; reads are 0 (except status bits)
684     case 0x34:
685     case 0x36:
686     case 0x38:
687       REG8IN16(r, a) = d;
688       return;
689     case 0x35:
690     case 0x37:
691     case 0x39:
692       d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
693       REG8IN16(r, a ^ 1) = 0;
694       goto pwm_write;
695     case 0x3a: // ignored, always 0?
696     case 0x3b:
697     case 0x3c:
698     case 0x3d:
699     case 0x3e:
700     case 0x3f:
701       return;
702     pwm_write:
703       p32x_pwm_write16(a & ~1, d, sh2, 0);
704       return;
705   }
706
707   if ((a & 0x30) == 0x20) {
708     int comreg;
709     if (REG8IN16(r, a) == d)
710       return;
711
712     REG8IN16(r, a) = d;
713     p32x_m68k_poll_event(P32XF_68KCPOLL);
714     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
715       sh2_cycles_done_m68k(sh2));
716     comreg = 1 << (a & 0x0f) / 2;
717     Pico32x.comm_dirty_sh2 |= comreg;
718     return;
719   }
720
721   elprintf(EL_32X|EL_ANOMALY,
722     "unhandled sysreg w8  [%02x] %02x @%08x", a, d, sh2_pc(sh2));
723 }
724
725 static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
726 {
727   a &= 0xfe;
728
729   sh2->poll_addr = 0;
730
731   // comm
732   if ((a & 0x30) == 0x20) {
733     int comreg;
734     if (Pico32x.regs[a / 2] == d)
735       return;
736
737     Pico32x.regs[a / 2] = d;
738     p32x_m68k_poll_event(P32XF_68KCPOLL);
739     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
740       sh2_cycles_done_m68k(sh2));
741     comreg = 1 << (a & 0x0f) / 2;
742     Pico32x.comm_dirty_sh2 |= comreg;
743     return;
744   }
745   // PWM
746   else if ((a & 0x30) == 0x30) {
747     p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2));
748     return;
749   }
750
751   switch (a) {
752     case 0: // FM
753       Pico32x.regs[0] &= ~P32XS_FM;
754       Pico32x.regs[0] |= d & P32XS_FM;
755       break;
756     case 0x14:
757       Pico32x.sh2irqs &= ~P32XI_VRES;
758       goto irls;
759     case 0x16:
760       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT;
761       goto irls;
762     case 0x18:
763       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT;
764       goto irls;
765     case 0x1a:
766       Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave);
767       p32x_update_cmd_irq(sh2, 0);
768       return;
769     case 0x1c:
770       p32x_pwm_sync_to_sh2(sh2);
771       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM;
772       p32x_pwm_schedule_sh2(sh2);
773       goto irls;
774   }
775
776   p32x_sh2reg_write8(a | 1, d, sh2);
777   return;
778
779 irls:
780   p32x_update_irls(sh2, 0);
781 }
782
783 // ------------------------------------------------------------------
784 // 32x 68k handlers
785
786 // after ADEN
787 static u32 PicoRead8_32x_on(u32 a)
788 {
789   u32 d = 0;
790   if ((a & 0xffc0) == 0x5100) { // a15100
791     d = p32x_reg_read16(a);
792     goto out_16to8;
793   }
794
795   if ((a & 0xfc00) != 0x5000)
796     return PicoRead8_io(a);
797
798   if ((a & 0xfff0) == 0x5180) { // a15180
799     d = p32x_vdp_read16(a);
800     goto out_16to8;
801   }
802
803   if ((a & 0xfe00) == 0x5200) { // a15200
804     d = Pico32xMem->pal[(a & 0x1ff) / 2];
805     goto out_16to8;
806   }
807
808   if ((a & 0xfffc) == 0x30ec) { // a130ec
809     d = str_mars[a & 3];
810     goto out;
811   }
812
813   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
814   return d;
815
816 out_16to8:
817   if (a & 1)
818     d &= 0xff;
819   else
820     d >>= 8;
821
822 out:
823   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
824   return d;
825 }
826
827 static u32 PicoRead16_32x_on(u32 a)
828 {
829   u32 d = 0;
830   if ((a & 0xffc0) == 0x5100) { // a15100
831     d = p32x_reg_read16(a);
832     goto out;
833   }
834
835   if ((a & 0xfc00) != 0x5000)
836     return PicoRead16_io(a);
837
838   if ((a & 0xfff0) == 0x5180) { // a15180
839     d = p32x_vdp_read16(a);
840     goto out;
841   }
842
843   if ((a & 0xfe00) == 0x5200) { // a15200
844     d = Pico32xMem->pal[(a & 0x1ff) / 2];
845     goto out;
846   }
847
848   if ((a & 0xfffc) == 0x30ec) { // a130ec
849     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
850     goto out;
851   }
852
853   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
854   return d;
855
856 out:
857   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
858   return d;
859 }
860
861 static void PicoWrite8_32x_on(u32 a, u32 d)
862 {
863   if ((a & 0xfc00) == 0x5000)
864     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
865
866   if ((a & 0xffc0) == 0x5100) { // a15100
867     p32x_reg_write8(a, d);
868     return;
869   }
870
871   if ((a & 0xfc00) != 0x5000) {
872     PicoWrite8_io(a, d);
873     if (a == 0xa130f1)
874       bank_switch(Pico32x.regs[4 / 2]);
875     return;
876   }
877
878   if (!(Pico32x.regs[0] & P32XS_FM)) {
879     if ((a & 0xfff0) == 0x5180) { // a15180
880       p32x_vdp_write8(a, d);
881       return;
882     }
883
884     // TODO: verify
885     if ((a & 0xfe00) == 0x5200) { // a15200
886       elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
887       ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
888       Pico32x.dirty_pal = 1;
889       return;
890     }
891   }
892
893   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
894 }
895
896 static void PicoWrite16_32x_on(u32 a, u32 d)
897 {
898   if ((a & 0xfc00) == 0x5000)
899     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
900
901   if ((a & 0xffc0) == 0x5100) { // a15100
902     p32x_reg_write16(a, d);
903     return;
904   }
905
906   if ((a & 0xfc00) != 0x5000) {
907     PicoWrite16_io(a, d);
908     if (a == 0xa130f0)
909       bank_switch(Pico32x.regs[4 / 2]);
910     return;
911   }
912
913   if (!(Pico32x.regs[0] & P32XS_FM)) {
914     if ((a & 0xfff0) == 0x5180) { // a15180
915       p32x_vdp_write16(a, d, NULL); // FIXME?
916       return;
917     }
918
919     if ((a & 0xfe00) == 0x5200) { // a15200
920       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
921       Pico32x.dirty_pal = 1;
922       return;
923     }
924   }
925
926   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
927 }
928
929 // before ADEN
930 u32 PicoRead8_32x(u32 a)
931 {
932   u32 d = 0;
933   if ((a & 0xffc0) == 0x5100) { // a15100
934     // regs are always readable
935     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
936     goto out;
937   }
938
939   if ((a & 0xfffc) == 0x30ec) { // a130ec
940     d = str_mars[a & 3];
941     goto out;
942   }
943
944   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
945   return d;
946
947 out:
948   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
949   return d;
950 }
951
952 u32 PicoRead16_32x(u32 a)
953 {
954   u32 d = 0;
955   if ((a & 0xffc0) == 0x5100) { // a15100
956     d = Pico32x.regs[(a & 0x3f) / 2];
957     goto out;
958   }
959
960   if ((a & 0xfffc) == 0x30ec) { // a130ec
961     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
962     goto out;
963   }
964
965   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
966   return d;
967
968 out:
969   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
970   return d;
971 }
972
973 void PicoWrite8_32x(u32 a, u32 d)
974 {
975   if ((a & 0xffc0) == 0x5100) { // a15100
976     u16 *r = Pico32x.regs;
977
978     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
979     a &= 0x3f;
980     if (a == 1) {
981       if ((d ^ r[0]) & d & P32XS_ADEN) {
982         Pico32xStartup();
983         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
984         r[0] |= P32XS_ADEN;
985         p32x_reg_write8(a, d); // forward for reset processing
986       }
987       return;
988     }
989
990     // allow only COMM for now
991     if ((a & 0x30) == 0x20) {
992       u8 *r8 = (u8 *)r;
993       r8[a ^ 1] = d;
994     }
995     return;
996   }
997
998   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
999 }
1000
1001 void PicoWrite16_32x(u32 a, u32 d)
1002 {
1003   if ((a & 0xffc0) == 0x5100) { // a15100
1004     u16 *r = Pico32x.regs;
1005
1006     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1007     a &= 0x3e;
1008     if (a == 0) {
1009       if ((d ^ r[0]) & d & P32XS_ADEN) {
1010         Pico32xStartup();
1011         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
1012         r[0] |= P32XS_ADEN;
1013         p32x_reg_write16(a, d); // forward for reset processing
1014       }
1015       return;
1016     }
1017
1018     // allow only COMM for now
1019     if ((a & 0x30) == 0x20)
1020       r[a / 2] = d;
1021     return;
1022   }
1023
1024   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1025 }
1026
1027 /* quirk: in both normal and overwrite areas only nonzero values go through */
1028 #define sh2_write8_dramN(n) \
1029   if ((d & 0xff) != 0) { \
1030     u8 *dram = (u8 *)Pico32xMem->dram[n]; \
1031     dram[(a & 0x1ffff) ^ 1] = d; \
1032   }
1033
1034 static void m68k_write8_dram0_ow(u32 a, u32 d)
1035 {
1036   sh2_write8_dramN(0);
1037 }
1038
1039 static void m68k_write8_dram1_ow(u32 a, u32 d)
1040 {
1041   sh2_write8_dramN(1);
1042 }
1043
1044 #define sh2_write16_dramN(n) \
1045   u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
1046   if (!(a & 0x20000)) { \
1047     *pd = d; \
1048     return; \
1049   } \
1050   /* overwrite */ \
1051   if (!(d & 0xff00)) d |= *pd & 0xff00; \
1052   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
1053   *pd = d;
1054
1055 static void m68k_write16_dram0_ow(u32 a, u32 d)
1056 {
1057   sh2_write16_dramN(0);
1058 }
1059
1060 static void m68k_write16_dram1_ow(u32 a, u32 d)
1061 {
1062   sh2_write16_dramN(1);
1063 }
1064
1065 // -----------------------------------------------------------------
1066
1067 // hint vector is writeable
1068 static void PicoWrite8_hint(u32 a, u32 d)
1069 {
1070   if ((a & 0xfffc) == 0x0070) {
1071     Pico32xMem->m68k_rom[a ^ 1] = d;
1072     return;
1073   }
1074
1075   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x",
1076     a, d & 0xff, SekPc);
1077 }
1078
1079 static void PicoWrite16_hint(u32 a, u32 d)
1080 {
1081   if ((a & 0xfffc) == 0x0070) {
1082     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
1083     return;
1084   }
1085
1086   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x",
1087     a, d & 0xffff, SekPc);
1088 }
1089
1090 // normally not writable, but somebody could make a RAM cart
1091 static void PicoWrite8_cart(u32 a, u32 d)
1092 {
1093   elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1094
1095   a &= 0xfffff;
1096   m68k_write8(a, d);
1097 }
1098
1099 static void PicoWrite16_cart(u32 a, u32 d)
1100 {
1101   elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1102
1103   a &= 0xfffff;
1104   m68k_write16(a, d);
1105 }
1106
1107 // same with bank, but save ram is sometimes here
1108 static u32 PicoRead8_bank(u32 a)
1109 {
1110   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1111   return m68k_read8(a);
1112 }
1113
1114 static u32 PicoRead16_bank(u32 a)
1115 {
1116   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1117   return m68k_read16(a);
1118 }
1119
1120 static void PicoWrite8_bank(u32 a, u32 d)
1121 {
1122   if (!(Pico.m.sram_reg & SRR_MAPPED))
1123     elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x",
1124       a, d & 0xff, SekPc);
1125
1126   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1127   m68k_write8(a, d);
1128 }
1129
1130 static void PicoWrite16_bank(u32 a, u32 d)
1131 {
1132   if (!(Pico.m.sram_reg & SRR_MAPPED))
1133     elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x",
1134       a, d & 0xffff, SekPc);
1135
1136   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1137   m68k_write16(a, d);
1138 }
1139
1140 static void bank_map_handler(void)
1141 {
1142   cpu68k_map_set(m68k_read8_map,   0x900000, 0x9fffff, PicoRead8_bank, 1);
1143   cpu68k_map_set(m68k_read16_map,  0x900000, 0x9fffff, PicoRead16_bank, 1);
1144 }
1145
1146 static void bank_switch(int b)
1147 {
1148   unsigned int rs, bank;
1149
1150   bank = b << 20;
1151   if ((Pico.m.sram_reg & SRR_MAPPED) && bank == SRam.start) {
1152     bank_map_handler();
1153     return;
1154   }
1155
1156   if (bank >= Pico.romsize) {
1157     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
1158     bank_map_handler();
1159     return;
1160   }
1161
1162   // 32X ROM (unbanked, XXX: consider mirroring?)
1163   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1164   rs -= bank;
1165   if (rs > 0x100000)
1166     rs = 0x100000;
1167   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
1168   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
1169
1170   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
1171
1172 #ifdef EMU_F68K
1173   // setup FAME fetchmap
1174   for (rs = 0x90; rs < 0xa0; rs++)
1175     PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom + bank - 0x900000;
1176 #endif
1177 }
1178
1179 // -----------------------------------------------------------------
1180 //                              SH2  
1181 // -----------------------------------------------------------------
1182
1183 // read8
1184 static u32 sh2_read8_unmapped(u32 a, SH2 *sh2)
1185 {
1186   elprintf_sh2(sh2, EL_32X, "unmapped r8  [%08x]       %02x @%06x",
1187     a, 0, sh2_pc(sh2));
1188   return 0;
1189 }
1190
1191 static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
1192 {
1193   u32 d = 0;
1194
1195   sh2_burn_cycles(sh2, 1*2);
1196
1197   // 0x3ff00 is veridied
1198   if ((a & 0x3ff00) == 0x4000) {
1199     d = p32x_sh2reg_read16(a, sh2);
1200     goto out_16to8;
1201   }
1202
1203   if ((a & 0x3ff00) == 0x4100) {
1204     d = p32x_vdp_read16(a);
1205     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
1206     goto out_16to8;
1207   }
1208
1209   // TODO: mirroring?
1210   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1211     return Pico32xMem->sh2_rom_m[a ^ 1];
1212   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1213     return Pico32xMem->sh2_rom_s[a ^ 1];
1214
1215   if ((a & 0x3fe00) == 0x4200) {
1216     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1217     goto out_16to8;
1218   }
1219
1220   return sh2_read8_unmapped(a, sh2);
1221
1222 out_16to8:
1223   if (a & 1)
1224     d &= 0xff;
1225   else
1226     d >>= 8;
1227
1228   elprintf_sh2(sh2, EL_32X, "r8  [%08x]       %02x @%06x",
1229     a, d, sh2_pc(sh2));
1230   return d;
1231 }
1232
1233 static u32 sh2_read8_da(u32 a, SH2 *sh2)
1234 {
1235   return sh2->data_array[(a & 0xfff) ^ 1];
1236 }
1237
1238 // read16
1239 static u32 sh2_read16_unmapped(u32 a, SH2 *sh2)
1240 {
1241   elprintf_sh2(sh2, EL_32X, "unmapped r16 [%08x]     %04x @%06x",
1242     a, 0, sh2_pc(sh2));
1243   return 0;
1244 }
1245
1246 static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
1247 {
1248   u32 d = 0;
1249
1250   sh2_burn_cycles(sh2, 1*2);
1251
1252   if ((a & 0x3ff00) == 0x4000) {
1253     d = p32x_sh2reg_read16(a, sh2);
1254     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
1255       return d;
1256     goto out;
1257   }
1258
1259   if ((a & 0x3ff00) == 0x4100) {
1260     d = p32x_vdp_read16(a);
1261     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
1262     goto out;
1263   }
1264
1265   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1266     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
1267   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1268     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
1269
1270   if ((a & 0x3fe00) == 0x4200) {
1271     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1272     goto out;
1273   }
1274
1275   return sh2_read16_unmapped(a, sh2);
1276
1277 out:
1278   elprintf_sh2(sh2, EL_32X, "r16 [%08x]     %04x @%06x",
1279     a, d, sh2_pc(sh2));
1280   return d;
1281 }
1282
1283 static u32 sh2_read16_da(u32 a, SH2 *sh2)
1284 {
1285   return ((u16 *)sh2->data_array)[(a & 0xfff) / 2];
1286 }
1287
1288 // writes
1289 static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
1290 {
1291 }
1292
1293 // write8
1294 static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2)
1295 {
1296   elprintf_sh2(sh2, EL_32X, "unmapped w8  [%08x]       %02x @%06x",
1297     a, d & 0xff, sh2_pc(sh2));
1298 }
1299
1300 static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
1301 {
1302   elprintf_sh2(sh2, EL_32X, "w8  [%08x]       %02x @%06x",
1303     a, d & 0xff, sh2_pc(sh2));
1304
1305   if (Pico32x.regs[0] & P32XS_FM) {
1306     if ((a & 0x3ff00) == 0x4100) {
1307       sh2->poll_addr = 0;
1308       p32x_vdp_write8(a, d);
1309       return;
1310     }
1311   }
1312
1313   if ((a & 0x3ff00) == 0x4000) {
1314     p32x_sh2reg_write8(a, d, sh2);
1315     return;
1316   }
1317
1318   sh2_write8_unmapped(a, d, sh2);
1319 }
1320
1321 static void REGPARM(3) sh2_write8_dram0(u32 a, u32 d, SH2 *sh2)
1322 {
1323   sh2_write8_dramN(0);
1324 }
1325
1326 static void REGPARM(3) sh2_write8_dram1(u32 a, u32 d, SH2 *sh2)
1327 {
1328   sh2_write8_dramN(1);
1329 }
1330
1331 static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2)
1332 {
1333   u32 a1 = a & 0x3ffff;
1334 #ifdef DRC_SH2
1335   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1336   if (t)
1337     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1338 #endif
1339   Pico32xMem->sdram[a1 ^ 1] = d;
1340 }
1341
1342 static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2)
1343 {
1344   // xmen sync hack..
1345   if (a < 0x26000200)
1346     sh2_end_run(sh2, 32);
1347
1348   sh2_write8_sdram(a, d, sh2);
1349 }
1350
1351 static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
1352 {
1353   u32 a1 = a & 0xfff;
1354 #ifdef DRC_SH2
1355   int id = sh2->is_slave;
1356   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1357   if (t)
1358     sh2_drc_wcheck_da(a, t, id);
1359 #endif
1360   sh2->data_array[a1 ^ 1] = d;
1361 }
1362
1363 // write16
1364 static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2)
1365 {
1366   elprintf_sh2(sh2, EL_32X, "unmapped w16 [%08x]     %04x @%06x",
1367     a, d & 0xffff, sh2_pc(sh2));
1368 }
1369
1370 static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
1371 {
1372   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1373     elprintf_sh2(sh2, EL_32X, "w16 [%08x]     %04x @%06x",
1374       a, d & 0xffff, sh2_pc(sh2));
1375
1376   if (Pico32x.regs[0] & P32XS_FM) {
1377     if ((a & 0x3ff00) == 0x4100) {
1378       sh2->poll_addr = 0;
1379       p32x_vdp_write16(a, d, sh2);
1380       return;
1381     }
1382
1383     if ((a & 0x3fe00) == 0x4200) {
1384       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1385       Pico32x.dirty_pal = 1;
1386       return;
1387     }
1388   }
1389
1390   if ((a & 0x3ff00) == 0x4000) {
1391     p32x_sh2reg_write16(a, d, sh2);
1392     return;
1393   }
1394
1395   sh2_write16_unmapped(a, d, sh2);
1396 }
1397
1398 static void REGPARM(3) sh2_write16_dram0(u32 a, u32 d, SH2 *sh2)
1399 {
1400   sh2_write16_dramN(0);
1401 }
1402
1403 static void REGPARM(3) sh2_write16_dram1(u32 a, u32 d, SH2 *sh2)
1404 {
1405   sh2_write16_dramN(1);
1406 }
1407
1408 static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2)
1409 {
1410   u32 a1 = a & 0x3ffff;
1411 #ifdef DRC_SH2
1412   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1413   if (t)
1414     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1415 #endif
1416   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1417 }
1418
1419 static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2)
1420 {
1421   u32 a1 = a & 0xfff;
1422 #ifdef DRC_SH2
1423   int id = sh2->is_slave;
1424   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1425   if (t)
1426     sh2_drc_wcheck_da(a, t, id);
1427 #endif
1428   ((u16 *)sh2->data_array)[a1 / 2] = d;
1429 }
1430
1431
1432 typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2);
1433 typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
1434
1435 #define SH2MAP_ADDR2OFFS_R(a) \
1436   ((u32)(a) >> SH2_READ_SHIFT)
1437
1438 #define SH2MAP_ADDR2OFFS_W(a) \
1439   ((u32)(a) >> SH2_WRITE_SHIFT)
1440
1441 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1442 {
1443   const sh2_memmap *sh2_map = sh2->read8_map;
1444   uptr p;
1445
1446   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1447   p = sh2_map->addr;
1448   if (map_flag_set(p))
1449     return ((sh2_read_handler *)(p << 1))(a, sh2);
1450   else
1451     return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1452 }
1453
1454 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1455 {
1456   const sh2_memmap *sh2_map = sh2->read16_map;
1457   uptr p;
1458
1459   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1460   p = sh2_map->addr;
1461   if (map_flag_set(p))
1462     return ((sh2_read_handler *)(p << 1))(a, sh2);
1463   else
1464     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1465 }
1466
1467 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1468 {
1469   const sh2_memmap *sh2_map = sh2->read16_map;
1470   sh2_read_handler *handler;
1471   u32 offs;
1472   uptr p;
1473
1474   offs = SH2MAP_ADDR2OFFS_R(a);
1475   sh2_map += offs;
1476   p = sh2_map->addr;
1477   if (!map_flag_set(p)) {
1478     // XXX: maybe 32bit access instead with ror?
1479     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1480     return (pd[0] << 16) | pd[1];
1481   }
1482
1483   if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000))
1484     return sh2_peripheral_read32(a, sh2);
1485
1486   handler = (sh2_read_handler *)(p << 1);
1487   return (handler(a, sh2) << 16) | handler(a + 2, sh2);
1488 }
1489
1490 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1491 {
1492   const void **sh2_wmap = sh2->write8_tab;
1493   sh2_write_handler *wh;
1494
1495   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1496   wh(a, d, sh2);
1497 }
1498
1499 void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1500 {
1501   const void **sh2_wmap = sh2->write16_tab;
1502   sh2_write_handler *wh;
1503
1504   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1505   wh(a, d, sh2);
1506 }
1507
1508 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1509 {
1510   const void **sh2_wmap = sh2->write16_tab;
1511   sh2_write_handler *wh;
1512   u32 offs;
1513
1514   offs = SH2MAP_ADDR2OFFS_W(a);
1515
1516   if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
1517     sh2_peripheral_write32(a, d, sh2);
1518     return;
1519   }
1520
1521   wh = sh2_wmap[offs];
1522   wh(a, d >> 16, sh2);
1523   wh(a + 2, d, sh2);
1524 }
1525
1526 // -----------------------------------------------------------------
1527
1528 static void z80_md_bank_write_32x(unsigned int a, unsigned char d)
1529 {
1530   unsigned int addr68k;
1531
1532   addr68k = Pico.m.z80_bank68k << 15;
1533   addr68k += a & 0x7fff;
1534   if ((addr68k & 0xfff000) == 0xa15000)
1535     Pico32x.emu_flags |= P32XF_Z80_32X_IO;
1536
1537   elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, d);
1538   m68k_write8(addr68k, d);
1539 }
1540
1541 // -----------------------------------------------------------------
1542
1543 static const u16 msh2_code[] = {
1544   // trap instructions
1545   0xaffe, // bra <self>
1546   0x0009, // nop
1547   // have to wait a bit until m68k initial program finishes clearing stuff
1548   // to avoid races with game SH2 code, like in Tempo
1549   0xd004, // mov.l   @(_m_ok,pc), r0
1550   0xd105, // mov.l   @(_cnt,pc), r1
1551   0xd205, // mov.l   @(_start,pc), r2
1552   0x71ff, // add     #-1, r1
1553   0x4115, // cmp/pl  r1
1554   0x89fc, // bt      -2
1555   0xc208, // mov.l   r0, @(h'20,gbr)
1556   0x6822, // mov.l   @r2, r8
1557   0x482b, // jmp     @r8
1558   0x0009, // nop
1559   ('M'<<8)|'_', ('O'<<8)|'K',
1560   0x0001, 0x0000,
1561   0x2200, 0x03e0  // master start pointer in ROM
1562 };
1563
1564 static const u16 ssh2_code[] = {
1565   0xaffe, // bra <self>
1566   0x0009, // nop
1567   // code to wait for master, in case authentic master BIOS is used
1568   0xd104, // mov.l   @(_m_ok,pc), r1
1569   0xd206, // mov.l   @(_start,pc), r2
1570   0xc608, // mov.l   @(h'20,gbr), r0
1571   0x3100, // cmp/eq  r0, r1
1572   0x8bfc, // bf      #-2
1573   0xd003, // mov.l   @(_s_ok,pc), r0
1574   0xc209, // mov.l   r0, @(h'24,gbr)
1575   0x6822, // mov.l   @r2, r8
1576   0x482b, // jmp     @r8
1577   0x0009, // nop
1578   ('M'<<8)|'_', ('O'<<8)|'K',
1579   ('S'<<8)|'_', ('O'<<8)|'K',
1580   0x2200, 0x03e4  // slave start pointer in ROM
1581 };
1582
1583 #define HWSWAP(x) (((u16)(x) << 16) | ((x) >> 16))
1584 static void get_bios(void)
1585 {
1586   u16 *ps;
1587   u32 *pl;
1588   int i;
1589
1590   // M68K ROM
1591   if (p32x_bios_g != NULL) {
1592     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1593     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
1594   }
1595   else {
1596     // generate 68k ROM
1597     ps = (u16 *)Pico32xMem->m68k_rom;
1598     pl = (u32 *)ps;
1599     for (i = 1; i < 0xc0/4; i++)
1600       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1601
1602     // fill with nops
1603     for (i = 0xc0/2; i < 0x100/2; i++)
1604       ps[i] = 0x4e71;
1605
1606 #if 0
1607     ps[0xc0/2] = 0x46fc;
1608     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1609     ps[0xfe/2] = 0x60fe; // jump to self
1610 #else
1611     ps[0xfe/2] = 0x4e75; // rts
1612 #endif
1613   }
1614   // fill remaining m68k_rom page with game ROM
1615   memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
1616     Pico.rom + sizeof(Pico32xMem->m68k_rom),
1617     sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
1618
1619   // MSH2
1620   if (p32x_bios_m != NULL) {
1621     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1622     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1623   }
1624   else {
1625     pl = (u32 *)Pico32xMem->sh2_rom_m;
1626
1627     // fill exception vector table to our trap address
1628     for (i = 0; i < 128; i++)
1629       pl[i] = HWSWAP(0x200);
1630
1631     // startup code
1632     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1633
1634     // reset SP
1635     pl[1] = pl[3] = HWSWAP(0x6040000);
1636     // start
1637     pl[0] = pl[2] = HWSWAP(0x204);
1638   }
1639
1640   // SSH2
1641   if (p32x_bios_s != NULL) {
1642     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1643     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1644   }
1645   else {
1646     pl = (u32 *)Pico32xMem->sh2_rom_s;
1647
1648     // fill exception vector table to our trap address
1649     for (i = 0; i < 128; i++)
1650       pl[i] = HWSWAP(0x200);
1651
1652     // startup code
1653     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1654
1655     // reset SP
1656     pl[1] = pl[3] = HWSWAP(0x603f800);
1657     // start
1658     pl[0] = pl[2] = HWSWAP(0x204);
1659   }
1660 }
1661
1662 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1663 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1664
1665 static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80];
1666 // for writes we are using handlers only
1667 static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
1668
1669 void Pico32xSwapDRAM(int b)
1670 {
1671   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1672   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1673   cpu68k_map_set(m68k_read8_map,   0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1674   cpu68k_map_set(m68k_read16_map,  0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1675   cpu68k_map_set(m68k_write8_map,  0x840000, 0x87ffff,
1676                  b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1);
1677   cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff,
1678                  b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1);
1679
1680   // SH2
1681   sh2_read8_map[0x04/2].addr  = sh2_read8_map[0x24/2].addr  =
1682   sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
1683
1684   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1685   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1686 }
1687
1688 void PicoMemSetup32x(void)
1689 {
1690   unsigned int rs;
1691   int i;
1692
1693   Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0);
1694   if (Pico32xMem == NULL) {
1695     elprintf(EL_STATUS, "OOM");
1696     return;
1697   }
1698
1699   get_bios();
1700
1701   // cartridge area becomes unmapped
1702   // XXX: we take the easy way and don't unmap ROM,
1703   // so that we can avoid handling the RV bit.
1704   // m68k_map_unmap(0x000000, 0x3fffff);
1705
1706   // MD ROM area
1707   rs = sizeof(Pico32xMem->m68k_rom_bank);
1708   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1709   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1710   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1711   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1712
1713   // 32X ROM (unbanked, XXX: consider mirroring?)
1714   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1715   if (rs > 0x80000)
1716     rs = 0x80000;
1717   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1718   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1719   cpu68k_map_set(m68k_write8_map,  0x880000, 0x880000 + rs - 1, PicoWrite8_cart, 1);
1720   cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1);
1721 #ifdef EMU_F68K
1722   // setup FAME fetchmap
1723   PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom;
1724   for (rs = 0x88; rs < 0x90; rs++)
1725     PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom - 0x880000;
1726 #endif
1727
1728   // 32X ROM (banked)
1729   bank_switch(0);
1730   cpu68k_map_set(m68k_write8_map,  0x900000, 0x9fffff, PicoWrite8_bank, 1);
1731   cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1);
1732
1733   // SYS regs
1734   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1735   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1736   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1737   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1738
1739   // SH2 maps: A31,A30,A29,CS1,CS0
1740   // all unmapped by default
1741   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
1742     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1743     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1744   }
1745
1746   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
1747     sh2_write8_map[i]       = sh2_write8_unmapped;
1748     sh2_write16_map[i]      = sh2_write16_unmapped;
1749   }
1750
1751   // "purge area"
1752   for (i = 0x40; i <= 0x5f; i++) {
1753     sh2_write8_map[i >> 1]  =
1754     sh2_write16_map[i >> 1] = sh2_write_ignore;
1755   }
1756
1757   // CS0
1758   sh2_read8_map[0x00/2].addr  = sh2_read8_map[0x20/2].addr  = MAP_HANDLER(sh2_read8_cs0);
1759   sh2_read16_map[0x00/2].addr = sh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0);
1760   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
1761   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
1762   // CS1 - ROM
1763   sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  =
1764   sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
1765   sh2_read8_map[0x02/2].mask  = sh2_read8_map[0x22/2].mask  =
1766   sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3fffff; // FIXME
1767   // CS2 - DRAM - done by Pico32xSwapDRAM()
1768   sh2_read8_map[0x04/2].mask  = sh2_read8_map[0x24/2].mask  =
1769   sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01ffff;
1770   // CS3 - SDRAM
1771   sh2_read8_map[0x06/2].addr   = sh2_read8_map[0x26/2].addr   =
1772   sh2_read16_map[0x06/2].addr  = sh2_read16_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
1773   sh2_write8_map[0x06/2]       = sh2_write8_sdram;
1774   sh2_write8_map[0x26/2]       = sh2_write8_sdram_wt;
1775   sh2_write16_map[0x06/2]      = sh2_write16_map[0x26/2]      = sh2_write16_sdram;
1776   sh2_read8_map[0x06/2].mask   = sh2_read8_map[0x26/2].mask   =
1777   sh2_read16_map[0x06/2].mask  = sh2_read16_map[0x26/2].mask  = 0x03ffff;
1778   // SH2 data array
1779   sh2_read8_map[0xc0/2].addr  = MAP_HANDLER(sh2_read8_da);
1780   sh2_read16_map[0xc0/2].addr = MAP_HANDLER(sh2_read16_da);
1781   sh2_write8_map[0xc0/2]      = sh2_write8_da;
1782   sh2_write16_map[0xc0/2]     = sh2_write16_da;
1783   // SH2 IO
1784   sh2_read8_map[0xff/2].addr  = MAP_HANDLER(sh2_peripheral_read8);
1785   sh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16);
1786   sh2_write8_map[0xff/2]      = sh2_peripheral_write8;
1787   sh2_write16_map[0xff/2]     = sh2_peripheral_write16;
1788
1789   // map DRAM area, both 68k and SH2
1790   Pico32xSwapDRAM(1);
1791
1792   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1793   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1794   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
1795   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
1796
1797   sh2_drc_mem_setup(&msh2);
1798   sh2_drc_mem_setup(&ssh2);
1799
1800   // z80 hack
1801   z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write_32x, 1);
1802 }
1803
1804 void Pico32xMemStateLoaded(void)
1805 {
1806   bank_switch(Pico32x.regs[4 / 2]);
1807   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
1808   memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
1809   Pico32x.dirty_pal = 1;
1810
1811   Pico32x.emu_flags &= ~(P32XF_68KCPOLL | P32XF_68KVPOLL);
1812   memset(&m68k_poll, 0, sizeof(m68k_poll));
1813   msh2.state = 0;
1814   msh2.poll_addr = msh2.poll_cycles = msh2.poll_cnt = 0;
1815   ssh2.state = 0;
1816   ssh2.poll_addr = ssh2.poll_cycles = ssh2.poll_cnt = 0;
1817
1818   sh2_drc_flush_all();
1819 }
1820
1821 // vim:shiftwidth=2:ts=2:expandtab