Fantasy 8Bit system (F8), is a fantasy 8bit console and a set of libraries for creating fantasy 8bit consoles.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

509 lines
15KB

  1. const expect = require('chai').expect;
  2. const sinon = require('sinon');
  3. const Mem = require('../src/memory');
  4. describe("Testing Memory Module", function(){
  5. describe("Core Memory Classes...", function(){
  6. describe("ROM Class", function(){
  7. var m1 = new Mem.ROM(1);
  8. var m2 = new Mem.ROM(4);
  9. it("Bytes match 256 byte page sizes", function(){
  10. expect(m1.size).to.equal(256);
  11. expect(m2.size).to.equal(1024);
  12. });
  13. it("Loading Bytes", function(){
  14. m1.load(0x80, [0x10, 0x44, 0xAB, 0x11, 0x9C]);
  15. expect(m1.__map[0x80]).to.equal(0x10);
  16. expect(m1.__map[0x81]).to.equal(0x44);
  17. expect(m1.__map[0x82]).to.equal(0xAB);
  18. expect(m1.__map[0x83]).to.equal(0x11);
  19. expect(m1.__map[0x84]).to.equal(0x9C);
  20. m2.load(0x0100, [0x88, 0x77, 0x66, 0x55]);
  21. m2.load(0x0200, [0xAA, 0xBB, 0xCC, 0xDD]);
  22. expect(m2.__map[0x0100]).to.equal(0x88);
  23. expect(m2.__map[0x0101]).to.equal(0x77);
  24. expect(m2.__map[0x0102]).to.equal(0x66);
  25. expect(m2.__map[0x0103]).to.equal(0x55);
  26. expect(m2.__map[0x0200]).to.equal(0xAA);
  27. expect(m2.__map[0x0201]).to.equal(0xBB);
  28. expect(m2.__map[0x0202]).to.equal(0xCC);
  29. expect(m2.__map[0x0203]).to.equal(0xDD);
  30. });
  31. it("Read Check", function(){
  32. expect(m1.read(0x81)).to.equal(0x44);
  33. expect(m1.address).to.equal(0x81);
  34. expect(m1.read(0x84)).to.equal(0x9C);
  35. expect(m1.address).to.equal(0x84);
  36. expect(m2.read(0x0102)).to.equal(0x66);
  37. expect(m2.address).to.equal(0x0102);
  38. expect(m2.read(0x0203)).to.equal(0xDD);
  39. expect(m2.address).to.equal(0x0203);
  40. });
  41. it("Address Within Memory Bounds", function(){
  42. m1.address = 0x0100;
  43. expect(m1.address).to.equal(0xFF);
  44. m2.address = -1;
  45. expect(m2.address).to.equal(0x00);
  46. m2.address = 0x0400;
  47. expect(m2.address).to.equal(0x03FF);
  48. });
  49. it("Set Address / Get Byte", function(){
  50. m1.address = 0x82;
  51. expect(m1.byte).to.equal(0xAB);
  52. m1.address = 0x83;
  53. expect(m1.byte).to.equal(0x11);
  54. m2.address = 0x0101;
  55. expect(m2.byte).to.equal(0x77);
  56. m2.address = 0x0202;
  57. expect(m2.byte).to.equal(0xCC);
  58. });
  59. it("Address Read Callback", function(){
  60. var cb = sinon.fake();
  61. m2.onAddressRead(0x0100, cb);
  62. m2.read(0x0100);
  63. m2.read(0x0201);
  64. m2.address = 0x0101;
  65. m2.byte;
  66. m2.address = 0x0100;
  67. m2.byte;
  68. expect(cb.callCount).to.equal(2);
  69. });
  70. it("Peek", function(){
  71. var cb = sinon.fake();
  72. m2.onAddressRead(0x0101, cb);
  73. expect(m2.peek(0x0101)).to.equal(0x77);
  74. expect(cb.callCount).to.equal(0);
  75. expect(m2.read(0x0101)).to.equal(0x77);
  76. expect(cb.callCount).to.equal(1);
  77. m2.peek(0x0101);
  78. expect(cb.callCount).to.equal(1);
  79. });
  80. it("Clear Page", function(){
  81. m2.clearPage(2);
  82. expect(m2.read(0x0200)).to.equal(0x00);
  83. expect(m2.read(0x0201)).to.equal(0x00);
  84. expect(m2.read(0x0202)).to.equal(0x00);
  85. expect(m2.read(0x0203)).to.equal(0x00);
  86. });
  87. it("Clear", function(){
  88. m1.clear();
  89. expect(m1.read(0x80)).to.equal(0x00);
  90. expect(m1.read(0x81)).to.equal(0x00);
  91. expect(m1.read(0x82)).to.equal(0x00);
  92. expect(m1.read(0x83)).to.equal(0x00);
  93. });
  94. });
  95. describe("RAM Class", function(){
  96. var m1 = new Mem.RAM(1);
  97. var m2 = new Mem.RAM(4);
  98. it("Bytes match 256 byte page sizes", function(){
  99. expect(m1.size).to.equal(256);
  100. expect(m2.size).to.equal(1024);
  101. });
  102. it("Loading Bytes", function(){
  103. m1.load(0x80, [0x10, 0x44, 0xAB, 0x11, 0x9C]);
  104. expect(m1.__map[0x80]).to.equal(0x10);
  105. expect(m1.__map[0x81]).to.equal(0x44);
  106. expect(m1.__map[0x82]).to.equal(0xAB);
  107. expect(m1.__map[0x83]).to.equal(0x11);
  108. expect(m1.__map[0x84]).to.equal(0x9C);
  109. m2.load(0x0100, [0x88, 0x77, 0x66, 0x55]);
  110. m2.load(0x0200, [0xAA, 0xBB, 0xCC, 0xDD]);
  111. expect(m2.__map[0x0100]).to.equal(0x88);
  112. expect(m2.__map[0x0101]).to.equal(0x77);
  113. expect(m2.__map[0x0102]).to.equal(0x66);
  114. expect(m2.__map[0x0103]).to.equal(0x55);
  115. expect(m2.__map[0x0200]).to.equal(0xAA);
  116. expect(m2.__map[0x0201]).to.equal(0xBB);
  117. expect(m2.__map[0x0202]).to.equal(0xCC);
  118. expect(m2.__map[0x0203]).to.equal(0xDD);
  119. });
  120. it("Read Check", function(){
  121. expect(m1.read(0x81)).to.equal(0x44);
  122. expect(m1.address).to.equal(0x81);
  123. expect(m1.read(0x84)).to.equal(0x9C);
  124. expect(m1.address).to.equal(0x84);
  125. expect(m2.read(0x0102)).to.equal(0x66);
  126. expect(m2.address).to.equal(0x0102);
  127. expect(m2.read(0x0203)).to.equal(0xDD);
  128. expect(m2.address).to.equal(0x0203);
  129. });
  130. it("Write Check", function(){
  131. expect(m1.read(0x85)).to.equal(0x00);
  132. m1.write(0x85, 0x12);
  133. expect(m1.read(0x85)).to.equal(0x12);
  134. m1.write(0x85, 0xDC);
  135. expect(m1.byte).to.equal(0xDC);
  136. });
  137. it("Set Address / Get Byte", function(){
  138. m1.address = 0x82;
  139. expect(m1.byte).to.equal(0xAB);
  140. m1.address = 0x83;
  141. expect(m1.byte).to.equal(0x11);
  142. m2.address = 0x0101;
  143. expect(m2.byte).to.equal(0x77);
  144. m2.address = 0x0202;
  145. expect(m2.byte).to.equal(0xCC);
  146. });
  147. it("Set Address / Set Byte", function(){
  148. m1.address = 0x86;
  149. m1.byte = 0xFE;
  150. m1.address = 0x87;
  151. m1.byte = 0xEF;
  152. expect(m1.read(0x86)).to.equal(0xFE);
  153. expect(m1.read(0x87)).to.equal(0xEF);
  154. });
  155. it("Address Within Memory Bounds", function(){
  156. m1.address = 0x0100;
  157. expect(m1.address).to.equal(0xFF);
  158. m2.address = -1;
  159. expect(m2.address).to.equal(0x00);
  160. m2.address = 0x0400;
  161. expect(m2.address).to.equal(0x03FF);
  162. });
  163. it("Address Read Callback", function(){
  164. var cb = sinon.fake();
  165. m2.onAddressRead(0x0100, cb);
  166. m2.read(0x0100);
  167. m2.read(0x0201);
  168. m2.address = 0x0101;
  169. m2.byte;
  170. m2.address = 0x0100;
  171. m2.byte;
  172. expect(cb.callCount).to.equal(2);
  173. });
  174. it("Address Write Callback", function(){
  175. var cb = sinon.fake();
  176. m1.onAddressWrite(0x86, cb);
  177. m1.write(0x86, 0x12);
  178. expect(cb.lastArg).to.equal(0x12);
  179. m1.write(0x86, 0x22);
  180. expect(cb.lastArg).to.equal(0x22);
  181. expect(cb.callCount).to.equal(2);
  182. });
  183. it("Peek", function(){
  184. var cb = sinon.fake();
  185. m2.onAddressRead(0x0101, cb);
  186. expect(m2.peek(0x0101)).to.equal(0x77);
  187. expect(cb.callCount).to.equal(0);
  188. expect(m2.read(0x0101)).to.equal(0x77);
  189. expect(cb.callCount).to.equal(1);
  190. m2.peek(0x0101);
  191. expect(cb.callCount).to.equal(1);
  192. });
  193. it("Poke", function(){
  194. var cb = sinon.fake();
  195. m2.onAddressWrite(0x0130, cb);
  196. m2.poke(0x0130, 0x42);
  197. expect(cb.callCount).to.equal(0);
  198. expect(m2.peek(0x0130)).to.equal(0x42);
  199. m2.write(0x0130, 0x46);
  200. expect(cb.callCount).to.equal(1);
  201. expect(m2.peek(0x0130)).to.equal(0x46);
  202. m2.poke(0x0130, 0x42);
  203. expect(cb.callCount).to.equal(1);
  204. });
  205. it("Clear Page", function(){
  206. m2.clearPage(2);
  207. expect(m2.read(0x0200)).to.equal(0x00);
  208. expect(m2.read(0x0201)).to.equal(0x00);
  209. expect(m2.read(0x0202)).to.equal(0x00);
  210. expect(m2.read(0x0203)).to.equal(0x00);
  211. });
  212. it("Clear", function(){
  213. m1.clear();
  214. expect(m1.read(0x80)).to.equal(0x00);
  215. expect(m1.read(0x81)).to.equal(0x00);
  216. expect(m1.read(0x82)).to.equal(0x00);
  217. expect(m1.read(0x83)).to.equal(0x00);
  218. });
  219. });
  220. describe("Shadow Class", function(){
  221. var sm = new Mem.Shadow(1, 4);
  222. it("Bytes Match 256 Size", function(){
  223. expect(sm.size).to.equal(256);
  224. });
  225. it("Load Bytes", function(){
  226. var stored = sm.load(0, [0x10, 0x20, 0x30, 0x40, 0x50]);
  227. expect(stored).to.equal(4);
  228. expect(sm.__map[0]).to.equal(0x10);
  229. expect(sm.__map[1]).to.equal(0x20);
  230. expect(sm.__map[2]).to.equal(0x30);
  231. expect(sm.__map[3]).to.equal(0x40);
  232. });
  233. it("Read Check", function(){
  234. expect(sm.read(0x01)).to.equal(0x20);
  235. expect(sm.read(0x05)).to.equal(0x20);
  236. expect(sm.read(0x09)).to.equal(0x20);
  237. expect(sm.read(0x0D)).to.equal(0x20);
  238. });
  239. it("Write Check", function(){
  240. sm.write(0x01, 0x11);
  241. expect(sm.read(0x01)).to.equal(0x11);
  242. expect(sm.read(0x05)).to.equal(0x11);
  243. sm.write(0x05, 0x12);
  244. expect(sm.read(0x05)).to.equal(0x11);
  245. });
  246. it("Set Address / Get Byte", function(){
  247. sm.address = 0x02;
  248. expect(sm.byte).to.equal(0x30);
  249. sm.address = 0x03;
  250. expect(sm.byte).to.equal(0x40);
  251. sm.address = 0x04;
  252. expect(sm.byte).to.equal(0x10);
  253. sm.address = 0x05;
  254. expect(sm.byte).to.equal(0x11);
  255. });
  256. it("Set Address / Set Byte", function(){
  257. sm.address = 0x02;
  258. sm.byte = 0x31;
  259. expect(sm.byte).to.equal(0x31);
  260. sm.address = 0x06;
  261. expect(sm.byte).to.equal(0x31);
  262. sm.byte = 0x32;
  263. expect(sm.byte).to.equal(0x31);
  264. });
  265. it("Address Within Memory Bounds", function(){
  266. sm.address = 0x0100;
  267. expect(sm.address).to.equal(0xFF);
  268. sm.address = -1;
  269. expect(sm.address).to.equal(0x00);
  270. });
  271. it("Address Read Callback", function(){
  272. var cb1 = sinon.fake();
  273. var cb2 = sinon.fake();
  274. sm.onAddressRead(0x01, cb1);
  275. sm.onAddressRead(0x05, cb2);
  276. sm.read(0x01);
  277. expect(cb1.callCount).to.equal(1);
  278. expect(cb2.callCount).to.equal(0);
  279. sm.read(0x05);
  280. expect(cb1.callCount).to.equal(1);
  281. expect(cb2.callCount).to.equal(1);
  282. });
  283. it("Address Write Callback", function(){
  284. var cb1 = sinon.fake();
  285. var cb2 = sinon.fake();
  286. sm.onAddressWrite(0x01, cb1);
  287. sm.write(0x01, 0x21);
  288. expect(cb1.callCount).to.equal(1);
  289. expect(cb1.lastArg).to.equal(0x21);
  290. sm.onAddressWrite(0x05, cb2);
  291. sm.write(0x05, 0x22);
  292. expect(cb2.callCount).to.equal(0);
  293. sm.write(0x01, 0x22);
  294. expect(cb2.callCount).to.equal(1);
  295. expect(cb2.lastArg).to.equal(0x22);
  296. expect(cb1.callCount).to.equal(2);
  297. expect(cb1.lastArg).to.equal(0x22);
  298. });
  299. it("Peek");
  300. it("Poke");
  301. it("Clear Page", function(){
  302. sm.clearPage(0);
  303. expect(sm.read(0x00)).to.equal(0x00);
  304. expect(sm.read(0x01)).to.equal(0x00);
  305. expect(sm.read(0x05)).to.equal(0x00);
  306. });
  307. it("Clear", function(){
  308. sm.load(0, [0x10, 0x20, 0x30, 0x40]);
  309. sm.clear();
  310. expect(sm.read(0x00)).to.equal(0x00);
  311. expect(sm.read(0x01)).to.equal(0x00);
  312. expect(sm.read(0x05)).to.equal(0x00);
  313. });
  314. });
  315. });
  316. describe("Memory Management Controller (MMC) Class", function(){
  317. var mmc = new Mem.MMC();
  318. var rcb = sinon.fake();
  319. var wcb = sinon.fake();
  320. let m1 = new Mem.RAM(1);
  321. m1.onAddressRead(0x31, rcb);
  322. m1.onAddressWrite(0x31, wcb);
  323. mmc.connectMemory(m1);
  324. mmc.connectMemory(new Mem.RAM(2));
  325. mmc.connectMemory(new Mem.RAM(1));
  326. it("Reports 4 pages", function(){
  327. expect(mmc.pages).to.equal(4);
  328. });
  329. it("Bytes match 4 pages", function(){
  330. expect(mmc.size).to.equal(1024);
  331. });
  332. it("Load / Read Check", function(){
  333. mmc.load(0, [0x01, 0x02, 0x03, 0x04]);
  334. mmc.load(0x0200, [0x11, 0x22, 0x33, 0x44]);
  335. mmc.load(0x0300, [0xAA, 0xBB, 0xCC, 0xDD]);
  336. mmc.load(0xFE, [0x41, 0x42, 0x43, 0x44]);
  337. expect(mmc.read(0x01)).to.equal(0x02);
  338. expect(mmc.read(0x0202)).to.equal(0x33);
  339. expect(mmc.read(0x0303)).to.equal(0xDD);
  340. expect(mmc.read(0xFF)).to.equal(0x42);
  341. expect(mmc.read(0x0101)).to.equal(0x44);
  342. });
  343. it("Write check", function(){
  344. mmc.write(0x02, 0x06);
  345. expect(mmc.read(0x02)).to.equal(0x06);
  346. mmc.write(0x0115, 0x15);
  347. expect(mmc.read(0x0115)).to.equal(0x15);
  348. mmc.write(0x0207, 0x07);
  349. expect(mmc.read(0x0207)).to.equal(0x07);
  350. });
  351. it("Adding Switchable Banks", function(){
  352. let b2 = new Mem.ROM(1);
  353. expect(function(){
  354. mmc.connectMemory(b2, 0x0100);
  355. }).to.throw("Memory modules assigned to the same bank must be the same byte size.");
  356. expect(function(){
  357. mmc.connectMemory(b2, 0xEE)
  358. }).to.throw("Cannot align memory module to bank at address " + (0xEE));
  359. mmc.connectMemory(b2, 0x00);
  360. expect(mmc.read(0x00)).to.equal(0x01);
  361. expect(mmc.read(0x01)).to.equal(0x02);
  362. mmc.switchBank(0x01);
  363. expect(mmc.read(0x01)).to.equal(0x00);
  364. mmc.switchBank(0x00);
  365. expect(mmc.read(0x01)).to.equal(0x02);
  366. mmc.connectMemory(new Mem.ROM(2), 0x0100);
  367. expect(mmc.read(0x0115)).to.equal(0x15);
  368. mmc.switchBank(0x11);
  369. expect(mmc.read(0x0115)).to.equal(0x00);
  370. mmc.switchBank(0x10);
  371. expect(mmc.read(0x0115)).to.equal(0x15);
  372. });
  373. it("Write Check 2 (switch between RAM and ROM)", function(){
  374. // Disable memory write passthrough for the initial tests...
  375. mmc.writePassthrough = false;
  376. mmc.write(0x0115, 0x16);
  377. expect(mmc.read(0x0115)).to.equal(0x16);
  378. mmc.switchBank(0x11);
  379. expect(mmc.read(0x0115)).to.equal(0x00);
  380. mmc.write(0x0115, 0x17);
  381. expect(mmc.read(0x0115)).to.equal(0x00);
  382. mmc.switchBank(0x10);
  383. expect(mmc.read(0x0115)).to.equal(0x16);
  384. // Reenable write passthrough!
  385. mmc.writePassthrough = true;
  386. mmc.switchBank(0x11);
  387. mmc.write(0x0115, 0x17);
  388. expect(mmc.read(0x0115)).to.equal(0x00);
  389. mmc.switchBank(0x10);
  390. expect(mmc.read(0x0115)).to.equal(0x17);
  391. });
  392. it("Set Address / Get Byte", function(){
  393. mmc.address = 0x0200;
  394. expect(mmc.byte).to.equal(0x11);
  395. mmc.address = 0x0301;
  396. expect(mmc.byte).to.equal(0xBB);
  397. mmc.address = 0x03;
  398. expect(mmc.byte).to.equal(0x04);
  399. });
  400. it("Set Address / Set Byte", function(){
  401. mmc.address = 0xEE;
  402. mmc.byte = 0x1A;
  403. mmc.address = 0xEF;
  404. mmc.byte = 0x2B;
  405. mmc.address = 0xF0;
  406. mmc.byte = 0x3C;
  407. expect(mmc.read(0xEE)).to.equal(0x1A);
  408. expect(mmc.read(0xEF)).to.equal(0x2B);
  409. expect(mmc.read(0xF0)).to.equal(0x3C);
  410. });
  411. it("Address Within Memory Bounds", function(){
  412. mmc.address = 0x05;
  413. expect(mmc.address).to.equal(0x05);
  414. mmc.address = 0x0201
  415. expect(mmc.address).to.equal(0x0201);
  416. mmc.address = -1;
  417. expect(mmc.address).to.equal(0);
  418. mmc.address = 0x0400;
  419. expect(mmc.address).to.equal(0x03FF);
  420. });
  421. it("Peek");
  422. it("Poke");
  423. it("Clear Page", function(){
  424. expect(mmc.read(0x0200)).to.equal(0x11);
  425. expect(mmc.read(0x0201)).to.equal(0x22);
  426. mmc.clearPage(2);
  427. expect(mmc.read(0x0200)).to.equal(0x00);
  428. expect(mmc.read(0x0201)).to.equal(0x00);
  429. expect(mmc.read(0xEE)).to.equal(0x1A);
  430. mmc.clearPage(0);
  431. expect(mmc.read(0x00)).to.equal(0x00);
  432. expect(mmc.read(0xEE)).to.equal(0x00);
  433. expect(mmc.read(0xEF)).to.equal(0x00);
  434. });
  435. it("Clear", function(){
  436. mmc.clear();
  437. for (let i=0; i < 10; i++){
  438. expect(mmc.read(0xF6 + i)).to.equal(0x00);
  439. }
  440. });
  441. });
  442. });