memory.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * 6502 Memory manager - The peTI-NESulator Project
  3. * memory.c - Taken from the Quick6502 project
  4. *
  5. * Created by Manoël Trapier on 18/09/06.
  6. * Copyright (c) 2002-2019 986-Studio.
  7. *
  8. */
  9. #include <stdio.h>
  10. #include <types.h>
  11. #include <os_dependent.h>
  12. #include <memory/manager.h>
  13. /* Private structures */
  14. #define KByte * (1024)
  15. /*
  16. * What inside memory manager:
  17. *
  18. * Table of attributes
  19. * Table of original page ptr
  20. * Table of modded page ptr
  21. *
  22. */
  23. /* Private data */
  24. uint8_t *memory_pages[0x100];
  25. uint8_t memory_pages_attr[0x100];
  26. func_rdhook rdh_table[0x100];
  27. func_wrhook wrh_table[0x100];
  28. //#define DEBUG
  29. #undef DEBUG
  30. #ifdef DEBUG
  31. #define LOG(s) s
  32. #else
  33. #define LOG(s) {}
  34. #endif
  35. /* Public functions */
  36. void set_page_ptr(uint8_t page, uint8_t *ptr)
  37. {
  38. LOG(console_printf(Console_Default, "Set page 0x%X to ptr %p\n", page, ptr));
  39. memory_pages[page] = ptr;
  40. }
  41. void set_page_ptr_1k(uint8_t page, uint8_t *ptr)
  42. { /* 1k = 4 * 256 */
  43. LOG(console_printf(Console_Default, "Set page(1k) 0x%X to ptr %p\n", page, ptr));
  44. memory_pages[page + 0] = ptr;
  45. memory_pages[page + 1] = ptr + 0x100;
  46. memory_pages[page + 2] = ptr + (0x100 * 2);
  47. memory_pages[page + 3] = ptr + (0x100 * 3);
  48. }
  49. void set_page_ptr_2k(uint8_t page, uint8_t *ptr)
  50. {
  51. LOG(console_printf(Console_Default, "Set page(2k) 0x%X to ptr %p\n", page, ptr));
  52. memory_pages[page + 0] = ptr;
  53. memory_pages[page + 1] = ptr + 0x100;
  54. memory_pages[page + 2] = ptr + (0x100 * 2);
  55. memory_pages[page + 3] = ptr + (0x100 * 3);
  56. memory_pages[page + 4] = ptr + (0x100 * 4);
  57. memory_pages[page + 5] = ptr + (0x100 * 5);
  58. memory_pages[page + 6] = ptr + (0x100 * 6);
  59. memory_pages[page + 7] = ptr + (0x100 * 7);
  60. }
  61. void set_page_ptr_4k(uint8_t page, uint8_t *ptr)
  62. {
  63. LOG(console_printf(Console_Default, "Set page(4k) 0x%X to ptr %p\n", page, ptr));
  64. set_page_ptr_2k(page, ptr);
  65. set_page_ptr_2k(page + ((4 KByte / 256) / 2), ptr + 2 KByte);
  66. }
  67. void set_page_ptr_8k(uint8_t page, uint8_t *ptr)
  68. {
  69. LOG(console_printf(Console_Default, "Set page(8k) 0x%X to ptr %p\n", page, ptr));
  70. set_page_ptr_4k(page, ptr);
  71. set_page_ptr_4k(page + ((8 KByte / 256) / 2), ptr + 4 KByte);
  72. }
  73. void set_page_ptr_16k(uint8_t page, uint8_t *ptr)
  74. {
  75. set_page_ptr_8k(page, ptr);
  76. set_page_ptr_8k(page + ((16 KByte / 256) / 2), ptr + 8 KByte);
  77. }
  78. void set_page_ptr_32k(uint8_t page, uint8_t *ptr)
  79. {
  80. set_page_ptr_16k(page, ptr);
  81. set_page_ptr_16k(page + ((32 KByte / 256) / 2), ptr + 16 KByte);
  82. }
  83. uint8_t *get_page_ptr(uint8_t page)
  84. {
  85. return memory_pages[page];
  86. }
  87. /* Functions to set pages attributes */
  88. void set_page_rd_hook(uint8_t page, func_rdhook func)
  89. {
  90. if (func == NULL)
  91. {
  92. memory_pages_attr[page] &= (~ATTR_PAGE_HAVE_RDHOOK);
  93. if (memory_pages[page] == (uint8_t *)0x01)
  94. {
  95. memory_pages[page] = NULL;
  96. }
  97. }
  98. else
  99. {
  100. memory_pages_attr[page] |= ATTR_PAGE_HAVE_RDHOOK;
  101. if (memory_pages[page] == NULL)
  102. {
  103. memory_pages[page] = (uint8_t *)0x01;
  104. }
  105. }
  106. rdh_table[page] = func;
  107. }
  108. void set_page_wr_hook(uint8_t page, func_wrhook func)
  109. {
  110. if (func == NULL)
  111. {
  112. memory_pages_attr[page] &= (~ATTR_PAGE_HAVE_WRHOOK);
  113. if (memory_pages[page] == (uint8_t *)0x01)
  114. {
  115. memory_pages[page] = NULL;
  116. }
  117. }
  118. else
  119. {
  120. memory_pages_attr[page] |= ATTR_PAGE_HAVE_WRHOOK;
  121. if (memory_pages[page] == NULL)
  122. {
  123. memory_pages[page] = (uint8_t *)0x01;
  124. }
  125. }
  126. wrh_table[page] = func;
  127. }
  128. void set_page_readable(uint8_t page, uint8_t value)
  129. {
  130. if (value == true)
  131. {
  132. memory_pages_attr[page] |= ATTR_PAGE_READABLE;
  133. }
  134. else
  135. {
  136. memory_pages_attr[page] &= (~ATTR_PAGE_READABLE);
  137. }
  138. }
  139. void set_page_writeable(uint8_t page, uint8_t value)
  140. {
  141. if (value == true)
  142. {
  143. memory_pages_attr[page] |= ATTR_PAGE_WRITEABLE;
  144. }
  145. else
  146. {
  147. memory_pages_attr[page] &= (~ATTR_PAGE_WRITEABLE);
  148. }
  149. }
  150. void set_page_ghost(uint8_t page, uint8_t value, uint8_t ghost)
  151. {
  152. if (value == true)
  153. {
  154. memory_pages_attr[page] = memory_pages_attr[ghost];
  155. rdh_table[page] = rdh_table[ghost];
  156. wrh_table[page] = wrh_table[ghost];
  157. memory_pages[page] = memory_pages[ghost];
  158. }
  159. }
  160. uint8_t get_page_attributes(uint8_t page)
  161. {
  162. return memory_pages_attr[page];
  163. }
  164. func_rdhook get_page_rdhook(uint8_t page)
  165. {
  166. if (memory_pages_attr[page] & ATTR_PAGE_HAVE_RDHOOK)
  167. {
  168. return rdh_table[page];
  169. }
  170. return NULL;
  171. }
  172. func_wrhook get_page_wrhook(uint8_t page)
  173. {
  174. if (memory_pages_attr[page] & ATTR_PAGE_HAVE_WRHOOK)
  175. {
  176. return wrh_table[page];
  177. }
  178. return NULL;
  179. }
  180. uint8_t ReadMemory(uint8_t page, uint8_t addr)
  181. {
  182. static uint8_t LastRetByte = 0xA5;
  183. uint8_t *page_ptr;
  184. uint8_t attributes;
  185. LOG(console_printf(Console_Default, "Read @ 0x%X-%X\n", page, addr));
  186. /* Est-ce que la page est mappé ? && Est-ce que la page est "readable" ? */
  187. if ((page_ptr = memory_pages[page]) &&
  188. ((attributes = memory_pages_attr[page]) & ATTR_PAGE_READABLE))
  189. {
  190. LOG(console_printf(Console_Default, "Page is non null & readable\n"));
  191. if (attributes & ATTR_PAGE_HAVE_RDHOOK)
  192. {
  193. return (LastRetByte = rdh_table[page](addr));
  194. }
  195. else
  196. {
  197. return (LastRetByte = page_ptr[addr]);
  198. }
  199. }
  200. //console_printf(Console_Default, "Trying to read @ 0x%X-%X\n", page, addr);
  201. return LastRetByte;
  202. }
  203. void WriteMemory(uint8_t page, uint8_t addr, uint8_t value)
  204. {
  205. uint8_t *page_ptr;
  206. uint8_t attributes;
  207. LOG(console_printf(Console_Default, "Write 0x%x @ 0x%X-%X\n", value, page, addr));
  208. /* Est-ce que la page est mappé ? && Est-ce que la page est "writable" ? */
  209. if ((page_ptr = memory_pages[page]) &&
  210. ((attributes = memory_pages_attr[page]) & ATTR_PAGE_WRITEABLE))
  211. {
  212. if (attributes & ATTR_PAGE_HAVE_WRHOOK)
  213. {
  214. #ifdef DETECT_BUS_CONFLICT
  215. if ((page >= 0x80) && (memory_pages[page][addr] != value))
  216. console_printf(Console_Default, "WriteHook: bus conflict at %02X%02X rom:%02X write:%02X\n", page, addr, memory_pages[page][addr], value);
  217. #endif
  218. wrh_table[page](addr, value);
  219. }
  220. else
  221. {
  222. page_ptr[addr] = value;
  223. }
  224. }
  225. else
  226. {
  227. console_printf(Console_Default, "Trying to write 0x%X @ 0x%X-%X\n", value, page, addr);
  228. }
  229. }
  230. void DumpMemoryState(FILE *fp)
  231. {
  232. int i;
  233. for (i = 0x00 ; i < 0x100 ; i++)
  234. {
  235. fprintf(fp,
  236. "Page 0x%02X : [%c%c%c%c%c%c] RdH:%p WrH:%p ptr:%p\n",
  237. i,
  238. (memory_pages_attr[i] & ATTR_PAGE_HAVE_RDHOOK) ? 'r' : '.',
  239. (memory_pages_attr[i] & ATTR_PAGE_HAVE_WRHOOK) ? 'w' : '.',
  240. (memory_pages_attr[i] & ATTR_PAGE_READABLE) ? 'R' : '.',
  241. (memory_pages_attr[i] & ATTR_PAGE_WRITEABLE) ? 'W' : '.',
  242. (memory_pages_attr[i] & ATTR_PAGE_GHOST) ? 'G' : '.',
  243. (memory_pages_attr[i] & ATTR_PAGE_MAPPED) ? 'M' : '.',
  244. rdh_table[i],
  245. wrh_table[i],
  246. memory_pages[i]
  247. );
  248. }
  249. }
  250. void InitMemory()
  251. {
  252. int page;
  253. for (page = 0 ; page < 0x100 ; page++)
  254. {
  255. set_page_ptr(page, NULL);
  256. memory_pages_attr[page] = 0x00;
  257. }
  258. }