diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index b339d44..11925a1 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 32439F8722ECD8AD0077AAE0 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; }; 32439F8822ECD8AD0077AAE0 /* apple.rom in Resources */ = {isa = PBXBuildFile; fileRef = 32439F8422ECD8AD0077AAE0 /* apple.rom */; }; + 3262F37623E169F8008BDB95 /* spk_dn.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3262F37423E169F8008BDB95 /* spk_dn.wav */; }; + 3262F37723E169F8008BDB95 /* spk_up.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3262F37523E169F8008BDB95 /* spk_up.wav */; }; 326ED2EF232D7A0000A41337 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */; }; 32BFFB5B22EACC630003B53F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BFFB5A22EACC630003B53F /* AppDelegate.swift */; }; 32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BFFB5C22EACC630003B53F /* ViewController.swift */; }; @@ -82,6 +84,8 @@ 32439F8422ECD8AD0077AAE0 /* apple.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = apple.rom; sourceTree = ""; }; 32439F8522ECD8AD0077AAE0 /* 6502.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 6502.h; sourceTree = ""; }; 32439F8622ECD8AD0077AAE0 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + 3262F37423E169F8008BDB95 /* spk_dn.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = spk_dn.wav; sourceTree = ""; }; + 3262F37523E169F8008BDB95 /* spk_up.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = spk_up.wav; sourceTree = ""; }; 3264261023284F6F008B615F /* Apple2_mmio_8bit_ioaddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Apple2_mmio_8bit_ioaddr.h; sourceTree = ""; }; 326426112328ADF4008B615F /* Apple_II_ROM.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = Apple_II_ROM.s; sourceTree = ""; }; 326C50802383CC0B00A05420 /* woz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = woz.h; sourceTree = ""; }; @@ -173,6 +177,15 @@ path = instructions; sourceTree = ""; }; + 3262F37823E17013008BDB95 /* Resources */ = { + isa = PBXGroup; + children = ( + 3262F37423E169F8008BDB95 /* spk_dn.wav */, + 3262F37523E169F8008BDB95 /* spk_up.wav */, + ); + path = Resources; + sourceTree = ""; + }; 32BFFB4E22EACC630003B53F = { isa = PBXGroup; children = ( @@ -201,6 +214,7 @@ 32BFFB5922EACC630003B53F /* A2Mac */ = { isa = PBXGroup; children = ( + 3262F37823E17013008BDB95 /* Resources */, 32439F7522ECD8AD0077AAE0 /* instructions */, 32439F8522ECD8AD0077AAE0 /* 6502.h */, 32439F7422ECD8AD0077AAE0 /* 6502.c */, @@ -389,10 +403,12 @@ buildActionMask = 2147483647; files = ( 32EDB7A223272CA80073AF2D /* fail1.txt in Resources */, + 3262F37723E169F8008BDB95 /* spk_up.wav in Resources */, 32C4533123335E560000EBA1 /* Main.storyboard in Resources */, 32BFFB5F22EACC660003B53F /* Assets.xcassets in Resources */, 32439F8822ECD8AD0077AAE0 /* apple.rom in Resources */, 326ED2EF232D7A0000A41337 /* 6502_functional_test.bin in Resources */, + 3262F37623E169F8008BDB95 /* spk_dn.wav in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -644,7 +660,11 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; + GCC_ENABLE_CPP_EXCEPTIONS = YES; + GCC_ENABLE_CPP_RTTI = YES; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_FAST_MATH = YES; + GCC_UNROLL_LOOPS = NO; INFOPLIST_FILE = A2Mac/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -674,8 +694,12 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; + GCC_ENABLE_CPP_EXCEPTIONS = YES; + GCC_ENABLE_CPP_RTTI = YES; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_FAST_MATH = YES; GCC_OPTIMIZATION_LEVEL = fast; + GCC_UNROLL_LOOPS = NO; INFOPLIST_FILE = A2Mac/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/A2Mac/6502.c b/A2Mac/6502.c index fb59d9c..a248566 100644 --- a/A2Mac/6502.c +++ b/A2Mac/6502.c @@ -27,11 +27,16 @@ woz_chunk_header_t woz_chunk_header; woz_tmap_t woz_tmap; woz_trks_t woz_trks; +uint64_t clklast = 0; +uint64_t clkelpased = 0; uint16_t trackOffset = 0; uint8_t bitOffset = 0; FILE * outdev = NULL; +void ViewController_spk_up_play(void); +void ViewController_spk_dn_play(void); + #ifdef DEBUG #define INLINE @@ -66,15 +71,18 @@ INLINE unsigned long long rdtsc(void) return ( (unsigned long long)lo) | ( ((unsigned long long)hi) << 32 ); } - m6502_t m6502 = { 0, // A 0, // X 0, // Y + 0, // SR 0, // PC 0, // SP - 0, // clk + +// 0, // clk + 0, // clktime + 0, // trace 0, // step 0, // brk @@ -156,10 +164,6 @@ void hires_Update () { **/ #include "6502_instructions.h" -///// -//#ifdef SPEEDTEST -unsigned long long int clktime = 0; -//#endif INLINE int m6502_Step() { @@ -734,9 +738,7 @@ void m6502_Run() { #endif // INTERRUPT_CHECK_PER_STEP // dbgPrintf("%llu %04X: ", clktime, m6502.PC); -//#ifdef SPEEDTEST - clktime += -//#endif + m6502.clktime += clk = m6502_Step(); printDisassembly( outdev ); @@ -789,7 +791,7 @@ void m6502_Run() { // mhz = clktime / (execution_time * M); } -void read_rom( const char * filename, const uint16_t addr ) { +void read_rom( const char * filename, const uint8_t * rom, const uint16_t addr ) { FILE * f = fopen(filename, "rb"); if (f == NULL) { perror("Failed: "); @@ -800,7 +802,7 @@ void read_rom( const char * filename, const uint16_t addr ) { uint16_t flen = ftell(f); fseek(f, 0L, SEEK_SET); - fread( RAM + addr, 1, flen, f); + fread( rom + addr, 1, flen, f); fclose(f); } @@ -897,10 +899,11 @@ void m6502_ColdReset() { m6502.PC = 0x400; #else - // Apple ][e ROM - read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Apple2Plus.rom", 0xD000); + // Apple ][+ ROM + read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Apple2Plus.rom", Apple2_12K_ROM, 0); + memcpy(Apple2_64K_RAM + 0xD000, Apple2_12K_ROM, sizeof(Apple2_12K_ROM)); // Disk ][ ROM in Slot 6 - read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DISK_II_C600.ROM", 0xC600); + read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DISK_II_C600.ROM", Apple2_64K_RAM, 0xC600); // WOZ DISK // read_woz("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DOS 3.3 System Master.woz"); @@ -1050,7 +1053,7 @@ void tst6502() { double execution_time = (double)elapsed / tick_per_sec; double mips = inst_cnt / (execution_time * M); - double mhz = clktime / (execution_time * M); + double mhz = m6502.clktime / (execution_time * M); printf("clk:%llu Elpased time: (%llu / %u / %llu), %.3lfs (%.3lf MIPS, %.3lf MHz)\n", iterations *3, tick_per_sec, MHz_6502, tick_6502_per_sec, execution_time, mips, mhz); // printf(" dd:%llu ee:%llu nn:%llu\n", dd, ee, ee - dd); #endif diff --git a/A2Mac/6502.h b/A2Mac/6502.h index d85781f..05ece1c 100644 --- a/A2Mac/6502.h +++ b/A2Mac/6502.h @@ -71,13 +71,17 @@ typedef struct m6502_s { }; uint16_t PC; // Program Counter uint8_t SP; // Stack Pointer ( stack addr = 0x01 + sp ) - unsigned clk; // Clock Counter + +// unsigned clk; // Clock Counter + uint64_t clktime; + debugLevel_t dbgLevel; // 0: No Debug, 1: Disassembly Only, 2: Run till BRK, 3: StepByStep union { unsigned int IF; // interrut flag interrupt_t interrupt; }; + } m6502_t; diff --git a/A2Mac/Apple2_mmio.h b/A2Mac/Apple2_mmio.h index 16163a7..ea7e916 100644 --- a/A2Mac/Apple2_mmio.h +++ b/A2Mac/Apple2_mmio.h @@ -24,11 +24,149 @@ typedef union { uint16_t shift16; } WOZread_t; -uint8_t Apple2_64K_RAM[ 64 * KB ] = {0}; -uint8_t * RAM = Apple2_64K_RAM; WOZread_t WOZread = {0}; +typedef union address16_u { + uint16_t addr; + struct { + uint8_t offs; + uint8_t page; + }; +} address16_t; + + + +uint8_t Apple2_Dummy_Page[ 1 * PG ]; // Dummy Page for discarding data +uint8_t Apple2_512_AUX[ 2 * PG ] = {0}; // Auxiliary bank for page 0 and 1 +uint8_t Apple2_12K_ROM[ 12 * KB ] = {0}; // ROM D0, D8, E0, E8, F0, F8 +uint8_t Apple2_16K_RAM[ 16 * KB ] = {0}; // 16K Memory Expansion Card +uint8_t Apple2_64K_RAM[ 64 * KB ] = {0}; // Main Memory +uint8_t * RAM = Apple2_64K_RAM; // Pointer to the main memory so we can use this from Swift + + +#define DEF_RAM_PAGE(mem,pg) \ + (mem) + ((pg) << 8) + +#define DEF_RAM_PAGE16(mem,pg) \ + DEF_RAM_PAGE(mem, (pg) + 0x00), \ + DEF_RAM_PAGE(mem, (pg) + 0x01), \ + DEF_RAM_PAGE(mem, (pg) + 0x02), \ + DEF_RAM_PAGE(mem, (pg) + 0x03), \ + DEF_RAM_PAGE(mem, (pg) + 0x04), \ + DEF_RAM_PAGE(mem, (pg) + 0x05), \ + DEF_RAM_PAGE(mem, (pg) + 0x06), \ + DEF_RAM_PAGE(mem, (pg) + 0x07), \ + DEF_RAM_PAGE(mem, (pg) + 0x08), \ + DEF_RAM_PAGE(mem, (pg) + 0x09), \ + DEF_RAM_PAGE(mem, (pg) + 0x0A), \ + DEF_RAM_PAGE(mem, (pg) + 0x0B), \ + DEF_RAM_PAGE(mem, (pg) + 0x0C), \ + DEF_RAM_PAGE(mem, (pg) + 0x0D), \ + DEF_RAM_PAGE(mem, (pg) + 0x0E), \ + DEF_RAM_PAGE(mem, (pg) + 0x0F) + +#define SWITCH_RAM_PAGE16( tbl,tpg, mem,mpg ) \ + (tbl)[ (tpg) + 0x00 ] = DEF_RAM_PAGE(mem, (mpg) + 0x00); \ + (tbl)[ (tpg) + 0x01 ] = DEF_RAM_PAGE(mem, (mpg) + 0x01); \ + (tbl)[ (tpg) + 0x02 ] = DEF_RAM_PAGE(mem, (mpg) + 0x02); \ + (tbl)[ (tpg) + 0x03 ] = DEF_RAM_PAGE(mem, (mpg) + 0x03); \ + (tbl)[ (tpg) + 0x04 ] = DEF_RAM_PAGE(mem, (mpg) + 0x04); \ + (tbl)[ (tpg) + 0x05 ] = DEF_RAM_PAGE(mem, (mpg) + 0x05); \ + (tbl)[ (tpg) + 0x06 ] = DEF_RAM_PAGE(mem, (mpg) + 0x06); \ + (tbl)[ (tpg) + 0x07 ] = DEF_RAM_PAGE(mem, (mpg) + 0x07); \ + (tbl)[ (tpg) + 0x08 ] = DEF_RAM_PAGE(mem, (mpg) + 0x08); \ + (tbl)[ (tpg) + 0x09 ] = DEF_RAM_PAGE(mem, (mpg) + 0x09); \ + (tbl)[ (tpg) + 0x0A ] = DEF_RAM_PAGE(mem, (mpg) + 0x0A); \ + (tbl)[ (tpg) + 0x0B ] = DEF_RAM_PAGE(mem, (mpg) + 0x0B); \ + (tbl)[ (tpg) + 0x0C ] = DEF_RAM_PAGE(mem, (mpg) + 0x0C); \ + (tbl)[ (tpg) + 0x0D ] = DEF_RAM_PAGE(mem, (mpg) + 0x0D); \ + (tbl)[ (tpg) + 0x0E ] = DEF_RAM_PAGE(mem, (mpg) + 0x0E); \ + (tbl)[ (tpg) + 0x0F ] = DEF_RAM_PAGE(mem, (mpg) + 0x0F); + + +#define DEF_RAM_DUMMY16 \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page, \ + Apple2_Dummy_Page + +#define DEF_RAM_NULL16 \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL + +uint8_t * RAM_PG_RD_TBL[256] = { + // 48K main memory + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x00), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x10), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x20), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x30), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x40), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x50), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x60), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x70), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x80), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x90), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0xA0), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0xB0), + // I/O Addresses + DEF_RAM_PAGE16( Apple2_64K_RAM, 0xC0), + // Reading from the ROM + DEF_RAM_PAGE16( Apple2_12K_ROM, 0x00), // D0 + DEF_RAM_PAGE16( Apple2_12K_ROM, 0x10), // E0 + DEF_RAM_PAGE16( Apple2_12K_ROM, 0x20) // F0 +}; + +uint8_t * RAM_PG_WR_TBL[256] = { + // 48K main memory + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x00), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x10), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x20), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x30), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x40), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x50), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x60), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x70), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x80), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0x90), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0xA0), + DEF_RAM_PAGE16( Apple2_64K_RAM, 0xB0), + // I/O Addresses + DEF_RAM_PAGE16( Apple2_64K_RAM, 0xC0), + // NO Writing to the ROM + DEF_RAM_DUMMY16, + DEF_RAM_DUMMY16, + DEF_RAM_DUMMY16, +}; + + + enum slot { SLOT0 = 0x00, SLOT1 = 0x10, @@ -41,10 +179,22 @@ enum slot { }; +// Memory Config +struct MEMcfg_s { + uint8_t RAM_16K : 1; + uint8_t RAM_128K : 1; + uint8_t RD_RAM : 1; + uint8_t WR_RAM : 1; + uint8_t RAM_BANK_2 : 1; + uint8_t AUX_BANK : 1; +} MEMcfg = { 1, 0, 0, 0, 0 }; + enum mmio { io_KBD = 0xC000, io_KBDSTRB = 0xC010, - + + io_SPKR = 0xC030, + io_DISK_PHASE0_OFF = 0xC080, io_DISK_PHASE0_ON = 0xC081, io_DISK_PHASE1_OFF = 0xC082, @@ -61,7 +211,15 @@ enum mmio { io_DISK_WRITE = 0xC08D, io_DISK_CLEAR = 0xC08E, io_DISK_SHIFT = 0xC08F, - + + 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_1 = 0xC088, + io_MEM_RDROM_WRAM_1 = 0xC089, + io_MEM_RDROM_NOWR_1 = 0xC08A, + io_MEM_RDRAM_WRAM_1 = 0xC08B, }; @@ -106,14 +264,6 @@ enum mmio { //uint8_t ( * mmio_read [ 64 * KB ] )( uint16_t addr ); -typedef union address16_u { - uint16_t addr; - struct { - uint8_t offs; - uint8_t page; - }; -} address16_t; - #define CASE_DISKII(x) \ case io_DISK_PHASE0_OFF + SLOT##x: \ @@ -259,6 +409,9 @@ INLINE void diskII_phase() { printf(", p:%d d:%d l:%d: ph:%u trk:%u)", position, direction, lastPosition, phase.count, woz_tmap.phase[phase.count]); } + else { + // invalid magnet config + } printf("\n"); } @@ -268,6 +421,7 @@ INLINE uint8_t ioRead( uint16_t addr ) { dbgPrintf("mmio read:%04X\n", addr); uint8_t currentMagnet = 0; + int clk = 0; switch (addr) { case io_KBD: @@ -279,7 +433,89 @@ INLINE uint8_t ioRead( uint16_t addr ) { // printf("io_KBDSTRB\n"); return RAM[io_KBD] &= 0x7F; + case io_SPKR: + // TODO: This is very slow! +// printf("io_KBDSTRB\n"); + + //ViewController_spk_up_play(); + + return RAM[io_SPKR]; + // CASE_DISKII(6) + + case io_MEM_RDRAM_NOWR_2: + case io_MEM_RDROM_WRAM_2: + case io_MEM_RDROM_NOWR_2: + case io_MEM_RDRAM_WRAM_2: + case io_MEM_RDRAM_NOWR_1: + case io_MEM_RDROM_WRAM_1: + case io_MEM_RDROM_NOWR_1: + case io_MEM_RDRAM_WRAM_1: + if ( MEMcfg.RAM_16K || MEMcfg.RAM_128K ) { + uint8_t * RAM_BANK = Apple2_16K_RAM; + + // RAM Bank 1 or 2? + switch (addr) { + case io_MEM_RDRAM_NOWR_2: + case io_MEM_RDROM_WRAM_2: + case io_MEM_RDROM_NOWR_2: + case io_MEM_RDRAM_WRAM_2: + MEMcfg.RAM_BANK_2 = 1; + RAM_BANK = Apple2_16K_RAM + 0x30; + break; + + default: + MEMcfg.RAM_BANK_2 = 0; + RAM_BANK = Apple2_16K_RAM; + break; + } + + // is RAM to read or ROM? + switch (addr) { + case io_MEM_RDRAM_NOWR_2: + case io_MEM_RDRAM_WRAM_2: + case io_MEM_RDRAM_NOWR_1: + case io_MEM_RDRAM_WRAM_1: + MEMcfg.RD_RAM = 1; + // set the RAM extension to read on the upper memory area + SWITCH_RAM_PAGE16( RAM_PG_RD_TBL, 0xD0, RAM_BANK, 0x00 ); + SWITCH_RAM_PAGE16( RAM_PG_RD_TBL, 0xE0, Apple2_16K_RAM, 0x10 ); + SWITCH_RAM_PAGE16( RAM_PG_RD_TBL, 0xF0, Apple2_16K_RAM, 0x20 ); + break; + + default: + MEMcfg.RD_RAM = 0; + // set the ROM to read on the upper memory area + SWITCH_RAM_PAGE16( RAM_PG_RD_TBL, 0xD0, Apple2_12K_ROM, 0x00 ); + SWITCH_RAM_PAGE16( RAM_PG_RD_TBL, 0xE0, Apple2_12K_ROM, 0x10 ); + SWITCH_RAM_PAGE16( RAM_PG_RD_TBL, 0xF0, Apple2_12K_ROM, 0x20 ); + break; + } + + // is RAM Writeable? + switch (addr) { + case io_MEM_RDROM_WRAM_2: + case io_MEM_RDRAM_WRAM_2: + case io_MEM_RDROM_WRAM_1: + case io_MEM_RDRAM_WRAM_1: + MEMcfg.WR_RAM = 1; + // set the RAM extension to read from the upper memory area + SWITCH_RAM_PAGE16( RAM_PG_WR_TBL, 0xD0, RAM_BANK, 0x00 ); + SWITCH_RAM_PAGE16( RAM_PG_WR_TBL, 0xE0, Apple2_16K_RAM, 0x10 ); + SWITCH_RAM_PAGE16( RAM_PG_WR_TBL, 0xF0, Apple2_16K_RAM, 0x20 ); + break; + + default: + MEMcfg.WR_RAM = 0; + // set the ROM to read on the upper memory area + SWITCH_RAM_PAGE16( RAM_PG_WR_TBL, 0xD0, Apple2_Dummy_Page, 0 ); + SWITCH_RAM_PAGE16( RAM_PG_WR_TBL, 0xE0, Apple2_Dummy_Page, 0 ); + SWITCH_RAM_PAGE16( RAM_PG_WR_TBL, 0xF0, Apple2_Dummy_Page, 0 ); + break; + } + + } // if there is RAM expansion card installed + break; // TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove case io_DISK_PHASE0_OFF + SLOT6: @@ -326,16 +562,29 @@ INLINE uint8_t ioRead( uint16_t addr ) { int track = woz_tmap.phase[phase.count]; if (outdev) fprintf(outdev, "track: %d (%d) ", track, phase.count); if ( track >= 40 ) { - printf("TRCK TOO HIGH!\n"); + dbgPrintf("TRCK TOO HIGH!\n"); return rand(); } + + clkelpased = m6502.clktime - clklast; + clklast = m6502.clktime; + + if ( clkelpased > 100 ) { + bitOffset = (clkelpased % 32) / 4; + trackOffset += (clkelpased / 32) % WOZ_TRACK_BYTE_COUNT; + WOZread.latch = woz_trks[track].data[trackOffset]; + } + // to avoid infinite loop and to search for bit 7 high for ( int i = 0; i < WOZ_TRACK_BYTE_COUNT * 8; i++ ) { if ( ++bitOffset >= 8 ) { bitOffset = 0; - if ( ++trackOffset >= WOZ_TRACK_BYTE_COUNT ) { - trackOffset = 0; - } +// if ( ++trackOffset >= WOZ_TRACK_BYTE_COUNT ) { +// trackOffset = 0; +// } + trackOffset++; + trackOffset %= WOZ_TRACK_BYTE_COUNT; + // printf("offs:%u\n", trackOffset); WOZread.latch = woz_trks[track].data[trackOffset]; } @@ -367,9 +616,11 @@ INLINE uint8_t ioRead( uint16_t addr ) { default: - return RAM[addr]; + //printf("mmio read:%04X\n", addr); + break; } + return RAM[addr]; } @@ -414,53 +665,23 @@ INLINE void ioWrite( uint16_t addr, uint8_t val ) { Naive implementation of RAM read from address **/ -INLINE uint8_t memread_zp( uint8_t addr ) { - return RAM[ addr ]; -} - /** Naive implementation of RAM read from address **/ INLINE uint8_t memread8( uint16_t addr ) { -// if ( addr == 0xD2AD ) { -// dbgPrintf("OUT OF MEMORY!\n"); -// } - - - return RAM[ addr ]; + return * ( RAM_PG_RD_TBL[addr >> 8] + (addr & 0xFF) ); +// return RAM[ addr ]; } /** Naive implementation of RAM read from address **/ INLINE uint16_t memread16( uint16_t addr ) { - return * (uint16_t*) (& RAM[ addr ]); + return * (uint16_t*) ( RAM_PG_RD_TBL[addr >> 8] + (addr & 0xFF) ); +// return * (uint16_t*) (& RAM[ addr ]); } INLINE uint8_t memread( uint16_t addr ) { -// switch ( ((address16_t)addr).page ) { -// case 0xC0: -// case 0xC1: -// case 0xC2: -// case 0xC3: -// case 0xC4: -// case 0xC5: -// case 0xC6: -// case 0xC7: -// case 0xC8: -// case 0xC9: -// case 0xCA: -// case 0xCB: -// case 0xCC: -// case 0xCD: -// case 0xCE: -// case 0xCF: -// return ioRead(addr); -// -// defaut: -// break; -// } - - if ( (addr >= 0xC000) && (addr < 0xC0FF) ) { + if ( (addr >= 0xC000) && (addr <= 0xC0FF) ) { return ioRead(addr); } @@ -478,9 +699,9 @@ INLINE uint8_t memread( uint16_t addr ) { /** Naive implementation of RAM write to address **/ -static void memwrite_zp( uint8_t addr, uint8_t byte ) { - RAM[ addr ] = byte; -} +//static void memwrite_zp( uint8_t addr, uint8_t byte ) { +// RAM[ addr ] = byte; +//} /** @@ -534,7 +755,8 @@ INLINE uint8_t src_abs() { return memread( addr_abs() ); } INLINE uint8_t * dest_abs() { - return & RAM[ addr_abs() ]; + uint16_t addr = addr_abs(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } @@ -565,7 +787,8 @@ INLINE uint8_t src_abs_X() { return memread( addr_abs_X() ); } INLINE uint8_t * dest_abs_X() { - return & RAM[ addr_abs_X() ]; + uint16_t addr = addr_abs_X(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } @@ -582,7 +805,8 @@ INLINE uint8_t src_abs_Y() { return memread(addr_abs_Y()); } INLINE uint8_t * dest_abs_Y() { - return & RAM[ addr_abs_Y() ]; + uint16_t addr = addr_abs_Y(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } INLINE uint16_t imm() { @@ -601,10 +825,11 @@ INLINE uint8_t addr_zp() { return fetch(); } INLINE uint8_t src_zp() { - return memread_zp(addr_zp()); + return memread8(addr_zp()); } INLINE uint8_t * dest_zp() { - return & RAM[ addr_zp() ]; + uint16_t addr = addr_zp(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } /** @@ -632,7 +857,8 @@ INLINE uint8_t src_X_ind() { return memread( addr_X_ind() ); } INLINE uint8_t * dest_X_ind() { - return & RAM[ addr_X_ind() ]; + uint16_t addr = addr_X_ind(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } /** @@ -652,12 +878,7 @@ INLINE uint8_t src_ind_Y() { } INLINE uint8_t * dest_ind_Y() { uint16_t addr = addr_ind_Y(); -// if ( (addr >= 0xC000) && (addr <= 0xC0FF) ) { -// addr = 0xC111; -// } - // return & RAM[ addr_abs_Y() ]; - return & RAM[ addr ]; -// return & RAM[ addr_ind_Y() ]; + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } /** @@ -670,10 +891,11 @@ INLINE uint8_t addr_zp_X() { return fetch() + m6502.X; } INLINE uint8_t src_zp_X() { - return memread_zp(addr_zp_X()); + return memread8(addr_zp_X()); } INLINE uint8_t * dest_zp_X() { - return & RAM[ addr_zp_X() ]; + uint16_t addr = addr_zp_X(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } /** @@ -686,10 +908,11 @@ INLINE uint8_t addr_zp_Y() { return fetch() + m6502.Y; } INLINE uint8_t src_zp_Y() { - return memread_zp(addr_zp_Y()); + return memread8(addr_zp_Y()); } INLINE uint8_t * dest_zp_Y() { - return & RAM[ addr_zp_Y() ]; + uint16_t addr = addr_zp_Y(); + return ( RAM_PG_WR_TBL[addr >> 8] + (addr & 0xFF) ); } diff --git a/A2Mac/Resources/spk_dn.wav b/A2Mac/Resources/spk_dn.wav new file mode 100644 index 0000000..1d799b1 Binary files /dev/null and b/A2Mac/Resources/spk_dn.wav differ diff --git a/A2Mac/Resources/spk_up.wav b/A2Mac/Resources/spk_up.wav new file mode 100644 index 0000000..e601d8a Binary files /dev/null and b/A2Mac/Resources/spk_up.wav differ diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index 8f629d5..d8bd418 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -8,6 +8,8 @@ import Cocoa +import AVFoundation + let K : Double = 1000.0 let M : Double = (K * K) @@ -20,6 +22,24 @@ let GB : Double = (MB * KB) let TB : Double = (GB * KB) +var spk_up: AVAudioPlayer? +var spk_dn: AVAudioPlayer? + +@_cdecl("ViewController_spk_up_play") +func spk_up_play() { + spk_up?.stop() + spk_dn?.stop() + spk_up?.play() +} + +@_cdecl("ViewController_spk_dn_play") +func spk_dn_play() { + spk_up?.stop() + spk_dn?.stop() + spk_dn?.play() +} + + #if METAL_YES import Metal #endif @@ -74,6 +94,8 @@ class ViewController: NSViewController { var workItem : DispatchWorkItem? = nil; @IBAction func Power(_ sender: Any) { + + #if SPEEDTEST if ( workItem != nil ) { workItem!.cancel(); @@ -336,9 +358,32 @@ class ViewController: NSViewController { let upd = RepeatingTimer(timeInterval: 1/Double(fps)) + override func viewDidLoad() { super.viewDidLoad() + + let spk_up_path = Bundle.main.path(forResource: "spk_up", ofType:"wav")! + let spk_up_url = URL(fileURLWithPath: spk_up_path) + do { + spk_up = try AVAudioPlayer(contentsOf: spk_up_url) +// spk_up?.play() + } catch { + // couldn't load file :( + } + + let spk_dn_path = Bundle.main.path(forResource: "spk_dn", ofType:"wav")! + let spk_dn_url = URL(fileURLWithPath: spk_dn_path) + do { + spk_dn = try AVAudioPlayer(contentsOf: spk_dn_url) +// spk_up?.play() + } catch { + // couldn't load file :( + } + + + + //view.frame = CGRect(origin: CGPoint(), size: NSScreen.main!.visibleFrame.size) // createHiRes() diff --git a/A2Mac/common.h b/A2Mac/common.h index 483c1d1..261623c 100644 --- a/A2Mac/common.h +++ b/A2Mac/common.h @@ -17,6 +17,7 @@ #define G (M * K) #define T (G * K) +#define PG 256ULL #define KB 1024ULL #define MB (KB * KB) #define GB (MB * KB) diff --git a/A2Mac/disassembler.h b/A2Mac/disassembler.h index cdc4799..a19762f 100644 --- a/A2Mac/disassembler.h +++ b/A2Mac/disassembler.h @@ -11,7 +11,7 @@ #ifdef DISASSEMBLER -extern unsigned long long int clktime; +//extern unsigned long long int clktime; unsigned long long discnt = 0; #define disHexB( to, b ) \ @@ -75,7 +75,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, - clktime, + m6502.clktime, disassembly.addr, disassembly.opcode, disassembly.inst, @@ -97,7 +97,7 @@ INLINE void printDisassembly( FILE * f ) { #define disPuts( to, from ) #define disPrintf( to, fmt, args... ) #define disNewInstruction() -#define printDisassembly() +#define printDisassembly( f ) #endif // DISASSEMBLER diff --git a/A2Mac/instructions/6502_instr_load_store.h b/A2Mac/instructions/6502_instr_load_store.h index 0ec45ca..dae249a 100644 --- a/A2Mac/instructions/6502_instr_load_store.h +++ b/A2Mac/instructions/6502_instr_load_store.h @@ -93,56 +93,31 @@ INLINE void STR( uint8_t * dst, uint8_t src ) { dbgPrintf("STR [%04X], %02X ", (int)(dst - RAM), src ); uint16_t addr = dst - RAM; -// if ( ( addr >= 0x400 ) && ( addr < 0x800 ) ) { -// char c = charConv[src]; -//// if ( c == '?' ) { -//// printf("? SYNTAX ERROR\n"); -//// } -// -// if (( src > ' ' ) && ( c < 0x7F )) -// printf("*** PRINT: %04X: t:%02X '%c'\n", addr, src, isprint(c) ? c : ' '); -// } -// else - if ( ( addr >= 0xC000 ) && ( addr < 0xD000 ) ) { - // printf("mmio write:[%04X] = %02X\n", addr, src); - } - // Need to protect ROM!!! - else if ( ( addr >= 0xE000 ) && ( addr < 0xF000 ) ) { + + // I/O or ROM or RAM EXP + if ( addr >= 0xC000 ) { + // ROM or RAM EXP + if ( addr >= 0xD000 ) { + uint8_t * pgaddr; + // DO NOT MAKE IT NICER! faster this way! + if ( (pgaddr = RAM_PG_WR_TBL[ addr >> 8 ]) ) { + dst = pgaddr + (addr & 0xFF); + } + else { + // NULL page table, so no need to do anything + return; + } + } + // I/O + else { // printf("mmio write:[%04X] = %02X\n", addr, src); + // dst = Apple2_Dummy_Page; + return; + } } - else { - *dst = src; - } + + *dst = src; - -// else switch ( addr ) { -// case 0x36: -// case 0x37: -// dbgPrintf("*** OUTROUT %04X: %02X\n", addr, src); -// break; -// -// case 0x9B: -// case 0x9C: -// dbgPrintf("*** LOWTR %04X: %02X\n", addr, src); -// break; -// -// case 0x6F: // FRETOP -// case 0x70: -// dbgPrintf("*** FRETOP %04X: %02X\n", addr, src); -// break; -// -// case 0x73: // MEMSIZ -// case 0x74: -// dbgPrintf("*** MEMSIZ %04X: %02X\n", addr, src); -// break; -// -// case 0x5E: -// dbgPrintf("*** ??? %04X: %02X\n", addr, src); -// break; -// -// default: -// break; -// } } /**