main.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. "use strict";
  2. Object.fromList = function(xs)
  3. {
  4. var result = {};
  5. for(var i = 0; i < xs.length; i++)
  6. {
  7. result[xs[i][0]] = xs[i][1];
  8. }
  9. return result;
  10. };
  11. var dbg_names = Object.fromList([
  12. [1, ""],
  13. [LOG_CPU, "CPU"],
  14. [LOG_DISK, "DISK"],
  15. [LOG_FPU, "FPU"],
  16. [LOG_MEM, "MEM"],
  17. [LOG_DMA, "DMA"],
  18. [LOG_IO, "IO"],
  19. [LOG_PS2, "PS2"],
  20. [LOG_PIC, "PIC"],
  21. [LOG_VGA, "VGA"],
  22. [LOG_PIT, "PIT"],
  23. [LOG_MOUSE, "MOUS"],
  24. [LOG_PCI, "PCI"],
  25. [LOG_BIOS, "BIOS"],
  26. [LOG_CD, "CD"],
  27. [LOG_SERIAL, "SERI"],
  28. [LOG_RTC, "RTC"],
  29. [LOG_HPET, "HPET"],
  30. [LOG_ACPI, "ACPI"],
  31. [LOG_APIC, "APIC"],
  32. ]);
  33. var log_last_message = "",
  34. log_message_repetitions = 0;
  35. /**
  36. * @param {number=} level
  37. */
  38. function dbg_log(stuff, level)
  39. {
  40. if(!DEBUG) return;
  41. level = level || 1;
  42. if(level & LOG_LEVEL)
  43. {
  44. var level_name = dbg_names[level] || "",
  45. message = "[" + String.pads(level_name, 4) + "] " + stuff;
  46. if(message === log_last_message)
  47. {
  48. log_message_repetitions++;
  49. if(log_message_repetitions < 2048)
  50. {
  51. return;
  52. }
  53. }
  54. if(log_message_repetitions)
  55. {
  56. if(log_message_repetitions === 1)
  57. {
  58. console.log(log_last_message);
  59. }
  60. else
  61. {
  62. console.log("Previous message repeated " + log_message_repetitions + " times");;
  63. }
  64. log_message_repetitions = 0;
  65. }
  66. console.log(message);
  67. log_last_message = message;
  68. }
  69. }
  70. /**
  71. * @param {number=} level
  72. */
  73. function dbg_trace(level)
  74. {
  75. if(!DEBUG) return;
  76. dbg_log(Error().stack, level);
  77. }
  78. /**
  79. * console.assert is fucking slow
  80. * @param {string=} msg
  81. * @param {number=} level
  82. */
  83. function dbg_assert(cond, msg, level)
  84. {
  85. if(!DEBUG) return;
  86. if(!cond)
  87. {
  88. //dump_regs();
  89. console.log(Error().stack);
  90. console.trace();
  91. if(msg)
  92. {
  93. throw "Assert failed: " + msg;
  94. }
  95. else
  96. {
  97. throw "Assert failed";
  98. }
  99. }
  100. };
  101. // pad string with spaces on the right
  102. String.pads = function(str, len)
  103. {
  104. str = str ? str + "" : "";
  105. while(str.length < len)
  106. {
  107. str = str + " ";
  108. }
  109. return str;
  110. }
  111. // pad string with zeros on the left
  112. String.pad0 = function(str, len)
  113. {
  114. str = str ? str + "" : "";
  115. while(str.length < len)
  116. {
  117. str = "0" + str;
  118. }
  119. return str;
  120. }
  121. /**
  122. * number to hex
  123. * @param {number=} len
  124. */
  125. function h(n, len)
  126. {
  127. //dbg_assert(typeof n === "number");
  128. if(!n) return String.pad0("", len || 1);
  129. if(len)
  130. {
  131. return String.pad0(n.toString(16).toUpperCase(), len);
  132. }
  133. else
  134. {
  135. return n.toString(16).toUpperCase();
  136. }
  137. }
  138. /**
  139. * Synchronous access to ArrayBuffer
  140. * @constructor
  141. */
  142. function SyncBuffer(buffer)
  143. {
  144. this.byteLength = buffer.byteLength;
  145. // warning: fn may be called synchronously or asynchronously
  146. this.get = function(start, len, fn)
  147. {
  148. dbg_assert(start + len <= buffer.byteLength);
  149. fn(new Uint8Array(buffer, start, len));
  150. };
  151. this.set = function(start, slice, fn)
  152. {
  153. dbg_assert(start + slice.length <= buffer.byteLength);
  154. new Uint8Array(buffer, start, slice.byteLength).set(slice);
  155. fn();
  156. };
  157. this.get_buffer = function(fn)
  158. {
  159. fn(buffer);
  160. };
  161. }
  162. /**
  163. * Simple circular queue for logs
  164. *
  165. * @param {number} size
  166. * @constructor
  167. */
  168. function CircularQueue(size)
  169. {
  170. var data,
  171. index;
  172. this.add = function(item)
  173. {
  174. data[index] = item;
  175. index = (index + 1) % size;
  176. };
  177. this.toArray = function()
  178. {
  179. return [].slice.call(data, index).concat([].slice.call(data, 0, index));
  180. };
  181. this.clear = function()
  182. {
  183. data = [];
  184. index = 0;
  185. };
  186. this.set = function(new_data)
  187. {
  188. data = new_data;
  189. index = 0;
  190. };
  191. this.clear();
  192. }
  193. Math.int_log2 = function(x)
  194. {
  195. dbg_assert(x > 0);
  196. // well optimized in modern browsers, http://jsperf.com/integer-log2/2
  197. return (Math.log(x) / Math.LN2) | 0;
  198. }
  199. /**
  200. * @constructor
  201. *
  202. * Queue wrapper around Uint8Array
  203. * Used by devices such as the PS2 controller
  204. */
  205. function ByteQueue(size)
  206. {
  207. var data = new Uint8Array(size),
  208. start,
  209. end;
  210. dbg_assert((size & size - 1) === 0);
  211. this.length = 0;
  212. this.push = function(item)
  213. {
  214. if(this.length === size)
  215. {
  216. // intentional overwrite
  217. }
  218. else
  219. {
  220. this.length++;
  221. }
  222. data[end] = item;
  223. end = end + 1 & size - 1;
  224. };
  225. this.shift = function()
  226. {
  227. if(!this.length)
  228. {
  229. return -1;
  230. }
  231. else
  232. {
  233. var item = data[start];
  234. start = start + 1 & size - 1;
  235. this.length--;
  236. return item;
  237. }
  238. };
  239. this.peek = function()
  240. {
  241. if(!this.length)
  242. {
  243. return -1;
  244. }
  245. else
  246. {
  247. return data[start];
  248. }
  249. };
  250. this.clear = function()
  251. {
  252. start = 0;
  253. end = 0;
  254. this.length = 0;
  255. };
  256. this.clear();
  257. }