ppu.memory.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * PPU Memory manager - The TI-NESulator Project
  3. * ppu.memory.c - Inspired from the memory manager of the Quick6502 Project.
  4. *
  5. * Created by Manoël Trapier on 12/04/07.
  6. * Copyright 2003-2008 986 Corp. All rights reserved.
  7. *
  8. * $LastChangedDate$
  9. * $Author$
  10. * $HeadURL$
  11. * $Revision$
  12. *
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #define __TINES_PPU_INTERNAL__
  17. #include <ppu.h>
  18. #include <ppu/ppu.memory.h>
  19. #include <types.h>
  20. /* Simple definition only for readability */
  21. #define KBYTE * (1024)
  22. /* Internal representation of the PPU memory */
  23. byte *ppu_memoryPages[0x40];
  24. byte ppu_memoryGhostLink[0x40];
  25. /* Internal PPU Sprite Ram */
  26. byte ppu_SpriteRam[0x100];
  27. /*
  28. * Memory management functions
  29. *
  30. * Yes that true, PPU memory & CPU memory work in a nearly same fashion despite
  31. * the fact that we actually didn't have any Read/Write hook and ReadWrite
  32. * protection. We even didn't need "attributes" for the page. One of the only
  33. * need is the "powerful" ghost system
  34. */
  35. int ppu_initMemory()
  36. {
  37. int page;
  38. for(page = 0 ; page < 0x40 ; page++)
  39. {
  40. ppu_setPagePtr(page,NULL);
  41. ppu_memoryGhostLink[page] = 0xFF; /* ( >= 0x40 is not possible) */
  42. }
  43. return 0;
  44. }
  45. void ppu_updateGhost(byte page)
  46. {
  47. byte cur_ghost;
  48. cur_ghost = ppu_memoryGhostLink[page];
  49. if (cur_ghost < 0x40)
  50. ppu_memoryPages[cur_ghost] = ppu_memoryPages[page];
  51. }
  52. void ppu_setPagePtr (byte page, byte *ptr)
  53. {
  54. ppu_memoryPages[page] = ptr;
  55. ppu_updateGhost(page);
  56. }
  57. void ppu_setPagePtr1k(byte page, byte *ptr)
  58. { /* 1k = 4 * 256 */
  59. ppu_memoryPages[page + 0] = ptr;
  60. ppu_memoryPages[page + 1] = ptr + 0x100;
  61. ppu_memoryPages[page + 2] = ptr + (0x100 * 2);
  62. ppu_memoryPages[page + 3] = ptr + (0x100 * 3);
  63. ppu_updateGhost(page + 0);
  64. ppu_updateGhost(page + 1);
  65. ppu_updateGhost(page + 2);
  66. ppu_updateGhost(page + 3);
  67. }
  68. void ppu_setPagePtr2k(byte page, byte *ptr)
  69. {
  70. ppu_memoryPages[page + 0] = ptr;
  71. ppu_memoryPages[page + 1] = ptr + 0x100;
  72. ppu_memoryPages[page + 2] = ptr + (0x100 * 2);
  73. ppu_memoryPages[page + 3] = ptr + (0x100 * 3);
  74. ppu_memoryPages[page + 4] = ptr + (0x100 * 4);
  75. ppu_memoryPages[page + 5] = ptr + (0x100 * 5);
  76. ppu_memoryPages[page + 6] = ptr + (0x100 * 6);
  77. ppu_memoryPages[page + 7] = ptr + (0x100 * 7);
  78. ppu_updateGhost(page + 0);
  79. ppu_updateGhost(page + 1);
  80. ppu_updateGhost(page + 2);
  81. ppu_updateGhost(page + 3);
  82. ppu_updateGhost(page + 4);
  83. ppu_updateGhost(page + 5);
  84. ppu_updateGhost(page + 6);
  85. ppu_updateGhost(page + 7);
  86. }
  87. void ppu_setPagePtr4k(byte page, byte *ptr)
  88. {
  89. ppu_setPagePtr2k(page, ptr);
  90. ppu_setPagePtr2k(page+((4 KBYTE / 256) / 2), ptr + 2 KBYTE);
  91. }
  92. void ppu_setPagePtr8k(byte page, byte *ptr)
  93. {
  94. ppu_setPagePtr4k(page, ptr);
  95. ppu_setPagePtr4k(page+((8 KBYTE / 256) / 2), ptr + 4 KBYTE);
  96. }
  97. void ppu_setPageGhost(byte page, bool value, byte ghost)
  98. {
  99. if (value == true)
  100. {
  101. ppu_memoryPages[page] = ppu_memoryPages[ghost];
  102. ppu_memoryGhostLink[ghost] = page;
  103. printf("set ghost of 0x%02X to 0x%02X (ptr: %p)\n", ghost, page, ppu_memoryGhostLink[ghost]);
  104. }
  105. }
  106. void ppu_memoryDumpState(FILE *fp)
  107. {
  108. int i;
  109. for (i = 0x00; i < 0x40; i++)
  110. {
  111. fprintf(fp,
  112. "Page 0x%02X : ptr:%p ghost:0x%02X\n",
  113. i,
  114. ppu_memoryPages[i],
  115. ppu_memoryGhostLink[i]
  116. );
  117. }
  118. }
  119. byte ppu_readMemory(byte page, byte addr)
  120. {
  121. byte *ptr;
  122. if (page == 0x3F)
  123. return ( ppu_memoryPages[0x3F][addr&0x1F] & 0x3F );
  124. ptr = ppu_memoryPages[page & 0x3F];
  125. return ptr[addr];
  126. }
  127. void ppu_writeMemory(byte page, byte addr, byte value)
  128. {
  129. byte *ptr;
  130. if (page == 0x3F)
  131. {
  132. /* Here we will cheat with the palette miroring, since we didn't write
  133. as often as we read the palette, we will mirror here */
  134. //printf("%s palette: color %02X new value : %02d (0x%02X%02X)\n", ((addr&0x10)< 0x10) ? "Bgnd" : "Sprt", addr&0x1F, value & 0x3F, page, addr);
  135. if ((addr & 0xEF) == 0x00)
  136. {
  137. ppu_memoryPages[0x3F][0x00] = value;
  138. ppu_memoryPages[0x3F][0x10] = value;
  139. }
  140. else
  141. ppu_memoryPages[0x3F][addr&0x1F] = value;
  142. }
  143. else
  144. {
  145. ptr = ppu_memoryPages[page & 0x3F];
  146. ptr[addr] = value;
  147. }
  148. }