2 // (c) Copyright 2007, Grazvydas "notaz" Ignotas
4 #include "../pico_int.h"
7 static unsigned char *cd_buffer = NULL;
8 static int prev_lba = 0x80000000;
10 static int hits, reads;
13 void PicoCDBufferInit(void)
17 prev_lba = 0x80000000;
20 if (PicoCDBuffers <= 1) {
22 return; /* buffering off */
25 /* try alloc'ing until we succeed */
26 while (PicoCDBuffers > 0)
28 tmp = realloc(cd_buffer, PicoCDBuffers * 2048 + 304);
29 if (tmp != NULL) break;
33 if (PicoCDBuffers <= 0) return; /* buffering became off */
39 void PicoCDBufferFree(void)
46 elprintf(EL_STATUS, "CD buffer hits: %i/%i (%i%%)\n", hits, reads, hits * 100 / reads);
50 void PicoCDBufferFlush(void)
52 prev_lba = 0x80000000;
56 /* this is was a try to fight slow SD access of GP2X */
57 PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
59 int is_bin, offs, read_len, moved = 0;
62 is_bin = Pico_mcd->TOC.Tracks[0].ftype == TYPE_BIN;
64 if (PicoCDBuffers <= 0)
67 int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
68 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
69 pm_read(dest, 2048, Pico_mcd->TOC.Tracks[0].F);
74 offs = lba - prev_lba;
75 if (offs >= 0 && offs < PicoCDBuffers)
78 if (offs == 0) dprintf("CD buffer seek to old %i -> %i\n", prev_lba, lba);
79 memcpy32(dest, (int *)(cd_buffer + offs*2048), 2048/4);
83 if (prev_lba + PicoCDBuffers != lba)
85 int where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
86 dprintf("CD buffer seek %i -> %i\n", prev_lba, lba);
87 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
90 dprintf("CD buffer miss %i -> %i\n", prev_lba, lba);
92 if (lba < prev_lba && prev_lba - lba < PicoCDBuffers)
94 read_len = prev_lba - lba;
95 dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
96 memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
101 read_len = PicoCDBuffers;
104 if (PicoMessage != NULL && read_len >= 512)
106 PicoMessage("Buffering data...");
113 int bufs = (read_len*2048) / (2048+304);
114 pm_read(cd_buffer, bufs*(2048+304), Pico_mcd->TOC.Tracks[0].F);
115 for (i = 1; i < bufs; i++)
116 // should really use memmove here, but my memcpy32 implementation is also suitable here
117 memcpy32((int *)(cd_buffer + i*2048), (int *)(cd_buffer + i*(2048+304)), 2048/4);
119 for (; i < read_len - 1; i++)
121 pm_read(cd_buffer + i*2048, 2048 + 304, Pico_mcd->TOC.Tracks[0].F);
122 // pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR); // seeking is slower, in PSP case even more
124 // further data might be moved, do not overwrite
125 pm_read(cd_buffer + i*2048, 2048, Pico_mcd->TOC.Tracks[0].F);
126 pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR);
130 pm_read(cd_buffer, read_len*2048, Pico_mcd->TOC.Tracks[0].F);
132 memcpy32(dest, (int *) cd_buffer, 2048/4);
137 /* file pointer must point to the same data in file, as would-be data after our buffer */
139 lba += PicoCDBuffers;
140 where_seek = is_bin ? (lba * 2352 + 16) : (lba << 11);
141 pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);