loading msgs, bugfixes
[picodrive.git] / Pico / cd / buffering.c
1 #include "../PicoInt.h"
2
3 //#include <stdlib.h>
4
5 int PicoCDBuffers = 0;
6 static unsigned char *cd_buffer = NULL;
7 static int prev_lba = 0x80000000;
8
9 static int hits, reads;
10
11
12 void PicoCDBufferInit(void)
13 {
14         void *tmp;
15
16         prev_lba = 0x80000000;
17         hits = reads = 0;
18
19         if (PicoCDBuffers <= 1) {
20                 PicoCDBuffers = 0;
21                 return; /* buffering off */
22         }
23
24         /* try alloc'ing until we succeed */
25         while (PicoCDBuffers > 0)
26         {
27                 tmp = realloc(cd_buffer, PicoCDBuffers * 2048);
28                 if (tmp != NULL) break;
29                 PicoCDBuffers >>= 1;
30         }
31
32         if (PicoCDBuffers <= 0) return; /* buffering became off */
33
34         cd_buffer = tmp;
35 }
36
37
38 void PicoCDBufferFree(void)
39 {
40         if (cd_buffer) {
41                 free(cd_buffer);
42                 cd_buffer = NULL;
43         }
44         if (reads)
45                 printf("CD buffer hits: %i/%i (%i%%)\n", hits, reads, hits * 100 / reads);
46 }
47
48
49 /* this is a try to fight slow SD access of GP2X */
50 void PicoCDBufferRead(void *dest, int lba)
51 {
52         int is_bin, offs, read_len, moved = 0;
53         reads++;
54
55         is_bin = Pico_mcd->TOC.Tracks[0].ftype == TYPE_BIN;
56
57         if (PicoCDBuffers <= 0)
58         {
59                 /* no buffering */
60                 int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
61                 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
62                 pm_read(dest, 2048, Pico_mcd->TOC.Tracks[0].F);
63                 return;
64         }
65
66         /* hit? */
67         offs = lba - prev_lba;
68         if (offs >= 0 && offs < PicoCDBuffers)
69         {
70                 hits++;
71                 if (offs == 0) dprintf("CD buffer seek to old %i -> %i\n", prev_lba, lba);
72                 memcpy32(dest, (int *)(cd_buffer + offs*2048), 2048/4);
73                 return;
74         }
75
76         if (prev_lba + PicoCDBuffers != lba)
77         {
78                 int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
79                 dprintf("CD buffer seek %i -> %i\n", prev_lba, lba);
80                 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
81         }
82
83         dprintf("CD buffer miss %i -> %i\n", prev_lba, lba);
84
85         if (lba < prev_lba && prev_lba - lba < PicoCDBuffers)
86         {
87                 read_len = prev_lba - lba;
88                 dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
89                 memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
90                 moved = 1;
91         }
92         else
93         {
94                 read_len = PicoCDBuffers;
95         }
96
97         if (PicoMessage != NULL && read_len >= 512)
98         {
99                 PicoMessage("Buffering data...");
100         }
101
102         if (is_bin)
103         {
104                 int i;
105                 for (i = 0; i < read_len; i++)
106                 {
107                         pm_read(cd_buffer + i*2048, 2048, Pico_mcd->TOC.Tracks[0].F);
108                         pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR);
109                 }
110         }
111         else
112         {
113                 pm_read(cd_buffer, read_len*2048, Pico_mcd->TOC.Tracks[0].F);
114         }
115         memcpy32(dest, (int *) cd_buffer, 2048/4);
116         prev_lba = lba;
117
118         if (moved)
119         {
120                 /* file pointer must point to the same data in file, as would-be data after our buffer */
121                 int where_seek;
122                 lba += PicoCDBuffers;
123                 where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
124                 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
125         }
126 }
127