From fe5f30114d90994e9b4d2355d93d49db52f39473 Mon Sep 17 00:00:00 2001 From: Tamas Rudnai Date: Tue, 17 Sep 2019 02:12:05 -0700 Subject: [PATCH] - Added debug breakpoints for 6502 function test - Fixed ADC/SBC in BCD mode - Added "burst" mode with sync to screen refresh - Reduced power consumption significantly - Speedometer on Screen --- A2Mac.xcodeproj/project.pbxproj | 4 + A2Mac/6502.c | 318 +++++++++++++++++---- A2Mac/6502.h | 14 +- A2Mac/Base.lproj/Main.storyboard | 17 +- A2Mac/ViewController.swift | 126 +++++--- A2Mac/common.h | 4 - A2Mac/instructions/6502_instr_arithmetic.h | 75 ++++- A2Mac/instructions/6502_instr_branch.h | 2 +- A2Mac/instructions/6502_instr_load_store.h | 11 +- 9 files changed, 447 insertions(+), 124 deletions(-) diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 8dcdff1..d6784b1 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -501,8 +501,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); + OTHER_CFLAGS = "-DFUNCTIONTEST"; + OTHER_SWIFT_FLAGS = "-DFUNCTIONTEST"; PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -525,6 +528,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); + OTHER_CFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h"; diff --git a/A2Mac/6502.c b/A2Mac/6502.c index df27a98..95ac9d6 100644 --- a/A2Mac/6502.c +++ b/A2Mac/6502.c @@ -43,21 +43,10 @@ ///// unsigned long long int clktime = 0; -m6502_t m6502 = {0}; +m6502_t m6502 = { 0, 0, 0, 0, 0, 0, 0, HLT }; -INLINE int m6502_step() { - -// switch ( fetch16() ) { -// case 0xFCD0: // D0 FC BNE -// BNE( 0xFC ); return 2; -// -// case 0x01E9: // E9 01 SBC -// SBC( 0x01 ) ; return 6; -// -// default: -// m6502.pc -= 2; -// +INLINE int m6502_Step() { #ifdef DEBUG switch ( m6502.PC ) { @@ -65,13 +54,180 @@ INLINE int m6502_step() { dbgPrintf("START...\n"); break; - case 0x9D1: - dbgPrintf("BREAK POINT...\n"); + case 0x0438: + dbgPrintf2("*** TEST 1 (%04X)\n", m6502.PC); break; - - case 0x35BD: - if ( ( m6502.A == 0x35 ) && ( m6502.C ) ) - dbgPrintf("BREAK POINT...\n"); + + case 0x0581: + dbgPrintf2("*** TEST 2 (%04X)\n", m6502.PC); + break; + + case 0x05C8: + dbgPrintf2("*** TEST 3 (%04X)\n", m6502.PC); + break; + + case 0x05FC: + dbgPrintf2("*** TEST 4 (%04X)\n", m6502.PC); + break; + + case 0x0776: + dbgPrintf2("*** TEST 5 (%04X)\n", m6502.PC); + break; + + case 0x0872: + dbgPrintf2("*** TEST 6 (%04X)\n", m6502.PC); + break; + + case 0x08A6: + dbgPrintf2("*** TEST 7 (%04X)\n", m6502.PC); + break; + + case 0x08F0: + dbgPrintf2("*** TEST 8 (%04X)\n", m6502.PC); + break; + + case 0x0946: + dbgPrintf2("*** TEST 9 (%04X)\n", m6502.PC); + break; + + case 0x0982: + dbgPrintf2("*** TEST 10 (%04X)\n", m6502.PC); + break; + + case 0x09B9: + dbgPrintf2("*** TEST 11 (%04X)\n", m6502.PC); + break; + + case 0x0A11: + dbgPrintf2("*** TEST 12 (%04X)\n", m6502.PC); + break; + + case 0x0AB7: + dbgPrintf2("*** TEST 13 (%04X)\n", m6502.PC); + break; + + case 0x0D7D: + dbgPrintf2("*** TEST 14 (%04X)\n", m6502.PC); + break; + + case 0x0E46: + dbgPrintf2("*** TEST 15 (%04X)\n", m6502.PC); + break; + + case 0x0F01: + dbgPrintf2("*** TEST 16 (%04X)\n", m6502.PC); + break; + + case 0x0F43: + dbgPrintf2("*** TEST 17 (%04X)\n", m6502.PC); + break; + + case 0x0FFA: + dbgPrintf2("*** TEST 18 (%04X)\n", m6502.PC); + break; + + case 0x103A: + dbgPrintf2("*** TEST 19 (%04X)\n", m6502.PC); + break; + + case 0x1330: + dbgPrintf2("*** TEST 20 (%04X)\n", m6502.PC); + break; + + case 0x162A: + dbgPrintf2("*** TEST 21 (%04X)\n", m6502.PC); + break; + + case 0x16DB: + dbgPrintf2("*** TEST 22 (%04X)\n", m6502.PC); + break; + + case 0x17FA: + dbgPrintf2("*** TEST 23 (%04X)\n", m6502.PC); + break; + + case 0x1899: + dbgPrintf2("*** TEST 24 (%04X)\n", m6502.PC); + break; + + case 0x1B63: + dbgPrintf2("*** TEST 25 (%04X)\n", m6502.PC); + break; + + case 0x1CB7: + dbgPrintf2("*** TEST 26 (%04X)\n", m6502.PC); + break; + + case 0x1DC5: + dbgPrintf("*** TEST 27 (%04X)\n", m6502.PC); + break; + + case 0x1ED3: + dbgPrintf2("*** TEST 28 (%04X)\n", m6502.PC); + break; + + case 0x22B7: + dbgPrintf2("*** TEST 29 (%04X)\n", m6502.PC); + break; + + case 0x23FB: + dbgPrintf2("*** TEST 30 (%04X)\n", m6502.PC); + break; + + case 0x257B: + dbgPrintf2("*** TEST 31 (%04X)\n", m6502.PC); + break; + + case 0x271F: + dbgPrintf2("*** TEST 32 (%04X)\n", m6502.PC); + break; + + case 0x289F: + dbgPrintf2("*** TEST 33 (%04X)\n", m6502.PC); + break; + + case 0x2A43: + dbgPrintf2("*** TEST 34 (%04X)\n", m6502.PC); + break; + + case 0x2AED: + dbgPrintf2("*** TEST 35 (%04X)\n", m6502.PC); + break; + + case 0x2BA7: + dbgPrintf2("*** TEST 36 (%04X)\n", m6502.PC); + break; + + case 0x2C55: + dbgPrintf2("*** TEST 37 (%04X)\n", m6502.PC); + break; + + case 0x2D13: + dbgPrintf2("*** TEST 38 (%04X)\n", m6502.PC); + break; + + case 0x3103: + dbgPrintf2("*** TEST 40 (%04X)\n", m6502.PC); + break; + + case 0x32FC: + dbgPrintf2("*** TEST 41 (%04X)\n", m6502.PC); + break; + + case 0x3361: + dbgPrintf2("*** TEST 42 (%04X)\n", m6502.PC); + break; + + case 0x3405: + dbgPrintf2("*** TEST 43 (%04X)\n", m6502.PC); + break; + + case 0x345D: + dbgPrintf2("*** TEST 44 (%04X)\n", m6502.PC); + break; + + case 0x3469: + dbgPrintf2("*** TEST PASSED (%04X)\n", m6502.PC); break; default: @@ -346,41 +502,56 @@ INLINE int m6502_step() { } const unsigned long long int iterations = G; +unsigned long long int inst_cnt = 0; + +const unsigned int fps = 30; +const unsigned int MHz_6502 = 1.023 * M; +const unsigned int clk_6502_per_frm = MHz_6502 / fps; unsigned long long tick_per_sec = G; unsigned long long tick_6502_per_sec = 0; -unsigned long long MHz_6502 = 1.023 * M; -static __attribute__((always_inline)) unsigned long long rdtsc(void) +INLINE unsigned long long rdtsc(void) { unsigned hi, lo; __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi) ); return ( (unsigned long long)lo) | ( ((unsigned long long)hi) << 32 ); } -// nanosec does not work very well for some reason -struct timespec tim, tim2; +unsigned long long ee = 0; +unsigned long long dd = 0; -INLINE void m6502_run() { +// nanosec does not work very well for some reason +struct timespec tim = { 0, 400L }; + +double mips = 0; +double mhz = 0; +unsigned long long epoch = 0; + +void m6502_Run() { + unsigned int clk = 0; + unsigned int clkfrm = 0; + // init time #ifdef CLK_WAIT - unsigned long long s = rdtsc(); - unsigned long long e = (unsigned long long)-1LL; + unsigned long long elpased = (unsigned long long)-1LL; #endif #ifdef SPEED_TEST for ( unsigned long long int i = 0; i < iterations ; i++ ) +#elif defined( CLK_WAIT ) + for ( clkfrm = 0; clkfrm < clk_6502_per_frm ; clkfrm += clk ) #else // for ( ; m6502.pc ; ) - - tim.tv_sec = 0; - tim.tv_nsec = 500L; - for ( ; ; ) #endif { if ( m6502.IF ) { switch (m6502.interrupt) { + case HLT: + // CPU is haletd, nothing to do here... + return; + case NMI: break; @@ -397,55 +568,84 @@ INLINE void m6502_run() { m6502.IF = 0; } - - dbgPrintf("%llu %04X: ", clktime, m6502.PC); - clktime += m6502_step(); + dbgPrintf("%llu %04X: ", clktime, m6502.PC); + clktime += clk = m6502_Step(); + + dbgPrintf("\nA:%02X X:%02X Y:%02X SP:%02X %c%c%c%c%c%c%c%c\n", + m6502.A, + m6502.X, + m6502.Y, + m6502.SP, + m6502.N ? 'N' : 'n', + m6502.V ? 'V' : 'v', + m6502.res ? 'R' : 'r', + m6502.B ? 'B' : 'b', + m6502.D ? 'D' : 'd', + m6502.I ? 'I' : 'i', + m6502.Z ? 'Z' : 'z', + m6502.C ? 'C' : 'c' + ); + #ifdef CLK_WAIT - e = tick_6502_per_sec * clktime; +// ee += tick_6502_per_sec * clk; +// ee /= 2; +// dd += rdtsc() - epoch - elpased; +// dd /= 2; + + // get the new time in ticks needed to simulate exact 6502 clock + elpased = tick_6502_per_sec * clktime; + // query time + wait // TODO: We should use nanosleep - usleep(1); // this is good enough for debugging +// usleep(1); // this is good enough for debugging -// nanosleep(&tim, &tim2); +// nanosleep(&tim, NULL); + +// printf(" tps:%llu s:%llu t:%llu d:%llu e:%llu n:%llu\n", tick_6502_per_sec, s, t, t - s, e, e - (t - s)); // tight loop gives us the most precise wait time -// while ( rdtsc() - s < e ) {} +// while ( rdtsc() - epoch < elpased ) {} #endif - dbgPrintf("\n"); } + + // clock_t end = clock(); + // double execution_time = ((double) (end - start)) / CLOCKS_PER_SEC; +// unsigned long long e = rdtsc(); +// unsigned long long t = e - epoch; +// double execution_time = (double)t / tick_per_sec; +// +// mips = inst_cnt / (execution_time * M); +// mhz = clktime / (execution_time * M); } -void init() { - unsigned long long s = rdtsc(); +void m6502_Reset() { + inst_cnt = 0; + mhz = (double)MHz_6502 / M; + + epoch = rdtsc(); sleep(1); unsigned long long e = rdtsc(); - tick_per_sec = e - s; + tick_per_sec = e - epoch; tick_6502_per_sec = tick_per_sec / MHz_6502; memset( RAM, 0, sizeof(RAM) ); - - -// RAM[ 0 ] = 0x4C; -// RAM[ 1 ] = 0; -// RAM[ 2 ] = 0; -// -// RAM[ 0xBFFD ] = 0x4C; -// RAM[ 0xBFFE ] = 0; -// RAM[ 0xBFFF ] = 0; m6502.A = m6502.X = m6502.Y = 0xFF; // reset vector m6502.SP = 0xFF -3; - m6502.SR = 0x30; + + // N V - B D I Z C + // 0 0 1 1 0 1 0 0 + m6502.SR = 0x34; + + m6502.IF = 0; // memory size *((uint16_t*)(&RAM[0x73])) = 0xC000; -#define NO_FUNCTIONTEST - #ifdef FUNCTIONTEST FILE * f = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/6502_functional_test.bin", "rb"); if (f == NULL) { @@ -582,20 +782,22 @@ void tst6502() { // insert code here... printf("6502\n"); - init(); + m6502_Reset(); // clock_t start = clock(); - unsigned long long s = rdtsc(); - m6502_run(); + epoch = rdtsc(); + m6502_Run(); // clock_t end = clock(); // double execution_time = ((double) (end - start)) / CLOCKS_PER_SEC; unsigned long long e = rdtsc(); - unsigned long long t = e - s; + unsigned long long t = e - epoch; double execution_time = (double)t / tick_per_sec; - double mips = iterations / (execution_time * M); + double mips = inst_cnt / (execution_time * M); double mhz = clktime / (execution_time * M); printf("clk:%llu Elpased time: (%llu / %llu / %llu), %.3lfs (%.3lf MIPS, %.3lf MHz)\n", clktime, 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); + } int ___main(int argc, const char * argv[]) { diff --git a/A2Mac/6502.h b/A2Mac/6502.h index a92ec2a..1f537be 100644 --- a/A2Mac/6502.h +++ b/A2Mac/6502.h @@ -12,12 +12,16 @@ #import "stdint.h" #ifdef DEBUG -#define dbgPrintf(format, ...) printf (format, ## __VA_ARGS__) +#define dbgPrintf(format, ...) +#define dbgPrintf2(format, ...) printf (format, ## __VA_ARGS__) #else #define dbgPrintf(format, ...) +#define dbgPrintf2(format, ...) #endif typedef enum { + NO_INT, + HLT, NMI, HARDRESET, SOFTRESET, @@ -53,7 +57,7 @@ typedef struct m6502_s { unsigned clk; // Clock Counter union { - int IF; // interrut flag + unsigned int IF; // interrut flag interrupt_t interrupt; }; } m6502_t; @@ -62,7 +66,11 @@ typedef struct m6502_s { extern m6502_t m6502; extern uint8_t RAM[ 64 * 1024 ]; -extern void tst6502(); +extern double mips; +extern double mhz; +extern void tst6502(); +extern void m6502_Reset(); +extern void m6502_Run(); #endif /* __6502_H__ */ diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index c4b8024..d9a6173 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -714,7 +714,7 @@ - + @@ -746,12 +746,26 @@ + + + + + + + + + + + + + + @@ -762,6 +776,7 @@ + diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index 29b90af..46f3dd4 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -11,7 +11,8 @@ import Cocoa class ViewController: NSViewController { @IBOutlet weak var display: NSTextFieldCell! - + @IBOutlet weak var speedometer: NSTextFieldCell! + // static let charConvStr : String = // "@πŸ„°πŸ„±πŸ„²πŸ„³πŸ„΄πŸ„΅πŸ„ΆπŸ„·πŸ„ΈπŸ„ΉπŸ„ΊπŸ„»πŸ„ΌπŸ„½πŸ„ΎπŸ„ΏπŸ…€πŸ…πŸ…‚πŸ…ƒπŸ…„πŸ……πŸ…†πŸ…‡πŸ…ˆπŸ…‰[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?" + // "@πŸ…°πŸ…±πŸ…²πŸ…³πŸ…΄πŸ…΅πŸ…ΆπŸ…·πŸ…ΈπŸ…ΉπŸ…ΊπŸ…»πŸ…ΌπŸ…½πŸ…ΎπŸ…ΏπŸ†€πŸ†πŸ†‚πŸ†ƒπŸ†„πŸ†…πŸ††πŸ†‡πŸ†ˆπŸ†‰[\\]^_β¬›οΈŽ!\"#$%&'()*+,-./0123456789:;<=>?" + // FL @@ -33,20 +34,22 @@ class ViewController: NSViewController { var workItem : DispatchWorkItem? = nil; @IBAction func Power(_ sender: Any) { - if ( workItem != nil ) { - workItem!.cancel(); - workItem = nil; - } - else { - workItem = DispatchWorkItem { +// if ( workItem != nil ) { +// workItem!.cancel(); +// workItem = nil; +// } +// else { +// workItem = DispatchWorkItem { // DispatchQueue.global(qos: .userInteractive).async { -// DispatchQueue.global(qos: .userInitiated).async { - DispatchQueue.global(qos: .background).async { - tst6502() - } - } - DispatchQueue.global().async(execute: workItem!); - } +//// DispatchQueue.global(qos: .userInitiated).async { +//// DispatchQueue.global(qos: .background).async { +// tst6502() +// } +// } +// DispatchQueue.global().async(execute: workItem!); +// } + + m6502_Reset() } @IBAction func Reset(_ sender: Any) { @@ -89,7 +92,7 @@ class ViewController: NSViewController { default: break } - print("keycode: \(code) --> \(A2code)") +// print("keycode: \(code) --> \(A2code)") let kbdPointer = UnsafeMutableRawBufferPointer(start: &RAM + 0xC000, count: 1) kbdPointer[0] = A2code @@ -137,37 +140,74 @@ class ViewController: NSViewController { } - func update() { + let textBaseAddr = 0x400 + let textBufferSize = 0x400 + let textLines = 24 + let textCols = 40 + + var frameCnt = 0 + let spaceChar : Character = " " + let blockChar : Character = "β–‘" + var flashingSpace : Character = " " + + let textBufferPointer = UnsafeRawBufferPointer(start: &RAM + 0x400, count: 0x400) + var txtArr = [Character](repeating: " ", count: 0x400) + + var s = String() + + func Update() { -// while true { -// usleep(33333) // 1/30 sec + m6502_Run() + + frameCnt += 1 + if ( frameCnt == 15 ) { + flashingSpace = blockChar + } + else if ( frameCnt >= 30 ) { + flashingSpace = spaceChar + frameCnt = 0 + } + + var txt : String = "" - let textBaseAddr = 0x400 - let textLines = 24 - let textCols = 40 - - var txt : String = "" - - for y in 0...textLines-1 { - let textAddr = textBaseAddr + textLineOfs[y] - let textBufferPointer = UnsafeRawBufferPointer(start: &RAM + textAddr, count: textCols) - - for (_, byte) in textBufferPointer.enumerated() { - let idx = Int(byte); - let chr = ViewController.charConvTbl[idx] - // print("byte \(index): \(chr)") - txt = txt + "\(chr)" + for y in 0...textLines-1 { +// let textAddr = textBaseAddr + textLineOfs[y] + for x in 0...textCols-1 { + let byte = textBufferPointer[ textLineOfs[y] + x ] + let idx = Int(byte); + var chr = ViewController.charConvTbl[idx] + // is it a cursor? (slashing space) + if ( chr == blockChar ) { + chr = flashingSpace } - - txt = txt + "\n" + // print("byte \(index): \(chr)") +// txt = txt + "\(chr)" + txtArr[ y * (textCols+1) + x ] = chr } + +// for (_, byte) in textBufferPointer.enumerated() { +// let idx = Int(byte); +// var chr = ViewController.charConvTbl[idx] +// // is it a cursor? (slashing space) +// if ( chr == blockChar ) { +// chr = flashingSpace +// } +// // print("byte \(index): \(chr)") +// txt = txt + "\(chr)" +// } - DispatchQueue.main.async { - self.display.stringValue = txt; - } -// } +// txt = txt + "\n" + txtArr[ y * (textCols+1) + textCols ] = "\n" + } +// txtArr[ textLines * (textCols+1) + textCols ] = "\0" + txt = String(txtArr) + + DispatchQueue.main.async { + self.display.stringValue = txt; + self.speedometer.stringValue = String(format: "%0.3lf MHz", mhz); + } } @@ -190,17 +230,17 @@ class ViewController: NSViewController { // self.update() // }) - #if FUNCTIONTEST - #else +// #if FUNCTIONTEST +// #else // DispatchQueue.global(qos: .background).async { // self.update() // } upd.eventHandler = { - self.update() + self.Update() } upd.resume() - #endif +// #endif } override var representedObject: Any? { diff --git a/A2Mac/common.h b/A2Mac/common.h index e1978c6..483c1d1 100644 --- a/A2Mac/common.h +++ b/A2Mac/common.h @@ -43,22 +43,18 @@ union { INLINE void set_flags_N( const uint8_t test ) { m6502.N = BITTEST(test, 7); - dbgPrintf("%c", m6502.N ? 'N' : 'n'); } INLINE void set_flags_V( const uint8_t test ) { m6502.V = BITTEST(test, 6); - dbgPrintf("%c", m6502.V ? 'V' : 'v'); } INLINE void set_flags_Z( const uint8_t test ) { m6502.Z = test == 0; - dbgPrintf("%c", m6502.Z ? 'Z' : 'z'); } INLINE void set_flags_C( const int16_t test ) { m6502.C = test >= 0; - dbgPrintf("%c", m6502.C ? 'C' : 'c'); } INLINE void set_flags_NZ( const uint8_t test ) { diff --git a/A2Mac/instructions/6502_instr_arithmetic.h b/A2Mac/instructions/6502_instr_arithmetic.h index 1e79fb0..849fd77 100644 --- a/A2Mac/instructions/6502_instr_arithmetic.h +++ b/A2Mac/instructions/6502_instr_arithmetic.h @@ -30,14 +30,50 @@ (indirect),Y ADC (oper),Y 71 2 5* **/ INLINE void ADC( uint8_t src ) { - dbgPrintf("ADC(%02X) A:%02X + %02X ", src, m6502.A, src); - + dbgPrintf("ADC(%02X) ", src); + uint16_t tmp; - set_flags_NZ( m6502.A = tmp = (uint16_t)m6502.A + src + m6502.C ); - m6502.V = (!((m6502.A ^ src) & 0x80)) && ((m6502.A ^ tmp) & 0x80); - m6502.C = tmp > 0xFF; + + // V = C7 != C6 + m6502.V = ((m6502.A & 0x7F) + (src & 0x7F) + m6502.C) > 0x7F; + + if ( m6502.D ) { + if ( (tmp = (m6502.A & 0x0F) + (src & 0x0F) + m6502.C) > 0x09 ) { + tmp += 0x06; + } + if ( (tmp += (m6502.A & 0xF0) + (src & 0xF0)) > 0x99 ) { + tmp += 0x60; + } + +// tmp = m6502.A + src + m6502.C; +// +// if ( (tmp & 0x0F) > 0x09 ) { +// tmp += 0x06; +// } +// if ( tmp > 0x99 ) { +// tmp += 0x60; +// } + } + else { + tmp = (uint16_t)m6502.A + src + m6502.C; + } + + set_flags_NZ( m6502.A = tmp ); + m6502.C = tmp > 0xFF; + m6502.V ^= m6502.C; + +// // this is good but slow: +// uint16_t tmp = (uint16_t)m6502.A + src + m6502.C; +// m6502.V = ( !((m6502.A ^ src) & 0x80)) && ( (m6502.A ^ tmp) & 0x80); +// m6502.C = tmp > 0xFF; +// set_flags_NZ( m6502.A = tmp ); + +// // this is good but slow: +// uint16_t tmp = (uint16_t)m6502.A + src + m6502.C; +// m6502.V = ( ((m6502.A ^ src) ^ (m6502.A ^ tmp)) & 0x80 ) != 0; +// m6502.C = tmp > 0xFF; +// set_flags_NZ( m6502.A = tmp ); - dbgPrintf("-> A:%02X ", m6502.A); } /** @@ -59,7 +95,32 @@ INLINE void ADC( uint8_t src ) { **/ INLINE void SBC( uint8_t src ) { dbgPrintf("SBC(%02X) ", src); - ADC( ~src ); +// ADC( ~src ); + + uint16_t tmp; + + if( m6502.D ) { + tmp = (m6502.A & 0x0F) - ( src & 0x0F ) - !m6502.C; + if( (tmp & 0x10) != 0) { + tmp = ( (tmp - 0x06 ) & 0x0F ) | ( (m6502.A & 0xF0) - (src & 0xF0) - 0x10 ); + } + else { + tmp = (tmp & 0x0F) | ( (m6502.A & 0xF0) - (src & 0xF0) ); + } + + if(( tmp & 0x100 ) != 0) { + tmp -= 0x60; + } + } + else + { + tmp = m6502.A - src - !m6502.C; + } + + m6502.C = tmp < 0x100; + + m6502.V = ( (m6502.A ^ tmp) & 0x80 ) && ( (m6502.A ^ src) & 0x80 ); + set_flags_NZ( m6502.A = tmp ); } #endif // __6502_INSTR_ARITHMETIC_H__ diff --git a/A2Mac/instructions/6502_instr_branch.h b/A2Mac/instructions/6502_instr_branch.h index 0b84efb..070b780 100644 --- a/A2Mac/instructions/6502_instr_branch.h +++ b/A2Mac/instructions/6502_instr_branch.h @@ -13,7 +13,7 @@ INLINE void BRA( int8_t reladdr ) { m6502.PC += reladdr; #ifdef DEBUG if ( reladdr == -2 ) { - dbgPrintf("Infinite Loop at %04X!\n", m6502.PC); + dbgPrintf2("Infinite Loop at %04X!\n", m6502.PC); } #endif dbgPrintf("BRA %04X ", m6502.PC); diff --git a/A2Mac/instructions/6502_instr_load_store.h b/A2Mac/instructions/6502_instr_load_store.h index 653edbb..e384776 100644 --- a/A2Mac/instructions/6502_instr_load_store.h +++ b/A2Mac/instructions/6502_instr_load_store.h @@ -31,8 +31,7 @@ **/ INLINE void LDA( uint8_t src ) { dbgPrintf("LDA(%02X) ", src); - m6502.A = src; - set_flags_NZ(src); + set_flags_NZ(m6502.A = src); } /** @@ -51,8 +50,7 @@ INLINE void LDA( uint8_t src ) { **/ INLINE void LDX( uint8_t src ) { dbgPrintf("LDX(%02X) ", src); - m6502.X = src; - set_flags_NZ(src); + set_flags_NZ(m6502.X = src); } /** @@ -71,8 +69,7 @@ INLINE void LDX( uint8_t src ) { **/ INLINE void LDY( uint8_t src ) { dbgPrintf("LDY(%02X) ", src); - m6502.Y = src; - set_flags_NZ(src); + set_flags_NZ(m6502.Y = src); } @@ -90,7 +87,7 @@ char * charConv = (not a real instruction, only a helper function) **/ INLINE void STR( uint8_t * dst, uint8_t src ) { - dbgPrintf("STR %02X -> %04X ", src, (int)(dst - RAM)); + dbgPrintf("STR [%04X], %02X ", (int)(dst - RAM), src ); *dst = src; // uint16_t addr = dst - RAM;