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