diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 1cc7416..e160778 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -18,8 +18,6 @@ 32440B64247C9C9C000F9DA1 /* merlin_assembler_1.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B61247C9C2D000F9DA1 /* merlin_assembler_1.woz */; }; 32440B65247C9C9C000F9DA1 /* merlin_assembler_2.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B62247C9C2D000F9DA1 /* merlin_assembler_2.woz */; }; 32440B66247C9C9C000F9DA1 /* merlin_assembler_3.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B63247C9C2D000F9DA1 /* merlin_assembler_3.woz */; }; - 32440B6A247CA1CE000F9DA1 /* 65C02.c in Sources */ = {isa = PBXBuildFile; fileRef = 32440B69247CA1CE000F9DA1 /* 65C02.c */; }; - 32440B6B247CA1E0000F9DA1 /* 65C02.c in Sources */ = {isa = PBXBuildFile; fileRef = 32440B69247CA1CE000F9DA1 /* 65C02.c */; }; 32440B75247CAA00000F9DA1 /* Merlin Pro v2.23 DOS3.3 (The Yegg-Men Crack).woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B72247CAA00000F9DA1 /* Merlin Pro v2.23 DOS3.3 (The Yegg-Men Crack).woz */; }; 32440B76247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 1-2.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B73247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 1-2.woz */; }; 32440B77247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 2-2.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B74247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 2-2.woz */; }; @@ -29,6 +27,8 @@ 32440B80247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side A.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B7E247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side A.woz */; }; 32440B81247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side B.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B7F247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side B.woz */; }; 32440B83247CC4C0000F9DA1 /* Wavy Navy (4am crack).woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B82247CC4C0000F9DA1 /* Wavy Navy (4am crack).woz */; }; + 32440B84247E27D3000F9DA1 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; }; + 32440B85247E27D7000F9DA1 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; }; 325EB62F23F8856F00C6B4A4 /* woz.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB62E23F8856F00C6B4A4 /* woz.c */; }; 325EB63623F8F78300C6B4A4 /* disk.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB63523F8F78300C6B4A4 /* disk.c */; }; 325EB63923F9E48100C6B4A4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB63823F9E48100C6B4A4 /* common.c */; }; @@ -891,7 +891,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32440B6B247CA1E0000F9DA1 /* 65C02.c in Sources */, + 32440B85247E27D7000F9DA1 /* 6502.c in Sources */, 325EB67623FBC44400C6B4A4 /* common.c in Sources */, 32A9F74B2467B60B004902A1 /* speaker.c in Sources */, 325EB67823FBC45300C6B4A4 /* disk.c in Sources */, @@ -923,13 +923,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32440B6A247CA1CE000F9DA1 /* 65C02.c in Sources */, 325EB63623F8F78300C6B4A4 /* disk.c in Sources */, 325EB63923F9E48100C6B4A4 /* common.c in Sources */, 32A9F74A2467B60B004902A1 /* speaker.c in Sources */, 32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */, 325EB69323FE6C6200C6B4A4 /* HiRes.swift in Sources */, 32C4532E233345430000EBA1 /* MonitorView.swift in Sources */, + 32440B84247E27D3000F9DA1 /* 6502.c in Sources */, 325EB62F23F8856F00C6B4A4 /* woz.c in Sources */, 32BFFB5B22EACC630003B53F /* AppDelegate.swift in Sources */, 32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */, diff --git a/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist b/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist index cb63d44..990f74d 100644 --- a/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist +++ b/A2Mac.xcodeproj/project.xcworkspace/xcuserdata/trudnai.xcuserdatad/xcdebugger/Expressions.xcexplist @@ -153,6 +153,14 @@ + + + + + + @@ -574,6 +582,12 @@ + + + + + + + + + + + + diff --git a/src/cpu/6502.c b/src/cpu/6502.c index cdc5381..b20dea5 100644 --- a/src/cpu/6502.c +++ b/src/cpu/6502.c @@ -40,6 +40,7 @@ const unsigned long long startup_MHz_6502 = 32 * M; unsigned long long MHz_6502 = default_MHz_6502; unsigned long long clk_6502_per_frm = default_MHz_6502 / fps; unsigned long long clk_6502_per_frm_set = default_MHz_6502 / fps; +unsigned long long clk_6502_per_frm_max_sound = 4 * default_MHz_6502 / fps; unsigned long long clk_6502_per_frm_max = 0; @@ -729,6 +730,8 @@ void m6502_Run() { for ( ; ; ) #endif { + + printDisassembly(outdev); #ifdef INTERRUPT_CHECK_PER_STEP if ( m6502.IF ) { diff --git a/src/cpu/6502.h b/src/cpu/6502.h index ecd1396..34d0761 100644 --- a/src/cpu/6502.h +++ b/src/cpu/6502.h @@ -19,6 +19,7 @@ extern unsigned long long MHz_6502; extern unsigned long long clk_6502_per_frm; extern unsigned long long clk_6502_per_frm_set; extern unsigned long long clk_6502_per_frm_max; +extern unsigned long long clk_6502_per_frm_max_sound; extern unsigned int clkfrm; diff --git a/src/dev/audio/speaker.c b/src/dev/audio/speaker.c index 5795d98..3461cd8 100644 --- a/src/dev/audio/speaker.c +++ b/src/dev/audio/speaker.c @@ -140,56 +140,60 @@ char spkr_state = 0; void spkr_toggle() { // TODO: This is very slow! - // printf("io_KBDSTRB\n"); - spkr_play_time = spkr_play_timeout; + spkr_play_time = 0; - // push a click into the speaker buffer - // (we will play the entire buffer at the end of the frame) - spkr_sample_idx = (clkfrm / (default_MHz_6502 / spkr_sample_rate)) * 2; - - if ( spkr_state ) { - // down edge - spkr_state = 0; + if ( clk_6502_per_frm_set < clk_6502_per_frm_max_sound ) { - float fadeLevel = spkr_level - SPKR_LEVEL_MIN; + spkr_play_time = spkr_play_timeout; - while ( fadeLevel > +1 ) { - spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel; - spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel; + // push a click into the speaker buffer + // (we will play the entire buffer at the end of the frame) + spkr_sample_idx = (clkfrm / (default_MHz_6502 / spkr_sample_rate)) * 2; + + if ( spkr_state ) { + // down edge + spkr_state = 0; - // how smooth we want the speeker to decay, so we will hear no pops and crackles - // 0.9 gives you a kind of saw wave at 1KHz (beep) - // 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same - fadeLevel *= 0.16; - } - spkr_level = SPKR_LEVEL_MIN; - } - else { - // up edge - spkr_state = 1; - - float fadeLevel = spkr_level - SPKR_LEVEL_MAX; - - while ( fadeLevel < -1 ) { - spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel; - spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel; + float fadeLevel = spkr_level - SPKR_LEVEL_MIN; - // how smooth we want the speeker to decay, so we will hear no pops and crackles - // 0.9 gives you a kind of saw wave at 1KHz (beep) - // 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same - fadeLevel *= 0.32; + while ( fadeLevel > +1 ) { + spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel; + spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel; + + // how smooth we want the speeker to decay, so we will hear no pops and crackles + // 0.9 gives you a kind of saw wave at 1KHz (beep) + // 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same + fadeLevel *= 0.16; + } + spkr_level = SPKR_LEVEL_MIN; + } + else { + // up edge + spkr_state = 1; + + float fadeLevel = spkr_level - SPKR_LEVEL_MAX; + + while ( fadeLevel < -1 ) { + spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel; + spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel; + + // how smooth we want the speeker to decay, so we will hear no pops and crackles + // 0.9 gives you a kind of saw wave at 1KHz (beep) + // 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same + fadeLevel *= 0.32; + } + spkr_level = SPKR_LEVEL_MAX; } - spkr_level = SPKR_LEVEL_MAX; - } - - //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; + + //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_samples[0])); + } -// memset(spkr_samples + spkr_sample_idx, spkr_level, spkr_buf_size * sizeof(spkr_samples[0])); - } diff --git a/src/dev/mem/mmio.h b/src/dev/mem/mmio.h index 4535ae9..5005044 100644 --- a/src/dev/mem/mmio.h +++ b/src/dev/mem/mmio.h @@ -43,10 +43,11 @@ uint8_t * const AUX = Apple2_64K_AUX; // Pointer to the Auxiliary Memo uint8_t * const RAM = Apple2_64K_RAM; // Pointer to the Main Memory so we can use this from Swift uint8_t * const MEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift -uint8_t * const RDLOMEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift -uint8_t * const WRLOMEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift -uint8_t * const RDHIMEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift -uint8_t * const WRHIMEM = Apple2_Dummy_RAM; // Pointer to the Shadow Memory Map so we can use this from Swift +uint8_t * const RDLOMEM = Apple2_64K_MEM; // for Read $0000 - $BFFF (shadow memory) +uint8_t * const WRLOMEM = Apple2_64K_MEM; // for Write $0000 - $BFFF (shadow memory) +uint8_t * const RDHIMEM = Apple2_64K_MEM; // for Read / Write $0000 - $BFFF (shadow memory) +uint8_t * WRD0MEM = Apple2_Dummy_RAM; // for writing $D000 - $DFFF +uint8_t * WRHIMEM = Apple2_Dummy_RAM; // for writing $E000 - $FFFF #define DEF_RAM_PAGE(mem,pg) \ @@ -281,14 +282,26 @@ enum mmio { io_RDALTZP = 0xC016, // ECG R7 Status of Main/Aux Stack and Zero Page io_RDC3ROM = 0xC017, // E G R7 Status of Slot 3/Aux Slot ROM io_RSTYINT = 0xC017, // C R Reset Mouse Y0 Interrupt + io_MEM_RDRAM_NOWR_2 = 0xC080, io_MEM_RDROM_WRAM_2 = 0xC081, io_MEM_RDROM_NOWR_2 = 0xC082, io_MEM_RDRAM_WRAM_2 = 0xC083, + + io_MEM_RDRAM_NOWR_2_ = 0xC084, + io_MEM_RDROM_WRAM_2_ = 0xC085, + io_MEM_RDROM_NOWR_2_ = 0xC086, + io_MEM_RDRAM_WRAM_2_ = 0xC087, + io_MEM_RDRAM_NOWR_1 = 0xC088, io_MEM_RDROM_WRAM_1 = 0xC089, io_MEM_RDROM_NOWR_1 = 0xC08A, io_MEM_RDRAM_WRAM_1 = 0xC08B, + + io_MEM_RDRAM_NOWR_1_ = 0xC08C, + io_MEM_RDROM_WRAM_1_ = 0xC08D, + io_MEM_RDROM_NOWR_1_ = 0xC08E, + io_MEM_RDRAM_WRAM_1_ = 0xC08F, }; @@ -397,6 +410,9 @@ void auxMemorySelect() { } +uint8_t * current_RAM_bank = Apple2_64K_AUX + 0xC000; + + INLINE uint8_t ioRead( uint16_t addr ) { // if (outdev) fprintf(outdev, "ioRead:%04X\n", addr); // printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC); @@ -499,24 +515,53 @@ INLINE uint8_t ioRead( uint16_t addr ) { case (uint8_t)io_MEM_RDROM_WRAM_2: case (uint8_t)io_MEM_RDROM_NOWR_2: case (uint8_t)io_MEM_RDRAM_WRAM_2: + + case (uint8_t)io_MEM_RDRAM_NOWR_2_: + case (uint8_t)io_MEM_RDROM_WRAM_2_: + case (uint8_t)io_MEM_RDROM_NOWR_2_: + case (uint8_t)io_MEM_RDRAM_WRAM_2_: + case (uint8_t)io_MEM_RDRAM_NOWR_1: case (uint8_t)io_MEM_RDROM_WRAM_1: case (uint8_t)io_MEM_RDROM_NOWR_1: case (uint8_t)io_MEM_RDRAM_WRAM_1: + + case (uint8_t)io_MEM_RDRAM_NOWR_1_: + case (uint8_t)io_MEM_RDROM_WRAM_1_: + case (uint8_t)io_MEM_RDROM_NOWR_1_: + case (uint8_t)io_MEM_RDRAM_WRAM_1_: + if ( MEMcfg.RAM_16K || MEMcfg.RAM_128K ) { uint8_t * RAM_BANK = Apple2_64K_AUX + 0xC000; + // save the content of Shadow Memory in needed + if ( MEMcfg.WR_RAM ) { +// printf("Saving RAM Bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank); + memcpy(current_RAM_bank, Apple2_64K_MEM + 0xD000, 0x1000); + memcpy(Apple2_64K_AUX + 0xE000, Apple2_64K_MEM + 0xE000, 0x2000); + } + // RAM Bank 1 or 2? switch ((uint8_t)addr) { case (uint8_t)io_MEM_RDRAM_NOWR_2: case (uint8_t)io_MEM_RDROM_WRAM_2: case (uint8_t)io_MEM_RDROM_NOWR_2: case (uint8_t)io_MEM_RDRAM_WRAM_2: + + case (uint8_t)io_MEM_RDRAM_NOWR_2_: + case (uint8_t)io_MEM_RDROM_WRAM_2_: + case (uint8_t)io_MEM_RDROM_NOWR_2_: + case (uint8_t)io_MEM_RDRAM_WRAM_2_: + +// printf("RAM_BANK_2\n"); + MEMcfg.RAM_BANK_2 = 1; RAM_BANK = Apple2_64K_AUX + 0xD000; break; default: +// printf("RAM_BANK_1\n"); + MEMcfg.RAM_BANK_2 = 0; RAM_BANK = Apple2_64K_AUX + 0xC000; break; @@ -528,23 +573,28 @@ INLINE uint8_t ioRead( uint16_t addr ) { case (uint8_t)io_MEM_RDRAM_WRAM_2: case (uint8_t)io_MEM_RDRAM_NOWR_1: case (uint8_t)io_MEM_RDRAM_WRAM_1: + + case (uint8_t)io_MEM_RDRAM_NOWR_2_: + case (uint8_t)io_MEM_RDRAM_WRAM_2_: + case (uint8_t)io_MEM_RDRAM_NOWR_1_: + case (uint8_t)io_MEM_RDRAM_WRAM_1_: + +// printf("RD_RAM\n"); + MEMcfg.RD_RAM = 1; - uint8_t * shadow = Apple2_64K_MEM + 0xD000; - // save the content of Shadow Memory - memcpy(Apple2_64K_RAM + 0xD000, shadow, 0x3000); // load the content of Aux Memory - memcpy(Apple2_64K_MEM + 0xD000, Apple2_64K_AUX, 0x3000); + memcpy(Apple2_64K_MEM + 0xD000, RAM_BANK, 0x1000); + memcpy(Apple2_64K_MEM + 0xE000, Apple2_64K_AUX + 0xE000, 0x2000); // set the RAM extension to read on the upper memory area break; default: +// printf("RD_ROM\n"); + MEMcfg.RD_RAM = 0; - shadow = Apple2_64K_MEM + 0xD000; - // save the content of Shadow Memory - memcpy(Apple2_64K_AUX + 0xD000, shadow, 0x3000); // load the content of ROM Memory memcpy(Apple2_64K_MEM + 0xD000, Apple2_16K_ROM + 0x1000, 0x3000); @@ -555,19 +605,52 @@ INLINE uint8_t ioRead( uint16_t addr ) { // is RAM Writeable? switch ((uint8_t)addr) { case (uint8_t)io_MEM_RDROM_WRAM_2: - case (uint8_t)io_MEM_RDRAM_WRAM_2: case (uint8_t)io_MEM_RDROM_WRAM_1: + + case (uint8_t)io_MEM_RDROM_WRAM_2_: + case (uint8_t)io_MEM_RDROM_WRAM_1_: + +// printf("RD_ROM + WR_AUX\n"); + + // will write directly to Auxiliary RAM, and mark it as NO need to commit from Shadow RAM + MEMcfg.WR_RAM = 0; + if ( MEMcfg.RAM_BANK_2 ) { + WRD0MEM = Apple2_64K_AUX; // for Write $D000 - $DFFF (shadow memory) - BANK 2 + } + else { + WRD0MEM = Apple2_64K_AUX - 0x1000; // for Write $D000 - $DFFF (shadow memory) - BANK 1 + } + WRHIMEM = Apple2_64K_AUX; // for Write $E000 - $FFFF (shadow memory) + break; + + case (uint8_t)io_MEM_RDRAM_WRAM_2: case (uint8_t)io_MEM_RDRAM_WRAM_1: + + case (uint8_t)io_MEM_RDRAM_WRAM_2_: + case (uint8_t)io_MEM_RDRAM_WRAM_1_: + +// printf("RD_RAM + WR_RAM\n"); + + // will write to Shadow RAM, and mark it as need to commit from Shadow RAM MEMcfg.WR_RAM = 1; - // set the RAM extension to read from the upper memory area + WRD0MEM = Apple2_64K_MEM; // for Write $D000 - $DFFF (shadow memory) - BANK X + WRHIMEM = Apple2_64K_MEM; // for Write $E000 - $FFFF (shadow memory) break; default: +// printf("RD_ROM + NO_WR\n"); + + // No writing (Readonly), and mark it as NO need to commit from Shadow RAM MEMcfg.WR_RAM = 0; - // set the ROM to read on the upper memory area + WRD0MEM = Apple2_Dummy_RAM; // for Discarding any writes to $D000 - $DFFF - BANK X + WRHIMEM = Apple2_Dummy_RAM; // for Discarding any writes to $E000 - $FFFF break; } + current_RAM_bank = RAM_BANK; +// printf("Set current_RAM_bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank); + + } // if there is RAM expansion card installed break; @@ -869,6 +952,9 @@ INLINE uint8_t memread( uint16_t addr ) { INLINE void memwrite8_low( uint16_t addr, uint8_t data ) { WRLOMEM[addr] = data; } +INLINE void memwrite8_bank2( uint16_t addr, uint8_t data ) { + WRD0MEM[addr] = data; +} INLINE void memwrite8_high( uint16_t addr, uint8_t data ) { WRHIMEM[addr] = data; } @@ -877,11 +963,21 @@ INLINE void memwrite( uint16_t addr, uint8_t data ) { if (addr < 0xC100) { ioWrite(addr, data); } + else if (addr < 0xD000) { + // this could be either Peripherial ROM or Internal ROM + memwrite8_high(addr, data); + } + else if (addr < 0xE000) { + // Aux RAM Bank 1 or 2 + memwrite8_bank2(addr, data); + } else { - memwrite8_high(addr, data); + // ROM (dummy memory to screape writings) or Aux RAM + memwrite8_high(addr, data); } } else { + // RAM memwrite8_low(addr, data); } diff --git a/src/util/disassembler.h b/src/util/disassembler.h index 5f7fd2e..b60f0bb 100644 --- a/src/util/disassembler.h +++ b/src/util/disassembler.h @@ -91,7 +91,7 @@ INLINE void printDisassembly( FILE * f ) { fprintf( f, "%llu\t%llu %s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t;\t%s\n", // Virtual ][ style ++discnt, - m6502.clktime, + m6502.clktime + clkfrm, disassembly.addr, disassembly.opcode, disassembly.inst,