get rid of port_config.h
[picodrive.git] / pico / cd / buffering.c
... / ...
CommitLineData
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
11int PicoCDBuffers = 0;
12static unsigned char *cd_buffer = NULL;
13static int prev_lba = 0x80000000;
14
15static int hits, reads;
16
17#undef dprintf
18#define dprintf(...)
19
20void 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
46void 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
57void PicoCDBufferFlush(void)
58{
59 prev_lba = 0x80000000;
60}
61
62
63/* this is was a try to fight slow SD access of GP2X */
64PICO_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