ppu.memory.c 4.4 KB

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