get rid of port_config.h
[picodrive.git] / pico / cd / buffering.c
1 /*
2  * Buffering handling
3  * (C) notaz, 2007,2008
4  *
5  * This work is licensed under the terms of MAME license.
6  * See COPYING file in the top-level directory.
7  */
8
9 #include "../pico_int.h"
10
11 int PicoCDBuffers = 0;
12 static unsigned char *cd_buffer = NULL;
13 static int prev_lba = 0x80000000;
14
15 static int hits, reads;
16
17 #undef dprintf
18 #define dprintf(...)
19
20 void PicoCDBufferInit(void)
21 {
22         void *tmp = NULL;
23
24         prev_lba = 0x80000000;
25         hits = reads = 0;
26
27         if (PicoCDBuffers <= 1) {
28                 PicoCDBuffers = 0;
29                 return; /* buffering off */
30         }
31
32         /* try alloc'ing until we succeed */
33         while (PicoCDBuffers > 0)
34         {
35                 tmp = realloc(cd_buffer, PicoCDBuffers * 2048 + 304);
36                 if (tmp != NULL) break;
37                 PicoCDBuffers >>= 1;
38         }
39
40         if (PicoCDBuffers <= 0) return; /* buffering became off */
41
42         cd_buffer = tmp;
43 }
44
45
46 void PicoCDBufferFree(void)
47 {
48         if (cd_buffer) {
49                 free(cd_buffer);
50                 cd_buffer = NULL;
51         }
52         if (reads)
53                 elprintf(EL_STATUS, "CD buffer hits: %i/%i (%i%%)\n", hits, reads, hits * 100 / reads);
54 }
55
56
57 void PicoCDBufferFlush(void)
58 {
59         prev_lba = 0x80000000;
60 }
61
62
63 /* this is was a try to fight slow SD access of GP2X */
64 PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
65 {
66         int is_bin, offs, read_len, moved = 0;
67         reads++;
68
69         is_bin = Pico_mcd->TOC.Tracks[0].ftype == TYPE_BIN;
70
71         if (PicoCDBuffers <= 0)
72         {
73                 /* no buffering */
74                 int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
75                 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
76                 pm_read(dest, 2048, Pico_mcd->TOC.Tracks[0].F);
77                 return;
78         }
79
80         /* hit? */
81         offs = lba - prev_lba;
82         if (offs >= 0 && offs < PicoCDBuffers)
83         {
84                 hits++;
85                 if (offs == 0) dprintf("CD buffer seek to old %i -> %i\n", prev_lba, lba);
86                 memcpy32(dest, (int *)(cd_buffer + offs*2048), 2048/4);
87                 return;
88         }
89
90         if (prev_lba + PicoCDBuffers != lba)
91         {
92                 int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
93                 dprintf("CD buffer seek %i -> %i\n", prev_lba, lba);
94                 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
95         }
96
97         dprintf("CD buffer miss %i -> %i\n", prev_lba, lba);
98
99         if (lba < prev_lba && prev_lba - lba < PicoCDBuffers)
100         {
101                 read_len = prev_lba - lba;
102                 dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
103                 memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
104                 moved = 1;
105         }
106         else
107         {
108                 read_len = PicoCDBuffers;
109         }
110
111         if (PicoMessage != NULL && read_len >= 512)
112         {
113                 PicoMessage("Buffering data...");
114         }
115
116         if (is_bin)
117         {
118                 int i = 0;
119 #ifdef _PSP_FW_VERSION
120                 int bufs = (read_len*2048) / (2048+304);
121                 pm_read(cd_buffer, bufs*(2048+304), Pico_mcd->TOC.Tracks[0].F);
122                 for (i = 1; i < bufs; i++)
123                         // should really use memmove here, but my memcpy32 implementation is also suitable here
124                         memcpy32((int *)(cd_buffer + i*2048), (int *)(cd_buffer + i*(2048+304)), 2048/4);
125 #endif
126                 for (; i < read_len - 1; i++)
127                 {
128                         pm_read(cd_buffer + i*2048, 2048 + 304, Pico_mcd->TOC.Tracks[0].F);
129                         // pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR); // seeking is slower, in PSP case even more
130                 }
131                 // further data might be moved, do not overwrite
132                 pm_read(cd_buffer + i*2048, 2048, Pico_mcd->TOC.Tracks[0].F);
133                 pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR);
134         }
135         else
136         {
137                 pm_read(cd_buffer, read_len*2048, Pico_mcd->TOC.Tracks[0].F);
138         }
139         memcpy32(dest, (int *) cd_buffer, 2048/4);
140         prev_lba = lba;
141
142         if (moved)
143         {
144                 /* file pointer must point to the same data in file, as would-be data after our buffer */
145                 int where_seek;
146                 lba += PicoCDBuffers;
147                 where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
148                 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
149         }
150 }
151