buffering.c 3.4 KB

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