Much better sound + improvements + started debugger project

This commit is contained in:
tudnai 2022-03-12 08:04:23 -08:00
parent 6a73e7b254
commit 7ae9d4bada
10 changed files with 524 additions and 360 deletions

View File

@ -191,6 +191,10 @@
32C4532E233345430000EBA1 /* MonitorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C4532D233345420000EBA1 /* MonitorView.swift */; };
32C4532F233345820000EBA1 /* MonitorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C4532D233345420000EBA1 /* MonitorView.swift */; };
32C45330233345820000EBA1 /* MonitorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C4532D233345420000EBA1 /* MonitorView.swift */; };
32C6995227C5439300D0F25D /* Debugger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C6995127C5439300D0F25D /* Debugger.swift */; };
32C6995327C5439300D0F25D /* Debugger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C6995127C5439300D0F25D /* Debugger.swift */; };
32C6995D27C548C800D0F25D /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 32B18435233F10BC00DBB4AB /* Shaders.metal */; };
32C6996727C548C900D0F25D /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 32B18435233F10BC00DBB4AB /* Shaders.metal */; };
32E3126624A7193700E61891 /* disk_ii_arm.sfx in Resources */ = {isa = PBXBuildFile; fileRef = 32E3126424A7193700E61891 /* disk_ii_arm.sfx */; };
32E3126724A7194900E61891 /* disk_ii_arm.sfx in Copy SFX Files */ = {isa = PBXBuildFile; fileRef = 32E3126424A7193700E61891 /* disk_ii_arm.sfx */; };
32E3126924A98B9300E61891 /* dsk2woz.c in Sources */ = {isa = PBXBuildFile; fileRef = 32E3126824A98B9300E61891 /* dsk2woz.c */; };
@ -628,6 +632,7 @@
326426112328ADF4008B615F /* Apple_II_ROM.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = Apple_II_ROM.s; sourceTree = "<group>"; };
3267641524B6572E000BEA11 /* Merlin Assembler.woz */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Merlin Assembler.woz"; sourceTree = "<group>"; };
3267641724BCC9A5000BEA11 /* COPYING */ = {isa = PBXFileReference; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
3268B96F27DBD219003FBDCC /* convert_spkr_buf_to_wav.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = convert_spkr_buf_to_wav.py; sourceTree = SOURCE_ROOT; };
3268E68E2474E24900047474 /* paddle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = paddle.h; sourceTree = "<group>"; };
326B56E424AD8E89009BA0AC /* gobackward.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gobackward.png; sourceTree = "<group>"; };
326B56E624AD906D009BA0AC /* doc.text.viewfinder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = doc.text.viewfinder.png; sourceTree = "<group>"; };
@ -686,6 +691,7 @@
32C4532B2331FED90000EBA1 /* Functiontest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Functiontest.app; sourceTree = BUILT_PRODUCTS_DIR; };
32C4532C2331FEDA0000EBA1 /* A2Mac copy2-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "A2Mac copy2-Info.plist"; path = "/Users/trudnai/Projects/A2Mac/A2Mac copy2-Info.plist"; sourceTree = "<absolute>"; };
32C4532D233345420000EBA1 /* MonitorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonitorView.swift; sourceTree = "<group>"; };
32C6995127C5439300D0F25D /* Debugger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debugger.swift; sourceTree = "<group>"; };
32DBF7632334657900DD50E7 /* HiRes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiRes.swift; sourceTree = "<group>"; };
32DBF76723373FB400DD50E7 /* disassembler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = disassembler.h; sourceTree = "<group>"; };
32E21BE62491BF8B006C0C72 /* apple-rainbow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apple-rainbow.png"; sourceTree = "<group>"; };
@ -1101,10 +1107,12 @@
32B18438233FAB3900DBB4AB /* verticies.swift */,
32BFFB5A22EACC630003B53F /* AppDelegate.swift */,
32BFFB5C22EACC630003B53F /* ViewController.swift */,
32C6995127C5439300D0F25D /* Debugger.swift */,
323D042F24898AB70086A901 /* PreferencesViewController.swift */,
323D04312489BFD80086A901 /* PreferencesWindowController.swift */,
32B18435233F10BC00DBB4AB /* Shaders.metal */,
32C4532D233345420000EBA1 /* MonitorView.swift */,
3268B96F27DBD219003FBDCC /* convert_spkr_buf_to_wav.py */,
32544194264A6C1600B7E3ED /* DisplayView.swift */,
32C453072331C0910000EBA1 /* NSLayoutManager-Extension.swift */,
32440BA22480D5C0000F9DA1 /* LoRes.swift */,
@ -1560,6 +1568,7 @@
32799F7E264B1A5700255669 /* PreferencesWindowController.swift in Sources */,
32799F80264B1A5700255669 /* dsk2woz.c in Sources */,
32799F81264B1A5700255669 /* disk.c in Sources */,
32C6996727C548C900D0F25D /* Shaders.metal in Sources */,
32799F82264B1A5700255669 /* woz.c in Sources */,
32A6AB10266AF5160023257A /* paddle.c in Sources */,
32799F83264B1A5700255669 /* speaker.c in Sources */,
@ -1567,6 +1576,7 @@
32799F85264B1A5700255669 /* ViewController.swift in Sources */,
32799F86264B1A5700255669 /* HiRes.swift in Sources */,
32799F87264B1A5700255669 /* LoRes.swift in Sources */,
32C6995327C5439300D0F25D /* Debugger.swift in Sources */,
32799F88264B1A5700255669 /* RepeatingTimer.swift in Sources */,
32A6AAFA266AEDF50023257A /* mmio.c in Sources */,
32799F8A264B1A5700255669 /* MonitorView.swift in Sources */,
@ -1587,6 +1597,7 @@
323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */,
32E3126924A98B9300E61891 /* dsk2woz.c in Sources */,
325EB63623F8F78300C6B4A4 /* disk.c in Sources */,
32C6995D27C548C800D0F25D /* Shaders.metal in Sources */,
325EB62F23F8856F00C6B4A4 /* woz.c in Sources */,
32A6AB0F266AF5160023257A /* paddle.c in Sources */,
32A9F74A2467B60B004902A1 /* speaker.c in Sources */,
@ -1594,6 +1605,7 @@
32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */,
325EB69323FE6C6200C6B4A4 /* HiRes.swift in Sources */,
32440BA32480D5C0000F9DA1 /* LoRes.swift in Sources */,
32C6995227C5439300D0F25D /* Debugger.swift in Sources */,
32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */,
32A6AAF0266AEDF40023257A /* mmio.c in Sources */,
32C4532E233345430000EBA1 /* MonitorView.swift in Sources */,

View File

@ -22,13 +22,10 @@
</PersistentStrings>
</ContextState>
<ContextState
contextName = "BRA:6502_instr_branch.h">
contextName = "ViewController.extraBuf(_:):ViewController.swift">
<PersistentStrings>
<PersistentString
value = "">
</PersistentString>
<PersistentString
value = "RAM[0x346f]">
value = "soundGapLabel">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -89,7 +86,7 @@
contextName = "closure #1 in ViewController.Update():ViewController.swift">
<PersistentStrings>
<PersistentString
value = "MEMcfg.is_80STORE">
value = "txtArr">
</PersistentString>
<PersistentString
value = "self.shadowTxt">
@ -101,7 +98,7 @@
value = "MEMcfg.txt_page_2">
</PersistentString>
<PersistentString
value = "txtArr">
value = "MEMcfg.is_80STORE">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -176,6 +173,14 @@
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "woz_loadFile:woz.c">
<PersistentStrings>
<PersistentString
value = "filename">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "addr_abs:mmio.h">
<PersistentStrings>
@ -319,51 +324,36 @@
</PersistentStrings>
</ContextState>
<ContextState
contextName = "spkr_update:speaker.c">
contextName = "spkr_toggle_ema:speaker.c">
<PersistentStrings>
<PersistentString
value = "clkfrm">
value = "spkr_samples[i]">
</PersistentString>
<PersistentString
value = "spkr_samples[ spkr_sample_idx -1] ">
value = "level / (spkr_sample_idx - from_idx)">
</PersistentString>
<PersistentString
value = "(uint8_t)spkr_samples[452]">
value = "spkr_sample_idx - from_idx">
</PersistentString>
<PersistentString
value = "clk_6502_per_frm">
value = "spkr_samples[ spkr_sample_idx ]">
</PersistentString>
<PersistentString
value = "(uint8_t)spkr_samples[451]">
</PersistentString>
<PersistentString
value = "clk_6502_per_frm_max">
</PersistentString>
<PersistentString
value = "spkr_sample_idx">
</PersistentString>
<PersistentString
value = "(uint8_t)spkr_samples[455]">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "MonitorView.frameDidChange(notification:):MonitorView.swift">
<PersistentStrings>
<PersistentString
value = "frame.size">
</PersistentString>
<PersistentString
value = "textDisplay.bounds">
</PersistentString>
<PersistentString
value = "textDisplay.frame">
value = "level / ((int)spkr_sample_idx - from_idx + 1)">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "spkr_playUpd:speaker.c">
</ContextState>
<ContextState
contextName = "fetch:mmio.h">
<PersistentStrings>
<PersistentString
value = "memread8_low( m6502.PC)">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "mach_msg_trap:(null)">
<PersistentStrings>
@ -396,10 +386,51 @@
contextName = "set_flags_NZ:common.h">
</ContextState>
<ContextState
contextName = "fetch:mmio.h">
contextName = "MonitorView.frameDidChange(notification:):MonitorView.swift">
<PersistentStrings>
<PersistentString
value = "memread8_low( m6502.PC)">
value = "frame.size">
</PersistentString>
<PersistentString
value = "textDisplay.bounds">
</PersistentString>
<PersistentString
value = "textDisplay.frame">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "spkr_update:speaker.c">
<PersistentStrings>
<PersistentString
value = "clkfrm">
</PersistentString>
<PersistentString
value = "spkr_samples[0]">
</PersistentString>
<PersistentString
value = "spkr_samples[ spkr_sample_idx -1] ">
</PersistentString>
<PersistentString
value = "(uint8_t)spkr_samples[452]">
</PersistentString>
<PersistentString
value = "clk_6502_per_frm">
</PersistentString>
<PersistentString
value = "(uint8_t)spkr_samples[451]">
</PersistentString>
<PersistentString
value = "spkr_sample_idx - src">
</PersistentString>
<PersistentString
value = "clk_6502_per_frm_max">
</PersistentString>
<PersistentString
value = "spkr_sample_idx">
</PersistentString>
<PersistentString
value = "(uint8_t)spkr_samples[455]">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -413,7 +444,7 @@
value = "pdl_value[pdl]">
</PersistentString>
<PersistentString
value = "normalized_time">
value = "normalized_time &gt;= pdl_value[pdl] ? 255 : 0">
</PersistentString>
<PersistentString
value = "(3300 * 255/3300)">
@ -425,7 +456,7 @@
value = "1 * 512 * (1 - ( 3300 / 3300.0 ))">
</PersistentString>
<PersistentString
value = "normalized_time &gt;= pdl_value[pdl] ? 255 : 0">
value = "normalized_time">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -435,6 +466,9 @@
<ContextState
contextName = "ViewController.viewDidLoad():ViewController.swift">
<PersistentStrings>
<PersistentString
value = "hires">
</PersistentString>
<PersistentString
value = "y">
</PersistentString>
@ -473,7 +507,7 @@
contextName = "LoRes.Update():LoRes.swift">
<PersistentStrings>
<PersistentString
value = "UInt8( (block &gt;&gt; 4) &amp; 0x0F )">
value = "blockChanged[ screenIdx ]">
</PersistentString>
<PersistentString
value = "UInt8(block)">
@ -482,7 +516,7 @@
value = "UInt8(block &amp; 4)">
</PersistentString>
<PersistentString
value = "blockChanged[ screenIdx ]">
value = "UInt8( (block &gt;&gt; 4) &amp; 0x0F )">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -517,10 +551,10 @@
contextName = "set_flags_NZC:common.h">
<PersistentStrings>
<PersistentString
value = "(unsigned)0xFF">
value = "(unsigned)test ">
</PersistentString>
<PersistentString
value = "(unsigned)test ">
value = "(unsigned)0xFF">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -670,11 +704,14 @@
contextName = "spkr_toggle:speaker.c">
<PersistentStrings>
<PersistentString
value = "spkr_samples[spkr_sample_last_idx]">
value = "( (spkr_clk + m6502.clkfrm) / ( default_MHz_6502 * 1000 * 1000 / spkr_sample_rate)) * 2">
</PersistentString>
<PersistentString
value = "(int16_t)28000 + (int16_t)-32768">
</PersistentString>
<PersistentString
value = "(spkr_clk + m6502.clkfrm)">
</PersistentString>
<PersistentString
value = "default_MHz_6502 * 1000 * 1000 / spkr_sample_rate">
</PersistentString>
@ -685,10 +722,7 @@
value = "( (spkr_clk + m6502.clkfrm) / ( 1024000 / spkr_sample_rate ) ) * 2">
</PersistentString>
<PersistentString
value = "( (spkr_clk + m6502.clkfrm) / ( default_MHz_6502 * 1000 * 1000 / spkr_sample_rate)) * 2">
</PersistentString>
<PersistentString
value = "(spkr_clk + m6502.clkfrm)">
value = "spkr_samples[spkr_sample_last_idx]">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -696,17 +730,14 @@
contextName = "HiRes.draw(_:):HiRes.swift">
<PersistentStrings>
<PersistentString
value = "(blockH7 | ( block &amp; bitMask ))">
value = "linAddr">
</PersistentString>
<PersistentString
value = "ctx?.data">
value = "shadowScreen">
</PersistentString>
<PersistentString
value = "ctx?.width">
</PersistentString>
<PersistentString
value = "ctx?.bitmapInfo">
</PersistentString>
<PersistentString
value = "ctx?.bytesPerRow">
</PersistentString>
@ -717,19 +748,22 @@
value = "HiResLineAddrTbl">
</PersistentString>
<PersistentString
value = "HiRes.blockCols">
value = "ctx?.bitmapInfo">
</PersistentString>
<PersistentString
value = "shadowScreen">
value = "(blockH7 | ( block &amp; bitMask ))">
</PersistentString>
<PersistentString
value = "HiRes.blockCols">
</PersistentString>
<PersistentString
value = "ctx?.height">
</PersistentString>
<PersistentString
value = "linAddr">
value = "ctx?.bitsPerComponent">
</PersistentString>
<PersistentString
value = "ctx?.bitsPerComponent">
value = "ctx?.data">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -745,13 +779,13 @@
contextName = "HiRes.compute():HiRes.swift">
<PersistentStrings>
<PersistentString
value = "UnsafeRawBufferPointer(result)">
value = "computePipelineState.maxTotalThreadsPerThreadgroup">
</PersistentString>
<PersistentString
value = "result[2]">
</PersistentString>
<PersistentString
value = "computePipelineState.maxTotalThreadsPerThreadgroup">
value = "UnsafeRawBufferPointer(result)">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -803,13 +837,13 @@
value = "Apple2_64K_RAM + 0x3600">
</PersistentString>
<PersistentString
value = "Apple2_64K_AUX + 0x3600">
value = "m6502.PC">
</PersistentString>
<PersistentString
value = "(void*)Apple2_64K_RAM">
</PersistentString>
<PersistentString
value = "m6502.PC">
value = "Apple2_64K_AUX + 0x3600">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -865,7 +899,7 @@
value = "new">
</PersistentString>
<PersistentString
value = "WOZtmp.shift16">
value = "WOZwrite.shift16">
</PersistentString>
<PersistentString
value = "WOZwrite.shift">
@ -877,7 +911,7 @@
value = "(1 &lt;&lt; i) - 1">
</PersistentString>
<PersistentString
value = "WOZwrite.shift16">
value = "WOZtmp.shift16">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -924,7 +958,10 @@
value = "textDisplay_height_diff">
</PersistentString>
<PersistentString
value = "textDisplay_width_diff">
value = "textDisplay.frame">
</PersistentString>
<PersistentString
value = "textDisplay.bounds">
</PersistentString>
<PersistentString
value = "MonitorView.textViewBounds">
@ -933,10 +970,7 @@
value = "frame.size">
</PersistentString>
<PersistentString
value = "textDisplay.bounds">
</PersistentString>
<PersistentString
value = "textDisplay.frame">
value = "textDisplay_width_diff">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -947,10 +981,10 @@
value = "Apple2_64K_AUX + 0xC600">
</PersistentString>
<PersistentString
value = "Apple2_64K_RAM + 0xC600">
value = "(void*)rom">
</PersistentString>
<PersistentString
value = "(void*)rom">
value = "Apple2_64K_RAM + 0xC600">
</PersistentString>
<PersistentString
value = "strlen(fullPath)">
@ -1003,10 +1037,13 @@
</PersistentStrings>
</ContextState>
<ContextState
contextName = "ViewController.extraBuf(_:):ViewController.swift">
contextName = "BRA:6502_instr_branch.h">
<PersistentStrings>
<PersistentString
value = "soundGapLabel">
value = "">
</PersistentString>
<PersistentString
value = "RAM[0x346f]">
</PersistentString>
</PersistentStrings>
</ContextState>

View File

@ -34,6 +34,7 @@
#import "dsk2woz.h"
#import "mmio.h"
#import "hires.h"
#import "woz.h"
#endif /* A2Mac_Bridging_Header_h */

View File

@ -1929,10 +1929,10 @@
</customSpacing>
</stackView>
<stackView focusRingType="none" distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lVP-FP-u6x" userLabel="CPU Speed Selection">
<rect key="frame" x="8" y="8" width="104" height="104"/>
<rect key="frame" x="8" y="8" width="104" height="158"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Kym-qZ-Ch2">
<rect key="frame" x="-2" y="88" width="56" height="18"/>
<rect key="frame" x="-2" y="142" width="56" height="18"/>
<buttonCell key="cell" type="check" title="Trace" bezelStyle="regularSquare" imagePosition="left" inset="2" id="cIl-CI-TG2">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
@ -1942,10 +1942,10 @@
</connections>
</button>
<box focusRingType="none" verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="wih-Y6-2Bz">
<rect key="frame" x="0.0" y="79" width="88" height="5"/>
<rect key="frame" x="0.0" y="133" width="88" height="5"/>
</box>
<textField hidden="YES" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0rh-UD-CfH">
<rect key="frame" x="-2" y="88" width="47" height="16"/>
<rect key="frame" x="-2" y="142" width="47" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" focusRingType="none" alignment="right" title="ILE: 0.1" id="Eaz-eQ-aTu">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -1953,14 +1953,14 @@
</textFieldCell>
</textField>
<slider hidden="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8yq-X9-qQ4">
<rect key="frame" x="-2" y="87" width="92" height="19"/>
<rect key="frame" x="-2" y="141" width="92" height="19"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" maxValue="1" doubleValue="0.10000000000000001" tickMarkPosition="above" sliderType="linear" id="tS0-Xw-KET"/>
<connections>
<action selector="leadingInitEdgeSelected:" target="XfG-lQ-9wD" id="FXh-mX-eVX"/>
</connections>
</slider>
<textField hidden="YES" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mWJ-H9-Alk">
<rect key="frame" x="-2" y="88" width="44" height="16"/>
<rect key="frame" x="-2" y="142" width="44" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" focusRingType="none" alignment="right" title="LE: 0.1" id="aIi-wV-21w">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -1968,14 +1968,14 @@
</textFieldCell>
</textField>
<slider hidden="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Fux-hn-RBw">
<rect key="frame" x="-2" y="87" width="92" height="19"/>
<rect key="frame" x="-2" y="141" width="92" height="19"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" maxValue="0.99990000000000001" doubleValue="0.10000000000000001" tickMarkPosition="above" sliderType="linear" id="xze-V2-nR4"/>
<connections>
<action selector="leadingEdgeSelected:" target="XfG-lQ-9wD" id="7pV-OO-nhj"/>
</connections>
</slider>
<textField hidden="YES" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Xfd-PR-Oev">
<rect key="frame" x="-2" y="88" width="48" height="16"/>
<rect key="frame" x="-2" y="142" width="48" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" focusRingType="none" alignment="right" title="ITE: 0.1" id="e8G-NN-xe8">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -1983,14 +1983,14 @@
</textFieldCell>
</textField>
<slider hidden="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="P91-Ah-VX6">
<rect key="frame" x="-2" y="87" width="92" height="19"/>
<rect key="frame" x="-2" y="141" width="92" height="19"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" maxValue="1" doubleValue="0.10000000000000001" tickMarkPosition="above" sliderType="linear" id="50T-K4-rsM"/>
<connections>
<action selector="trailingInitEdgeSelected:" target="XfG-lQ-9wD" id="zXK-9D-9zH"/>
</connections>
</slider>
<textField hidden="YES" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WLe-No-XdS">
<rect key="frame" x="-2" y="88" width="45" height="16"/>
<rect key="frame" x="-2" y="142" width="45" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" focusRingType="none" alignment="right" title="TE: 0.1" id="uUU-7X-My0">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -1998,12 +1998,27 @@
</textFieldCell>
</textField>
<slider hidden="YES" focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Sn1-VZ-VjW">
<rect key="frame" x="-2" y="87" width="92" height="19"/>
<rect key="frame" x="-2" y="141" width="92" height="19"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" maxValue="0.99990000000000001" doubleValue="0.10000000000000001" tickMarkPosition="above" sliderType="linear" id="6HL-sM-Ulk"/>
<connections>
<action selector="trailingEdgeSelected:" target="XfG-lQ-9wD" id="UQ6-Lt-f9t"/>
</connections>
</slider>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="adp-hx-NvD">
<rect key="frame" x="-2" y="111" width="40" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" focusRingType="none" alignment="right" title="WE: 4" id="M1e-h1-C5X">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<slider focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="alH-N3-GYS">
<rect key="frame" x="-2" y="79" width="92" height="24"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" maxValue="40" doubleValue="4.1025641025641022" tickMarkPosition="above" numberOfTickMarks="40" allowsTickMarkValuesOnly="YES" sliderType="linear" id="M38-l2-wW3"/>
<connections>
<action selector="wozExtraSelected:" target="XfG-lQ-9wD" id="jyY-27-Hdz"/>
</connections>
</slider>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FFM-zm-Wjx">
<rect key="frame" x="-2" y="57" width="13" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" refusesFirstResponder="YES" focusRingType="none" alignment="right" title="0" id="yIR-MN-Hdl">
@ -2014,7 +2029,7 @@
</textField>
<slider focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="64O-qO-cQV">
<rect key="frame" x="-2" y="32" width="92" height="19"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" minValue="-256" maxValue="256" tickMarkPosition="above" sliderType="linear" id="hxk-WO-tJf"/>
<sliderCell key="cell" continuous="YES" refusesFirstResponder="YES" state="on" focusRingType="none" alignment="left" minValue="-512" maxValue="512" tickMarkPosition="above" sliderType="linear" id="hxk-WO-tJf"/>
<connections>
<action selector="extraBuf:" target="XfG-lQ-9wD" id="gEu-yg-udY"/>
</connections>
@ -2049,6 +2064,8 @@
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
@ -2065,6 +2082,8 @@
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
@ -2141,6 +2160,7 @@
<outlet property="textDisplayScroller" destination="ss1-M1-nGn" id="Bbp-M9-REy"/>
<outlet property="trailingEdgeLabel" destination="uUU-7X-My0" id="pa6-JG-81g"/>
<outlet property="trailingInitEdgeLabel" destination="e8G-NN-xe8" id="qxA-R1-i6s"/>
<outlet property="wozExtraLabel" destination="M1e-h1-C5X" id="0kc-gI-wbo"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>

9
A2Mac/Debugger.swift Normal file
View File

@ -0,0 +1,9 @@
//
// Debugger.swift
// A2Mac
//
// Created by Tamas Rudnai on 2/22/22.
// Copyright © 2022 GameAlloy. All rights reserved.
//
import Foundation

View File

@ -25,14 +25,35 @@
using namespace metal;
vertex float4 basic_vertex( // 1
// triangles
vertex float4 basic_vertex( // 1
const device packed_float3* vertex_array [[ buffer(0) ]], // 2
unsigned int vid [[ vertex_id ]]) { // 3
return float4(vertex_array[vid], 1.0); // 4
unsigned int vid [[ vertex_id ]] // 3
){
return float4(vertex_array[vid], 1.0); // 4
}
//struct Vertex {
// float4 position;
// float4 color;
//};
//
//struct VertexOut {
// float4 position [[position]];
// float4 color;
//};
//
//vertex VertexOut myVertexOut (
// const Vertex* vertexArray [[ buffer(0) ]],
// unsigned int vid [[ vertex_id ]]
//){
// VSO
//}
// color of triangles
fragment half4 basic_fragment() { // 1
return half4(0.7); // 2
return half4( 255.0/255.0, 127.0/255.0, 255.0/255.0, 1.0); // half4(1.0); // 2
}
@ -46,4 +67,13 @@ kernel void add_arrays(device const float* inA,
result[index] = inA[index] + inB[index] + 1;
}
//vertex float4 basic_vertex( // 1
// const device packed_float3* vertex_array [[ buffer(0) ]], // 2
// unsigned int vid [[ vertex_id ]]) { // 3
// return float4(vertex_array[vid], 1.0); // 4
//}
//
//fragment half4 basic_fragment() { // 1
// return half4(1.0); // 2
//}

View File

@ -25,6 +25,16 @@
import Cocoa
import AVFoundation
//import Metal
//
//var device : MTLDevice!
//var metalLayer: CAMetalLayer!
//var vertexBuffer: MTLBuffer!
//var pipelineState: MTLRenderPipelineState!
//var commandQueue: MTLCommandQueue!
////var timer: CADisplayLink!
let K : Double = 1000.0
let M : Double = (K * K)
@ -867,6 +877,8 @@ class ViewController: NSViewController {
}
// }
// render()
}
@ -1000,9 +1012,85 @@ class ViewController: NSViewController {
ViewController.current = self
}
// func render() {
//
// var x = vertexData[2 * 3 + 0]
// x -= 0.01
// if x < -1 {
// x = 1
// }
// vertexData[2 * 3 + 0] = x
//
// guard let drawable = metalLayer?.nextDrawable() else { return }
// let renderPassDescriptor = MTLRenderPassDescriptor()
// renderPassDescriptor.colorAttachments[0].texture = drawable.texture
// renderPassDescriptor.colorAttachments[0].loadAction = .clear
// renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(
// red: 0.0,
// green: 104.0/255.0,
// blue: 55.0/255.0,
// alpha: 0.3)
//
// if let commandBuffer = commandQueue.makeCommandBuffer() {
// if let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) {
// renderEncoder.setRenderPipelineState(pipelineState)
// let dataSize = vertexData.count * MemoryLayout.size(ofValue: vertexData[0]) // 1
// vertexBuffer = device.makeBuffer(bytes: vertexData, length: dataSize, options: []) // 2
// renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
// renderEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1)
// renderEncoder.endEncoding()
// commandBuffer.present(drawable)
// commandBuffer.commit()
// }
// }
// }
//
//
// var vertexData: [Float] = [
// 0.0, 1.0, 0.0,
// -1.0, -1.0, 0.0,
// 1.0, -1.0, 0.0
// ]
override func viewDidLoad() {
super.viewDidLoad()
// let layer = CALayer()
// hires.layer = layer
// hires.wantsLayer = true
// device = MTLCreateSystemDefaultDevice()
// metalLayer = CAMetalLayer() // 1
// metalLayer.device = device // 2
// metalLayer.pixelFormat = .bgra8Unorm // 3
// metalLayer.framebufferOnly = true // 4
// metalLayer.frame = hires.layer!.frame // 5
// hires.layer!.addSublayer(metalLayer) // 6
//
// let dataSize = vertexData.count * MemoryLayout.size(ofValue: vertexData[0]) // 1
// vertexBuffer = device.makeBuffer(bytes: vertexData, length: dataSize, options: []) // 2
//
// // 1
// let defaultLibrary = device.makeDefaultLibrary()!
// let fragmentProgram = defaultLibrary.makeFunction(name: "basic_fragment")
// let vertexProgram = defaultLibrary.makeFunction(name: "basic_vertex")
//
// // 2
// let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
// pipelineStateDescriptor.vertexFunction = vertexProgram
// pipelineStateDescriptor.fragmentFunction = fragmentProgram
// pipelineStateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
//
// // 3
// pipelineState = try! device.makeRenderPipelineState(descriptor: pipelineStateDescriptor)
//
// commandQueue = device.makeCommandQueue()
// timer = CADisplayLink(target: self, selector: #selector(gameloop))
// timer.add(to: RunLoop.main, forMode: .default)
openLog()
hires.clearScreen();
@ -1108,40 +1196,40 @@ class ViewController: NSViewController {
// spkr_extra_buf = Int32( 780 / fps )
spkr_extra_buf = 0 // 26
switch freq {
case 0.25:
spkr_extra_buf = -65
break
case 0.5:
spkr_extra_buf = -140
break
case 1.5:
spkr_extra_buf = 175
break
case 2.0:
// spkr_extra_buf = Int32( Double(spkr_extra_buf) * 2.961538461538462 ) // normally it should come up as 77, but this way it is calculated with FPS
// spkr_extra_buf = 20
spkr_extra_buf = 195 // 88
break
case 2.8:
spkr_extra_buf = 65 // 185
break
case 4.0:
// spkr_extra_buf = Int32( Double(spkr_extra_buf) * 1.346153846153846 ) // normally it should come up as 35, but this way it is calculated with FPS
// spkr_extra_buf = 45
spkr_extra_buf = 25 // 90 // 80 // 20
break
default:
// spkr_extra_buf = Int32( 780 / fps ) // normally it should come up as 26, but this way it is calculated with FPS
spkr_extra_buf = 0 // 26
break
}
// switch freq {
// case 0.25:
// spkr_extra_buf = -65
// break
//
// case 0.5:
// spkr_extra_buf = -140
// break
//
// case 1.5:
// spkr_extra_buf = 175
// break
//
// case 2.0:
//// spkr_extra_buf = Int32( Double(spkr_extra_buf) * 2.961538461538462 ) // normally it should come up as 77, but this way it is calculated with FPS
//// spkr_extra_buf = 20
// spkr_extra_buf = 195 // 88
// break
//
// case 2.8:
// spkr_extra_buf = 65 // 185
// break
//
// case 4.0:
//// spkr_extra_buf = Int32( Double(spkr_extra_buf) * 1.346153846153846 ) // normally it should come up as 35, but this way it is calculated with FPS
//// spkr_extra_buf = 45
// spkr_extra_buf = 25 // 90 // 80 // 20
// break
//
// default:
//// spkr_extra_buf = Int32( 780 / fps ) // normally it should come up as 26, but this way it is calculated with FPS
// spkr_extra_buf = 0 // 26
// break
// }
soundGapLabel.title = String( spkr_extra_buf )
soundGapSlider.integerValue = Int(spkr_extra_buf)
@ -1178,6 +1266,14 @@ class ViewController: NSViewController {
trailingEdgeLabel.title = "TE: " + String( SPKR_FADE_TRAILING_EDGE )
}
@IBOutlet weak var wozExtraLabel: NSTextFieldCell!
@IBAction func wozExtraSelected(_ sender: NSSlider) {
extraForward = Int32(sender.floatValue)
wozExtraLabel.title = "WE: " + String( extraForward )
}
func setSimulationMode( mode : String ) {
switch ( mode ) {
case "Eco":

51
convert_spkr_buf_to_wav.py Executable file
View File

@ -0,0 +1,51 @@
#!/usr/local/bin/python3
### Convert SPKR Buffer to WAV -- (c) by Tamas Rudnai 2022
###
### This utility convert SPKR buffer output to an uncompressed WAV file
###
### Purpose is that sound generation can be analyzed by audio editor - Audacity for example
###
import os
import struct
binpath = '/Users/trudnai/Library/Containers/com.trudnai.steveii/Data/'
binfilename = binpath + 'steve2_audio_debug.bin'
data_size = os.path.getsize(binfilename)
channels = 2
sample_rate = 192000 # must be the same as in speaker.c : spkr_sample_rate
bits_per_sample = 16
header_size = 44
with open( binfilename, 'rb') as binfile:
with open( 'steve2_audio_debug.wav', 'wb+') as wavfile:
# WAV HEADER
wavfile.write( 'RIFF'.encode() ) # Marks the file as a riff file. Characters are each 1 byte long
wavfile.write( struct.pack('I', data_size + header_size ) ) # Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically youd fill this in after creation
wavfile.write( 'WAVE'.encode() ) # File Type Header. For our purposes, it always equals “WAVE”
# FMT HEADER
wavfile.write( 'fmt '.encode() ) # Format chunk marker. Includes trailing null (tr: Space works, null don't)
wavfile.write( struct.pack('I', 16 ) ) # Length of format data as listed above
# FMT DATA
wavfile.write( struct.pack('H', 1 ) ) # Type of format (1 is PCM) - 2 byte integer
wavfile.write( struct.pack('H', channels ) ) # Number of Channels - 2 byte integer
wavfile.write( struct.pack('I', sample_rate ) ) # Sample Rate - 32 byte integer. Common values are 44100 (CD), 48000 (DAT). Sample Rate = Number of Samples per second, or Hertz
wavfile.write( struct.pack('I', int(sample_rate * bits_per_sample * channels / 8) ) ) # (Sample Rate * BitsPerSample * Channels) / 8
wavfile.write( struct.pack('H', 4 ) ) # 0: (BitsPerSample * Channels) / 8
# 1: 8 bit mono2
# 2: 8 bit stereo
# 3: 16 bit mono
# 4: 16 bit stereo
wavfile.write( struct.pack('H', bits_per_sample ) ) # Bits per sample
# DATA HEADER
wavfile.write( 'data'.encode() ) # “data” chunk header. Marks the beginning of the data section
wavfile.write( struct.pack('I', data_size ) ) # Size of the data section
# // WAV DATA
wavfile.write( binfile.read() )

View File

@ -198,7 +198,7 @@ extern double mhz;
#define DEF_VIDEO_DIV 1U
#define DEF_SPKR_DIV 1U
#define GAME_FPS 480U // 480U
#define GAME_FPS 180U // 480U
#define GAME_VIDEO_DIV (GAME_FPS / 60U)
extern unsigned int video_fps_divider;

View File

@ -70,9 +70,6 @@ ALCcontext *ctx = NULL;
int spkr_att = 0;
int spkr_level = SPKR_LEVEL_ZERO;
int spkr_level_ema = SPKR_LEVEL_ZERO;
int spkr_level_dema = SPKR_LEVEL_ZERO;
int spkr_level_tema = SPKR_LEVEL_ZERO;
int spkr_level_qema = SPKR_LEVEL_ZERO;
int spkr_last_level = SPKR_LEVEL_ZERO;
#define BUFFER_COUNT 256
@ -173,17 +170,41 @@ void spkr_load_sfx( const char * bundlePath ) {
diskioerr_sfx_len = load_sfx(bundlePath, "disk_ii_io_error.sfx", &diskioerr_sfx);
}
#define NO_SPKR_KEEP_PITCH
#define NO_SPKR_DEBUG
#ifdef SPKR_DEBUG
static const char * spkr_debug_filename = "steve2_audio_debug.bin";
FILE * spkr_debug_file = NULL;
#endif
void spkr_fade(float fadeLevel, unsigned idx) {
// Fade
while ( ( fadeLevel < -1 ) || ( fadeLevel > 1 ) ) {
spkr_samples[ idx++ ] = SPKR_LEVEL_ZERO + fadeLevel;
spkr_samples[ idx++ ] = SPKR_LEVEL_ZERO + fadeLevel; // stereo
// how smooth we want the speeker to decay, so we will hear no pops and crackles
fadeLevel *= 0.999;
}
// Fill with Zero to avoid pops
memset(spkr_samples + idx * sizeof(spkr_sample_t), 0, spkr_buf_size * sizeof(spkr_sample_t) * SPKR_CHANNELS);
}
FILE * af = NULL;
// initialize OpenAL
void spkr_init() {
const char *defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
printf( "Default device: %s\n", defname );
// // DEBUG ONLY!!!
// af = fopen("steve2_audio_debug.bin", "w+");
// DEBUG ONLY!!!
#ifdef SPKR_DEBUG
spkr_debug_file = fopen(spkr_debug_filename, "w+");
#endif
// restart OpenAL when restarting the virtual machine
spkr_exit();
@ -194,40 +215,16 @@ void spkr_init() {
// Fill buffer with zeros
memset( spkr_samples, 0, spkr_buf_alloc_size + spkr_extra_buf * sizeof(spkr_sample_t));
float fadeLevel = SPKR_LEVEL_MAX;
spkr_sample_idx = spkr_buf_size * (BUFFER_COUNT - 2);
while ( ( fadeLevel < -1 ) || ( fadeLevel > 1 ) ) {
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel;
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel; // stereo
// how smooth we want the speeker to decay, so we will hear no pops and crackles
fadeLevel *= 0.999;
}
fadeLevel = SPKR_LEVEL_MIN;
spkr_sample_idx = spkr_buf_size * (BUFFER_COUNT - 1);
while ( ( fadeLevel < -1 ) || ( fadeLevel > 1 ) ) {
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel;
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel; // stereo
// how smooth we want the speeker to decay, so we will hear no pops and crackles
fadeLevel *= 0.999;
}
//spkr_samples[sample_idx] = spkr_level;
// memset(spkr_samples + spkr_sample_idx, 0, spkr_extra_buf * sizeof(spkr_sample_t));
memset(spkr_samples + spkr_sample_idx, 0, (sample_buf_array_len - spkr_sample_idx) * sizeof(spkr_sample_t));
// memset(spkr_samples + spkr_sample_idx * sizeof(spkr_sample_t), 0, (sample_buf_array_len - spkr_sample_idx) * sizeof(spkr_sample_t));
freeBuffers--;
// // DEBUG ONLY!!!
// fwrite(spkr_samples, sizeof(spkr_sample_t), spkr_sample_idx, af);
// fflush(af);
// DEBUG ONLY!!!
#ifdef SPKR_DEBUG
fwrite(spkr_samples, sizeof(spkr_sample_t), spkr_sample_idx, spkr_debug_file);
fflush(spkr_debug_file);
#endif
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, spkr_sample_idx * sizeof(spkr_sample_t), spkr_sample_rate);
al_check_error();
alSourceQueueBuffers(spkr_src[SPKR_SRC_GAME_SFX], 1, &spkr_buffers[freeBuffers]);
@ -418,86 +415,18 @@ INLINE int ema( int val, int prev, float ema_len ) {
}
void spkr_toggle_edge ( int level_max, const float initial_edge, const float fade_edge, const unsigned idx_diff ) {
// float dumping = spkr_level - level_max;
// dumping *= initial_edge;
// float ema_len = 21;
int ema_len = 7; // 8;
int ema_len_smooth = 8;
unsigned threshold = SPKR_SAMPLE_PWM_THRESHOLD;
unsigned limiter = 150;
switch ((int)(MHz_6502 * 10)) {
case 02:
case 05:
ema_len = 8;
ema_len_smooth = 8;
threshold = SPKR_SAMPLE_PWM_THRESHOLD * 2;
limiter = 10;
break;
case 15:
ema_len = 5;
ema_len_smooth = 7;
threshold = SPKR_SAMPLE_PWM_THRESHOLD / 1.5;
limiter = 128;
break;
case 20:
case 28:
ema_len = 4;
ema_len_smooth = 6;
threshold = SPKR_SAMPLE_PWM_THRESHOLD / 2;
limiter = 128;
break;
case 40:
ema_len = 3;
ema_len_smooth = 5;
threshold = SPKR_SAMPLE_PWM_THRESHOLD / 4;
limiter = 1024;
break;
default:
break;
void spkr_toggle_square ( int level_max, const unsigned idx_diff ) {
// finish the aquare wave
while ( spkr_sample_last_idx < spkr_sample_idx ) {
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level;
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level; // stereo
}
// save last index before we advance it...
spkr_sample_last_idx = spkr_sample_idx;
// start a new speaker level -- it might not be necessary, but...
spkr_samples[ spkr_sample_idx++ ] = level_max;
spkr_samples[ spkr_sample_idx++ ] = level_max; // stereo
spkr_level = spkr_samples[ spkr_sample_idx ];
spkr_level_ema = spkr_level;
spkr_level_dema = spkr_level;
spkr_level_tema = spkr_level;
spkr_level_qema = spkr_level;
if ( idx_diff < threshold ) {
ema_len = ema_len_smooth;
if ( --spkr_att < 0 ) {
level_max = SPKR_LEVEL_ZERO;
}
}
else {
spkr_att = 1024;
}
for ( int i = 0; (i < spkr_buf_size * 2) && (abs(spkr_level - level_max) > limiter); i++ ) {
spkr_level_ema = ema(level_max, spkr_level_ema, ema_len);
spkr_level_dema = ema(spkr_level_ema, spkr_level_dema, ema_len);
spkr_level_tema = ema(spkr_level_dema, spkr_level_tema, ema_len);
spkr_level_qema = ema(spkr_level_tema, spkr_level_qema, ema_len);
spkr_level = spkr_level_ema;
spkr_samples[ spkr_sample_idx++ ] = spkr_level_qema;
spkr_samples[ spkr_sample_idx++ ] = spkr_level_qema; // stereo
}
spkr_last_level = spkr_level;
spkr_level = level_max;
}
@ -527,10 +456,6 @@ float SPKR_INITIAL_TRAILING_EDGE = 0.64; // need a bit of slope to get Xonix so
void spkr_toggle() {
// TODO: This is very slow!
// spkr_play_time = 0;
if ( diskAccelerator_count ) {
// turn off disk acceleration immediately
diskAccelerator_count = 0;
@ -543,49 +468,42 @@ void spkr_toggle() {
// push a click into the speaker buffer
// (we will play the entire buffer at the end of the frame)
double indexer = (double)spkr_sample_rate / MHZ(MHz_6502);
double multiplier = (double)spkr_sample_rate / MHZ(MHz_6502);
#ifdef SPKR_KEEP_PITCH
if ( MHz_6502 < default_MHz_6502 ) {
indexer = (double)spkr_sample_rate / MHZ(default_MHz_6502);
multiplier = (double)spkr_sample_rate / MHZ(default_MHz_6502);
// indexer = (double)spkr_sample_rate / MHZ(default_MHz_6502) * MHz_6502;
}
#endif
spkr_sample_idx = round( (double)(spkr_clk + m6502.clkfrm) * indexer ) * SPKR_CHANNELS;
spkr_sample_idx = round( (double)(spkr_clk + m6502.clkfrm) * multiplier ) * SPKR_CHANNELS;
spkr_sample_idx &= UINTMAX_MAX - 1;
unsigned spkr_sample_idx_diff = spkr_sample_idx - spkr_sample_last_idx;
// if ( (int)spkr_sample_idx_diff == 0 ) {
// // printf("m:%u\n", spkr_sample_idx_diff);
// spkr_sample_idx_diff = UINT_MAX - spkr_sample_idx_diff;
// }
if ( (int)spkr_sample_idx_diff < 0 ) {
// printf("m:%u\n", spkr_sample_idx_diff);
spkr_sample_idx_diff = UINT_MAX - spkr_sample_idx_diff;
}
spkr_level = spkr_samples[ spkr_sample_idx ];
if ( spkr_state ) {
// down edge
spkr_state = 0;
spkr_toggle_edge(SPKR_LEVEL_MIN, SPKR_INITIAL_TRAILING_EDGE, SPKR_FADE_TRAILING_EDGE, spkr_sample_idx_diff);
// spkr_toggle_tick(SPKR_LEVEL_MIN, spkr_sample_idx_diff);
spkr_toggle_square(SPKR_LEVEL_MIN, spkr_sample_idx_diff);
}
else {
// up edge
spkr_state = 1;
spkr_toggle_edge(SPKR_LEVEL_MAX, SPKR_INITIAL_LEADING_EDGE, SPKR_FADE_LEADING_EDGE, spkr_sample_idx_diff);
// spkr_toggle_tick(SPKR_LEVEL_MAX, spkr_sample_idx_diff);
spkr_toggle_square(SPKR_LEVEL_MAX, spkr_sample_idx_diff);
}
//spkr_samples[sample_idx] = spkr_level;
for ( int i = spkr_sample_idx; i < spkr_buf_size + spkr_extra_buf; i++ ) {
spkr_samples[i] = spkr_level;
}
// memset(spkr_samples + spkr_sample_idx, spkr_level, spkr_buf_size * sizeof(spkr_sample_t));
}
}
@ -608,6 +526,13 @@ void spkr_update() {
if ( ( spkr_play_time ) && ( queued < SPKR_MAX_QUEUED ) ) {
if ( freeBuffers ) {
double multiplier = 1;
#ifdef SPKR_KEEP_PITCH
if (MHz_6502 > default_MHz_6502 ) {
multiplier = 1 / MHz_6502;
}
#endif
// in Game Mode do not fade out and stop playing
if ( /*( cpuMode_game != cpuMode ) && */( --spkr_play_time == 0 ) ) {
@ -615,84 +540,98 @@ void spkr_update() {
printf("freeBuffer < 0 (%i)\n", freeBuffers);
freeBuffers = 0;
}
// Need to Cool Down Speaker -- Soft Fade to Zero
else {
if ( spkr_samples[0] > 0 ) {
spkr_fade(spkr_level, 0);
#ifdef SPKR_DEBUG
fwrite(spkr_samples, sizeof(spkr_sample_t), spkr_buf_size, spkr_debug_file);
fflush(spkr_debug_file);
#endif
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, spkr_buf_size * sizeof(spkr_sample_t), spkr_sample_rate);
al_check_error();
// // DEBUG ONLY!!!
// fwrite(spkr_samples + spkr_buf_size * (BUFFER_COUNT - 2), sizeof(spkr_sample_t), spkr_buf_size, af);
// fflush(af);
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples + spkr_buf_size * (BUFFER_COUNT - 2), spkr_buf_size * sizeof(spkr_sample_t), spkr_sample_rate);
al_check_error();
}
else {
// fwrite(spkr_samples + spkr_buf_size * (BUFFER_COUNT - 1), sizeof(spkr_sample_t), spkr_buf_size, af);
// fflush(af);
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples + spkr_buf_size * (BUFFER_COUNT - 1), spkr_buf_size * sizeof(spkr_sample_t), spkr_sample_rate);
al_check_error();
}
alSourceQueueBuffers(spkr_src[SPKR_SRC_GAME_SFX], 1, &spkr_buffers[freeBuffers]);
al_check_error();
}
memset(spkr_samples, 0, spkr_buf_size * 2 * sizeof(spkr_sample_t));
memset(spkr_samples, 0, sample_buf_array_len * sizeof(spkr_sample_t)); // spkr_buf_size * sizeof(spkr_sample_t) * SPKR_CHANNELS);
spkr_sample_idx = 0;
spkr_sample_last_idx = 0;
spkr_level = SPKR_LEVEL_ZERO;
spkr_last_level = SPKR_LEVEL_ZERO;
spkr_level_ema = SPKR_LEVEL_ZERO;
// spkr_last_level = SPKR_LEVEL_ZERO;
}
else {
// push a click into the speaker buffer
// (we will play the entire buffer at the end of the frame)
// spkr_sample_idx = ( (spkr_clk + m6502.clkfrm) / ( MHZ(default_MHz_6502) / spkr_sample_rate)) * SPKR_CHANNELS;
// // DEBUG spike
// spkr_sample_idx = 0;
// spkr_samples[ spkr_sample_idx++ ] = -28000;
// spkr_samples[ spkr_sample_idx++ ] = 28000; // stereo
// spkr_samples[ spkr_sample_idx++ ] = -28000;
// spkr_samples[ spkr_sample_idx++ ] = 28000; // stereo
// spkr_samples[ spkr_sample_idx++ ] = spkr_level;
// spkr_samples[ spkr_sample_idx++ ] = spkr_level; // stereo
// //spkr_samples[sample_idx] = spkr_level;
// memset(spkr_samples + spkr_sample_idx, spkr_level, spkr_buf_alloc_size * DEFAULT_FPS - spkr_sample_idx);
// push a click into the speaker buffer
// (we will play the entire buffer at the end of the frame)
// spkr_sample_idx = ( (spkr_clk + m6502.clkfrm) / ( MHZ(default_MHz_6502) / spkr_sample_rate)) * SPKR_CHANNELS;
// // DEBUG spike
// spkr_sample_idx = 0;
// spkr_samples[ spkr_sample_idx++ ] = -28000;
// spkr_samples[ spkr_sample_idx++ ] = 28000; // stereo
// spkr_samples[ spkr_sample_idx++ ] = -28000;
// spkr_samples[ spkr_sample_idx++ ] = 28000; // stereo
// spkr_samples[ spkr_sample_idx++ ] = spkr_level;
// spkr_samples[ spkr_sample_idx++ ] = spkr_level; // stereo
// //spkr_samples[sample_idx] = spkr_level;
// memset(spkr_samples + spkr_sample_idx, spkr_level, spkr_buf_alloc_size * DEFAULT_FPS - spkr_sample_idx);
if (--freeBuffers < 0) {
printf("freeBuffer < 0 (%i)\n", freeBuffers);
freeBuffers = 0;
}
// Normal Sound Buffer Feed
else {
// finish the aquare wave
while ( spkr_sample_last_idx < spkr_buf_size ) {
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level;
spkr_samples[ spkr_sample_last_idx++ ] = spkr_level; // stereo
}
// // DEBUG ONLY!!!
// fwrite(spkr_samples, sizeof(spkr_sample_t), (spkr_buf_size + spkr_extra_buf), af);
// fflush(af);
// if (MHz_6502 < default_MHz_6502) {
// size_t size = (spkr_buf_size + spkr_extra_buf) * sizeof(spkr_sample_t);
// memcpy(spkr_samples + size, spkr_samples, size);
// }
// if (MHz_6502 < default_MHz_6502 / 2) {
// size_t size = (spkr_buf_size + spkr_extra_buf) * sizeof(spkr_sample_t) * 2;
// memcpy(spkr_samples + size, spkr_samples, size);
// }
int buf_len = round((double)spkr_buf_size * multiplier + spkr_extra_buf) * sizeof(spkr_sample_t);
#ifdef SPKR_DEBUG // Debug SPKR Buffer Before EMA
#ifdef SPKR_DEBUG_BEFORE_EMA
fwrite(spkr_samples, 1, buf_len, spkr_debug_file);
fflush(spkr_debug_file);
#endif
#endif
double multiplier = default_MHz_6502 / MHz_6502;
if (MHz_6502 < default_MHz_6502 ) {
multiplier = MHz_6502;
static const int ema_len = 30; // soft: 70;
int i = 0;
while ( i <= spkr_buf_size ) {
spkr_level_ema = ema(spkr_samples[i], spkr_level_ema, ema_len);
// super smooth Quadratic EMA
spkr_samples[i++] = spkr_level_ema;
spkr_samples[i++] = spkr_level_ema;
}
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, (spkr_buf_size * multiplier + spkr_extra_buf) * sizeof(spkr_sample_t), spkr_sample_rate * multiplier);
// alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, (spkr_buf_size + spkr_extra_buf) * sizeof(spkr_sample_t), spkr_sample_rate);
#ifdef SPKR_DEBUG // Debug SPKR Buffer After EMA
#ifdef SPKR_DEBUG_AFTER_EMA
fwrite(spkr_samples, 1, buf_len, spkr_debug_file);
fflush(spkr_debug_file);
#endif
#endif
// alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, (spkr_sample_idx + spkr_extra_buf) * sizeof(spkr_sample_t), spkr_sample_rate);
// ALint bufSize = spkr_sample_idx + 20 < spkr_buf_size ? spkr_sample_idx * sizeof(spkr_sample_t) + 20 : spkr_buf_alloc_size;
// alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, bufSize + spkr_extra_buf, spkr_sample_rate);
alBufferData(spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, spkr_samples, buf_len, spkr_sample_rate * multiplier);
al_check_error();
alSourceQueueBuffers(spkr_src[SPKR_SRC_GAME_SFX], 1, &spkr_buffers[freeBuffers]);
al_check_error();
@ -701,7 +640,7 @@ void spkr_update() {
ALenum state;
alGetSourcei( spkr_src[SPKR_SRC_GAME_SFX], AL_SOURCE_STATE, &state );
// al_check_error();
// al_check_error();
switch (state) {
case AL_PAUSED:
@ -726,56 +665,34 @@ void spkr_update() {
break;
}
int size = spkr_buf_size + spkr_extra_buf;
int src = size;
int dst = 0;
// int dst = 0;
int src = spkr_buf_size * multiplier + spkr_extra_buf;
int size = max(0, (int)spkr_sample_idx - src);
// copy the buffer leftover -- needed to finish wave form
while( src < spkr_sample_idx ) {
spkr_samples[dst++] = spkr_samples[src++];
if (size) {
memcpy(spkr_samples, spkr_samples + src * sizeof(spkr_sample_t), size * sizeof(spkr_sample_t) * SPKR_CHANNELS );
}
// clear the slack buffer, so we can fill it up by new data
while( dst < size ) {
spkr_samples[dst++] = spkr_level;
}
// float fadeLevel = spkr_level - SPKR_LEVEL_ZERO;
// while ( ( fadeLevel < -1 ) || ( fadeLevel > 1 ) ) {
// spkr_samples[ dst++ ] = SPKR_LEVEL_ZERO + fadeLevel;
// spkr_samples[ dst++ ] = SPKR_LEVEL_ZERO + fadeLevel; // stereo
//
// // how smooth we want the speeker to decay, so we will hear no pops and crackles
// fadeLevel *= 0.999;
memset(spkr_samples + size, 0, spkr_buf_size * sizeof(spkr_sample_t));
// if ( spkr_sample_idx >= size ) {
// spkr_sample_idx -= size;
// }
// else {
spkr_sample_idx = 0;
// }
// memcpy( spkr_samples + dst, spkr_samples + src, size * sizeof(spkr_sample_t) * 2 );
// TODO: Problems on Wavy Navy
// if ( ( spkr_sample_idx >= size ) && ( spkr_level == SPKR_LEVEL_ZERO ) ) {
if ( spkr_sample_idx >= size ) {
spkr_sample_idx -= size;
}
else {
spkr_sample_idx = 0;
}
spkr_sample_last_idx = spkr_sample_idx;
// spkr_samples[0] = 10000;
spkr_sample_last_idx = 0;
}
else {
printf("No FreeBuffers!\n");
printf("Warning: No FreeBuffers!\n");
}
// start from the beginning
// spkr_sample_idx = 0;
}
// else {
// printf("spkr_play_time: %u, queued: %i\n", spkr_play_time, queued);
// }
// else {
// printf("spkr_play_time: %u, queued: %i\n", spkr_play_time, queued);
// }
spkr_clk = 0;
@ -790,15 +707,9 @@ void spkr_update() {
void spkr_playqueue_sfx( ALuint src, uint8_t * sfx, int len ) {
// printf("%s freeBuffers:%d\n", __FUNCTION__, freeBuffers);
if ( freeBuffers ) {
ALenum queued;
alGetSourcei( src, AL_BUFFERS_QUEUED, &queued );
// printf("Q:%u\n", queued);
// printf("%s queued:%d\n", __FUNCTION__, queued);
if ( queued < 16 ) {
if (--freeBuffers < 0) {
@ -814,7 +725,7 @@ void spkr_playqueue_sfx( ALuint src, uint8_t * sfx, int len ) {
ALenum state;
alGetSourcei( src, AL_SOURCE_STATE, &state );
// al_check_error();
// al_check_error();
switch (state) {
case AL_PLAYING:
@ -831,13 +742,10 @@ void spkr_playqueue_sfx( ALuint src, uint8_t * sfx, int len ) {
void spkr_play_sfx( ALuint src, uint8_t * sfx, int len ) {
// printf("%s freeBuffers:%d\n", __FUNCTION__, freeBuffers);
if ( freeBuffers ) {
ALenum state;
alGetSourcei( src, AL_SOURCE_STATE, &state );
// al_check_error();
// al_check_error();
switch (state) {
case AL_PAUSED: