@joezilla/8sim 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +542 -0
  3. package/dist/8sim.browser.js +4728 -0
  4. package/dist/bundles/CardBundle.d.ts +83 -0
  5. package/dist/bundles/CardBundle.d.ts.map +1 -0
  6. package/dist/bundles/CardBundle.js +41 -0
  7. package/dist/bundles/CardBundle.js.map +1 -0
  8. package/dist/bundles/kernels.d.ts +48 -0
  9. package/dist/bundles/kernels.d.ts.map +1 -0
  10. package/dist/bundles/kernels.js +132 -0
  11. package/dist/bundles/kernels.js.map +1 -0
  12. package/dist/bundles/seed/index.d.ts +24 -0
  13. package/dist/bundles/seed/index.d.ts.map +1 -0
  14. package/dist/bundles/seed/index.js +266 -0
  15. package/dist/bundles/seed/index.js.map +1 -0
  16. package/dist/bus/Bus.d.ts +21 -0
  17. package/dist/bus/Bus.d.ts.map +1 -0
  18. package/dist/bus/Bus.js +62 -0
  19. package/dist/bus/Bus.js.map +1 -0
  20. package/dist/bus/BusRegion.d.ts +8 -0
  21. package/dist/bus/BusRegion.d.ts.map +1 -0
  22. package/dist/bus/BusRegion.js +8 -0
  23. package/dist/bus/BusRegion.js.map +1 -0
  24. package/dist/bus/SnoopBus.d.ts +15 -0
  25. package/dist/bus/SnoopBus.d.ts.map +1 -0
  26. package/dist/bus/SnoopBus.js +41 -0
  27. package/dist/bus/SnoopBus.js.map +1 -0
  28. package/dist/cards/BankRamCard.d.ts +35 -0
  29. package/dist/cards/BankRamCard.d.ts.map +1 -0
  30. package/dist/cards/BankRamCard.js +56 -0
  31. package/dist/cards/BankRamCard.js.map +1 -0
  32. package/dist/cards/DazzlerCard.d.ts +42 -0
  33. package/dist/cards/DazzlerCard.d.ts.map +1 -0
  34. package/dist/cards/DazzlerCard.js +83 -0
  35. package/dist/cards/DazzlerCard.js.map +1 -0
  36. package/dist/cards/DisplaySurface.d.ts +32 -0
  37. package/dist/cards/DisplaySurface.d.ts.map +1 -0
  38. package/dist/cards/DisplaySurface.js +11 -0
  39. package/dist/cards/DisplaySurface.js.map +1 -0
  40. package/dist/cards/FdcPlusClient.d.ts +35 -0
  41. package/dist/cards/FdcPlusClient.d.ts.map +1 -0
  42. package/dist/cards/FdcPlusClient.js +130 -0
  43. package/dist/cards/FdcPlusClient.js.map +1 -0
  44. package/dist/cards/ImsaiMioCard.d.ts +36 -0
  45. package/dist/cards/ImsaiMioCard.d.ts.map +1 -0
  46. package/dist/cards/ImsaiMioCard.js +48 -0
  47. package/dist/cards/ImsaiMioCard.js.map +1 -0
  48. package/dist/cards/ImsaiSioCard.d.ts +19 -0
  49. package/dist/cards/ImsaiSioCard.d.ts.map +1 -0
  50. package/dist/cards/ImsaiSioCard.js +54 -0
  51. package/dist/cards/ImsaiSioCard.js.map +1 -0
  52. package/dist/cards/KeyboardCard.d.ts +37 -0
  53. package/dist/cards/KeyboardCard.d.ts.map +1 -0
  54. package/dist/cards/KeyboardCard.js +79 -0
  55. package/dist/cards/KeyboardCard.js.map +1 -0
  56. package/dist/cards/Mc6850Acia.d.ts +68 -0
  57. package/dist/cards/Mc6850Acia.d.ts.map +1 -0
  58. package/dist/cards/Mc6850Acia.js +132 -0
  59. package/dist/cards/Mc6850Acia.js.map +1 -0
  60. package/dist/cards/Mits2SioCard.d.ts +27 -0
  61. package/dist/cards/Mits2SioCard.d.ts.map +1 -0
  62. package/dist/cards/Mits2SioCard.js +36 -0
  63. package/dist/cards/Mits2SioCard.js.map +1 -0
  64. package/dist/cards/MitsDcddCard.d.ts +52 -0
  65. package/dist/cards/MitsDcddCard.d.ts.map +1 -0
  66. package/dist/cards/MitsDcddCard.js +294 -0
  67. package/dist/cards/MitsDcddCard.js.map +1 -0
  68. package/dist/cards/ParallelCard.d.ts +35 -0
  69. package/dist/cards/ParallelCard.d.ts.map +1 -0
  70. package/dist/cards/ParallelCard.js +32 -0
  71. package/dist/cards/ParallelCard.js.map +1 -0
  72. package/dist/cards/Port8212.d.ts +31 -0
  73. package/dist/cards/Port8212.d.ts.map +1 -0
  74. package/dist/cards/Port8212.js +47 -0
  75. package/dist/cards/Port8212.js.map +1 -0
  76. package/dist/cards/RtcCard.d.ts +30 -0
  77. package/dist/cards/RtcCard.d.ts.map +1 -0
  78. package/dist/cards/RtcCard.js +61 -0
  79. package/dist/cards/RtcCard.js.map +1 -0
  80. package/dist/cards/SerialCard.d.ts +31 -0
  81. package/dist/cards/SerialCard.d.ts.map +1 -0
  82. package/dist/cards/SerialCard.js +28 -0
  83. package/dist/cards/SerialCard.js.map +1 -0
  84. package/dist/cards/Tr1602Uart.d.ts +55 -0
  85. package/dist/cards/Tr1602Uart.d.ts.map +1 -0
  86. package/dist/cards/Tr1602Uart.js +102 -0
  87. package/dist/cards/Tr1602Uart.js.map +1 -0
  88. package/dist/cards/Usart8251.d.ts +28 -0
  89. package/dist/cards/Usart8251.d.ts.map +1 -0
  90. package/dist/cards/Usart8251.js +88 -0
  91. package/dist/cards/Usart8251.js.map +1 -0
  92. package/dist/cards/VdmCard.d.ts +27 -0
  93. package/dist/cards/VdmCard.d.ts.map +1 -0
  94. package/dist/cards/VdmCard.js +40 -0
  95. package/dist/cards/VdmCard.js.map +1 -0
  96. package/dist/clock/ImmediateClock.d.ts +8 -0
  97. package/dist/clock/ImmediateClock.d.ts.map +1 -0
  98. package/dist/clock/ImmediateClock.js +13 -0
  99. package/dist/clock/ImmediateClock.js.map +1 -0
  100. package/dist/clock/SystemClock.d.ts +45 -0
  101. package/dist/clock/SystemClock.d.ts.map +1 -0
  102. package/dist/clock/SystemClock.js +71 -0
  103. package/dist/clock/SystemClock.js.map +1 -0
  104. package/dist/cpu/Cpu8080.d.ts +34 -0
  105. package/dist/cpu/Cpu8080.d.ts.map +1 -0
  106. package/dist/cpu/Cpu8080.js +126 -0
  107. package/dist/cpu/Cpu8080.js.map +1 -0
  108. package/dist/cpu/Decoder.d.ts +12 -0
  109. package/dist/cpu/Decoder.d.ts.map +1 -0
  110. package/dist/cpu/Decoder.js +23 -0
  111. package/dist/cpu/Decoder.js.map +1 -0
  112. package/dist/cpu/Flags.d.ts +18 -0
  113. package/dist/cpu/Flags.d.ts.map +1 -0
  114. package/dist/cpu/Flags.js +33 -0
  115. package/dist/cpu/Flags.js.map +1 -0
  116. package/dist/cpu/Registers.d.ts +22 -0
  117. package/dist/cpu/Registers.d.ts.map +1 -0
  118. package/dist/cpu/Registers.js +26 -0
  119. package/dist/cpu/Registers.js.map +1 -0
  120. package/dist/cpu/instructions/alu.d.ts +3 -0
  121. package/dist/cpu/instructions/alu.d.ts.map +1 -0
  122. package/dist/cpu/instructions/alu.js +221 -0
  123. package/dist/cpu/instructions/alu.js.map +1 -0
  124. package/dist/cpu/instructions/branch.d.ts +3 -0
  125. package/dist/cpu/instructions/branch.d.ts.map +1 -0
  126. package/dist/cpu/instructions/branch.js +117 -0
  127. package/dist/cpu/instructions/branch.js.map +1 -0
  128. package/dist/cpu/instructions/control.d.ts +3 -0
  129. package/dist/cpu/instructions/control.d.ts.map +1 -0
  130. package/dist/cpu/instructions/control.js +12 -0
  131. package/dist/cpu/instructions/control.js.map +1 -0
  132. package/dist/cpu/instructions/data.d.ts +3 -0
  133. package/dist/cpu/instructions/data.d.ts.map +1 -0
  134. package/dist/cpu/instructions/data.js +137 -0
  135. package/dist/cpu/instructions/data.js.map +1 -0
  136. package/dist/cpu/instructions/io.d.ts +3 -0
  137. package/dist/cpu/instructions/io.d.ts.map +1 -0
  138. package/dist/cpu/instructions/io.js +18 -0
  139. package/dist/cpu/instructions/io.js.map +1 -0
  140. package/dist/cpu/instructions/logical.d.ts +3 -0
  141. package/dist/cpu/instructions/logical.d.ts.map +1 -0
  142. package/dist/cpu/instructions/logical.js +129 -0
  143. package/dist/cpu/instructions/logical.js.map +1 -0
  144. package/dist/cpu/instructions/rotate.d.ts +3 -0
  145. package/dist/cpu/instructions/rotate.d.ts.map +1 -0
  146. package/dist/cpu/instructions/rotate.js +34 -0
  147. package/dist/cpu/instructions/rotate.js.map +1 -0
  148. package/dist/cpu/instructions/stack.d.ts +3 -0
  149. package/dist/cpu/instructions/stack.d.ts.map +1 -0
  150. package/dist/cpu/instructions/stack.js +84 -0
  151. package/dist/cpu/instructions/stack.js.map +1 -0
  152. package/dist/cpu/status8080.d.ts +33 -0
  153. package/dist/cpu/status8080.d.ts.map +1 -0
  154. package/dist/cpu/status8080.js +73 -0
  155. package/dist/cpu/status8080.js.map +1 -0
  156. package/dist/cpu/z80/CpuZ80.d.ts +53 -0
  157. package/dist/cpu/z80/CpuZ80.d.ts.map +1 -0
  158. package/dist/cpu/z80/CpuZ80.js +168 -0
  159. package/dist/cpu/z80/CpuZ80.js.map +1 -0
  160. package/dist/cpu/z80/DecoderZ80.d.ts +26 -0
  161. package/dist/cpu/z80/DecoderZ80.d.ts.map +1 -0
  162. package/dist/cpu/z80/DecoderZ80.js +107 -0
  163. package/dist/cpu/z80/DecoderZ80.js.map +1 -0
  164. package/dist/cpu/z80/FlagsZ80.d.ts +27 -0
  165. package/dist/cpu/z80/FlagsZ80.d.ts.map +1 -0
  166. package/dist/cpu/z80/FlagsZ80.js +47 -0
  167. package/dist/cpu/z80/FlagsZ80.js.map +1 -0
  168. package/dist/cpu/z80/RegistersZ80.d.ts +60 -0
  169. package/dist/cpu/z80/RegistersZ80.d.ts.map +1 -0
  170. package/dist/cpu/z80/RegistersZ80.js +90 -0
  171. package/dist/cpu/z80/RegistersZ80.js.map +1 -0
  172. package/dist/cpu/z80/flagHelpers.d.ts +25 -0
  173. package/dist/cpu/z80/flagHelpers.d.ts.map +1 -0
  174. package/dist/cpu/z80/flagHelpers.js +136 -0
  175. package/dist/cpu/z80/flagHelpers.js.map +1 -0
  176. package/dist/cpu/z80/instructions/alu16.d.ts +4 -0
  177. package/dist/cpu/z80/instructions/alu16.d.ts.map +1 -0
  178. package/dist/cpu/z80/instructions/alu16.js +27 -0
  179. package/dist/cpu/z80/instructions/alu16.js.map +1 -0
  180. package/dist/cpu/z80/instructions/alu8.d.ts +4 -0
  181. package/dist/cpu/z80/instructions/alu8.d.ts.map +1 -0
  182. package/dist/cpu/z80/instructions/alu8.js +100 -0
  183. package/dist/cpu/z80/instructions/alu8.js.map +1 -0
  184. package/dist/cpu/z80/instructions/bits.d.ts +10 -0
  185. package/dist/cpu/z80/instructions/bits.d.ts.map +1 -0
  186. package/dist/cpu/z80/instructions/bits.js +164 -0
  187. package/dist/cpu/z80/instructions/bits.js.map +1 -0
  188. package/dist/cpu/z80/instructions/block.d.ts +10 -0
  189. package/dist/cpu/z80/instructions/block.d.ts.map +1 -0
  190. package/dist/cpu/z80/instructions/block.js +141 -0
  191. package/dist/cpu/z80/instructions/block.js.map +1 -0
  192. package/dist/cpu/z80/instructions/control.d.ts +4 -0
  193. package/dist/cpu/z80/instructions/control.d.ts.map +1 -0
  194. package/dist/cpu/z80/instructions/control.js +62 -0
  195. package/dist/cpu/z80/instructions/control.js.map +1 -0
  196. package/dist/cpu/z80/instructions/ed.d.ts +4 -0
  197. package/dist/cpu/z80/instructions/ed.d.ts.map +1 -0
  198. package/dist/cpu/z80/instructions/ed.js +149 -0
  199. package/dist/cpu/z80/instructions/ed.js.map +1 -0
  200. package/dist/cpu/z80/instructions/exchange.d.ts +4 -0
  201. package/dist/cpu/z80/instructions/exchange.d.ts.map +1 -0
  202. package/dist/cpu/z80/instructions/exchange.js +37 -0
  203. package/dist/cpu/z80/instructions/exchange.js.map +1 -0
  204. package/dist/cpu/z80/instructions/io.d.ts +8 -0
  205. package/dist/cpu/z80/instructions/io.d.ts.map +1 -0
  206. package/dist/cpu/z80/instructions/io.js +22 -0
  207. package/dist/cpu/z80/instructions/io.js.map +1 -0
  208. package/dist/cpu/z80/instructions/jump.d.ts +4 -0
  209. package/dist/cpu/z80/instructions/jump.d.ts.map +1 -0
  210. package/dist/cpu/z80/instructions/jump.js +113 -0
  211. package/dist/cpu/z80/instructions/jump.js.map +1 -0
  212. package/dist/cpu/z80/instructions/load.d.ts +7 -0
  213. package/dist/cpu/z80/instructions/load.d.ts.map +1 -0
  214. package/dist/cpu/z80/instructions/load.js +103 -0
  215. package/dist/cpu/z80/instructions/load.js.map +1 -0
  216. package/dist/cpu/z80/instructions/rotate.d.ts +9 -0
  217. package/dist/cpu/z80/instructions/rotate.d.ts.map +1 -0
  218. package/dist/cpu/z80/instructions/rotate.js +48 -0
  219. package/dist/cpu/z80/instructions/rotate.js.map +1 -0
  220. package/dist/cpu/z80/instructions/stack.d.ts +4 -0
  221. package/dist/cpu/z80/instructions/stack.d.ts.map +1 -0
  222. package/dist/cpu/z80/instructions/stack.js +19 -0
  223. package/dist/cpu/z80/instructions/stack.js.map +1 -0
  224. package/dist/cpu/z80/regcodes.d.ts +22 -0
  225. package/dist/cpu/z80/regcodes.d.ts.map +1 -0
  226. package/dist/cpu/z80/regcodes.js +93 -0
  227. package/dist/cpu/z80/regcodes.js.map +1 -0
  228. package/dist/cpu/z80/types.d.ts +59 -0
  229. package/dist/cpu/z80/types.d.ts.map +1 -0
  230. package/dist/cpu/z80/types.js +2 -0
  231. package/dist/cpu/z80/types.js.map +1 -0
  232. package/dist/cpu/z80/views.d.ts +8 -0
  233. package/dist/cpu/z80/views.d.ts.map +1 -0
  234. package/dist/cpu/z80/views.js +40 -0
  235. package/dist/cpu/z80/views.js.map +1 -0
  236. package/dist/index.d.ts +67 -0
  237. package/dist/index.d.ts.map +1 -0
  238. package/dist/index.js +49 -0
  239. package/dist/index.js.map +1 -0
  240. package/dist/interfaces/IBus.d.ts +8 -0
  241. package/dist/interfaces/IBus.d.ts.map +1 -0
  242. package/dist/interfaces/IBus.js +2 -0
  243. package/dist/interfaces/IBus.js.map +1 -0
  244. package/dist/interfaces/IBusObserver.d.ts +7 -0
  245. package/dist/interfaces/IBusObserver.d.ts.map +1 -0
  246. package/dist/interfaces/IBusObserver.js +2 -0
  247. package/dist/interfaces/IBusObserver.js.map +1 -0
  248. package/dist/interfaces/IClock.d.ts +6 -0
  249. package/dist/interfaces/IClock.d.ts.map +1 -0
  250. package/dist/interfaces/IClock.js +2 -0
  251. package/dist/interfaces/IClock.js.map +1 -0
  252. package/dist/interfaces/ICpu.d.ts +46 -0
  253. package/dist/interfaces/ICpu.d.ts.map +1 -0
  254. package/dist/interfaces/ICpu.js +2 -0
  255. package/dist/interfaces/ICpu.js.map +1 -0
  256. package/dist/interfaces/IIODevice.d.ts +7 -0
  257. package/dist/interfaces/IIODevice.d.ts.map +1 -0
  258. package/dist/interfaces/IIODevice.js +2 -0
  259. package/dist/interfaces/IIODevice.js.map +1 -0
  260. package/dist/interfaces/IInterruptController.d.ts +8 -0
  261. package/dist/interfaces/IInterruptController.d.ts.map +1 -0
  262. package/dist/interfaces/IInterruptController.js +2 -0
  263. package/dist/interfaces/IInterruptController.js.map +1 -0
  264. package/dist/interfaces/IMemory.d.ts +9 -0
  265. package/dist/interfaces/IMemory.d.ts.map +1 -0
  266. package/dist/interfaces/IMemory.js +2 -0
  267. package/dist/interfaces/IMemory.js.map +1 -0
  268. package/dist/interfaces/IModule.d.ts +5 -0
  269. package/dist/interfaces/IModule.d.ts.map +1 -0
  270. package/dist/interfaces/IModule.js +2 -0
  271. package/dist/interfaces/IModule.js.map +1 -0
  272. package/dist/interfaces/IS100Card.d.ts +6 -0
  273. package/dist/interfaces/IS100Card.d.ts.map +1 -0
  274. package/dist/interfaces/IS100Card.js +2 -0
  275. package/dist/interfaces/IS100Card.js.map +1 -0
  276. package/dist/interfaces/index.d.ts +10 -0
  277. package/dist/interfaces/index.d.ts.map +1 -0
  278. package/dist/interfaces/index.js +2 -0
  279. package/dist/interfaces/index.js.map +1 -0
  280. package/dist/interrupt/InterruptController.d.ts +13 -0
  281. package/dist/interrupt/InterruptController.d.ts.map +1 -0
  282. package/dist/interrupt/InterruptController.js +36 -0
  283. package/dist/interrupt/InterruptController.js.map +1 -0
  284. package/dist/io/IoSpace.d.ts +9 -0
  285. package/dist/io/IoSpace.d.ts.map +1 -0
  286. package/dist/io/IoSpace.js +30 -0
  287. package/dist/io/IoSpace.js.map +1 -0
  288. package/dist/machine/MachineRunner.d.ts +54 -0
  289. package/dist/machine/MachineRunner.d.ts.map +1 -0
  290. package/dist/machine/MachineRunner.js +102 -0
  291. package/dist/machine/MachineRunner.js.map +1 -0
  292. package/dist/machine/MachineSpec.d.ts +80 -0
  293. package/dist/machine/MachineSpec.d.ts.map +1 -0
  294. package/dist/machine/MachineSpec.js +9 -0
  295. package/dist/machine/MachineSpec.js.map +1 -0
  296. package/dist/machine/buildMachine.d.ts +19 -0
  297. package/dist/machine/buildMachine.d.ts.map +1 -0
  298. package/dist/machine/buildMachine.js +122 -0
  299. package/dist/machine/buildMachine.js.map +1 -0
  300. package/dist/memory/MemoryMappedIOAdapter.d.ts +14 -0
  301. package/dist/memory/MemoryMappedIOAdapter.d.ts.map +1 -0
  302. package/dist/memory/MemoryMappedIOAdapter.js +23 -0
  303. package/dist/memory/MemoryMappedIOAdapter.js.map +1 -0
  304. package/dist/memory/Ram.d.ts +17 -0
  305. package/dist/memory/Ram.d.ts.map +1 -0
  306. package/dist/memory/Ram.js +36 -0
  307. package/dist/memory/Ram.js.map +1 -0
  308. package/dist/memory/Rom.d.ts +13 -0
  309. package/dist/memory/Rom.d.ts.map +1 -0
  310. package/dist/memory/Rom.js +25 -0
  311. package/dist/memory/Rom.js.map +1 -0
  312. package/dist/util/bits.d.ts +11 -0
  313. package/dist/util/bits.d.ts.map +1 -0
  314. package/dist/util/bits.js +35 -0
  315. package/dist/util/bits.js.map +1 -0
  316. package/dist/util/hostConsole.d.ts +2 -0
  317. package/dist/util/hostConsole.d.ts.map +1 -0
  318. package/dist/util/hostConsole.js +4 -0
  319. package/dist/util/hostConsole.js.map +1 -0
  320. package/package.json +39 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mc6850Acia.js","sourceRoot":"","sources":["../../src/cards/Mc6850Acia.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { IS100Card } from '../interfaces/IS100Card.js';
2
+ import type { Bus } from '../bus/Bus.js';
3
+ import { Mc6850Acia } from './Mc6850Acia.js';
4
+ export interface Sio2CardOptions {
5
+ readonly basePort?: number;
6
+ }
7
+ /**
8
+ * MITS Altair 88-2SIO dual serial card — two Motorola MC6850 ACIAs. Consumes
9
+ * four consecutive I/O addresses; the standard MITS base is 0x10:
10
+ *
11
+ * base+0 / base+1 Port 0 — control/status (0x10) + data (0x11)
12
+ * base+2 / base+3 Port 1 — control/status (0x12) + data (0x13)
13
+ *
14
+ * Port 0 is the conventional console. The 88-2SIO is the assumed serial board
15
+ * for nearly all MITS software (Altair BASIC, Altair DOS, and most CP/M BIOS
16
+ * implementations), so this is the card to attach when booting Altair CP/M.
17
+ */
18
+ export declare class Mits2SioCard implements IS100Card {
19
+ readonly id: string;
20
+ readonly port0: Mc6850Acia;
21
+ readonly port1: Mc6850Acia;
22
+ constructor(id?: string, options?: Sio2CardOptions);
23
+ attach(bus: Bus): void;
24
+ wireToConsole(): void;
25
+ reset(): void;
26
+ }
27
+ //# sourceMappingURL=Mits2SioCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mits2SioCard.d.ts","sourceRoot":"","sources":["../../src/cards/Mits2SioCard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAa,YAAW,SAAS;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;gBAEf,EAAE,SAAS,EAAE,OAAO,GAAE,eAAoB;IAOtD,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAKtB,aAAa,IAAI,IAAI;IAIrB,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,36 @@
1
+ import { Mc6850Acia } from './Mc6850Acia.js';
2
+ import { writeHostStdout } from '../util/hostConsole.js';
3
+ /**
4
+ * MITS Altair 88-2SIO dual serial card — two Motorola MC6850 ACIAs. Consumes
5
+ * four consecutive I/O addresses; the standard MITS base is 0x10:
6
+ *
7
+ * base+0 / base+1 Port 0 — control/status (0x10) + data (0x11)
8
+ * base+2 / base+3 Port 1 — control/status (0x12) + data (0x13)
9
+ *
10
+ * Port 0 is the conventional console. The 88-2SIO is the assumed serial board
11
+ * for nearly all MITS software (Altair BASIC, Altair DOS, and most CP/M BIOS
12
+ * implementations), so this is the card to attach when booting Altair CP/M.
13
+ */
14
+ export class Mits2SioCard {
15
+ id;
16
+ port0;
17
+ port1;
18
+ constructor(id = '2sio', options = {}) {
19
+ const base = options.basePort ?? 0x10;
20
+ this.id = id;
21
+ this.port0 = new Mc6850Acia(`${id}:port0`, base + 0, base + 1);
22
+ this.port1 = new Mc6850Acia(`${id}:port1`, base + 2, base + 3);
23
+ }
24
+ attach(bus) {
25
+ bus.attachIODevice(this.port0);
26
+ bus.attachIODevice(this.port1);
27
+ }
28
+ wireToConsole() {
29
+ this.port0.onTransmit((byte) => writeHostStdout(String.fromCharCode(byte & 0x7f)));
30
+ }
31
+ reset() {
32
+ this.port0.reset();
33
+ this.port1.reset();
34
+ }
35
+ }
36
+ //# sourceMappingURL=Mits2SioCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mits2SioCard.js","sourceRoot":"","sources":["../../src/cards/Mits2SioCard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,YAAY;IACd,EAAE,CAAS;IACX,KAAK,CAAa;IAClB,KAAK,CAAa;IAE3B,YAAY,EAAE,GAAG,MAAM,EAAE,UAA2B,EAAE;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QACtC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,GAAQ;QACb,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,aAAa;QACX,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACrF,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,52 @@
1
+ import type { IS100Card } from '../interfaces/IS100Card.js';
2
+ import type { IIODevice } from '../interfaces/IIODevice.js';
3
+ import type { Bus } from '../bus/Bus.js';
4
+ import { type WebSocketLike } from './FdcPlusClient.js';
5
+ export interface DcddOptions {
6
+ readonly basePort?: number;
7
+ }
8
+ export declare class MitsDcddCard implements IS100Card, IIODevice {
9
+ readonly id: string;
10
+ readonly basePorts: ReadonlyArray<number>;
11
+ private readonly fdcClient;
12
+ private readonly p1;
13
+ private readonly p2;
14
+ private readonly p3;
15
+ private selectedDrive;
16
+ private readonly driveTrack;
17
+ private headLoaded;
18
+ private writeEnabled;
19
+ private fetchPending;
20
+ private trackData;
21
+ private writeBuffer;
22
+ private writtenSectors;
23
+ private writeDirty;
24
+ private lastSector;
25
+ private byteInSector;
26
+ private cacheDrive;
27
+ /** Head position of the currently selected drive (0 when none selected). */
28
+ private get currentTrack();
29
+ private set currentTrack(value);
30
+ constructor(id: string, ws: WebSocketLike, options?: DcddOptions);
31
+ attach(bus: Bus): void;
32
+ ioRead(port: number): number;
33
+ ioWrite(port: number, value: number): void;
34
+ reset(): void;
35
+ private readStatus;
36
+ private writeDriveSelect;
37
+ private readSector;
38
+ private writeCommand;
39
+ private readData;
40
+ private writeData;
41
+ /**
42
+ * Start fetching the current track if the head is loaded, a drive is
43
+ * selected, we don't already have the data, and no fetch is in flight. Safe
44
+ * to call from any read/command path — it converges on caching the track the
45
+ * head is currently over.
46
+ */
47
+ private ensureTrack;
48
+ private fetchTrack;
49
+ private flushWrite;
50
+ private issueStep;
51
+ }
52
+ //# sourceMappingURL=MitsDcddCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MitsDcddCard.d.ts","sourceRoot":"","sources":["../../src/cards/MitsDcddCard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMvE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,YAAa,YAAW,SAAS,EAAE,SAAS;IACvD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAE5B,OAAO,CAAC,aAAa,CAAQ;IAK7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,UAAU,CAAW;IAE7B,4EAA4E;IAC5E,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,YAAY,QAEvB;gBAEW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,GAAE,WAAgB;IAUpE,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAItB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAO5B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAM1C,KAAK,IAAI,IAAI;IAkBb,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,gBAAgB;IA8BxB,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,SAAS;IAmBjB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,UAAU;IA0BlB,OAAO,CAAC,UAAU;IAyBlB,OAAO,CAAC,SAAS;CAWlB"}
@@ -0,0 +1,294 @@
1
+ import { FdcPlusClient } from './FdcPlusClient.js';
2
+ const TRACK_LEN = 137 * 32; // 4384 bytes — one full 8-inch track
3
+ const BYTES_PER_SECTOR = 137;
4
+ const MAX_TRACK = 76;
5
+ export class MitsDcddCard {
6
+ id;
7
+ basePorts;
8
+ fdcClient;
9
+ p1;
10
+ p2;
11
+ p3;
12
+ selectedDrive = 0xFF;
13
+ // Head position is PER-DRIVE state: each drive's arm stays where it was
14
+ // left. The BIOS seeks relatively from a per-drive track table in RAM, so a
15
+ // single shared counter desyncs the moment two drives interleave seeks
16
+ // (e.g. PIP copying between disks) and lands reads/writes on wrong tracks.
17
+ driveTrack = new Array(16).fill(0);
18
+ headLoaded = false;
19
+ writeEnabled = false;
20
+ fetchPending = false;
21
+ trackData = null;
22
+ writeBuffer = null;
23
+ writtenSectors = new Set(); // sectors touched since Write Enable
24
+ writeDirty = false;
25
+ lastSector = -1;
26
+ byteInSector = 0;
27
+ cacheDrive = 0xFF; // which drive the cached trackData belongs to
28
+ /** Head position of the currently selected drive (0 when none selected). */
29
+ get currentTrack() {
30
+ return this.selectedDrive === 0xFF ? 0 : (this.driveTrack[this.selectedDrive] ?? 0);
31
+ }
32
+ set currentTrack(track) {
33
+ if (this.selectedDrive !== 0xFF)
34
+ this.driveTrack[this.selectedDrive] = track;
35
+ }
36
+ constructor(id, ws, options = {}) {
37
+ this.id = id;
38
+ const base = options.basePort ?? 0x08;
39
+ this.p1 = base;
40
+ this.p2 = base + 1;
41
+ this.p3 = base + 2;
42
+ this.basePorts = [this.p1, this.p2, this.p3];
43
+ this.fdcClient = new FdcPlusClient(ws);
44
+ }
45
+ attach(bus) {
46
+ bus.attachIODevice(this);
47
+ }
48
+ ioRead(port) {
49
+ if (port === this.p1)
50
+ return this.readStatus();
51
+ if (port === this.p2)
52
+ return this.readSector();
53
+ if (port === this.p3)
54
+ return this.readData();
55
+ return 0xff;
56
+ }
57
+ ioWrite(port, value) {
58
+ if (port === this.p1) {
59
+ this.writeDriveSelect(value);
60
+ return;
61
+ }
62
+ if (port === this.p2) {
63
+ this.writeCommand(value);
64
+ return;
65
+ }
66
+ if (port === this.p3) {
67
+ this.writeData(value);
68
+ return;
69
+ }
70
+ }
71
+ reset() {
72
+ this.flushWrite();
73
+ this.selectedDrive = 0xFF;
74
+ this.driveTrack.fill(0);
75
+ this.headLoaded = false;
76
+ this.writeEnabled = false;
77
+ this.fetchPending = false;
78
+ this.trackData = null;
79
+ this.writeBuffer = null;
80
+ this.writtenSectors.clear();
81
+ this.writeDirty = false;
82
+ this.lastSector = -1;
83
+ this.byteInSector = 0;
84
+ this.cacheDrive = 0xFF;
85
+ }
86
+ // --- Port 1: status (READ) / drive select (WRITE) ---
87
+ readStatus() {
88
+ this.ensureTrack(); // lazily (re)start a fetch if the current track isn't cached
89
+ // 88-DCDD status register, all bits active-low (0 = condition true):
90
+ // bit7 NRDA — new read data available
91
+ // bit6 TRK0 — head at track 0
92
+ // bit3 DRVRDY — drive ready (a drive is selected and its disk is present)
93
+ // bit2 HDSTAT — head loaded / positioning valid
94
+ // bit1 MVHEAD — head movement complete (instantaneous in emulation)
95
+ // bit0 ENWDAT — ready to accept write data
96
+ const nrda = (!this.headLoaded || !this.trackData || this.fetchPending) ? 0x80 : 0;
97
+ const trk0 = this.currentTrack === 0 ? 0x00 : 0x40;
98
+ const drvrdy = this.selectedDrive !== 0xFF ? 0x00 : 0x08;
99
+ const hdstat = this.headLoaded ? 0x00 : 0x04;
100
+ const mvhd = 0x00;
101
+ const enwd = this.writeEnabled ? 0x00 : 0x01;
102
+ return nrda | trk0 | drvrdy | hdstat | mvhd | enwd;
103
+ }
104
+ writeDriveSelect(value) {
105
+ if ((value & 0x80) !== 0) {
106
+ // Disable/deselect the drive. On real hardware this drops the drive-enable
107
+ // line but the head-load solenoid and the data already under the head are
108
+ // physical state that persists — the drive can be reselected with the head
109
+ // still loaded. The MITS multi-stage boot relies on exactly this (it
110
+ // reselects the drive and expects HEDLD to already be active). Only an
111
+ // explicit Head Unload command (Port 2 bit 3) lifts the head.
112
+ this.flushWrite();
113
+ this.selectedDrive = 0xFF;
114
+ this.writeEnabled = false;
115
+ return;
116
+ }
117
+ const drive = value & 0x0F;
118
+ // A dirty write buffer belongs to the drive we're switching away from —
119
+ // flush it before the selection changes, or it lands on the new drive.
120
+ if (drive !== this.selectedDrive)
121
+ this.flushWrite();
122
+ this.selectedDrive = drive;
123
+ // Selecting a different drive invalidates the cached track (different disk).
124
+ if (drive !== this.cacheDrive) {
125
+ this.trackData = null;
126
+ }
127
+ this.ensureTrack();
128
+ this.fdcClient
129
+ .stat(this.selectedDrive, this.headLoaded, this.currentTrack)
130
+ .catch(() => { });
131
+ }
132
+ // --- Port 2: sector position (READ) / command (WRITE) ---
133
+ readSector() {
134
+ const revMs = 166.667;
135
+ const secMs = revMs / 32;
136
+ const pos = performance.now() % revMs;
137
+ const sector = Math.floor(pos / secMs) & 0x1F;
138
+ const offset = pos % secMs;
139
+ // Sector True (bit 0) pulses LOW for first 1 ms of each sector window
140
+ const sectorTrue = offset < 1.0 ? 0 : 1;
141
+ if (sector !== this.lastSector || sectorTrue === 0) {
142
+ // New sector under the head, or the start-of-sector pulse. Sector True
143
+ // marks the beginning of the sector: software that samples it here (the
144
+ // BIOS waits for it before every transfer) expects the byte stream to
145
+ // start at byte 0 — even when re-targeting the sector it just finished,
146
+ // where the sector number alone wouldn't change.
147
+ this.lastSector = sector;
148
+ this.byteInSector = 0;
149
+ }
150
+ return 0xC0 | ((sector & 0x1F) << 1) | sectorTrue;
151
+ }
152
+ writeCommand(value) {
153
+ // Process all command bits; multiple may be set simultaneously
154
+ if ((value & 0x80) !== 0) { // Write Enable
155
+ // The BIOS issues Write Enable once per sector write. On real hardware
156
+ // each sector hits the disk immediately; here writes accumulate in the
157
+ // track buffer until flush, so Write Enable must NOT discard sectors
158
+ // buffered by earlier enables — only ensure a buffer exists.
159
+ this.writeEnabled = true;
160
+ if (!this.writeBuffer)
161
+ this.writeBuffer = new Uint8Array(TRACK_LEN);
162
+ }
163
+ if ((value & 0x08) !== 0) { // Head Unload
164
+ this.flushWrite();
165
+ this.headLoaded = false;
166
+ this.trackData = null;
167
+ }
168
+ if ((value & 0x04) !== 0) { // Head Load
169
+ this.headLoaded = true;
170
+ this.ensureTrack();
171
+ }
172
+ if ((value & 0x02) !== 0)
173
+ this.issueStep('out'); // Step Out
174
+ if ((value & 0x01) !== 0)
175
+ this.issueStep('in'); // Step In
176
+ }
177
+ // --- Port 3: data (READ/WRITE) ---
178
+ readData() {
179
+ if (!this.headLoaded || !this.trackData || this.fetchPending)
180
+ return 0xff;
181
+ // Past the 137th byte the head is over the inter-sector gap — nothing to
182
+ // read until the sector counter advances (which resets byteInSector).
183
+ if (this.byteInSector >= BYTES_PER_SECTOR)
184
+ return 0xff;
185
+ const sector = this.lastSector < 0 ? 0 : this.lastSector;
186
+ const offset = sector * BYTES_PER_SECTOR + this.byteInSector;
187
+ // A sector rewritten since Write Enable reads back its new contents.
188
+ const source = (this.writeBuffer && this.writtenSectors.has(sector))
189
+ ? this.writeBuffer
190
+ : this.trackData;
191
+ if (offset >= source.length)
192
+ return 0xff;
193
+ const byte = source[offset] ?? 0xff;
194
+ this.byteInSector++;
195
+ return byte;
196
+ }
197
+ writeData(value) {
198
+ if (!this.writeEnabled || !this.writeBuffer)
199
+ return;
200
+ // The BIOS pads its 137-byte sector burst with trailing bytes; on real
201
+ // hardware they land in the inter-sector gap. Discard them — wrapping
202
+ // around would overwrite the start of the sector (the track-marker byte),
203
+ // corrupting it.
204
+ if (this.byteInSector >= BYTES_PER_SECTOR)
205
+ return;
206
+ const sector = this.lastSector < 0 ? 0 : this.lastSector;
207
+ const offset = sector * BYTES_PER_SECTOR + this.byteInSector;
208
+ if (offset < this.writeBuffer.length) {
209
+ this.writeBuffer[offset] = value & 0xff;
210
+ this.writtenSectors.add(sector);
211
+ this.writeDirty = true;
212
+ }
213
+ this.byteInSector++;
214
+ }
215
+ // --- Private helpers ---
216
+ /**
217
+ * Start fetching the current track if the head is loaded, a drive is
218
+ * selected, we don't already have the data, and no fetch is in flight. Safe
219
+ * to call from any read/command path — it converges on caching the track the
220
+ * head is currently over.
221
+ */
222
+ ensureTrack() {
223
+ if (!this.headLoaded || this.selectedDrive === 0xFF)
224
+ return;
225
+ if (this.trackData || this.fetchPending)
226
+ return;
227
+ this.fetchTrack();
228
+ }
229
+ fetchTrack() {
230
+ if (this.selectedDrive === 0xFF || !this.headLoaded || this.fetchPending)
231
+ return;
232
+ this.fetchPending = true;
233
+ const drive = this.selectedDrive;
234
+ const track = this.currentTrack;
235
+ this.fdcClient
236
+ .readTrack(drive, track, TRACK_LEN)
237
+ .then((data) => {
238
+ // Only install the data if the head hasn't moved (and the same drive is
239
+ // still selected) since the fetch began — otherwise it belongs to a
240
+ // track we're no longer over and would corrupt the next read. A cache
241
+ // that appeared meanwhile is a flushed write image, which is fresher
242
+ // than what we just fetched — keep it.
243
+ if (track === this.currentTrack && drive === this.selectedDrive && !this.trackData) {
244
+ this.trackData = data;
245
+ this.cacheDrive = drive;
246
+ }
247
+ })
248
+ .catch(() => { })
249
+ .finally(() => {
250
+ this.fetchPending = false;
251
+ // If the head moved during the fetch, chase the track it's now over.
252
+ this.ensureTrack();
253
+ });
254
+ }
255
+ flushWrite() {
256
+ if (!this.writeDirty || !this.writeBuffer || this.selectedDrive === 0xFF)
257
+ return;
258
+ // WRIT replaces the whole track on the server, but the program only wrote
259
+ // some sectors — merge those over the cached track image so the rest keep
260
+ // their contents.
261
+ const image = this.trackData ? new Uint8Array(this.trackData) : new Uint8Array(TRACK_LEN);
262
+ for (const sector of this.writtenSectors) {
263
+ const off = sector * BYTES_PER_SECTOR;
264
+ image.set(this.writeBuffer.subarray(off, off + BYTES_PER_SECTOR), off);
265
+ }
266
+ const drive = this.selectedDrive;
267
+ const track = this.currentTrack;
268
+ this.writeBuffer = null;
269
+ this.writtenSectors.clear();
270
+ this.writeDirty = false;
271
+ this.writeEnabled = false;
272
+ // The merged image is now the freshest copy of the track — reads must see
273
+ // the written data, not the pre-write cache.
274
+ this.trackData = image;
275
+ this.cacheDrive = drive;
276
+ this.fdcClient.writeTrack(drive, track, image).catch((e) => {
277
+ console.error(`[${this.id}] track write failed (drive ${drive}, track ${track}): ${String(e)}`);
278
+ });
279
+ }
280
+ issueStep(dir) {
281
+ // Seeks are instantaneous in emulation. A real-time settle delay would
282
+ // desync from the emulated CPU (which the software paces itself), and
283
+ // dropping "too-fast" step pulses would lose track position entirely.
284
+ this.flushWrite(); // a dirty buffer belongs to the track we're leaving
285
+ if (dir === 'in')
286
+ this.currentTrack = Math.min(MAX_TRACK, this.currentTrack + 1);
287
+ else
288
+ this.currentTrack = Math.max(0, this.currentTrack - 1);
289
+ this.trackData = null; // head moved; cached track is no longer under it
290
+ this.writeEnabled = false;
291
+ this.ensureTrack(); // begin fetching the new track
292
+ }
293
+ }
294
+ //# sourceMappingURL=MitsDcddCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MitsDcddCard.js","sourceRoot":"","sources":["../../src/cards/MitsDcddCard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { IS100Card } from '../interfaces/IS100Card.js';
2
+ import type { Bus } from '../bus/Bus.js';
3
+ /** Data direction of a parallel port from the operator's peripheral view. */
4
+ export type PortDirection = 'out' | 'in' | 'inout';
5
+ export interface ParallelCardOptions {
6
+ readonly port?: number;
7
+ readonly direction?: PortDirection;
8
+ }
9
+ /** The host-side surface a GPIO peripheral (LEDs / switches / printer) binds to. */
10
+ export interface GpioPort {
11
+ readonly direction: PortDirection;
12
+ /** The byte the CPU last latched on the output pins (drive LEDs / a printer). */
13
+ read(): number;
14
+ /** Drive the input pins — the value the CPU reads (sense switches). */
15
+ setInput(byte: number): void;
16
+ /** Fired whenever the CPU writes the output latch. */
17
+ onOutput(cb: (byte: number) => void): void;
18
+ }
19
+ /**
20
+ * A single 8-bit parallel I/O card (Story 5.8) — an 8212-style latched port the
21
+ * general GPIO cards resolve to. A CPU write latches the output byte; a CPU read
22
+ * returns the input pins. It exposes a `gpio` surface so the host wires it to a
23
+ * peripheral — an LED bank, sense switches, a printer, or real hardware GPIO.
24
+ * `direction` is a hint for the peripheral viewer (the 8212 is bidirectional).
25
+ */
26
+ export declare class ParallelCard implements IS100Card {
27
+ readonly id: string;
28
+ readonly direction: PortDirection;
29
+ readonly gpio: GpioPort;
30
+ private readonly dev;
31
+ constructor(id?: string, opts?: ParallelCardOptions);
32
+ attach(bus: Bus): void;
33
+ reset(): void;
34
+ }
35
+ //# sourceMappingURL=ParallelCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParallelCard.d.ts","sourceRoot":"","sources":["../../src/cards/ParallelCard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGzC,6EAA6E;AAC7E,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;CACpC;AAED,oFAAoF;AACpF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,iFAAiF;IACjF,IAAI,IAAI,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,SAAS;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAW;gBAEnB,EAAE,SAAa,EAAE,IAAI,GAAE,mBAAwB;IAY3D,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAItB,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,32 @@
1
+ import { Port8212 } from './Port8212.js';
2
+ /**
3
+ * A single 8-bit parallel I/O card (Story 5.8) — an 8212-style latched port the
4
+ * general GPIO cards resolve to. A CPU write latches the output byte; a CPU read
5
+ * returns the input pins. It exposes a `gpio` surface so the host wires it to a
6
+ * peripheral — an LED bank, sense switches, a printer, or real hardware GPIO.
7
+ * `direction` is a hint for the peripheral viewer (the 8212 is bidirectional).
8
+ */
9
+ export class ParallelCard {
10
+ id;
11
+ direction;
12
+ gpio;
13
+ dev;
14
+ constructor(id = 'parallel', opts = {}) {
15
+ this.id = id;
16
+ this.direction = opts.direction ?? 'out';
17
+ this.dev = new Port8212(`${id}:port`, opts.port ?? 0x00);
18
+ this.gpio = {
19
+ direction: this.direction,
20
+ read: () => this.dev.output,
21
+ setInput: (byte) => this.dev.setInput(byte),
22
+ onOutput: (cb) => this.dev.onWrite(cb),
23
+ };
24
+ }
25
+ attach(bus) {
26
+ bus.attachIODevice(this.dev);
27
+ }
28
+ reset() {
29
+ this.dev.reset();
30
+ }
31
+ }
32
+ //# sourceMappingURL=ParallelCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParallelCard.js","sourceRoot":"","sources":["../../src/cards/ParallelCard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAqBzC;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACd,EAAE,CAAS;IACX,SAAS,CAAgB;IACzB,IAAI,CAAW;IACP,GAAG,CAAW;IAE/B,YAAY,EAAE,GAAG,UAAU,EAAE,OAA4B,EAAE;QACzD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;QACzC,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG;YACV,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM;YAC3B,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YACnD,QAAQ,EAAE,CAAC,EAA0B,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;SAC/D,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,GAAQ;QACb,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ import type { IIODevice } from '../interfaces/IIODevice.js';
2
+ type PortWriteCallback = (value: number) => void;
3
+ /**
4
+ * Intel / AMD 8212 eight-bit latched I/O port, as used for the IMSAI MIO
5
+ * board's two parallel ports. A CPU write latches the output byte (held on the
6
+ * output pins); a CPU read returns whatever is currently presented on the input
7
+ * pins. Output and input are independent, modelling a bidirectional 8212 port.
8
+ *
9
+ * The host drives the input pins with {@link setInput} and observes the latched
10
+ * output via {@link output} or an {@link onWrite} callback — this is how a
11
+ * printer, LED bank, switch bank, or other peripheral is wired to the port.
12
+ */
13
+ export declare class Port8212 implements IIODevice {
14
+ readonly id: string;
15
+ readonly basePorts: ReadonlyArray<number>;
16
+ private outputLatch;
17
+ private inputLatch;
18
+ private writeCb;
19
+ constructor(id: string, port: number);
20
+ ioRead(_port: number): number;
21
+ ioWrite(_port: number, value: number): void;
22
+ reset(): void;
23
+ /** Drive the port's input pins — the value the CPU reads from this port. */
24
+ setInput(value: number): void;
25
+ /** The byte currently latched on the output pins. */
26
+ get output(): number;
27
+ /** Register a callback fired whenever the CPU writes the output latch. */
28
+ onWrite(cb: PortWriteCallback): void;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=Port8212.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Port8212.d.ts","sourceRoot":"","sources":["../../src/cards/Port8212.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D,KAAK,iBAAiB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAEjD;;;;;;;;;GASG;AACH,qBAAa,QAAS,YAAW,SAAS;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,OAAO,CAAgC;gBAEnC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAKpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI7B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK3C,KAAK,IAAI,IAAI;IAMb,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,qDAAqD;IACrD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,0EAA0E;IAC1E,OAAO,CAAC,EAAE,EAAE,iBAAiB,GAAG,IAAI;CAGrC"}
@@ -0,0 +1,47 @@
1
+ import { u8 } from '../util/bits.js';
2
+ /**
3
+ * Intel / AMD 8212 eight-bit latched I/O port, as used for the IMSAI MIO
4
+ * board's two parallel ports. A CPU write latches the output byte (held on the
5
+ * output pins); a CPU read returns whatever is currently presented on the input
6
+ * pins. Output and input are independent, modelling a bidirectional 8212 port.
7
+ *
8
+ * The host drives the input pins with {@link setInput} and observes the latched
9
+ * output via {@link output} or an {@link onWrite} callback — this is how a
10
+ * printer, LED bank, switch bank, or other peripheral is wired to the port.
11
+ */
12
+ export class Port8212 {
13
+ id;
14
+ basePorts;
15
+ outputLatch = 0;
16
+ inputLatch = 0xff; // unconnected TTL inputs float high
17
+ writeCb;
18
+ constructor(id, port) {
19
+ this.id = id;
20
+ this.basePorts = [port];
21
+ }
22
+ ioRead(_port) {
23
+ return this.inputLatch;
24
+ }
25
+ ioWrite(_port, value) {
26
+ this.outputLatch = u8(value);
27
+ this.writeCb?.(this.outputLatch);
28
+ }
29
+ reset() {
30
+ this.outputLatch = 0;
31
+ this.inputLatch = 0xff;
32
+ // writeCb survives reset — it is host wiring.
33
+ }
34
+ /** Drive the port's input pins — the value the CPU reads from this port. */
35
+ setInput(value) {
36
+ this.inputLatch = u8(value);
37
+ }
38
+ /** The byte currently latched on the output pins. */
39
+ get output() {
40
+ return this.outputLatch;
41
+ }
42
+ /** Register a callback fired whenever the CPU writes the output latch. */
43
+ onWrite(cb) {
44
+ this.writeCb = cb;
45
+ }
46
+ }
47
+ //# sourceMappingURL=Port8212.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Port8212.js","sourceRoot":"","sources":["../../src/cards/Port8212.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAIrC;;;;;;;;;GASG;AACH,MAAM,OAAO,QAAQ;IACV,EAAE,CAAS;IACX,SAAS,CAAwB;IAElC,WAAW,GAAG,CAAC,CAAC;IAChB,UAAU,GAAG,IAAI,CAAC,CAAC,oCAAoC;IACvD,OAAO,CAAgC;IAE/C,YAAY,EAAU,EAAE,IAAY;QAClC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,KAAa;QAClC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,8CAA8C;IAChD,CAAC;IAED,4EAA4E;IAC5E,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,qDAAqD;IACrD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,0EAA0E;IAC1E,OAAO,CAAC,EAAqB;QAC3B,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ import type { IS100Card } from '../interfaces/IS100Card.js';
2
+ import type { Bus } from '../bus/Bus.js';
3
+ /** Host time source injected via CardContext.services.clock. */
4
+ export type RtcClock = () => Date;
5
+ export interface RtcCardOptions {
6
+ /** Base I/O port; the chip occupies base..base+0x1F (32 registers). */
7
+ readonly base?: number;
8
+ }
9
+ /**
10
+ * National MM58167 real-time clock (Story 5.10). A 32-register clock/calendar
11
+ * chip on an I/O window: the counter registers (0x00–0x07) read the host wall
12
+ * clock as BCD, the rest (RAM / compare / interrupt / status) are plain storage.
13
+ *
14
+ * The host time comes from `ctx.services.clock` (a `() => Date`), so the machine
15
+ * reads real time while tests stay deterministic by injecting a fixed clock.
16
+ * Writes to the live counters are ignored — you can't set the host's clock.
17
+ */
18
+ export declare class RtcCard implements IS100Card {
19
+ readonly id: string;
20
+ private readonly base;
21
+ private readonly now;
22
+ private readonly ram;
23
+ private readonly dev;
24
+ constructor(id?: string, opts?: RtcCardOptions, clock?: RtcClock);
25
+ attach(bus: Bus): void;
26
+ reset(): void;
27
+ private readReg;
28
+ private writeReg;
29
+ }
30
+ //# sourceMappingURL=RtcCard.d.ts.map