Finish migrating to new mem handling. Make carthw db external.
[picodrive.git] / pico / pico / pico.c
1 #include "../pico_int.h"
2
3 // x: 0x03c - 0x19d
4 // y: 0x1fc - 0x2f7
5 //    0x2f8 - 0x3f3
6 picohw_state PicoPicohw;
7
8 static int prev_line_cnt_irq3 = 0, prev_line_cnt_irq5 = 0;
9 static int fifo_bytes_line = (16000<<16)/60/262/2;
10
11 static const int guessed_rates[] = { 8000, 14000, 12000, 14000, 16000, 18000, 16000, 16000 }; // ?
12
13 #define PICOHW_FIFO_IRQ_THRESHOLD 12
14
15 PICO_INTERNAL void PicoReratePico(void)
16 {
17   int rate = guessed_rates[PicoPicohw.r12 & 7];
18   if (Pico.m.pal)
19        fifo_bytes_line = (rate<<16)/50/312/2;
20   else fifo_bytes_line = (rate<<16)/60/262/2;
21   PicoPicoPCMRerate(rate);
22 }
23
24 static void PicoLinePico(void)
25 {
26   PicoPicohw.line_counter++;
27
28 #if 1
29   if ((PicoPicohw.r12 & 0x4003) && PicoPicohw.line_counter - prev_line_cnt_irq3 > 200) {
30     prev_line_cnt_irq3 = PicoPicohw.line_counter;
31     // just a guess/hack, allows 101 Dalmantians to boot
32     elprintf(EL_PICOHW, "irq3");
33     SekInterrupt(3);
34     return;
35   }
36 #endif
37
38   if (PicoPicohw.fifo_bytes > 0)
39   {
40     PicoPicohw.fifo_line_bytes += fifo_bytes_line;
41     if (PicoPicohw.fifo_line_bytes >= (1<<16)) {
42       PicoPicohw.fifo_bytes -= PicoPicohw.fifo_line_bytes >> 16;
43       PicoPicohw.fifo_line_bytes &= 0xffff;
44       if (PicoPicohw.fifo_bytes < 0)
45         PicoPicohw.fifo_bytes = 0;
46     }
47   }
48   else
49     PicoPicohw.fifo_line_bytes = 0;
50
51 #if 1
52   if (PicoPicohw.fifo_bytes_prev >= PICOHW_FIFO_IRQ_THRESHOLD &&
53       PicoPicohw.fifo_bytes < PICOHW_FIFO_IRQ_THRESHOLD) {
54     prev_line_cnt_irq3 = PicoPicohw.line_counter; // ?
55     elprintf(EL_PICOHW, "irq3, fb=%i", PicoPicohw.fifo_bytes);
56     SekInterrupt(3);
57   }
58   PicoPicohw.fifo_bytes_prev = PicoPicohw.fifo_bytes;
59 #endif
60
61 #if 0
62   if (PicoPicohw.line_counter - prev_line_cnt_irq5 > 512) {
63     prev_line_cnt_irq5 = PicoPicohw.line_counter;
64     elprintf(EL_PICOHW, "irq5");
65     SekInterrupt(5);
66   }
67 #endif
68 }
69
70 static void PicoResetPico(void)
71 {
72   PicoPicoPCMReset();
73   PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer;
74 }
75
76 PICO_INTERNAL void PicoInitPico(void)
77 {
78   elprintf(EL_STATUS, "Pico startup");
79   PicoLineHook = PicoLinePico;
80   PicoResetHook = PicoResetPico;
81
82   PicoAHW = PAHW_PICO;
83   memset(&PicoPicohw, 0, sizeof(PicoPicohw));
84   PicoPicohw.pen_pos[0] = 0x03c + 320/2;
85   PicoPicohw.pen_pos[1] = 0x200 + 240/2;
86   prev_line_cnt_irq3 = prev_line_cnt_irq5 = 0;
87
88   // map version register
89   PicoDetectRegion();
90   switch (Pico.m.hardware >> 6) {
91     case 0: PicoPicohw.r1 = 0x00; break;
92     case 1: PicoPicohw.r1 = 0x00; break;
93     case 2: PicoPicohw.r1 = 0x40; break;
94     case 3: PicoPicohw.r1 = 0x20; break;
95   }
96 }
97