mirror of
https://github.com/trudnai/Steve2.git
synced 2025-04-14 05:37:32 +00:00
- 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:
parent
26c413df6b
commit
fe5f30114d
@ -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";
|
||||
|
318
A2Mac/6502.c
318
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[]) {
|
||||
|
14
A2Mac/6502.h
14
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__ */
|
||||
|
@ -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"/>
|
||||
|
@ -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? {
|
||||
|
@ -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 ) {
|
||||
|
@ -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__
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user