- 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
This commit is contained in:
Tamas Rudnai 2019-09-17 02:12:05 -07:00
parent 26c413df6b
commit fe5f30114d
9 changed files with 447 additions and 124 deletions

View File

@ -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";

View File

@ -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[]) {

View File

@ -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__ */

View File

@ -714,7 +714,7 @@
<constraint firstAttribute="width" constant="700" id="YGY-gy-pSn"/>
<constraint firstAttribute="height" constant="420" id="dWL-EL-ab7"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" enabled="NO" allowsUndo="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="border" alignment="justified" placeholderString="Apple ][ Emulator Virtual Monitor" drawsBackground="YES" id="5AO-Gd-Lzo">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" enabled="NO" allowsUndo="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="border" placeholderString="Apple ][ Emulator Virtual Monitor" drawsBackground="YES" id="5AO-Gd-Lzo">
<font key="font" size="14" name="Courier-Bold"/>
<color key="textColor" name="systemGreenColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" red="0.12549019607843137" green="0.17933968321917809" blue="0.12549019607843137" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -746,12 +746,26 @@
</connections>
</buttonCell>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FZk-VW-alq">
<rect key="frame" x="718" y="20" width="84" height="17"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="ai1-6C-5tW"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Label" id="FBZ-dh-6Fs">
<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>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="mfd-12-bcR" secondAttribute="trailing" constant="10" id="3NC-0i-OPC"/>
<constraint firstAttribute="trailing" secondItem="rR3-9T-NFu" secondAttribute="trailing" constant="10" id="68s-0C-BVZ"/>
<constraint firstItem="FZk-VW-alq" firstAttribute="leading" secondItem="Uza-t6-XSw" secondAttribute="trailing" constant="10" id="Aab-ZA-fW3"/>
<constraint firstItem="mfd-12-bcR" firstAttribute="leading" secondItem="Uza-t6-XSw" secondAttribute="trailing" constant="10" id="CFN-hq-O5V"/>
<constraint firstItem="Uza-t6-XSw" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" constant="10" id="Dmb-dB-rhg"/>
<constraint firstAttribute="bottom" secondItem="FZk-VW-alq" secondAttribute="bottom" constant="20" id="E2f-MY-c2Y"/>
<constraint firstAttribute="trailing" secondItem="FZk-VW-alq" secondAttribute="trailing" constant="10" id="Q0s-uC-GPT"/>
<constraint firstAttribute="trailing" secondItem="Uza-t6-XSw" secondAttribute="trailing" constant="100" id="UBG-e6-psp"/>
<constraint firstAttribute="bottom" secondItem="Uza-t6-XSw" secondAttribute="bottom" constant="10" id="agC-TV-DPy"/>
<constraint firstItem="Uza-t6-XSw" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" constant="10" id="kDF-dq-M0E"/>
@ -762,6 +776,7 @@
</view>
<connections>
<outlet property="display" destination="5AO-Gd-Lzo" id="Khc-vv-2HB"/>
<outlet property="speedometer" destination="FBZ-dh-6Fs" id="L0v-RY-xwB"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>

View File

@ -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? {

View File

@ -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 ) {

View File

@ -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__

View File

@ -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);

View File

@ -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;