diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 1c0691a..7441aed 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -84,7 +84,10 @@ 32439F8622ECD8AD0077AAE0 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; 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 = ""; }; 326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = SOURCE_ROOT; }; + 32B18435233F10BC00DBB4AB /* Shaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; + 32B18438233FAB3900DBB4AB /* verticies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = verticies.swift; sourceTree = ""; }; 32BFFB5722EACC630003B53F /* A2Mac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = A2Mac.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32BFFB5A22EACC630003B53F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 32BFFB5C22EACC630003B53F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -204,11 +207,13 @@ 32DBF76723373FB400DD50E7 /* disassembler.h */, 32439F8422ECD8AD0077AAE0 /* apple.rom */, 326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */, + 32B18438233FAB3900DBB4AB /* verticies.swift */, 32439F7322ECD8AD0077AAE0 /* Apple2_mmio.h */, 3264261023284F6F008B615F /* Apple2_mmio_8bit_ioaddr.h */, 32439F8622ECD8AD0077AAE0 /* common.h */, 32BFFB5A22EACC630003B53F /* AppDelegate.swift */, 32BFFB5C22EACC630003B53F /* ViewController.swift */, + 32B18435233F10BC00DBB4AB /* Shaders.metal */, 32C4532D233345420000EBA1 /* MonitorView.swift */, 32DBF7632334657900DD50E7 /* HiRes.swift */, 32C453072331C0910000EBA1 /* NSLayoutManager-Extension.swift */, @@ -219,6 +224,7 @@ 32BFFB6322EACC660003B53F /* Info.plist */, 32BFFB6422EACC660003B53F /* A2Mac.entitlements */, 32439F7222ECD8AC0077AAE0 /* A2Mac-Bridging-Header.h */, + 326C50802383CC0B00A05420 /* woz.h */, ); path = A2Mac; sourceTree = ""; @@ -338,7 +344,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1020; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1100; ORGANIZATIONNAME = GameAlloy; TargetAttributes = { 32BFFB5622EACC630003B53F = { @@ -634,6 +640,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = A2Mac/A2Mac.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; @@ -643,8 +650,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); - OTHER_CFLAGS = ""; - OTHER_SWIFT_FLAGS = ""; + OTHER_CFLAGS = ( + "-DDISASSEMBLER", + "-DINTERRUPR_CHECK_PER_STEP", + ); + OTHER_SWIFT_FLAGS = "-D_NO_HIRES -D_NO_HIRESDRAW -D_NO_HIRESLOW"; PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -660,6 +670,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = A2Mac/A2Mac.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; @@ -670,7 +681,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); - OTHER_CFLAGS = ""; + OTHER_CFLAGS = ( + "-DDISASSEMBLER", + "-DINTERRUPR_CHECK_PER_STEP", + ); + OTHER_SWIFT_FLAGS = "-D_NO_HIRES -D_NO_HIRESDRAW -D_NO_HIRESLOW"; PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h"; @@ -766,6 +781,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = A2Mac/A2Mac.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; @@ -792,6 +808,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = A2Mac/A2Mac.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; @@ -817,6 +834,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = A2Mac/A2Mac.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; @@ -843,6 +861,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = A2Mac/A2Mac.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = W6TFQTZ4DA; diff --git a/A2Mac/6502.c b/A2Mac/6502.c index 1c085ed..44ce429 100644 --- a/A2Mac/6502.c +++ b/A2Mac/6502.c @@ -12,6 +12,21 @@ #include #include #include +#include "woz.h" + +#define WOZ1_MAGIC 0x315A4F57 +#define WOZ2_MAGIC 0x325A4F57 +#define WOZ_INFO_CHUNK_ID 0x4F464E49 +#define WOZ_TMAP_CHUNK_ID 0x50414D54 +#define WOZ_TRKS_CHUNK_ID 0x534B5254 +#define WOZ_META_CHUNK_ID 0x4154454D + +woz_header_t woz_header; +woz_chunk_header_t woz_chunk_header; +woz_tmap_t woz_tmap; +woz_trks_t woz_trks; + +uint16_t trackOffset = 0; #ifdef DEBUG #define INLINE @@ -28,7 +43,7 @@ #define RESET_VECTOR 0xFFFC #define IRQ_VECTOR 0xFFFE -const unsigned long long int iterations = 100*G; +const unsigned long long int iterations = G; unsigned long long int inst_cnt = 0; const unsigned int fps = 30; @@ -46,7 +61,24 @@ INLINE unsigned long long rdtsc(void) } -m6502_t m6502 = { 0, 0, 0, 0, 0, 0, 0, NO_DEBUG, HLT }; +m6502_t m6502 = { + 0, // A + 0, // X + 0, // Y + 0, // SR + 0, // PC + 0, // SP + 0, // clk + 0, // trace + 0, // step + 0, // brk + 0, // rts + 0, // bra + 0, // bra_true + 0, // bra_false + 0, // compile + HLT // IF +}; disassembly_t disassembly; @@ -54,6 +86,62 @@ disassembly_t disassembly; #include "Apple2_mmio.h" +uint16_t videoShadow [0x1000]; +uint32_t videoMem [0x2000]; +uint32_t * videoMemPtr = videoMem; + +uint16_t HiResLineAddrTbl [0x2000]; + +void initHiResLineAddresses() { + uint16_t i = 0; + for ( uint16_t x = 0; x <= 0x50; x+= 0x28 ) { + for ( uint16_t y = 0; y <= 0x380; y += 0x80 ) { + for ( uint16_t z = 0; z <= 0x1C00; z += 0x400) { + HiResLineAddrTbl[i++] = x + y + z; + } + } + } +} + + +typedef struct { + uint8_t L; + uint8_t H; +} bytes_t; + +void hires_Update () { + // lines + int videoMemIndex = 0; + for( int y = 0; y < 192; y++ ) { + // 16 bit blocks of columns + for ( int x = 0; x < 20; x++ ) { + // odd + bytes_t block = * (bytes_t*)(& RAM[ HiResLineAddrTbl[y * 20] + x * 2 ]); + for ( uint8_t bit = 0; bit < 7; bit++ ) { + uint8_t bitMask = 1 << bit; + + if (block.L & bitMask) { + videoMem[videoMemIndex++] = 0x7F12A208; + } + else { // 28CD41 + videoMem[videoMemIndex++] = 0x00000000; + } + } + // even + for ( uint8_t bit = 0; bit < 7; bit++ ) { + uint8_t bitMask = 1 << bit; + + if (block.H & bitMask) { + videoMem[videoMemIndex++] = 0x7F12A208; + } + else { // 28CD41 + videoMem[videoMemIndex++] = 0x00000000; + } + } + } + } +} + /** Instruction Implementations !!!! `his has to be here!!! @@ -63,12 +151,28 @@ disassembly_t disassembly; #include "6502_instructions.h" ///// +#ifdef SPEEDTEST unsigned long long int clktime = 0; - +#endif INLINE int m6502_Step() { -#ifdef DEBUG + +#ifdef DEBUG___ + switch ( m6502.PC ) { + case 0xC600: + printf("DISK...\n"); + break; + + case 0xC62F: + printf("DISK IO...\n"); + break; + + default: + break; + } + + switch ( m6502.PC ) { case 0xE000: dbgPrintf("START...\n"); @@ -539,7 +643,7 @@ INLINE int m6502_Step() { // case 0xFF: default: - printf("%04X: Unimplemented Instruction 0x%02X\n", m6502.PC -1, memread( m6502.PC -1 )); + dbgPrintf("%04X: Unimplemented Instruction 0x%02X\n", m6502.PC -1, memread( m6502.PC -1 )); return 2; } // } // fetch16 @@ -558,8 +662,8 @@ double mhz = 0; unsigned long long epoch = 0; void m6502_Run() { - unsigned int clk = 0; - unsigned int clkfrm = 0; + static unsigned int clk = 0; + static unsigned int clkfrm = 0; // init time //#ifdef CLK_WAIT @@ -567,28 +671,52 @@ void m6502_Run() { //#endif #ifdef SPEEDTEST - for ( unsigned long long int i = 0; i < iterations ; i++ ) + for ( inst_cnt = 0; inst_cnt < iterations ; inst_cnt++ ) #elif defined( CLK_WAIT ) - for ( clkfrm = 0; clkfrm < clk_6502_per_frm ; clkfrm += clk ) + for ( clkfrm = 0; clkfrm < clk_6502_per_frm ; clkfrm += clk ) #else // for ( ; m6502.pc ; ) for ( ; ; ) #endif { + +#ifdef INTERRUPR_CHECK_PER_STEP if ( m6502.IF ) { switch (m6502.interrupt) { case HLT: // CPU is haletd, nothing to do here... return; + case IRQ: + m6502.PC = memread16(IRQ_VECTOR); + // TODO: PUSH things onto stack? + break; + case NMI: + m6502.PC = memread16(NMI_VECTOR); + // TODO: PUSH things onto stack? break; case HARDRESET: + m6502.PC = memread16(RESET_VECTOR); + // make sure it will be a cold reset... + memwrite(0x3F4, 0); + m6502.SP = 0xFF; + // N V - B D I Z C + // 0 0 1 0 0 1 0 1 + m6502.SR = 0x25; + break; case SOFTRESET: - m6502.PC = memread16(SOFTRESET_VECTOR); +// m6502.PC = memread16(SOFTRESET_VECTOR); + m6502.PC = memread16( RESET_VECTOR ); + + m6502.SP = 0xFF; + // N V - B D I Z C + // 0 0 1 0 0 1 0 1 + m6502.SR = 0x25; + break; default: @@ -597,12 +725,16 @@ void m6502_Run() { m6502.IF = 0; } - - dbgPrintf("%llu %04X: ", clktime, m6502.PC); - clktime += clk = m6502_Step(); +#endif // INTERRUPR_CHECK_PER_STEP + +// dbgPrintf("%llu %04X: ", clktime, m6502.PC); +#ifdef SPEEDTEST + clktime += +#endif + clk = m6502_Step(); printDisassembly(); - dbgPrintf("\nA:%02X X:%02X Y:%02X SP:%02X %c%c%c%c%c%c%c%c\n", + dbgPrintf2("A:%02X X:%02X Y:%02X SP:%02X %c%c%c%c%c%c%c%c\n\n", m6502.A, m6502.X, m6502.Y, @@ -651,7 +783,82 @@ void m6502_Run() { // mhz = clktime / (execution_time * M); } -void m6502_Reset() { +void read_rom( const char * filename, const uint16_t addr ) { + FILE * f = fopen(filename, "rb"); + if (f == NULL) { + perror("Failed: "); + return; + } + + fseek(f, 0L, SEEK_END); + uint16_t flen = ftell(f); + fseek(f, 0L, SEEK_SET); + + fread( RAM + addr, 1, flen, f); + fclose(f); + +} + + +void read_woz( const char * filename ) { + FILE * f = fopen(filename, "rb"); + if (f == NULL) { + perror("Failed: "); + return; + } + + fread( &woz_header, 1, sizeof(woz_header_t), f); + if ( woz_header.magic != WOZ1_MAGIC ) { + return; + } + + while ( ! feof(f) ) { + // beginning of the chunk, so we can skip it later + + long r = fread( &woz_chunk_header, 1, sizeof(woz_chunk_header_t), f); + if ( r != sizeof(woz_chunk_header_t) ) { + break; + } + long foffs = ftell(f); + + void * buf = NULL; + + switch ( woz_chunk_header.magic ) { + case WOZ_INFO_CHUNK_ID: + break; + + case WOZ_TMAP_CHUNK_ID: + buf = &woz_tmap; + break; + + case WOZ_TRKS_CHUNK_ID: + buf = woz_trks; + break; + + case WOZ_META_CHUNK_ID: + break; + + default: + break; + } + + if (buf) { + r = fread( buf, 1, woz_chunk_header.size, f); + if ( r != woz_chunk_header.size ) { + break; + } + } + + // make sure we are skipping unhandled chunks correctly + fseek(f, foffs + woz_chunk_header.size, SEEK_SET); + } + + fclose(f); + + +} + +void m6502_ColdReset() { inst_cnt = 0; mhz = (double)MHz_6502 / M; @@ -661,12 +868,12 @@ void m6502_Reset() { tick_per_sec = e - epoch; tick_6502_per_sec = tick_per_sec / MHz_6502; - memset( RAM, 0xFF, sizeof(RAM) ); + memset( RAM, 0xFF, sizeof(Apple2_64K_RAM) ); memset( RAM + 0xC000, 0, 0x1000 ); // I/O area should be 0 m6502.A = m6502.X = m6502.Y = 0xFF; // reset vector - m6502.SP = 0xFF -3; + m6502.SP = 0xFF; //-3; // N V - B D I Z C // 0 0 1 1 0 1 0 0 @@ -690,15 +897,16 @@ void m6502_Reset() { m6502.PC = 0x400; #else - FILE * f = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Apple2Plus.rom", "rb"); - if (f == NULL) { - perror("Failed: "); - return; - } + // Apple ][e ROM + read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Apple2Plus.rom", 0xD000); + // Disk ][ ROM in Slot 6 +// read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DISK_II_C600.ROM", 0xC600); - fread( RAM + 0xD000, 1, 0x3000, f); - fclose(f); + // WOZ DISK +// read_woz("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DOS 3.3 System Master.woz"); +// read_woz("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Hard Hat Mack - Disk 1, Side A.woz"); + m6502.PC = memread16( RESET_VECTOR ); #endif @@ -812,22 +1020,24 @@ void tst6502() { // insert code here... printf("6502\n"); - m6502_Reset(); + m6502_ColdReset(); // clock_t start = clock(); epoch = rdtsc(); m6502_Run(); // clock_t end = clock(); // double execution_time = ((double) (end - start)) / CLOCKS_PER_SEC; + +#ifdef SPEEDTEST unsigned long long end = rdtsc(); unsigned long long elapsed = end - epoch; double execution_time = (double)elapsed / tick_per_sec; double mips = inst_cnt / (execution_time * M); double mhz = clktime / (execution_time * M); - printf("clk:%llu Elpased time: (%llu / %u / %llu), %.3lfs (%.3lf MIPS, %.3lf MHz)\n", clktime, tick_per_sec, MHz_6502, tick_6502_per_sec, execution_time, mips, mhz); + 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 } int ___main(int argc, const char * argv[]) { diff --git a/A2Mac/6502.h b/A2Mac/6502.h index 6eff18c..36955ac 100644 --- a/A2Mac/6502.h +++ b/A2Mac/6502.h @@ -9,7 +9,7 @@ #ifndef __6502_H__ #define __6502_H__ -#import "stdint.h" +#import #ifdef DEBUG //#define dbgPrintf(format, ...) printf (format, ## __VA_ARGS__) @@ -23,16 +23,21 @@ typedef enum { NO_INT, HLT, + IRQ, NMI, HARDRESET, SOFTRESET, } interrupt_t; -typedef enum { - NO_DEBUG, - DISASSEMBLY, - DEBUGBRK, - STEPBYSTEP, +typedef struct debugLevel_s { + uint8_t trace : 1; + uint8_t step : 1; + uint8_t brk : 1; + uint8_t rts : 1; + uint8_t bra : 1; + uint8_t bra_true : 1; + uint8_t bra_false : 1; + uint8_t compile : 1; } debugLevel_t; typedef struct m6502_s { @@ -73,25 +78,28 @@ typedef struct m6502_s { typedef struct disassembly_s { - char codeAddr[5]; // 4 digits + \0 - char hex[4 * 3 + 1]; // max 4 bytes * (2 digits + 1 space) + \0 - char * pHex; - char inst[6 + 1]; // 3 char (unknown instr? -- give it 6 chars) + \0 - char addr[4 + 2 + 1 + 1 + 1]; // 4 digits + 2 brackets + 1 comma + 1 index + \0 - char comment[256]; // to be able to add some comments + char addr[5]; // 4 digits + \0 + char opcode[4 * 3 + 1]; // max 4 bytes * (2 digits + 1 space) + \0 + char * pOpcode; // pointer for opcode string builder + char inst[6 + 1]; // 3 char (unknown instr? -- give it 6 chars) + \0 + char oper[14 + 2 + 1 + 1 + 1]; // 4 digits + 2 brackets + 1 comma + 1 index + \0 + char comment[256]; // to be able to add some comments } disassembly_t; extern m6502_t m6502; -extern uint8_t RAM[ 64 * 1024 ]; +extern uint8_t * RAM; +extern uint32_t * videoMemPtr; + +extern void hires_Update(void); extern double mips; extern double mhz; extern const unsigned int fps; -extern void tst6502(); -extern void m6502_Reset(); -extern void m6502_Run(); +extern void tst6502(void); +extern void m6502_ColdReset(void); +extern void m6502_Run(void); extern void kbdInput ( uint8_t code ); #endif /* __6502_H__ */ diff --git a/A2Mac/Apple2_mmio.h b/A2Mac/Apple2_mmio.h index 1debd31..f7f20e4 100644 --- a/A2Mac/Apple2_mmio.h +++ b/A2Mac/Apple2_mmio.h @@ -13,13 +13,44 @@ #include "6502.h" -enum mmio { - io_KBD = 0xC000, - io_KBDSTRB = 0xC010, +uint8_t Apple2_64K_RAM[ 64 * KB ] = {0}; +uint8_t * RAM = Apple2_64K_RAM; + +enum slot { + SLOT0 = 0x00, + SLOT1 = 0x10, + SLOT2 = 0x20, + SLOT3 = 0x30, + SLOT4 = 0x40, + SLOT5 = 0x50, + SLOT6 = 0x60, + SLOT7 = 0x70, }; -uint8_t RAM[ 64 * KB ] = {0}; +enum mmio { + io_KBD = 0xC000, + io_KBDSTRB = 0xC010, + + io_DISK_PHASE0_OFF = 0xC080, + io_DISK_PHASE0_ON = 0xC081, + io_DISK_PHASE1_OFF = 0xC082, + io_DISK_PHASE1_ON = 0xC083, + io_DISK_PHASE2_OFF = 0xC084, + io_DISK_PHASE2_ON = 0xC085, + io_DISK_PHASE3_OFF = 0xC086, + io_DISK_PHASE3_ON = 0xC087, + io_DISK_POWER_OFF = 0xC088, + io_DISK_POWER_ON = 0xC089, + io_DISK_SELECT_1 = 0xC08A, + io_DISK_SELECT_2 = 0xC08B, + io_DISK_READ = 0xC08C, + io_DISK_WRITE = 0xC08D, + io_DISK_CLEAR = 0xC08E, + io_DISK_SHIFT = 0xC08F, + +}; + #define PAGESIZE 256 #define PAGES 16 @@ -71,8 +102,79 @@ typedef union address16_u { } address16_t; +#define CASE_DISKII(x) \ + case io_DISK_PHASE0_OFF + SLOT##x: \ + printf("io_DISK_PHASE0_OFF (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE0_ON + SLOT##x: \ + printf("io_DISK_PHASE0_ON (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE1_OFF + SLOT##x: \ + printf("io_DISK_PHASE1_OFF (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE1_ON + SLOT##x: \ + printf("io_DISK_PHASE1_ON (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE2_OFF + SLOT##x: \ + printf("io_DISK_PHASE2_OFF (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE2_ON + SLOT##x: \ + printf("io_DISK_PHASE2_ON (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE3_OFF + SLOT##x: \ + printf("io_DISK_PHASE3_OFF (S%u)\n", x); \ + return 0; \ + case io_DISK_PHASE3_ON + SLOT##x: \ + printf("io_DISK_PHASE3_ON (S%u)\n", x); \ + return 0; \ + case io_DISK_POWER_OFF + SLOT##x: \ + printf("io_DISK_POWER_OFF (S%u)\n", x); \ + return 0; \ + case io_DISK_POWER_ON + SLOT##x: \ + printf("io_DISK_POWER_ON (S%u)\n", x); \ + return 0; \ + case io_DISK_SELECT_1 + SLOT##x: \ + printf("io_DISK_SELECT_1 (S%u)\n", x); \ + return 0; \ + case io_DISK_SELECT_2 + SLOT##x: \ + printf("io_DISK_SELECT_2 (S%u)\n", x); \ + return 0; \ + case io_DISK_READ + SLOT##x: \ + printf("io_DISK_READ (S%u)\n", x); \ + return 0; \ + case io_DISK_WRITE + SLOT##x: \ + printf("io_DISK_WRITE (S%u)\n", x); \ + return 0; \ + case io_DISK_CLEAR + SLOT##x: \ + printf("io_DISK_CLEAR (S%u)\n", x); \ + return 0; \ + case io_DISK_SHIFT + SLOT##x: \ + printf("io_DISK_SHIFT (S%u)\n", x); \ + return 0; + + +static const minDiskPhaseNum = 0; +static const maxDiskPhaseNum = 80; +static int trackPhase = maxDiskPhaseNum; + +struct phase_t { + uint8_t current : 2; + uint8_t last : 2; +} phase = {0}; + +static const int8_t phaseTransition[4][4] = { + { 0, -1, 0, +1 }, + { +1, 0, -1, 0 }, + { 0, +1, 0, -1 }, + { -1, 0, +1, 0 }, +}; + + + + INLINE uint8_t ioRead( uint16_t addr ) { -// printf("mmio read:%04X\n", addr); + dbgPrintf("mmio read:%04X\n", addr); + switch (addr) { case io_KBD: // if ( RAM[io_KBD] > 0x7F ) printf("io_KBD:%04X\n", addr); @@ -83,10 +185,68 @@ INLINE uint8_t ioRead( uint16_t addr ) { // printf("io_KBDSTRB\n"); return RAM[io_KBD] &= 0x7F; +// CASE_DISKII(6) + + // TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove + case io_DISK_PHASE0_OFF + SLOT6: + case io_DISK_PHASE1_OFF + SLOT6: + case io_DISK_PHASE2_OFF + SLOT6: + case io_DISK_PHASE3_OFF + SLOT6: + dbgPrintf2("io_DISK_PHASE%u_OFF (S%u)\n", phase.current, 6); + phase.last = phase.current; + return 0; + + case io_DISK_PHASE0_ON + SLOT6: + case io_DISK_PHASE1_ON + SLOT6: + case io_DISK_PHASE2_ON + SLOT6: + case io_DISK_PHASE3_ON + SLOT6: { + phase.current = (addr - io_DISK_PHASE0_ON - SLOT6) / 2; + trackPhase += phaseTransition[phase.current][phase.last]; + if ( trackPhase < minDiskPhaseNum ) { + trackPhase = minDiskPhaseNum; + } + if ( trackPhase > maxDiskPhaseNum ) { + trackPhase = maxDiskPhaseNum; + } + dbgPrintf2("io_DISK_PHASE%u_ON (S%u, trk:%u)\n", phase.current, 6, trackPhase); + return 0; + } + case io_DISK_POWER_OFF + SLOT6: + dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6); + return 0; + case io_DISK_POWER_ON + SLOT6: + dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6); + return 0; + case io_DISK_SELECT_1 + SLOT6: + dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6); + return 0; + case io_DISK_SELECT_2 + SLOT6: + dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6); + return 0; + case io_DISK_READ + SLOT6: + dbgPrintf("io_DISK_READ (S%u)\n", 6); + int track = woz_tmap.phase[trackPhase]; + if (trackOffset >= WOZ_TRACK_BYTE_COUNT ) { + trackOffset = 0; + } + printf("offs:%u\n", trackOffset); + return woz_trks[track].data[trackOffset++]; + case io_DISK_WRITE + SLOT6: + dbgPrintf2("io_DISK_WRITE (S%u)\n", 6); + return 0; + case io_DISK_CLEAR + SLOT6: + dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6); + return 0; + case io_DISK_SHIFT + SLOT6: + dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6); + return 0; + + + default: - break; + return RAM[addr]; } - return 0; + } @@ -135,6 +295,24 @@ 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 ]; +} +/** + Naive implementation of RAM read from address + **/ +INLINE uint16_t memread16( uint16_t addr ) { + return * (uint16_t*) (& RAM[ addr ]); +} + INLINE uint8_t memread( uint16_t addr ) { // switch ( ((address16_t)addr).page ) { // case 0xC0: @@ -159,29 +337,11 @@ INLINE uint8_t memread( uint16_t addr ) { // break; // } - if ( (addr >= 0xC000) && (addr < 0xD000) ) { + if ( (addr >= 0xC000) && (addr < 0xC0FF) ) { return ioRead(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 ]; -} -/** - Naive implementation of RAM read from address - **/ -INLINE uint16_t memread16( uint16_t addr ) { - return * (uint16_t*) (& RAM[ addr ]); + return memread8(addr); } /** @@ -222,7 +382,7 @@ static void memwrite( uint16_t addr, uint8_t byte ) { increase pc by one **/ INLINE uint8_t fetch() { - disHexB( disassembly.pHex, RAM[m6502.PC] ); + disHexB( disassembly.pOpcode, RAM[m6502.PC] ); return memread( m6502.PC++ ); } @@ -233,7 +393,7 @@ INLINE uint8_t fetch() { INLINE uint16_t fetch16() { uint16_t word = memread16( m6502.PC ); m6502.PC += 2; - disHexW( disassembly.pHex, word ); + disHexW( disassembly.pOpcode, word ); return word; } @@ -243,7 +403,7 @@ INLINE uint16_t fetch16() { **/ INLINE uint16_t addr_abs() { dbgPrintf("abs:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]), RAM[*((uint16_t*)&RAM[m6502.PC])]); - disPrintf(disassembly.addr, "$%04X", memread16(m6502.PC)) + disPrintf(disassembly.oper, "$%04X", memread16(m6502.PC)) return fetch16(); } INLINE uint8_t src_abs() { @@ -255,15 +415,15 @@ INLINE uint8_t * dest_abs() { INLINE int8_t rel_addr() { - disPrintf(disassembly.addr, "$%04X", m6502.PC + 1 + (int)memread8(m6502.PC)) + disPrintf(disassembly.oper, "$%04X", m6502.PC + 1 + (int8_t)memread8(m6502.PC)) return fetch(); } INLINE uint16_t abs_addr() { - disPrintf(disassembly.addr, "$%04X", memread16(m6502.PC)) + disPrintf(disassembly.oper, "$%04X", memread16(m6502.PC)) return fetch16(); } INLINE uint16_t ind_addr() { - disPrintf(disassembly.addr, "($%04X)", memread16(m6502.PC)) + disPrintf(disassembly.oper, "($%04X)", memread16(m6502.PC)) return memread16( fetch16() ); } @@ -273,11 +433,11 @@ INLINE uint16_t ind_addr() { **/ INLINE uint16_t addr_abs_X() { dbgPrintf("abs,X:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]) + m6502.X, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.X]); - disPrintf(disassembly.addr, "$%04X,X", memread16(m6502.PC)) + disPrintf(disassembly.oper, "$%04X,X", memread16(m6502.PC)) return fetch16() + m6502.X; } INLINE uint8_t src_abs_X() { - return memread8( addr_abs_X() ); + return memread( addr_abs_X() ); } INLINE uint8_t * dest_abs_X() { return & RAM[ addr_abs_X() ]; @@ -290,18 +450,18 @@ INLINE uint8_t * dest_abs_X() { **/ INLINE uint16_t addr_abs_Y() { dbgPrintf("abs,Y:%04X(%02X) ", *((uint16_t*)&RAM[m6502.PC]) + m6502.Y, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.Y]); - disPrintf(disassembly.addr, "$%04X,Y", memread16(m6502.PC)) - return abs_addr() + m6502.Y; + disPrintf(disassembly.oper, "$%04X,Y", memread16(m6502.PC)) + return fetch16() + m6502.Y; } INLINE uint8_t src_abs_Y() { - return memread8(addr_abs_Y()); + return memread(addr_abs_Y()); } INLINE uint8_t * dest_abs_Y() { return & RAM[ addr_abs_Y() ]; } INLINE uint16_t imm() { - disPrintf(disassembly.addr, "#$%02X", memread8(m6502.PC)) + disPrintf(disassembly.oper, "#$%02X", memread8(m6502.PC)) return fetch(); } @@ -312,7 +472,7 @@ INLINE uint16_t imm() { **/ INLINE uint8_t addr_zp() { dbgPrintf("zp:%02X(%02X) ", RAM[m6502.PC], RAM[ RAM[m6502.PC]] ); - disPrintf(disassembly.addr, "$%02X", memread8(m6502.PC)) + disPrintf(disassembly.oper, "$%02X", memread8(m6502.PC)) return fetch(); } INLINE uint8_t src_zp() { @@ -327,7 +487,7 @@ INLINE uint8_t * dest_zp() { **/ INLINE uint16_t addr_zp_ind( uint8_t addr ) { dbgPrintf("zpi:%02X:%04X(%02X) ", RAM[m6502.PC], *((uint16_t*)&RAM[m6502.PC]), RAM[*((uint16_t*)&RAM[m6502.PC])]); - disPrintf(disassembly.addr, "($%02X)", memread8(m6502.PC)) + disPrintf(disassembly.oper, "($%02X) {$%04X}", memread8(m6502.PC), memread16( memread8(m6502.PC) ) ) return memread16(addr); } @@ -338,11 +498,11 @@ INLINE uint16_t addr_zp_ind( uint8_t addr ) { **/ INLINE uint16_t addr_X_ind() { dbgPrintf("zpXi:%02X:%04X(%02X) ", RAM[m6502.PC], *((uint16_t*)&RAM[m6502.PC]) + m6502.X, RAM[*((uint16_t*)&RAM[m6502.PC]) + m6502.X]); - disPrintf(disassembly.addr, "($%02X,X)", memread8(m6502.PC)) - return addr_zp_ind( fetch() + m6502.X ); + disPrintf(disassembly.oper, "($%02X,X) {$%04X}", memread8(m6502.PC), memread16( memread8(m6502.PC) + m6502.X) ) + return memread16( fetch() + m6502.X ); } INLINE uint8_t src_X_ind() { - return memread8( addr_X_ind() ); + return memread( addr_X_ind() ); } INLINE uint8_t * dest_X_ind() { return & RAM[ addr_X_ind() ]; @@ -356,17 +516,17 @@ INLINE uint8_t * dest_X_ind() { INLINE uint16_t addr_ind_Y() { // uint8_t a = fetch(); // dbgPrintf("addr_ind_Y: %04X + %02X = %04X ", addr_zpg_ind( a ), m6502.Y, addr_zpg_ind( a ) + m6502.Y); - disPrintf(disassembly.addr, "($%02X),Y", memread8(m6502.PC)) - return addr_zp_ind( fetch() ) + m6502.Y; + disPrintf(disassembly.oper, "($%02X),Y {$%04X}", memread8(m6502.PC), memread16( memread8(m6502.PC) ) + m6502.Y) + return memread16( fetch() ) + m6502.Y; } INLINE uint8_t src_ind_Y() { - return memread8( addr_ind_Y() ); + return memread( addr_ind_Y() ); } INLINE uint8_t * dest_ind_Y() { uint16_t addr = addr_ind_Y(); - if ( (addr >= 0xC000) && (addr <= 0xC0FF) ) { - addr = 0xC111; - } +// if ( (addr >= 0xC000) && (addr <= 0xC0FF) ) { +// addr = 0xC111; +// } // return & RAM[ addr_abs_Y() ]; return & RAM[ addr ]; // return & RAM[ addr_ind_Y() ]; @@ -378,7 +538,7 @@ INLINE uint8_t * dest_ind_Y() { effective address is address incremented by X without carry ** **/ INLINE uint8_t addr_zp_X() { - disPrintf(disassembly.addr, "$%02X,X", memread8(m6502.PC)) + disPrintf(disassembly.oper, "$%02X,X", memread8(m6502.PC)) return fetch() + m6502.X; } INLINE uint8_t src_zp_X() { @@ -394,7 +554,7 @@ INLINE uint8_t * dest_zp_X() { effective address is address incremented by Y without carry ** **/ INLINE uint8_t addr_zp_Y() { - disPrintf(disassembly.addr, "$%02X,Y", memread8(m6502.PC)) + disPrintf(disassembly.oper, "$%02X,Y", memread8(m6502.PC)) return fetch() + m6502.Y; } INLINE uint8_t src_zp_Y() { diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index f7d781d..24ab6ff 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - - + + @@ -705,7 +705,7 @@ - + @@ -720,13 +720,13 @@ - + - + 1234567890123456789012345678901234567890 @@@@@@@@@1@@@@@@@@@2@@@@@@@@@3@@@@@@@@@4 @@ -753,10 +753,7 @@ @@@@@@@@@@@@@@@@@@23@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@24@@@@@@@@@@@@@@@@@@@@ - - - NSAllRomanInputSourcesLocaleIdentifier - +