ppu.memory.c 4.4 KB

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