nonogamer9

test

Aug 21st, 2026 (edited)
122
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 70.21 KB | None | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local computer = require("computer")
  4. local bit = require("bit32")
  5.  
  6. if not component.isAvailable("sound") then
  7. error("A Computronics Sound Card is required.")
  8. end
  9.  
  10. local sound = component.sound
  11.  
  12. ----------------------------------------------------------------
  13. -- Configuration
  14. ----------------------------------------------------------------
  15.  
  16. local RAM_SIZE = 65536
  17.  
  18. local SID_BASE = 0xD400
  19. local SID_END = 0xD41F
  20.  
  21. local MAX_SIDS = 2
  22. local VOICES_PER_SID = 3
  23. local TOTAL_VOICES = MAX_SIDS * VOICES_PER_SID
  24.  
  25. local PAL_HZ = 50
  26. local NTSC_HZ = 60
  27.  
  28. local PAL_CLOCK = 985248
  29. local NTSC_CLOCK = 1022727
  30. local SID_FREQ_DIV = 16777216
  31.  
  32. local DEFAULT_VOLUME = 0.55
  33. local MIN_VOLUME = 0.0
  34. local MAX_VOLUME = 1.0
  35.  
  36. local MAX_INSTRUCTIONS_PER_CALL = 200000
  37. local MAX_INSTRUCTIONS_PER_IRQ = 200000
  38.  
  39. -- Common C64 KERNAL IRQ exit.
  40. -- We emulate the effect of reaching it instead of requiring
  41. -- the KERNAL ROM to actually be present.
  42. local KERNAL_IRQ_EXIT = 0xEA31
  43.  
  44. local WAVE_NOISE = sound.modes.noise
  45. local WAVE_SQUARE = sound.modes.square
  46. local WAVE_SAW = sound.modes.sawtooth
  47. local WAVE_TRIANGLE = sound.modes.triangle
  48.  
  49. ----------------------------------------------------------------
  50. -- Basic helpers
  51. ----------------------------------------------------------------
  52.  
  53. local function u8(x)
  54. x = x % 256
  55. if x < 0 then
  56. x = x + 256
  57. end
  58. return x
  59. end
  60.  
  61. local function u16(x)
  62. x = x % 65536
  63. if x < 0 then
  64. x = x + 65536
  65. end
  66. return x
  67. end
  68.  
  69. local function lo(x)
  70. return bit.band(x, 0xFF)
  71. end
  72.  
  73. local function hi(x)
  74. return bit.band(bit.rshift(x, 8), 0xFF)
  75. end
  76.  
  77. local function signed8(x)
  78. if x >= 128 then
  79. return x - 256
  80. end
  81. return x
  82. end
  83.  
  84. local function clamp(x, a, b)
  85. if x < a then
  86. return a
  87. end
  88.  
  89. if x > b then
  90. return b
  91. end
  92.  
  93. return x
  94. end
  95.  
  96. ----------------------------------------------------------------
  97. -- SID file parser
  98. ----------------------------------------------------------------
  99.  
  100. local SID = {}
  101.  
  102. function SID.readBE16(data, p)
  103. local a, b = string.byte(data, p, p + 1)
  104.  
  105. if not a or not b then
  106. error("Unexpected end of SID header.")
  107. end
  108.  
  109. return a * 256 + b
  110. end
  111.  
  112. function SID.readBE32(data, p)
  113. local a, b, c, d = string.byte(data, p, p + 3)
  114.  
  115. if not a or not b or not c or not d then
  116. error("Unexpected end of SID header.")
  117. end
  118.  
  119. return ((a * 256 + b) * 256 + c) * 256 + d
  120. end
  121.  
  122. function SID.text(data, p, length)
  123. local s = data:sub(p, p + length - 1)
  124.  
  125. s = s:gsub("%z.*$", "")
  126. s = s:gsub("[%c]", "")
  127.  
  128. return s
  129. end
  130.  
  131. function SID.decodeClock(flags)
  132. if flags == 0 then
  133. return "unknown"
  134. end
  135.  
  136. local clockBits =
  137. bit.band(
  138. bit.rshift(flags, 2),
  139. 0x03
  140. )
  141.  
  142. if clockBits == 1 then
  143. return "PAL"
  144. end
  145.  
  146. if clockBits == 2 then
  147. return "NTSC"
  148. end
  149.  
  150. if clockBits == 3 then
  151. return "PAL+NTSC"
  152. end
  153.  
  154. return "unknown"
  155. end
  156.  
  157. function SID.decodeModel(flags, shift)
  158. local modelBits =
  159. bit.band(
  160. bit.rshift(flags, shift),
  161. 0x03
  162. )
  163.  
  164. if modelBits == 1 then
  165. return "6581"
  166. end
  167.  
  168. if modelBits == 2 then
  169. return "8580"
  170. end
  171.  
  172. if modelBits == 3 then
  173. return "6581/8580"
  174. end
  175.  
  176. return "unknown"
  177. end
  178.  
  179. ----------------------------------------------------------------
  180. -- PSID/RSID multi-SID address decoding
  181. --
  182. -- Header byte 0x42 = $D420
  183. -- Header byte 0x50 = $D500
  184. -- Header byte 0xE0 = $DE00
  185. --
  186. -- Only even values in:
  187. -- $42-$7F
  188. -- $E0-$FE
  189. -- are valid.
  190. ----------------------------------------------------------------
  191.  
  192. function SID.decodeSIDAddress(selector)
  193. if not selector or selector == 0 then
  194. return 0
  195. end
  196.  
  197. selector = bit.band(selector, 0xFF)
  198.  
  199. if bit.band(selector, 1) ~= 0 then
  200. return 0
  201. end
  202.  
  203. if selector < 0x42 then
  204. return 0
  205. end
  206.  
  207. if selector > 0x7F and selector < 0xE0 then
  208. return 0
  209. end
  210.  
  211. if selector > 0xFE then
  212. return 0
  213. end
  214.  
  215. return 0xD000 + bit.lshift(selector, 4)
  216. end
  217.  
  218. function SID.loadFile(path)
  219. local f, err = io.open(path, "rb")
  220.  
  221. if not f then
  222. error("Cannot open SID file: " .. tostring(err))
  223. end
  224.  
  225. local data = f:read("*a")
  226. f:close()
  227.  
  228. if not data or #data < 0x76 then
  229. error("File is too small to be a valid SID file.")
  230. end
  231.  
  232. local magic = data:sub(1, 4)
  233.  
  234. if magic ~= "PSID" and magic ~= "RSID" then
  235. error("Not a PSID/RSID file.")
  236. end
  237.  
  238. local version = SID.readBE16(data, 5)
  239. local dataOffset = SID.readBE16(data, 7)
  240. local loadAddress = SID.readBE16(data, 9)
  241. local initAddress = SID.readBE16(data, 11)
  242. local playAddress = SID.readBE16(data, 13)
  243. local songs = SID.readBE16(data, 15)
  244. local startSong = SID.readBE16(data, 17)
  245. local speed = SID.readBE32(data, 19)
  246.  
  247. if songs < 1 then
  248. songs = 1
  249. end
  250.  
  251. if startSong < 1 or startSong > songs then
  252. startSong = 1
  253. end
  254.  
  255. if dataOffset < 0x76 or dataOffset > #data then
  256. error("Invalid SID data offset.")
  257. end
  258.  
  259. local flags = 0
  260.  
  261. if version >= 2 and #data >= 0x7C then
  262. flags = SID.readBE16(data, 0x77)
  263. end
  264.  
  265. local secondSID = 0
  266. local thirdSID = 0
  267.  
  268. if version >= 3 and #data >= 0x7C then
  269. secondSID =
  270. SID.decodeSIDAddress(
  271. string.byte(data, 0x7B)
  272. )
  273. end
  274.  
  275. if version >= 4 and #data >= 0x7C then
  276. thirdSID =
  277. SID.decodeSIDAddress(
  278. string.byte(data, 0x7C)
  279. )
  280. end
  281.  
  282. -- A secondary SID cannot be the primary SID.
  283. if secondSID == SID_BASE then
  284. secondSID = 0
  285. end
  286.  
  287. -- Third SID must not collide with SID #1 or SID #2.
  288. if thirdSID == SID_BASE or
  289. thirdSID == secondSID then
  290. thirdSID = 0
  291. end
  292.  
  293. local name = SID.text(data, 0x15, 32)
  294. local author = SID.text(data, 0x35, 32)
  295. local released = SID.text(data, 0x55, 32)
  296.  
  297. local binary = data:sub(dataOffset + 1)
  298.  
  299. if loadAddress == 0 then
  300. if #binary < 2 then
  301. error("SID data has no embedded load address.")
  302. end
  303.  
  304. local a = string.byte(binary, 1)
  305. local b = string.byte(binary, 2)
  306.  
  307. loadAddress = a + b * 256
  308. binary = binary:sub(3)
  309. end
  310.  
  311. if loadAddress < 0 or
  312. loadAddress + #binary > RAM_SIZE then
  313. error("SID program does not fit into C64 memory.")
  314. end
  315.  
  316. local effectiveInitAddress = initAddress
  317.  
  318. if effectiveInitAddress == 0 then
  319. effectiveInitAddress = loadAddress
  320. end
  321.  
  322. local sidBases = {
  323. SID_BASE
  324. }
  325.  
  326. if secondSID ~= 0 then
  327. sidBases[2] = secondSID
  328. end
  329.  
  330. return {
  331. magic = magic,
  332. version = version,
  333. dataOffset = dataOffset,
  334.  
  335. loadAddress = loadAddress,
  336. initAddress = initAddress,
  337. effectiveInitAddress = effectiveInitAddress,
  338. playAddress = playAddress,
  339.  
  340. songs = songs,
  341. startSong = startSong,
  342. speed = speed,
  343.  
  344. flags = flags,
  345.  
  346. clock = SID.decodeClock(flags),
  347.  
  348. sidModel1 = SID.decodeModel(flags, 4),
  349. sidModel2 = SID.decodeModel(flags, 6),
  350. sidModel3 = SID.decodeModel(flags, 8),
  351.  
  352. secondSID = secondSID,
  353. thirdSID = thirdSID,
  354.  
  355. sidBases = sidBases,
  356.  
  357. name = name,
  358. author = author,
  359. released = released,
  360.  
  361. data = binary
  362. }
  363. end
  364.  
  365. ----------------------------------------------------------------
  366. -- SID chip
  367. ----------------------------------------------------------------
  368.  
  369. local SIDChip = {}
  370. SIDChip.__index = SIDChip
  371.  
  372. function SIDChip.new()
  373. local self = setmetatable({}, SIDChip)
  374.  
  375. self.reg = {}
  376.  
  377. for i = 0, 0x1F do
  378. self.reg[i] = 0
  379. end
  380.  
  381. self.voices = {
  382. {},
  383. {},
  384. {}
  385. }
  386.  
  387. return self
  388. end
  389.  
  390. function SIDChip:read(reg)
  391. reg = bit.band(reg, 0x1F)
  392.  
  393. -- These are read-only SID registers. We do not have a
  394. -- cycle-perfect oscillator/envelope implementation, so
  395. -- don't pretend that writes to them are valid readback.
  396. if reg >= 0x19 then
  397. if reg <= 0x1C then
  398. return 0
  399. end
  400. end
  401.  
  402. return self.reg[reg] or 0
  403. end
  404.  
  405. function SIDChip:write(reg, value)
  406. reg = bit.band(reg, 0x1F)
  407. value = u8(value)
  408.  
  409. -- Pulse width high byte only uses four bits.
  410. if reg == 0x03 or
  411. reg == 0x0A or
  412. reg == 0x11 then
  413. value = bit.band(value, 0x0F)
  414. end
  415.  
  416. -- Filter control has only the defined low bits plus
  417. -- voice-3-off in bit 7.
  418. if reg == 0x18 then
  419. value =
  420. bit.band(
  421. value,
  422. 0x8F
  423. )
  424. end
  425.  
  426. -- Oscillator/envelope read-only registers should not
  427. -- become writable shadow registers.
  428. if reg >= 0x19 and reg <= 0x1C then
  429. return
  430. end
  431.  
  432. self.reg[reg] = value
  433. end
  434.  
  435. function SIDChip:masterVolume()
  436. return bit.band(
  437. self.reg[0x18] or 0,
  438. 0x0F
  439. )
  440. end
  441.  
  442. function SIDChip:voice3Off()
  443. return bit.band(
  444. self.reg[0x18] or 0,
  445. 0x80
  446. ) ~= 0
  447. end
  448.  
  449. function SIDChip:voice(v)
  450. local base = (v - 1) * 7
  451. local out = self.voices[v]
  452.  
  453. local freqLo =
  454. self.reg[base] or 0
  455.  
  456. local freqHi =
  457. self.reg[base + 1] or 0
  458.  
  459. local pwLo =
  460. self.reg[base + 2] or 0
  461.  
  462. local pwHi =
  463. self.reg[base + 3] or 0
  464.  
  465. local control =
  466. self.reg[base + 4] or 0
  467.  
  468. local attackDecay =
  469. self.reg[base + 5] or 0
  470.  
  471. local sustainRelease =
  472. self.reg[base + 6] or 0
  473.  
  474. local freq =
  475. freqLo +
  476. bit.lshift(freqHi, 8)
  477.  
  478. local pulse =
  479. pwLo +
  480. bit.lshift(
  481. bit.band(pwHi, 0x0F),
  482. 8
  483. )
  484.  
  485. local attack =
  486. bit.rshift(
  487. attackDecay,
  488. 4
  489. )
  490.  
  491. local decay =
  492. bit.band(
  493. attackDecay,
  494. 0x0F
  495. )
  496.  
  497. local sustain =
  498. bit.rshift(
  499. sustainRelease,
  500. 4
  501. )
  502.  
  503. local release =
  504. bit.band(
  505. sustainRelease,
  506. 0x0F
  507. )
  508.  
  509. out.frequency = freq
  510. out.pulse = pulse
  511. out.control = control
  512.  
  513. out.attack = attack
  514. out.decay = decay
  515. out.sustain = sustain
  516. out.release = release
  517.  
  518. out.gate =
  519. bit.band(control, 0x01) ~= 0
  520.  
  521. out.sync =
  522. bit.band(control, 0x02) ~= 0
  523.  
  524. out.ring =
  525. bit.band(control, 0x04) ~= 0
  526.  
  527. out.test =
  528. bit.band(control, 0x08) ~= 0
  529.  
  530. out.triangle =
  531. bit.band(control, 0x10) ~= 0
  532.  
  533. out.saw =
  534. bit.band(control, 0x20) ~= 0
  535.  
  536. out.square =
  537. bit.band(control, 0x40) ~= 0
  538.  
  539. out.noise =
  540. bit.band(control, 0x80) ~= 0
  541.  
  542. return out
  543. end
  544.  
  545. ----------------------------------------------------------------
  546. -- 6502 CPU
  547. ----------------------------------------------------------------
  548.  
  549. local CPU = {}
  550. CPU.__index = CPU
  551.  
  552. function CPU.new(memory, sids, sidBases)
  553. local self = setmetatable({}, CPU)
  554.  
  555. self.mem = memory
  556.  
  557. self.sids = sids
  558. self.sidBases = sidBases
  559.  
  560. self.sidCount = #sids
  561.  
  562. self.A = 0
  563. self.X = 0
  564. self.Y = 0
  565.  
  566. self.P = 0x24
  567. self.SP = 0xFD
  568. self.PC = 0
  569.  
  570. self.running = true
  571.  
  572. return self
  573. end
  574.  
  575. function CPU:sidAt(addr)
  576. if addr >= SID_BASE and
  577. addr <= SID_END then
  578.  
  579. return self.sids[1],
  580. addr - SID_BASE
  581. end
  582.  
  583. for i = 2, self.sidCount do
  584. local base = self.sidBases[i]
  585.  
  586. if base and base ~= 0 and
  587. addr >= base and
  588. addr <= base + 0x1F then
  589.  
  590. return self.sids[i],
  591. addr - base
  592. end
  593. end
  594.  
  595. return nil
  596. end
  597.  
  598. function CPU:read(addr)
  599. addr = bit.band(addr, 0xFFFF)
  600.  
  601. local sid, reg =
  602. self:sidAt(addr)
  603.  
  604. if sid then
  605. return sid:read(reg)
  606. end
  607.  
  608. return self.mem[addr] or 0
  609. end
  610.  
  611. function CPU:write(addr, value)
  612. addr = bit.band(addr, 0xFFFF)
  613. value = u8(value)
  614.  
  615. local sid, reg =
  616. self:sidAt(addr)
  617.  
  618. if sid then
  619. sid:write(reg, value)
  620. return
  621. end
  622.  
  623. self.mem[addr] = value
  624. end
  625.  
  626. function CPU:fetch()
  627. local pc = self.PC
  628.  
  629. local value =
  630. self:read(pc)
  631.  
  632. self.PC =
  633. bit.band(
  634. pc + 1,
  635. 0xFFFF
  636. )
  637.  
  638. return value
  639. end
  640.  
  641. function CPU:fetch16()
  642. local l = self:fetch()
  643. local h = self:fetch()
  644.  
  645. return l +
  646. bit.lshift(h, 8)
  647. end
  648.  
  649. function CPU:push(v)
  650. self:write(
  651. 0x100 + self.SP,
  652. v
  653. )
  654.  
  655. self.SP =
  656. u8(self.SP - 1)
  657. end
  658.  
  659. function CPU:pull()
  660. self.SP =
  661. u8(self.SP + 1)
  662.  
  663. return self:read(
  664. 0x100 + self.SP
  665. )
  666. end
  667.  
  668. function CPU:push16(v)
  669. self:push(hi(v))
  670. self:push(lo(v))
  671. end
  672.  
  673. function CPU:pull16()
  674. local l = self:pull()
  675. local h = self:pull()
  676.  
  677. return l +
  678. bit.lshift(h, 8)
  679. end
  680.  
  681. function CPU:getFlag(mask)
  682. return bit.band(
  683. self.P,
  684. mask
  685. ) ~= 0
  686. end
  687.  
  688. function CPU:setFlag(mask, value)
  689. if value then
  690. self.P =
  691. bit.bor(
  692. self.P,
  693. mask
  694. )
  695. else
  696. self.P =
  697. bit.band(
  698. self.P,
  699. bit.bnot(mask)
  700. )
  701. end
  702.  
  703. -- Bit 5 is always high on the 6502 status byte.
  704. self.P =
  705. bit.bor(
  706. self.P,
  707. 0x20
  708. )
  709. end
  710.  
  711. function CPU:setZN(v)
  712. v = u8(v)
  713.  
  714. self:setFlag(
  715. 0x02,
  716. v == 0
  717. )
  718.  
  719. self:setFlag(
  720. 0x80,
  721. bit.band(v, 0x80) ~= 0
  722. )
  723. end
  724.  
  725. function CPU:adc(v)
  726. v = u8(v)
  727.  
  728. local carry =
  729. self:getFlag(0x01)
  730. and 1 or 0
  731.  
  732. local a = self.A
  733. local result =
  734. a + v + carry
  735.  
  736. self:setFlag(
  737. 0x01,
  738. result > 255
  739. )
  740.  
  741. local r = u8(result)
  742.  
  743. local overflow =
  744. bit.band(
  745. bit.bnot(
  746. bit.bxor(a, v)
  747. ),
  748. bit.bxor(a, r),
  749. 0x80
  750. ) ~= 0
  751.  
  752. self:setFlag(
  753. 0x40,
  754. overflow
  755. )
  756.  
  757. self.A = r
  758.  
  759. self:setZN(self.A)
  760. end
  761.  
  762. function CPU:sbc(v)
  763. self:adc(
  764. bit.bxor(
  765. v,
  766. 0xFF
  767. )
  768. )
  769. end
  770.  
  771. function CPU:cmp(reg, v)
  772. v = u8(v)
  773.  
  774. local result =
  775. u8(reg - v)
  776.  
  777. self:setFlag(
  778. 0x01,
  779. reg >= v
  780. )
  781.  
  782. self:setZN(result)
  783. end
  784.  
  785. function CPU:asl(v)
  786. v = u8(v)
  787.  
  788. local carry =
  789. bit.band(
  790. v,
  791. 0x80
  792. ) ~= 0
  793.  
  794. v =
  795. u8(
  796. bit.lshift(v, 1)
  797. )
  798.  
  799. self:setFlag(
  800. 0x01,
  801. carry
  802. )
  803.  
  804. self:setZN(v)
  805.  
  806. return v
  807. end
  808.  
  809. function CPU:lsr(v)
  810. v = u8(v)
  811.  
  812. local carry =
  813. bit.band(v, 1) ~= 0
  814.  
  815. v =
  816. bit.rshift(v, 1)
  817.  
  818. self:setFlag(
  819. 0x01,
  820. carry
  821. )
  822.  
  823. self:setZN(v)
  824.  
  825. return v
  826. end
  827.  
  828. function CPU:rol(v)
  829. v = u8(v)
  830.  
  831. local carryIn =
  832. self:getFlag(0x01)
  833. and 1 or 0
  834.  
  835. local carryOut =
  836. bit.band(v, 0x80) ~= 0
  837.  
  838. v =
  839. u8(
  840. bit.lshift(v, 1) +
  841. carryIn
  842. )
  843.  
  844. self:setFlag(
  845. 0x01,
  846. carryOut
  847. )
  848.  
  849. self:setZN(v)
  850.  
  851. return v
  852. end
  853.  
  854. function CPU:ror(v)
  855. v = u8(v)
  856.  
  857. local carryIn =
  858. self:getFlag(0x01)
  859. and 0x80 or 0
  860.  
  861. local carryOut =
  862. bit.band(v, 1) ~= 0
  863.  
  864. v =
  865. bit.bor(
  866. bit.rshift(v, 1),
  867. carryIn
  868. )
  869.  
  870. self:setFlag(
  871. 0x01,
  872. carryOut
  873. )
  874.  
  875. self:setZN(v)
  876.  
  877. return v
  878. end
  879.  
  880. ----------------------------------------------------------------
  881. -- Addressing
  882. ----------------------------------------------------------------
  883.  
  884. function CPU:addr(mode)
  885. if mode == "imp" or
  886. mode == "acc" then
  887. return nil
  888. end
  889.  
  890. if mode == "imm" then
  891. local a = self.PC
  892.  
  893. self.PC =
  894. u16(self.PC + 1)
  895.  
  896. return a
  897. end
  898.  
  899. if mode == "zp" then
  900. return self:fetch()
  901. end
  902.  
  903. if mode == "zpx" then
  904. return bit.band(
  905. self:fetch() + self.X,
  906. 0xFF
  907. )
  908. end
  909.  
  910. if mode == "zpy" then
  911. return bit.band(
  912. self:fetch() + self.Y,
  913. 0xFF
  914. )
  915. end
  916.  
  917. if mode == "abs" then
  918. return self:fetch16()
  919. end
  920.  
  921. if mode == "abx" then
  922. return u16(
  923. self:fetch16() +
  924. self.X
  925. )
  926. end
  927.  
  928. if mode == "aby" then
  929. return u16(
  930. self:fetch16() +
  931. self.Y
  932. )
  933. end
  934.  
  935. if mode == "izx" then
  936. local p =
  937. bit.band(
  938. self:fetch() +
  939. self.X,
  940. 0xFF
  941. )
  942.  
  943. local l =
  944. self:read(p)
  945.  
  946. local h =
  947. self:read(
  948. bit.band(
  949. p + 1,
  950. 0xFF
  951. )
  952. )
  953.  
  954. return l +
  955. bit.lshift(h, 8)
  956. end
  957.  
  958. if mode == "izy" then
  959. local p =
  960. self:fetch()
  961.  
  962. local l =
  963. self:read(p)
  964.  
  965. local h =
  966. self:read(
  967. bit.band(
  968. p + 1,
  969. 0xFF
  970. )
  971. )
  972.  
  973. return u16(
  974. l +
  975. bit.lshift(h, 8) +
  976. self.Y
  977. )
  978. end
  979.  
  980. if mode == "ind" then
  981. local p =
  982. self:fetch16()
  983.  
  984. local l =
  985. self:read(p)
  986.  
  987. -- Correct NMOS 6502 JMP indirect page-wrap behavior.
  988. local hp =
  989. bit.bor(
  990. bit.band(p, 0xFF00),
  991. bit.band(
  992. p + 1,
  993. 0xFF
  994. )
  995. )
  996.  
  997. local h =
  998. self:read(hp)
  999.  
  1000. return l +
  1001. bit.lshift(h, 8)
  1002. end
  1003.  
  1004. if mode == "rel" then
  1005. local r =
  1006. signed8(
  1007. self:fetch()
  1008. )
  1009.  
  1010. return u16(
  1011. self.PC + r
  1012. )
  1013. end
  1014.  
  1015. error(
  1016. "Unknown addressing mode: " ..
  1017. tostring(mode)
  1018. )
  1019. end
  1020.  
  1021. ----------------------------------------------------------------
  1022. -- Opcode table
  1023. ----------------------------------------------------------------
  1024.  
  1025. local opcodeRows = {
  1026. "BRK/imp ORA/izx */imp */imp NOP/zp ORA/zp ASL/zp */imp PHP/imp ORA/imm ASL/acc */imp NOP/abs ORA/abs ASL/abs */imp",
  1027. "BPL/rel ORA/izy */imp */imp NOP/zpx ORA/zpx ASL/zpx */imp CLC/imp ORA/aby NOP/imp */imp NOP/abx ORA/abx ASL/abx */imp",
  1028. "JSR/abs AND/izx */imp */imp BIT/zp AND/zp ROL/zp */imp PLP/imp AND/imm ROL/acc */imp BIT/abs AND/abs ROL/abs */imp",
  1029. "BMI/rel AND/izy */imp */imp NOP/zpx AND/zpx ROL/zpx */imp SEC/imp AND/aby NOP/imp */imp NOP/abx AND/abx ROL/abx */imp",
  1030. "RTI/imp EOR/izx */imp */imp NOP/zp EOR/zp LSR/zp */imp PHA/imp EOR/imm LSR/acc */imp JMP/abs EOR/abs LSR/abs */imp",
  1031. "BVC/rel EOR/izy */imp */imp NOP/zpx EOR/zpx LSR/zpx */imp CLI/imp EOR/aby NOP/imp */imp NOP/abx EOR/abx LSR/abx */imp",
  1032. "RTS/imp ADC/izx */imp */imp NOP/zp ADC/zp ROR/zp */imp PLA/imp ADC/imm ROR/acc */imp JMP/ind ADC/abs ROR/abs */imp",
  1033. "BVS/rel ADC/izy */imp */imp NOP/zpx ADC/zpx ROR/zpx */imp SEI/imp ADC/aby NOP/imp */imp NOP/abx ADC/abx ROR/abx */imp",
  1034. "NOP/imm STA/izx NOP/imm */imp STY/zp STA/zp STX/zp */imp DEY/imp NOP/imm TXA/imp */imp STY/abs STA/abs STX/abs */imp",
  1035. "BCC/rel STA/izy */imp */imp STY/zpx STA/zpx STX/zpy */imp TYA/imp STA/aby TXS/imp */imp */imp STA/abx */imp */imp",
  1036. "LDY/imm LDA/izx LDX/imm */imp LDY/zp LDA/zp LDX/zp */imp TAY/imp LDA/imm TAX/imp */imp LDY/abs LDA/abs LDX/abs */imp",
  1037. "BCS/rel LDA/izy */imp */imp LDY/zpx LDA/zpx LDX/zpy */imp CLV/imp LDA/aby TSX/imp */imp LDY/abx LDA/abx LDX/aby */imp",
  1038. "CPY/imm CMP/izx NOP/imm */imp CPY/zp CMP/zp DEC/zp */imp INY/imp CMP/imm DEX/imp */imp CPY/abs CMP/abs DEC/abs */imp",
  1039. "BNE/rel CMP/izy */imp */imp NOP/zpx CMP/zpx DEC/zpx */imp CLD/imp CMP/aby NOP/imp */imp NOP/abx CMP/abx DEC/abx */imp",
  1040. "CPX/imm SBC/izx NOP/imm */imp CPX/zp SBC/zp INC/zp */imp INX/imp SBC/imm NOP/imp */imp CPX/abs SBC/abs INC/abs */imp",
  1041. "BEQ/rel SBC/izy */imp */imp NOP/zpx SBC/zpx INC/zpx */imp SED/imp SBC/aby NOP/imp */imp NOP/abx SBC/abx INC/abx */imp"
  1042. }
  1043.  
  1044. local OPCODE = {}
  1045.  
  1046. for rowIndex = 1, #opcodeRows do
  1047. local col = 0
  1048.  
  1049. for token in string.gmatch(
  1050. opcodeRows[rowIndex],
  1051. "%S+"
  1052. ) do
  1053. col = col + 1
  1054.  
  1055. local slash =
  1056. string.find(
  1057. token,
  1058. "/",
  1059. 1,
  1060. true
  1061. )
  1062.  
  1063. local mnemonic =
  1064. token:sub(
  1065. 1,
  1066. slash - 1
  1067. )
  1068.  
  1069. local mode =
  1070. token:sub(
  1071. slash + 1
  1072. )
  1073.  
  1074. local opcode =
  1075. (rowIndex - 1) * 16 +
  1076. (col - 1)
  1077.  
  1078. OPCODE[opcode] = {
  1079. op = mnemonic,
  1080. mode = mode
  1081. }
  1082. end
  1083. end
  1084.  
  1085. ----------------------------------------------------------------
  1086. -- Illegal / undocumented opcodes
  1087. ----------------------------------------------------------------
  1088.  
  1089. local ILLEGAL = {
  1090. [0x03] = {"SLO", "izx"},
  1091. [0x07] = {"SLO", "zp"},
  1092. [0x0F] = {"SLO", "abs"},
  1093. [0x13] = {"SLO", "izy"},
  1094. [0x17] = {"SLO", "zpx"},
  1095. [0x1B] = {"SLO", "aby"},
  1096. [0x1F] = {"SLO", "abx"},
  1097.  
  1098. [0x23] = {"RLA", "izx"},
  1099. [0x27] = {"RLA", "zp"},
  1100. [0x2F] = {"RLA", "abs"},
  1101. [0x33] = {"RLA", "izy"},
  1102. [0x37] = {"RLA", "zpx"},
  1103. [0x3B] = {"RLA", "aby"},
  1104. [0x3F] = {"RLA", "abx"},
  1105.  
  1106. [0x43] = {"SRE", "izx"},
  1107. [0x47] = {"SRE", "zp"},
  1108. [0x4F] = {"SRE", "abs"},
  1109. [0x53] = {"SRE", "izy"},
  1110. [0x57] = {"SRE", "zpx"},
  1111. [0x5B] = {"SRE", "aby"},
  1112. [0x5F] = {"SRE", "abx"},
  1113.  
  1114. [0x63] = {"RRA", "izx"},
  1115. [0x67] = {"RRA", "zp"},
  1116. [0x6F] = {"RRA", "abs"},
  1117. [0x73] = {"RRA", "izy"},
  1118. [0x77] = {"RRA", "zpx"},
  1119. [0x7B] = {"RRA", "aby"},
  1120. [0x7F] = {"RRA", "abx"},
  1121.  
  1122. [0x83] = {"SAX", "izx"},
  1123. [0x87] = {"SAX", "zp"},
  1124. [0x8F] = {"SAX", "abs"},
  1125. [0x97] = {"SAX", "zpy"},
  1126.  
  1127. [0xA3] = {"LAX", "izx"},
  1128. [0xA7] = {"LAX", "zp"},
  1129. [0xAB] = {"LAX", "imm"},
  1130. [0xAF] = {"LAX", "abs"},
  1131. [0xB3] = {"LAX", "izy"},
  1132. [0xB7] = {"LAX", "zpy"},
  1133. [0xBF] = {"LAX", "aby"},
  1134.  
  1135. [0xC3] = {"DCP", "izx"},
  1136. [0xC7] = {"DCP", "zp"},
  1137. [0xCF] = {"DCP", "abs"},
  1138. [0xD3] = {"DCP", "izy"},
  1139. [0xD7] = {"DCP", "zpx"},
  1140. [0xDB] = {"DCP", "aby"},
  1141. [0xDF] = {"DCP", "abx"},
  1142.  
  1143. [0xE3] = {"ISC", "izx"},
  1144. [0xE7] = {"ISC", "zp"},
  1145. [0xEF] = {"ISC", "abs"},
  1146. [0xF3] = {"ISC", "izy"},
  1147. [0xF7] = {"ISC", "zpx"},
  1148. [0xFB] = {"ISC", "aby"},
  1149. [0xFF] = {"ISC", "abx"},
  1150.  
  1151. [0x1A] = {"NOP", "imp"},
  1152. [0x3A] = {"NOP", "imp"},
  1153. [0x5A] = {"NOP", "imp"},
  1154. [0x7A] = {"NOP", "imp"},
  1155. [0xDA] = {"NOP", "imp"},
  1156. [0xFA] = {"NOP", "imp"},
  1157.  
  1158. [0x80] = {"NOP", "imm"},
  1159. [0x82] = {"NOP", "imm"},
  1160. [0x89] = {"NOP", "imm"},
  1161.  
  1162. [0x04] = {"NOP", "zp"},
  1163. [0x44] = {"NOP", "zp"},
  1164. [0x64] = {"NOP", "zp"},
  1165.  
  1166. [0x14] = {"NOP", "zpx"},
  1167. [0x34] = {"NOP", "zpx"},
  1168. [0x54] = {"NOP", "zpx"},
  1169. [0x74] = {"NOP", "zpx"},
  1170. [0xD4] = {"NOP", "zpx"},
  1171. [0xF4] = {"NOP", "zpx"},
  1172.  
  1173. [0x0C] = {"NOP", "abs"},
  1174.  
  1175. [0x1C] = {"NOP", "abx"},
  1176. [0x3C] = {"NOP", "abx"},
  1177. [0x5C] = {"NOP", "abx"},
  1178. [0x7C] = {"NOP", "abx"},
  1179. [0xDC] = {"NOP", "abx"},
  1180. [0xFC] = {"NOP", "abx"},
  1181.  
  1182. [0x0B] = {"ANC", "imm"},
  1183. [0x2B] = {"ANC", "imm"},
  1184. [0x4B] = {"ALR", "imm"},
  1185. [0x6B] = {"ARR", "imm"},
  1186. [0xCB] = {"AXS", "imm"},
  1187.  
  1188. [0xBB] = {"LAS", "aby"},
  1189.  
  1190. [0x9C] = {"SHY", "abx"},
  1191. [0x9E] = {"SHX", "aby"},
  1192. [0x9B] = {"TAS", "aby"},
  1193. [0x93] = {"AHX", "izy"},
  1194. [0x9F] = {"AHX", "aby"}
  1195. }
  1196.  
  1197. for opcode, info in pairs(ILLEGAL) do
  1198. OPCODE[opcode] = {
  1199. op = info[1],
  1200. mode = info[2]
  1201. }
  1202. end
  1203.  
  1204. local KIL = {
  1205. [0x02] = true,
  1206. [0x12] = true,
  1207. [0x22] = true,
  1208. [0x32] = true,
  1209. [0x42] = true,
  1210. [0x52] = true,
  1211. [0x62] = true,
  1212. [0x72] = true,
  1213. [0x92] = true,
  1214. [0xB2] = true,
  1215. [0xD2] = true,
  1216. [0xF2] = true
  1217. }
  1218.  
  1219. for opcode in pairs(KIL) do
  1220. OPCODE[opcode] = {
  1221. op = "KIL",
  1222. mode = "imp"
  1223. }
  1224. end
  1225.  
  1226. ----------------------------------------------------------------
  1227. -- CPU execution
  1228. ----------------------------------------------------------------
  1229.  
  1230. function CPU:execute(opcode)
  1231. local entry = OPCODE[opcode]
  1232.  
  1233. if not entry then
  1234. return
  1235. end
  1236.  
  1237. local op = entry.op
  1238. local mode = entry.mode
  1239.  
  1240. if op == "KIL" then
  1241. self.running = false
  1242. return
  1243. end
  1244.  
  1245. ------------------------------------------------------------
  1246. -- Undocumented one/two/three byte NOPs
  1247. ------------------------------------------------------------
  1248.  
  1249. if op == "*" then
  1250. if mode == "imm" or
  1251. mode == "zp" or
  1252. mode == "zpx" or
  1253. mode == "zpy" or
  1254. mode == "rel" then
  1255.  
  1256. self.PC =
  1257. u16(self.PC + 1)
  1258.  
  1259. elseif mode == "abs" or
  1260. mode == "abx" or
  1261. mode == "aby" then
  1262.  
  1263. self.PC =
  1264. u16(self.PC + 2)
  1265.  
  1266. elseif mode == "izx" or
  1267. mode == "izy" or
  1268. mode == "ind" then
  1269.  
  1270. self.PC =
  1271. u16(self.PC + 1)
  1272. end
  1273.  
  1274. return
  1275. end
  1276.  
  1277. ------------------------------------------------------------
  1278. -- Branches
  1279. ------------------------------------------------------------
  1280.  
  1281. if op == "BPL" then
  1282. local a = self:addr("rel")
  1283.  
  1284. if not self:getFlag(0x80) then
  1285. self.PC = a
  1286. end
  1287.  
  1288. return
  1289. end
  1290.  
  1291. if op == "BMI" then
  1292. local a = self:addr("rel")
  1293.  
  1294. if self:getFlag(0x80) then
  1295. self.PC = a
  1296. end
  1297.  
  1298. return
  1299. end
  1300.  
  1301. if op == "BVC" then
  1302. local a = self:addr("rel")
  1303.  
  1304. if not self:getFlag(0x40) then
  1305. self.PC = a
  1306. end
  1307.  
  1308. return
  1309. end
  1310.  
  1311. if op == "BVS" then
  1312. local a = self:addr("rel")
  1313.  
  1314. if self:getFlag(0x40) then
  1315. self.PC = a
  1316. end
  1317.  
  1318. return
  1319. end
  1320.  
  1321. if op == "BCC" then
  1322. local a = self:addr("rel")
  1323.  
  1324. if not self:getFlag(0x01) then
  1325. self.PC = a
  1326. end
  1327.  
  1328. return
  1329. end
  1330.  
  1331. if op == "BCS" then
  1332. local a = self:addr("rel")
  1333.  
  1334. if self:getFlag(0x01) then
  1335. self.PC = a
  1336. end
  1337.  
  1338. return
  1339. end
  1340.  
  1341. if op == "BNE" then
  1342. local a = self:addr("rel")
  1343.  
  1344. if not self:getFlag(0x02) then
  1345. self.PC = a
  1346. end
  1347.  
  1348. return
  1349. end
  1350.  
  1351. if op == "BEQ" then
  1352. local a = self:addr("rel")
  1353.  
  1354. if self:getFlag(0x02) then
  1355. self.PC = a
  1356. end
  1357.  
  1358. return
  1359. end
  1360.  
  1361. ------------------------------------------------------------
  1362. -- Jumps / subroutines / interrupts
  1363. ------------------------------------------------------------
  1364.  
  1365. if op == "JMP" then
  1366. self.PC = self:addr(mode)
  1367. return
  1368. end
  1369.  
  1370. if op == "JSR" then
  1371. local target =
  1372. self:addr("abs")
  1373.  
  1374. self:push16(
  1375. u16(self.PC - 1)
  1376. )
  1377.  
  1378. self.PC = target
  1379. return
  1380. end
  1381.  
  1382. if op == "RTS" then
  1383. self.PC =
  1384. u16(
  1385. self:pull16() + 1
  1386. )
  1387. return
  1388. end
  1389.  
  1390. if op == "RTI" then
  1391. self.P =
  1392. self:pull()
  1393.  
  1394. self.PC =
  1395. self:pull16()
  1396.  
  1397. self.P =
  1398. bit.bor(
  1399. self.P,
  1400. 0x20
  1401. )
  1402.  
  1403. return
  1404. end
  1405.  
  1406. if op == "BRK" then
  1407. self.PC =
  1408. u16(self.PC + 1)
  1409.  
  1410. self:push16(self.PC)
  1411.  
  1412. self:push(
  1413. bit.bor(
  1414. self.P,
  1415. 0x30
  1416. )
  1417. )
  1418.  
  1419. self:setFlag(
  1420. 0x04,
  1421. true
  1422. )
  1423.  
  1424. local l =
  1425. self:read(0xFFFE)
  1426.  
  1427. local h =
  1428. self:read(0xFFFF)
  1429.  
  1430. self.PC =
  1431. l +
  1432. bit.lshift(h, 8)
  1433.  
  1434. return
  1435. end
  1436.  
  1437. ------------------------------------------------------------
  1438. -- Flags
  1439. ------------------------------------------------------------
  1440.  
  1441. if op == "CLC" then
  1442. self:setFlag(0x01, false)
  1443. return
  1444. end
  1445.  
  1446. if op == "SEC" then
  1447. self:setFlag(0x01, true)
  1448. return
  1449. end
  1450.  
  1451. if op == "CLI" then
  1452. self:setFlag(0x04, false)
  1453. return
  1454. end
  1455.  
  1456. if op == "SEI" then
  1457. self:setFlag(0x04, true)
  1458. return
  1459. end
  1460.  
  1461. if op == "CLV" then
  1462. self:setFlag(0x40, false)
  1463. return
  1464. end
  1465.  
  1466. if op == "CLD" then
  1467. self:setFlag(0x08, false)
  1468. return
  1469. end
  1470.  
  1471. if op == "SED" then
  1472. self:setFlag(0x08, true)
  1473. return
  1474. end
  1475.  
  1476. ------------------------------------------------------------
  1477. -- Stack
  1478. ------------------------------------------------------------
  1479.  
  1480. if op == "PHA" then
  1481. self:push(self.A)
  1482. return
  1483. end
  1484.  
  1485. if op == "PLA" then
  1486. self.A = self:pull()
  1487. self:setZN(self.A)
  1488. return
  1489. end
  1490.  
  1491. if op == "PHP" then
  1492. self:push(
  1493. bit.bor(
  1494. self.P,
  1495. 0x30
  1496. )
  1497. )
  1498. return
  1499. end
  1500.  
  1501. if op == "PLP" then
  1502. self.P = self:pull()
  1503. self.P =
  1504. bit.bor(
  1505. self.P,
  1506. 0x20
  1507. )
  1508. return
  1509. end
  1510.  
  1511. ------------------------------------------------------------
  1512. -- Transfers
  1513. ------------------------------------------------------------
  1514.  
  1515. if op == "TAX" then
  1516. self.X = self.A
  1517. self:setZN(self.X)
  1518. return
  1519. end
  1520.  
  1521. if op == "TAY" then
  1522. self.Y = self.A
  1523. self:setZN(self.Y)
  1524. return
  1525. end
  1526.  
  1527. if op == "TXA" then
  1528. self.A = self.X
  1529. self:setZN(self.A)
  1530. return
  1531. end
  1532.  
  1533. if op == "TYA" then
  1534. self.A = self.Y
  1535. self:setZN(self.A)
  1536. return
  1537. end
  1538.  
  1539. if op == "TSX" then
  1540. self.X = self.SP
  1541. self:setZN(self.X)
  1542. return
  1543. end
  1544.  
  1545. if op == "TXS" then
  1546. self.SP = self.X
  1547. return
  1548. end
  1549.  
  1550. ------------------------------------------------------------
  1551. -- Inc / dec registers
  1552. ------------------------------------------------------------
  1553.  
  1554. if op == "INX" then
  1555. self.X = u8(self.X + 1)
  1556. self:setZN(self.X)
  1557. return
  1558. end
  1559.  
  1560. if op == "DEX" then
  1561. self.X = u8(self.X - 1)
  1562. self:setZN(self.X)
  1563. return
  1564. end
  1565.  
  1566. if op == "INY" then
  1567. self.Y = u8(self.Y + 1)
  1568. self:setZN(self.Y)
  1569. return
  1570. end
  1571.  
  1572. if op == "DEY" then
  1573. self.Y = u8(self.Y - 1)
  1574. self:setZN(self.Y)
  1575. return
  1576. end
  1577.  
  1578. ------------------------------------------------------------
  1579. -- Shifts
  1580. ------------------------------------------------------------
  1581.  
  1582. if op == "ASL" then
  1583. if mode == "acc" then
  1584. self.A =
  1585. self:asl(self.A)
  1586. else
  1587. local a =
  1588. self:addr(mode)
  1589.  
  1590. self:write(
  1591. a,
  1592. self:asl(
  1593. self:read(a)
  1594. )
  1595. )
  1596. end
  1597.  
  1598. return
  1599. end
  1600.  
  1601. if op == "LSR" then
  1602. if mode == "acc" then
  1603. self.A =
  1604. self:lsr(self.A)
  1605. else
  1606. local a =
  1607. self:addr(mode)
  1608.  
  1609. self:write(
  1610. a,
  1611. self:lsr(
  1612. self:read(a)
  1613. )
  1614. )
  1615. end
  1616.  
  1617. return
  1618. end
  1619.  
  1620. if op == "ROL" then
  1621. if mode == "acc" then
  1622. self.A =
  1623. self:rol(self.A)
  1624. else
  1625. local a =
  1626. self:addr(mode)
  1627.  
  1628. self:write(
  1629. a,
  1630. self:rol(
  1631. self:read(a)
  1632. )
  1633. )
  1634. end
  1635.  
  1636. return
  1637. end
  1638.  
  1639. if op == "ROR" then
  1640. if mode == "acc" then
  1641. self.A =
  1642. self:ror(self.A)
  1643. else
  1644. local a =
  1645. self:addr(mode)
  1646.  
  1647. self:write(
  1648. a,
  1649. self:ror(
  1650. self:read(a)
  1651. )
  1652. )
  1653. end
  1654.  
  1655. return
  1656. end
  1657.  
  1658. ------------------------------------------------------------
  1659. -- Loads / stores
  1660. ------------------------------------------------------------
  1661.  
  1662. if op == "LDA" then
  1663. local a =
  1664. self:addr(mode)
  1665.  
  1666. self.A =
  1667. self:read(a)
  1668.  
  1669. self:setZN(self.A)
  1670. return
  1671. end
  1672.  
  1673. if op == "LDX" then
  1674. local a =
  1675. self:addr(mode)
  1676.  
  1677. self.X =
  1678. self:read(a)
  1679.  
  1680. self:setZN(self.X)
  1681. return
  1682. end
  1683.  
  1684. if op == "LDY" then
  1685. local a =
  1686. self:addr(mode)
  1687.  
  1688. self.Y =
  1689. self:read(a)
  1690.  
  1691. self:setZN(self.Y)
  1692. return
  1693. end
  1694.  
  1695. if op == "STA" then
  1696. local a =
  1697. self:addr(mode)
  1698.  
  1699. self:write(
  1700. a,
  1701. self.A
  1702. )
  1703.  
  1704. return
  1705. end
  1706.  
  1707. if op == "STX" then
  1708. local a =
  1709. self:addr(mode)
  1710.  
  1711. self:write(
  1712. a,
  1713. self.X
  1714. )
  1715.  
  1716. return
  1717. end
  1718.  
  1719. if op == "STY" then
  1720. local a =
  1721. self:addr(mode)
  1722.  
  1723. self:write(
  1724. a,
  1725. self.Y
  1726. )
  1727.  
  1728. return
  1729. end
  1730.  
  1731. ------------------------------------------------------------
  1732. -- Logic
  1733. ------------------------------------------------------------
  1734.  
  1735. if op == "AND" then
  1736. local a =
  1737. self:addr(mode)
  1738.  
  1739. self.A =
  1740. bit.band(
  1741. self.A,
  1742. self:read(a)
  1743. )
  1744.  
  1745. self:setZN(self.A)
  1746. return
  1747. end
  1748.  
  1749. if op == "ORA" then
  1750. local a =
  1751. self:addr(mode)
  1752.  
  1753. self.A =
  1754. bit.bor(
  1755. self.A,
  1756. self:read(a)
  1757. )
  1758.  
  1759. self:setZN(self.A)
  1760. return
  1761. end
  1762.  
  1763. if op == "EOR" then
  1764. local a =
  1765. self:addr(mode)
  1766.  
  1767. self.A =
  1768. bit.bxor(
  1769. self.A,
  1770. self:read(a)
  1771. )
  1772.  
  1773. self:setZN(self.A)
  1774. return
  1775. end
  1776.  
  1777. if op == "BIT" then
  1778. local a =
  1779. self:addr(mode)
  1780.  
  1781. local v =
  1782. self:read(a)
  1783.  
  1784. self:setFlag(
  1785. 0x02,
  1786. bit.band(
  1787. self.A,
  1788. v
  1789. ) == 0
  1790. )
  1791.  
  1792. self:setFlag(
  1793. 0x80,
  1794. bit.band(v, 0x80) ~= 0
  1795. )
  1796.  
  1797. self:setFlag(
  1798. 0x40,
  1799. bit.band(v, 0x40) ~= 0
  1800. )
  1801.  
  1802. return
  1803. end
  1804.  
  1805. ------------------------------------------------------------
  1806. -- Arithmetic
  1807. ------------------------------------------------------------
  1808.  
  1809. if op == "ADC" then
  1810. local a =
  1811. self:addr(mode)
  1812.  
  1813. self:adc(
  1814. self:read(a)
  1815. )
  1816.  
  1817. return
  1818. end
  1819.  
  1820. if op == "SBC" then
  1821. local a =
  1822. self:addr(mode)
  1823.  
  1824. self:sbc(
  1825. self:read(a)
  1826. )
  1827.  
  1828. return
  1829. end
  1830.  
  1831. if op == "CMP" then
  1832. local a =
  1833. self:addr(mode)
  1834.  
  1835. self:cmp(
  1836. self.A,
  1837. self:read(a)
  1838. )
  1839.  
  1840. return
  1841. end
  1842.  
  1843. if op == "CPX" then
  1844. local a =
  1845. self:addr(mode)
  1846.  
  1847. self:cmp(
  1848. self.X,
  1849. self:read(a)
  1850. )
  1851.  
  1852. return
  1853. end
  1854.  
  1855. if op == "CPY" then
  1856. local a =
  1857. self:addr(mode)
  1858.  
  1859. self:cmp(
  1860. self.Y,
  1861. self:read(a)
  1862. )
  1863.  
  1864. return
  1865. end
  1866.  
  1867. ------------------------------------------------------------
  1868. -- Memory inc/dec
  1869. ------------------------------------------------------------
  1870.  
  1871. if op == "INC" then
  1872. local a =
  1873. self:addr(mode)
  1874.  
  1875. local v =
  1876. u8(
  1877. self:read(a) + 1
  1878. )
  1879.  
  1880. self:write(a, v)
  1881. self:setZN(v)
  1882.  
  1883. return
  1884. end
  1885.  
  1886. if op == "DEC" then
  1887. local a =
  1888. self:addr(mode)
  1889.  
  1890. local v =
  1891. u8(
  1892. self:read(a) - 1
  1893. )
  1894.  
  1895. self:write(a, v)
  1896. self:setZN(v)
  1897.  
  1898. return
  1899. end
  1900.  
  1901. ------------------------------------------------------------
  1902. -- NOP
  1903. ------------------------------------------------------------
  1904.  
  1905. if op == "NOP" then
  1906. if mode ~= "imp" and
  1907. mode ~= "acc" then
  1908. self:addr(mode)
  1909. end
  1910.  
  1911. return
  1912. end
  1913.  
  1914. ------------------------------------------------------------
  1915. -- Undocumented opcodes
  1916. ------------------------------------------------------------
  1917.  
  1918. if op == "SLO" then
  1919. local a =
  1920. self:addr(mode)
  1921.  
  1922. local v =
  1923. self:asl(
  1924. self:read(a)
  1925. )
  1926.  
  1927. self:write(a, v)
  1928.  
  1929. self.A =
  1930. bit.bor(
  1931. self.A,
  1932. v
  1933. )
  1934.  
  1935. self:setZN(self.A)
  1936. return
  1937. end
  1938.  
  1939. if op == "RLA" then
  1940. local a =
  1941. self:addr(mode)
  1942.  
  1943. local v =
  1944. self:rol(
  1945. self:read(a)
  1946. )
  1947.  
  1948. self:write(a, v)
  1949.  
  1950. self.A =
  1951. bit.band(
  1952. self.A,
  1953. v
  1954. )
  1955.  
  1956. self:setZN(self.A)
  1957. return
  1958. end
  1959.  
  1960. if op == "SRE" then
  1961. local a =
  1962. self:addr(mode)
  1963.  
  1964. local v =
  1965. self:lsr(
  1966. self:read(a)
  1967. )
  1968.  
  1969. self:write(a, v)
  1970.  
  1971. self.A =
  1972. bit.bxor(
  1973. self.A,
  1974. v
  1975. )
  1976.  
  1977. self:setZN(self.A)
  1978. return
  1979. end
  1980.  
  1981. if op == "RRA" then
  1982. local a =
  1983. self:addr(mode)
  1984.  
  1985. local v =
  1986. self:ror(
  1987. self:read(a)
  1988. )
  1989.  
  1990. self:write(a, v)
  1991. self:adc(v)
  1992.  
  1993. return
  1994. end
  1995.  
  1996. if op == "SAX" then
  1997. local a =
  1998. self:addr(mode)
  1999.  
  2000. self:write(
  2001. a,
  2002. bit.band(
  2003. self.A,
  2004. self.X
  2005. )
  2006. )
  2007.  
  2008. return
  2009. end
  2010.  
  2011. if op == "LAX" then
  2012. local a =
  2013. self:addr(mode)
  2014.  
  2015. local v =
  2016. self:read(a)
  2017.  
  2018. self.A = v
  2019. self.X = v
  2020.  
  2021. self:setZN(v)
  2022.  
  2023. return
  2024. end
  2025.  
  2026. if op == "DCP" then
  2027. local a =
  2028. self:addr(mode)
  2029.  
  2030. local v =
  2031. u8(
  2032. self:read(a) - 1
  2033. )
  2034.  
  2035. self:write(a, v)
  2036.  
  2037. self:cmp(
  2038. self.A,
  2039. v
  2040. )
  2041.  
  2042. return
  2043. end
  2044.  
  2045. if op == "ISC" then
  2046. local a =
  2047. self:addr(mode)
  2048.  
  2049. local v =
  2050. u8(
  2051. self:read(a) + 1
  2052. )
  2053.  
  2054. self:write(a, v)
  2055.  
  2056. self:sbc(v)
  2057.  
  2058. return
  2059. end
  2060.  
  2061. if op == "ANC" then
  2062. local a =
  2063. self:addr(mode)
  2064.  
  2065. self.A =
  2066. bit.band(
  2067. self.A,
  2068. self:read(a)
  2069. )
  2070.  
  2071. self:setZN(self.A)
  2072.  
  2073. self:setFlag(
  2074. 0x01,
  2075. bit.band(
  2076. self.A,
  2077. 0x80
  2078. ) ~= 0
  2079. )
  2080.  
  2081. return
  2082. end
  2083.  
  2084. if op == "ALR" then
  2085. local a =
  2086. self:addr(mode)
  2087.  
  2088. self.A =
  2089. bit.band(
  2090. self.A,
  2091. self:read(a)
  2092. )
  2093.  
  2094. self.A =
  2095. self:lsr(self.A)
  2096.  
  2097. return
  2098. end
  2099.  
  2100. if op == "ARR" then
  2101. local a =
  2102. self:addr(mode)
  2103.  
  2104. local value =
  2105. bit.band(
  2106. self.A,
  2107. self:read(a)
  2108. )
  2109.  
  2110. local carryIn =
  2111. self:getFlag(0x01)
  2112. and 0x80
  2113. or 0
  2114.  
  2115. value =
  2116. bit.bor(
  2117. bit.rshift(value, 1),
  2118. carryIn
  2119. )
  2120.  
  2121. self.A = value
  2122.  
  2123. self:setZN(value)
  2124.  
  2125. self:setFlag(
  2126. 0x01,
  2127. bit.band(
  2128. value,
  2129. 0x40
  2130. ) ~= 0
  2131. )
  2132.  
  2133. self:setFlag(
  2134. 0x40,
  2135. bit.bxor(
  2136. bit.band(
  2137. value,
  2138. 0x40
  2139. ),
  2140. bit.band(
  2141. value,
  2142. 0x20
  2143. )
  2144. ) ~= 0
  2145. )
  2146.  
  2147. return
  2148. end
  2149.  
  2150. if op == "AXS" then
  2151. local a =
  2152. self:addr(mode)
  2153.  
  2154. local value =
  2155. self:read(a)
  2156.  
  2157. local result =
  2158. bit.band(
  2159. self.A,
  2160. self.X
  2161. ) - value
  2162.  
  2163. self:setFlag(
  2164. 0x01,
  2165. result >= 0
  2166. )
  2167.  
  2168. self.X =
  2169. u8(result)
  2170.  
  2171. self:setZN(self.X)
  2172.  
  2173. return
  2174. end
  2175.  
  2176. if op == "LAS" then
  2177. local a =
  2178. self:addr(mode)
  2179.  
  2180. local v =
  2181. bit.band(
  2182. self:read(a),
  2183. self.SP
  2184. )
  2185.  
  2186. self.A = v
  2187. self.X = v
  2188. self.SP = v
  2189.  
  2190. self:setZN(v)
  2191.  
  2192. return
  2193. end
  2194.  
  2195. if op == "SHY" then
  2196. local base =
  2197. self:fetch16()
  2198.  
  2199. local address =
  2200. u16(
  2201. base + self.X
  2202. )
  2203.  
  2204. local value =
  2205. bit.band(
  2206. self.Y,
  2207. hi(address) + 1
  2208. )
  2209.  
  2210. self:write(
  2211. address,
  2212. value
  2213. )
  2214.  
  2215. return
  2216. end
  2217.  
  2218. if op == "SHX" then
  2219. local base =
  2220. self:fetch16()
  2221.  
  2222. local address =
  2223. u16(
  2224. base + self.Y
  2225. )
  2226.  
  2227. local value =
  2228. bit.band(
  2229. self.X,
  2230. hi(address) + 1
  2231. )
  2232.  
  2233. self:write(
  2234. address,
  2235. value
  2236. )
  2237.  
  2238. return
  2239. end
  2240.  
  2241. if op == "TAS" then
  2242. local base =
  2243. self:fetch16()
  2244.  
  2245. local address =
  2246. u16(
  2247. base + self.Y
  2248. )
  2249.  
  2250. self.SP =
  2251. bit.band(
  2252. self.A,
  2253. self.X
  2254. )
  2255.  
  2256. local value =
  2257. bit.band(
  2258. self.SP,
  2259. hi(address) + 1
  2260. )
  2261.  
  2262. self:write(
  2263. address,
  2264. value
  2265. )
  2266.  
  2267. return
  2268. end
  2269.  
  2270. if op == "AHX" then
  2271. local a =
  2272. self:addr(mode)
  2273.  
  2274. local value =
  2275. bit.band(
  2276. self.A,
  2277. self.X,
  2278. hi(a) + 1
  2279. )
  2280.  
  2281. self:write(
  2282. a,
  2283. value
  2284. )
  2285.  
  2286. return
  2287. end
  2288. end
  2289.  
  2290. ----------------------------------------------------------------
  2291. -- CPU execution loops
  2292. ----------------------------------------------------------------
  2293.  
  2294. function CPU:runUntilReturn(maxInstructions)
  2295. maxInstructions =
  2296. maxInstructions or
  2297. MAX_INSTRUCTIONS_PER_CALL
  2298.  
  2299. local count = 0
  2300.  
  2301. while self.running and
  2302. count < maxInstructions do
  2303.  
  2304. if self.PC == 0xFFFF then
  2305. self.running = false
  2306. return true
  2307. end
  2308.  
  2309. local opcode =
  2310. self:fetch()
  2311.  
  2312. self:execute(opcode)
  2313.  
  2314. count = count + 1
  2315. end
  2316.  
  2317. if not self.running then
  2318. return false,
  2319. "CPU stopped on KIL/JAM opcode"
  2320. end
  2321.  
  2322. self.running = false
  2323.  
  2324. return false,
  2325. "CPU watchdog triggered"
  2326. end
  2327.  
  2328. ----------------------------------------------------------------
  2329. -- IRQ handling
  2330. ----------------------------------------------------------------
  2331.  
  2332. function CPU:finishSyntheticIRQ()
  2333. -- Equivalent to the RTI at the end of a normal IRQ,
  2334. -- restoring the synthetic interrupt frame.
  2335. self.P =
  2336. self:pull()
  2337.  
  2338. self.PC =
  2339. self:pull16()
  2340.  
  2341. self.P =
  2342. bit.bor(
  2343. self.P,
  2344. 0x20
  2345. )
  2346.  
  2347. self.PC =
  2348. u16(self.PC)
  2349.  
  2350. return true
  2351. end
  2352.  
  2353. function CPU:runUntilIRQReturn(maxInstructions)
  2354. maxInstructions =
  2355. maxInstructions or
  2356. MAX_INSTRUCTIONS_PER_IRQ
  2357.  
  2358. local count = 0
  2359.  
  2360. while self.running and
  2361. count < maxInstructions do
  2362.  
  2363. -- Standard PSID IRQ wrappers commonly JMP to the
  2364. -- KERNAL IRQ exit at $EA31.
  2365. if self.PC == KERNAL_IRQ_EXIT then
  2366. return self:finishSyntheticIRQ()
  2367. end
  2368.  
  2369. local opcode =
  2370. self:fetch()
  2371.  
  2372. if opcode == 0x40 then
  2373. -- RTI.
  2374. self:execute(opcode)
  2375. return true
  2376. end
  2377.  
  2378. self:execute(opcode)
  2379.  
  2380. count = count + 1
  2381. end
  2382.  
  2383. if not self.running then
  2384. return false,
  2385. "IRQ CPU stopped on KIL/JAM opcode"
  2386. end
  2387.  
  2388. return false,
  2389. "IRQ watchdog triggered"
  2390. end
  2391.  
  2392. function CPU:interrupt(vector)
  2393. -- Hardware IRQ entry:
  2394. --
  2395. -- push PC
  2396. -- push P with B cleared
  2397. -- set I
  2398. -- load vector
  2399. --
  2400. -- We don't emulate individual CPU cycles, but the register
  2401. -- and stack behavior is preserved closely enough for PSID
  2402. -- IRQ-driven players.
  2403.  
  2404. local oldP = self.P
  2405.  
  2406. self:push16(self.PC)
  2407.  
  2408. self:push(
  2409. bit.band(
  2410. oldP,
  2411. 0xEF
  2412. )
  2413. )
  2414.  
  2415. self.P =
  2416. bit.bor(
  2417. bit.band(
  2418. oldP,
  2419. 0xFB
  2420. ),
  2421. 0x20
  2422. )
  2423.  
  2424. local low =
  2425. self:read(vector)
  2426.  
  2427. local high =
  2428. self:read(
  2429. bit.band(
  2430. vector + 1,
  2431. 0xFFFF
  2432. )
  2433. )
  2434.  
  2435. self.PC =
  2436. low +
  2437. bit.lshift(
  2438. high,
  2439. 8
  2440. )
  2441.  
  2442. self.running = true
  2443.  
  2444. return self:runUntilIRQReturn()
  2445. end
  2446.  
  2447. function CPU:call(address, a, x, y)
  2448. self.A = u8(a or 0)
  2449. self.X = u8(x or 0)
  2450. self.Y = u8(y or 0)
  2451.  
  2452. self.P = 0x24
  2453. self.SP = 0xFB
  2454. self.running = true
  2455.  
  2456. self:push16(0xFFFE)
  2457.  
  2458. self.PC =
  2459. u16(address)
  2460.  
  2461. return self:runUntilReturn()
  2462. end
  2463.  
  2464. ----------------------------------------------------------------
  2465. -- Audio
  2466. ----------------------------------------------------------------
  2467.  
  2468. local AUDIO = {}
  2469. AUDIO.__index = AUDIO
  2470.  
  2471. local ATTACK_TIMES = {
  2472. 2, 8, 16, 24,
  2473. 38, 56, 68, 80,
  2474. 100, 250, 500, 800,
  2475. 1000, 3000, 8000, 24000
  2476. }
  2477.  
  2478. local DECAY_TIMES = {
  2479. 6, 24, 48, 72,
  2480. 114, 168, 204, 240,
  2481. 300, 750, 1500, 2400,
  2482. 3000, 9000, 24000, 72000
  2483. }
  2484.  
  2485. function AUDIO.new(sids, sidCount)
  2486. local self =
  2487. setmetatable({}, AUDIO)
  2488.  
  2489. self.sids = sids
  2490. self.sidCount = sidCount
  2491.  
  2492. self.volume =
  2493. DEFAULT_VOLUME
  2494.  
  2495. self.channels = {}
  2496.  
  2497. for i = 1, TOTAL_VOICES do
  2498. self.channels[i] = {
  2499. opened = false,
  2500. gate = false,
  2501.  
  2502. waveform = nil,
  2503. frequency = nil,
  2504. volume = nil,
  2505.  
  2506. attack = nil,
  2507. decay = nil,
  2508. sustain = nil,
  2509. release = nil,
  2510.  
  2511. audible = false
  2512. }
  2513. end
  2514.  
  2515. return self
  2516. end
  2517.  
  2518. function AUDIO:frequencyFromSID(value, pal)
  2519. value = bit.band(
  2520. value or 0,
  2521. 0xFFFF
  2522. )
  2523.  
  2524. -- SID frequency register zero is genuinely zero.
  2525. -- The previous version converted it to 1 Hz.
  2526. if value == 0 then
  2527. return 0
  2528. end
  2529.  
  2530. local clock =
  2531. pal and
  2532. PAL_CLOCK or
  2533. NTSC_CLOCK
  2534.  
  2535. local f =
  2536. value *
  2537. clock /
  2538. SID_FREQ_DIV
  2539.  
  2540. if f <= 0 then
  2541. return 0
  2542. end
  2543.  
  2544. if f > 20000 then
  2545. return 20000
  2546. end
  2547.  
  2548. return f
  2549. end
  2550.  
  2551. function AUDIO:waveform(v)
  2552. -- Priority follows the SID control bits, with noise
  2553. -- taking precedence in the approximation.
  2554. if v.noise then
  2555. return WAVE_NOISE
  2556. end
  2557.  
  2558. if v.square then
  2559. return WAVE_SQUARE
  2560. end
  2561.  
  2562. if v.saw then
  2563. return WAVE_SAW
  2564. end
  2565.  
  2566. if v.triangle then
  2567. return WAVE_TRIANGLE
  2568. end
  2569.  
  2570. return WAVE_SQUARE
  2571. end
  2572.  
  2573. function AUDIO:adsr(v)
  2574. local attack =
  2575. ATTACK_TIMES[
  2576. v.attack + 1
  2577. ] or 8
  2578.  
  2579. local decay =
  2580. DECAY_TIMES[
  2581. v.decay + 1
  2582. ] or 24
  2583.  
  2584. local sustain =
  2585. v.sustain / 15
  2586.  
  2587. local release =
  2588. DECAY_TIMES[
  2589. v.release + 1
  2590. ] or 24
  2591.  
  2592. return
  2593. attack,
  2594. decay,
  2595. sustain,
  2596. release
  2597. end
  2598.  
  2599. function AUDIO:setVolume(v)
  2600. self.volume =
  2601. clamp(
  2602. v,
  2603. MIN_VOLUME,
  2604. MAX_VOLUME
  2605. )
  2606. end
  2607.  
  2608. function AUDIO:updateVoice(
  2609. channel,
  2610. voiceNumber,
  2611. v,
  2612. pal,
  2613. masterVolume,
  2614. muted
  2615. )
  2616. local ch =
  2617. self.channels[channel]
  2618.  
  2619. local frequency =
  2620. self:frequencyFromSID(
  2621. v.frequency,
  2622. pal
  2623. )
  2624.  
  2625. local wave =
  2626. self:waveform(v)
  2627.  
  2628. local attack,
  2629. decay,
  2630. sustain,
  2631. release =
  2632. self:adsr(v)
  2633.  
  2634. local hasWave =
  2635. v.noise or
  2636. v.square or
  2637. v.saw or
  2638. v.triangle
  2639.  
  2640. local audible =
  2641. (not v.test) and
  2642. hasWave and
  2643. (not muted)
  2644.  
  2645. local master =
  2646. masterVolume / 15
  2647.  
  2648. local targetVolume
  2649.  
  2650. if audible then
  2651. targetVolume =
  2652. self.volume *
  2653. master
  2654. else
  2655. targetVolume = 0
  2656. end
  2657.  
  2658. ------------------------------------------------------------
  2659. -- Waveform
  2660. ------------------------------------------------------------
  2661.  
  2662. if ch.waveform ~= wave then
  2663. sound.setWave(
  2664. channel,
  2665. wave
  2666. )
  2667.  
  2668. ch.waveform = wave
  2669. end
  2670.  
  2671. ------------------------------------------------------------
  2672. -- Frequency
  2673. ------------------------------------------------------------
  2674.  
  2675. if ch.frequency == nil or
  2676. math.abs(
  2677. ch.frequency - frequency
  2678. ) > 0.25 then
  2679.  
  2680. sound.setFrequency(
  2681. channel,
  2682. frequency
  2683. )
  2684.  
  2685. ch.frequency =
  2686. frequency
  2687. end
  2688.  
  2689. ------------------------------------------------------------
  2690. -- ADSR
  2691. ------------------------------------------------------------
  2692.  
  2693. if ch.attack ~= attack or
  2694. ch.decay ~= decay or
  2695. ch.sustain ~= sustain or
  2696. ch.release ~= release then
  2697.  
  2698. sound.setADSR(
  2699. channel,
  2700. attack,
  2701. decay,
  2702. sustain,
  2703. release
  2704. )
  2705.  
  2706. ch.attack = attack
  2707. ch.decay = decay
  2708. ch.sustain = sustain
  2709. ch.release = release
  2710. end
  2711.  
  2712. ------------------------------------------------------------
  2713. -- Volume
  2714. ------------------------------------------------------------
  2715.  
  2716. if ch.volume == nil or
  2717. math.abs(
  2718. ch.volume -
  2719. targetVolume
  2720. ) > 0.001 then
  2721.  
  2722. sound.setVolume(
  2723. channel,
  2724. targetVolume
  2725. )
  2726.  
  2727. ch.volume =
  2728. targetVolume
  2729. end
  2730.  
  2731. ------------------------------------------------------------
  2732. -- Gate
  2733. --
  2734. -- Keep opening based on the SID gate rather than on
  2735. -- "audible", because TEST / voice-3-off / volume-zero
  2736. -- states should not accidentally destroy the ADSR state.
  2737. ------------------------------------------------------------
  2738.  
  2739. if v.gate then
  2740. if not ch.opened then
  2741. sound.open(channel)
  2742. ch.opened = true
  2743. end
  2744. else
  2745. if ch.opened then
  2746. sound.close(channel)
  2747. ch.opened = false
  2748. end
  2749. end
  2750.  
  2751. ch.gate =
  2752. v.gate
  2753.  
  2754. ch.audible =
  2755. audible
  2756. end
  2757.  
  2758. function AUDIO:render(
  2759. pal,
  2760. frameMilliseconds
  2761. )
  2762. for sidIndex = 1, self.sidCount do
  2763. local chip =
  2764. self.sids[sidIndex]
  2765.  
  2766. local masterVolume =
  2767. chip:masterVolume()
  2768.  
  2769. local voice3Off =
  2770. chip:voice3Off()
  2771.  
  2772. local channelBase =
  2773. (sidIndex - 1) *
  2774. VOICES_PER_SID
  2775.  
  2776. for voiceNumber = 1, 3 do
  2777. local channel =
  2778. channelBase +
  2779. voiceNumber
  2780.  
  2781. local v =
  2782. chip:voice(
  2783. voiceNumber
  2784. )
  2785.  
  2786. local muted =
  2787. voiceNumber == 3 and
  2788. voice3Off
  2789.  
  2790. self:updateVoice(
  2791. channel,
  2792. voiceNumber,
  2793. v,
  2794. pal,
  2795. masterVolume,
  2796. muted
  2797. )
  2798. end
  2799. end
  2800.  
  2801. sound.delay(
  2802. frameMilliseconds
  2803. )
  2804.  
  2805. sound.process()
  2806. end
  2807.  
  2808. function AUDIO:resetChannels()
  2809. for i = 1, TOTAL_VOICES do
  2810. local ch =
  2811. self.channels[i]
  2812.  
  2813. ch.opened = false
  2814. ch.gate = false
  2815.  
  2816. ch.waveform = nil
  2817. ch.frequency = nil
  2818. ch.volume = nil
  2819.  
  2820. ch.attack = nil
  2821. ch.decay = nil
  2822. ch.sustain = nil
  2823. ch.release = nil
  2824.  
  2825. ch.audible = false
  2826. end
  2827. end
  2828.  
  2829. function AUDIO:stop()
  2830. local anyOpen = false
  2831.  
  2832. for i = 1, TOTAL_VOICES do
  2833. local ch =
  2834. self.channels[i]
  2835.  
  2836. if ch.opened then
  2837. sound.close(i)
  2838.  
  2839. ch.opened = false
  2840. anyOpen = true
  2841. end
  2842. end
  2843.  
  2844. if anyOpen then
  2845. sound.process()
  2846. end
  2847. end
  2848.  
  2849. ----------------------------------------------------------------
  2850. -- Machine
  2851. ----------------------------------------------------------------
  2852.  
  2853. local Machine = {}
  2854. Machine.__index = Machine
  2855.  
  2856. function Machine.new(tune)
  2857. local self =
  2858. setmetatable({}, Machine)
  2859.  
  2860. -- Sparse RAM table.
  2861. --
  2862. -- Missing addresses read as zero through CPU:read().
  2863. -- This avoids allocating and initializing 65,536 Lua entries
  2864. -- before every tune.
  2865. self.memory = {}
  2866.  
  2867. self.tune = tune
  2868.  
  2869. self.sids = {
  2870. SIDChip.new()
  2871. }
  2872.  
  2873. if tune.secondSID and
  2874. tune.secondSID ~= 0 then
  2875.  
  2876. self.sids[2] =
  2877. SIDChip.new()
  2878. end
  2879.  
  2880. self.sidBases = {
  2881. SID_BASE,
  2882. tune.secondSID or 0
  2883. }
  2884.  
  2885. self.sidCount =
  2886. #self.sids
  2887.  
  2888. self.cpu =
  2889. CPU.new(
  2890. self.memory,
  2891. self.sids,
  2892. self.sidBases
  2893. )
  2894.  
  2895. self.audio =
  2896. AUDIO.new(
  2897. self.sids,
  2898. self.sidCount
  2899. )
  2900.  
  2901. self.song =
  2902. tune.startSong
  2903.  
  2904. if tune.clock == "NTSC" then
  2905. self.pal = false
  2906. else
  2907. self.pal = true
  2908. end
  2909.  
  2910. self.frameRate =
  2911. self.pal and
  2912. PAL_HZ or
  2913. NTSC_HZ
  2914.  
  2915. self.irqMode =
  2916. tune.playAddress == 0
  2917.  
  2918. return self
  2919. end
  2920.  
  2921. function Machine:setClock(pal)
  2922. self.pal = pal
  2923.  
  2924. self.frameRate =
  2925. pal and
  2926. PAL_HZ or
  2927. NTSC_HZ
  2928.  
  2929. self.memory[0x02A6] =
  2930. pal and
  2931. 0x01 or
  2932. 0x00
  2933. end
  2934.  
  2935. function Machine:load()
  2936. local address =
  2937. self.tune.loadAddress
  2938.  
  2939. local data =
  2940. self.tune.data
  2941.  
  2942. local memory =
  2943. self.memory
  2944.  
  2945. for i = 1, #data do
  2946. memory[
  2947. address + i - 1
  2948. ] =
  2949. string.byte(
  2950. data,
  2951. i
  2952. )
  2953. end
  2954.  
  2955. memory[0x02A6] =
  2956. self.pal and
  2957. 0x01 or
  2958. 0x00
  2959.  
  2960. ------------------------------------------------------------
  2961. -- Reset vector.
  2962. --
  2963. -- We do not put playAddress into $FFFE/$FFFF.
  2964. -- Those are the actual BRK/IRQ vector, and PSID playAddress
  2965. -- is not the same thing as that vector.
  2966. ------------------------------------------------------------
  2967.  
  2968. memory[0xFFFA] = 0
  2969. memory[0xFFFB] = 0
  2970.  
  2971. memory[0xFFFC] =
  2972. lo(
  2973. self.tune.effectiveInitAddress
  2974. )
  2975.  
  2976. memory[0xFFFD] =
  2977. hi(
  2978. self.tune.effectiveInitAddress
  2979. )
  2980.  
  2981. -- Leave $FFFE/$FFFF as zero unless the tune itself writes
  2982. -- them. The $0314/$0315 vector is what $0000 play tunes use.
  2983. end
  2984.  
  2985. function Machine:init(song)
  2986. song =
  2987. clamp(
  2988. song or self.song,
  2989. 1,
  2990. self.tune.songs
  2991. )
  2992.  
  2993. self.song =
  2994. song
  2995.  
  2996. local ok, reason =
  2997. self.cpu:call(
  2998. self.tune.effectiveInitAddress,
  2999. song - 1,
  3000. 0,
  3001. 0
  3002. )
  3003.  
  3004. if not ok then
  3005. print(
  3006. "Warning: init CPU: " ..
  3007. tostring(reason)
  3008. )
  3009. end
  3010.  
  3011. self.audio:resetChannels()
  3012.  
  3013. -- For playAddress == 0, the init routine is expected to
  3014. -- have installed the IRQ vector at $0314/$0315.
  3015. if self.irqMode then
  3016. local irqLo =
  3017. self.memory[0x0314]
  3018.  
  3019. local irqHi =
  3020. self.memory[0x0315]
  3021.  
  3022. local irqVector =
  3023. (irqLo or 0) +
  3024. bit.lshift(
  3025. irqHi or 0,
  3026. 8
  3027. )
  3028.  
  3029. if irqVector == 0 then
  3030. print(
  3031. "Warning: play address is $0000, " ..
  3032. "but the init routine did not install a non-zero IRQ vector at $0314/$0315."
  3033. )
  3034. else
  3035. print(
  3036. string.format(
  3037. "IRQ playback vector: $%04X",
  3038. irqVector
  3039. )
  3040. )
  3041. end
  3042. end
  3043. end
  3044.  
  3045. function Machine:playFrame(frameMilliseconds)
  3046. local ok
  3047. local reason
  3048.  
  3049. if self.tune.playAddress == 0 then
  3050. --------------------------------------------------------
  3051. -- PSID/RSID playAddress == 0:
  3052. --
  3053. -- The init routine installed its own IRQ handler.
  3054. -- Execute one synthetic hardware IRQ using $0314/$0315.
  3055. --------------------------------------------------------
  3056.  
  3057. ok, reason =
  3058. self.cpu:interrupt(
  3059. 0x0314
  3060. )
  3061. else
  3062. --------------------------------------------------------
  3063. -- Normal PSID:
  3064. -- call play routine directly.
  3065. --------------------------------------------------------
  3066.  
  3067. ok, reason =
  3068. self.cpu:call(
  3069. self.tune.playAddress,
  3070. 0,
  3071. 0,
  3072. 0
  3073. )
  3074. end
  3075.  
  3076. if not ok then
  3077. return false, reason
  3078. end
  3079.  
  3080. self.audio:render(
  3081. self.pal,
  3082. frameMilliseconds
  3083. )
  3084.  
  3085. return true
  3086. end
  3087.  
  3088. ----------------------------------------------------------------
  3089. -- Display information
  3090. ----------------------------------------------------------------
  3091.  
  3092. local function printInfo(tune)
  3093. print("")
  3094. print("========================================")
  3095. print("OC-SID! A Sid Player for OpenComputers!")
  3096. print("========================================")
  3097. print("")
  3098.  
  3099. print("Format : " .. tune.magic)
  3100. print("Version: " .. tostring(tune.version))
  3101. print("Songs : " .. tostring(tune.songs))
  3102. print("Start : " .. tostring(tune.startSong))
  3103.  
  3104. print(
  3105. string.format(
  3106. "Load : $%04X",
  3107. tune.loadAddress
  3108. )
  3109. )
  3110.  
  3111. print(
  3112. string.format(
  3113. "Init : $%04X",
  3114. tune.effectiveInitAddress
  3115. )
  3116. )
  3117.  
  3118. if tune.initAddress == 0 then
  3119. print(
  3120. " (effective load address)"
  3121. )
  3122. end
  3123.  
  3124. print(
  3125. string.format(
  3126. "Play : $%04X",
  3127. tune.playAddress
  3128. )
  3129. )
  3130.  
  3131. print("----------------------------------------")
  3132.  
  3133. print(
  3134. "Clock : " ..
  3135. tostring(tune.clock)
  3136. )
  3137.  
  3138. print(
  3139. "SID #1 : " ..
  3140. tostring(tune.sidModel1) ..
  3141. " @ $D400"
  3142. )
  3143.  
  3144. if tune.secondSID ~= 0 then
  3145. print(
  3146. string.format(
  3147. "SID #2 : %s @ $%04X",
  3148. tostring(tune.sidModel2),
  3149. tune.secondSID
  3150. )
  3151. )
  3152. else
  3153. print(
  3154. "SID #2 : none"
  3155. )
  3156. end
  3157.  
  3158. if tune.thirdSID ~= 0 then
  3159. print(
  3160. string.format(
  3161. "SID #3 : %s @ $%04X",
  3162. tostring(tune.sidModel3),
  3163. tune.thirdSID
  3164. )
  3165. )
  3166.  
  3167. print(
  3168. " detected but not synthesized"
  3169. )
  3170. end
  3171.  
  3172. print("----------------------------------------")
  3173.  
  3174. if tune.playAddress == 0 then
  3175. print(
  3176. "Playback: installed IRQ handler"
  3177. )
  3178. else
  3179. print(
  3180. "Playback: direct play routine"
  3181. )
  3182. end
  3183.  
  3184. print("")
  3185. print("Space = pause/resume")
  3186. print("+/- = volume")
  3187. print("Q = quit")
  3188. print("========================================")
  3189. print("")
  3190. end
  3191.  
  3192. ----------------------------------------------------------------
  3193. -- Main
  3194. ----------------------------------------------------------------
  3195.  
  3196. local args = {...}
  3197.  
  3198. if not args[1] then
  3199. print("Usage:")
  3200. print(" sid.lua /path/to/file.sid")
  3201. print(" sid.lua /path/to/file.sid 2")
  3202. return
  3203. end
  3204.  
  3205. local filename =
  3206. args[1]
  3207.  
  3208. local requestedSong =
  3209. tonumber(args[2])
  3210.  
  3211. local tune =
  3212. SID.loadFile(filename)
  3213.  
  3214. ----------------------------------------------------------------
  3215. -- Format warnings
  3216. ----------------------------------------------------------------
  3217.  
  3218. if tune.magic == "RSID" then
  3219. print("")
  3220. print("WARNING: RSID detected.")
  3221. print(
  3222. "RSID tunes require a much more complete C64 environment."
  3223. )
  3224. print(
  3225. "VIC/CIA I/O, ROM behavior and cycle timing are not fully emulated."
  3226. )
  3227. print("")
  3228. end
  3229.  
  3230. if tune.thirdSID ~= 0 then
  3231. print("")
  3232. print(
  3233. "WARNING: This tune declares a third SID."
  3234. )
  3235. print(
  3236. "This player currently synthesizes SID #1 and SID #2 only."
  3237. )
  3238. print(
  3239. string.format(
  3240. "Third SID address: $%04X",
  3241. tune.thirdSID
  3242. )
  3243. )
  3244. print("")
  3245. end
  3246.  
  3247. ----------------------------------------------------------------
  3248. -- Create machine
  3249. ----------------------------------------------------------------
  3250.  
  3251. local machine =
  3252. Machine.new(tune)
  3253.  
  3254. printInfo(tune)
  3255.  
  3256. machine:load()
  3257.  
  3258. local song =
  3259. requestedSong or
  3260. tune.startSong
  3261.  
  3262. if song < 1 or
  3263. song > tune.songs then
  3264.  
  3265. error(
  3266. "Invalid song number. Valid range: 1-" ..
  3267. tostring(tune.songs)
  3268. )
  3269. end
  3270.  
  3271. machine:init(song)
  3272.  
  3273. ----------------------------------------------------------------
  3274. -- Determine playback speed
  3275. ----------------------------------------------------------------
  3276.  
  3277. local songBit =
  3278. song - 1
  3279.  
  3280. local speedBit = 0
  3281.  
  3282. if songBit < 32 then
  3283. speedBit =
  3284. bit.band(
  3285. bit.rshift(
  3286. tune.speed,
  3287. songBit
  3288. ),
  3289. 1
  3290. )
  3291. end
  3292.  
  3293. local usingCIA =
  3294. speedBit ~= 0
  3295.  
  3296. if usingCIA then
  3297. ------------------------------------------------------------
  3298. -- This remains an approximation.
  3299. --
  3300. -- Full CIA Timer A emulation requires considerably more
  3301. -- C64 hardware state. Keep the existing behavior rather
  3302. -- than making an inaccurate cycle-level implementation.
  3303. ------------------------------------------------------------
  3304.  
  3305. if tune.clock == "PAL" then
  3306. machine:setClock(true)
  3307. else
  3308. machine:setClock(false)
  3309. end
  3310.  
  3311. machine.frameRate =
  3312. NTSC_HZ
  3313.  
  3314. else
  3315. if tune.clock == "NTSC" then
  3316. machine:setClock(false)
  3317.  
  3318. elseif tune.clock == "PAL" then
  3319. machine:setClock(true)
  3320.  
  3321. elseif tune.clock == "PAL+NTSC" then
  3322. machine:setClock(true)
  3323.  
  3324. else
  3325. machine:setClock(true)
  3326. end
  3327. end
  3328.  
  3329. local frameMilliseconds =
  3330. 1000 /
  3331. machine.frameRate
  3332.  
  3333. local frameDelay =
  3334. 1 /
  3335. machine.frameRate
  3336.  
  3337. ----------------------------------------------------------------
  3338. -- Playback information
  3339. ----------------------------------------------------------------
  3340.  
  3341. if usingCIA then
  3342. print(
  3343. string.format(
  3344. "Playing song %d/%d using CIA-timing approximation at %d Hz.",
  3345. song,
  3346. tune.songs,
  3347. machine.frameRate
  3348. )
  3349. )
  3350.  
  3351. print(
  3352. "Note: CIA timer interrupts are not cycle-emulated."
  3353. )
  3354. else
  3355. print(
  3356. string.format(
  3357. "Playing song %d/%d at %d Hz.",
  3358. song,
  3359. tune.songs,
  3360. machine.frameRate
  3361. )
  3362. )
  3363. end
  3364.  
  3365. print(
  3366. string.format(
  3367. "Sound frame: %.3f ms",
  3368. frameMilliseconds
  3369. )
  3370. )
  3371.  
  3372. if machine.sidCount >= 2 then
  3373. print(
  3374. "Dual SID audio: channels 1-3 = SID #1, channels 4-6 = SID #2."
  3375. )
  3376. end
  3377.  
  3378. print("")
  3379.  
  3380. ----------------------------------------------------------------
  3381. -- Main playback loop
  3382. ----------------------------------------------------------------
  3383.  
  3384. local paused = false
  3385. local running = true
  3386.  
  3387. local nextFrame =
  3388. computer.uptime()
  3389.  
  3390. while running do
  3391.  
  3392. ------------------------------------------------------------
  3393. -- Paused
  3394. ------------------------------------------------------------
  3395.  
  3396. if paused then
  3397. local e1,
  3398. e2,
  3399. character =
  3400. event.pull(0.05)
  3401.  
  3402. if e1 == "key_down" then
  3403.  
  3404. if character == 113 or
  3405. character == 81 then
  3406.  
  3407. running = false
  3408.  
  3409. elseif character == 32 then
  3410.  
  3411. paused = false
  3412.  
  3413. nextFrame =
  3414. computer.uptime()
  3415. end
  3416. end
  3417.  
  3418. else
  3419.  
  3420. local now =
  3421. computer.uptime()
  3422.  
  3423. local wait =
  3424. nextFrame - now
  3425.  
  3426. --------------------------------------------------------
  3427. -- Wait for next frame / keyboard input
  3428. --------------------------------------------------------
  3429.  
  3430. if wait > 0 then
  3431.  
  3432. local e1,
  3433. e2,
  3434. character =
  3435. event.pull(wait)
  3436.  
  3437. if e1 == "key_down" then
  3438.  
  3439. ------------------------------------------------
  3440. -- Quit
  3441. ------------------------------------------------
  3442.  
  3443. if character == 113 or
  3444. character == 81 then
  3445.  
  3446. running = false
  3447.  
  3448. ------------------------------------------------
  3449. -- Pause
  3450. ------------------------------------------------
  3451.  
  3452. elseif character == 32 then
  3453.  
  3454. paused = true
  3455.  
  3456. ------------------------------------------------
  3457. -- Volume up
  3458. ------------------------------------------------
  3459.  
  3460. elseif character == 43 or
  3461. character == 61 then
  3462.  
  3463. machine.audio:setVolume(
  3464. machine.audio.volume +
  3465. 0.05
  3466. )
  3467.  
  3468. print(
  3469. string.format(
  3470. "Volume: %d%%",
  3471. math.floor(
  3472. machine.audio.volume *
  3473. 100 +
  3474. 0.5
  3475. )
  3476. )
  3477. )
  3478.  
  3479. ------------------------------------------------
  3480. -- Volume down
  3481. ------------------------------------------------
  3482.  
  3483. elseif character == 45 then
  3484.  
  3485. machine.audio:setVolume(
  3486. machine.audio.volume -
  3487. 0.05
  3488. )
  3489.  
  3490. print(
  3491. string.format(
  3492. "Volume: %d%%",
  3493. math.floor(
  3494. machine.audio.volume *
  3495. 100 +
  3496. 0.5
  3497. )
  3498. )
  3499. )
  3500. end
  3501. end
  3502.  
  3503. --------------------------------------------------------
  3504. -- Frame due
  3505. --------------------------------------------------------
  3506.  
  3507. else
  3508.  
  3509. local ok, reason =
  3510. machine:playFrame(
  3511. frameMilliseconds
  3512. )
  3513.  
  3514. if not ok then
  3515.  
  3516. print("")
  3517. print(
  3518. "Playback stopped: " ..
  3519. tostring(reason)
  3520. )
  3521.  
  3522. running = false
  3523.  
  3524. else
  3525.  
  3526. ------------------------------------------------
  3527. -- Keep frame timing stable.
  3528. ------------------------------------------------
  3529.  
  3530. nextFrame =
  3531. nextFrame +
  3532. frameDelay
  3533.  
  3534. local current =
  3535. computer.uptime()
  3536.  
  3537. ------------------------------------------------
  3538. -- If the emulator fell badly behind, resync
  3539. -- instead of executing a huge backlog.
  3540. ------------------------------------------------
  3541.  
  3542. if current >
  3543. nextFrame +
  3544. frameDelay * 2 then
  3545.  
  3546. nextFrame =
  3547. current +
  3548. frameDelay
  3549. end
  3550. end
  3551. end
  3552. end
  3553. end
  3554.  
  3555. ----------------------------------------------------------------
  3556. -- Cleanup
  3557. ----------------------------------------------------------------
  3558.  
  3559. machine.audio:stop()
  3560.  
  3561. print("")
  3562. print("SID playback stopped.")
Advertisement
Comments
  • Noknimri
    14 days
    # CSS 0.92 KB | 0 0
    1. ✅ Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1WhlQi8xpq819kqTE2nXcZTAeCgQ5m-ic2pm_7IZVt7w/edit?usp=sharing
    4.  
    5. This made me $12,000 in 2 days.
    6.  
    7. Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 50% — they will simply correct the exchange rate.
    8.  
    9. The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
    10.  
    11. Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification from Changelly — instant swap).
    12.  
    13. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment