mirror of
https://github.com/trudnai/Steve2.git
synced 2025-04-09 04:37:06 +00:00
- Reads WOZ files! DOS compatibility only for now
- MHz can be changed from GUI
This commit is contained in:
parent
fddb1d9642
commit
ace3a8f68e
@ -652,9 +652,9 @@
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DDISASSEMBLER",
|
||||
"-DINTERRUPR_CHECK_PER_STEP",
|
||||
"-DINTERRUPT_CHECK_PER_STEP",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-D_NO_HIRES -D_NO_HIRESDRAW -D_NO_HIRESLOW";
|
||||
OTHER_SWIFT_FLAGS = "-D_NO_HIRES -DHIRESDRAW -D_NO_HIRESLOW";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
@ -683,9 +683,9 @@
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DDISASSEMBLER",
|
||||
"-DINTERRUPR_CHECK_PER_STEP",
|
||||
"-DINTERRUPT_CHECK_PER_STEP",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-D_NO_HIRES -D_NO_HIRESDRAW -D_NO_HIRESLOW";
|
||||
OTHER_SWIFT_FLAGS = "-D_NO_HIRES -DHIRESDRAW -D_NO_HIRESLOW";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h";
|
||||
|
88
A2Mac/6502.c
88
A2Mac/6502.c
@ -9,6 +9,7 @@
|
||||
#define CLK_WAIT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@ -27,6 +28,10 @@ woz_tmap_t woz_tmap;
|
||||
woz_trks_t woz_trks;
|
||||
|
||||
uint16_t trackOffset = 0;
|
||||
uint8_t bitOffset = 0;
|
||||
|
||||
FILE * outdev = NULL;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define INLINE
|
||||
@ -47,8 +52,9 @@ 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; // 2 * M; // 4 * M; // 8 * M; // 16 * M; // 128 * M; // 256 * M; // 512 * M;
|
||||
const unsigned int clk_6502_per_frm = MHz_6502 / fps;
|
||||
const unsigned long long default_MHz_6502 = 1.023 * M; // 2 * M; // 4 * M; // 8 * M; // 16 * M; // 128 * M; // 256 * M; // 512 * M;
|
||||
unsigned long long MHz_6502 = default_MHz_6502;
|
||||
unsigned long long clk_6502_per_frm = default_MHz_6502 / fps;
|
||||
|
||||
unsigned long long tick_per_sec = G;
|
||||
unsigned long long tick_6502_per_sec = 0;
|
||||
@ -151,9 +157,9 @@ void hires_Update () {
|
||||
#include "6502_instructions.h"
|
||||
|
||||
/////
|
||||
#ifdef SPEEDTEST
|
||||
//#ifdef SPEEDTEST
|
||||
unsigned long long int clktime = 0;
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
INLINE int m6502_Step() {
|
||||
|
||||
@ -680,7 +686,7 @@ void m6502_Run() {
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef INTERRUPR_CHECK_PER_STEP
|
||||
#ifdef INTERRUPT_CHECK_PER_STEP
|
||||
if ( m6502.IF ) {
|
||||
switch (m6502.interrupt) {
|
||||
case HLT:
|
||||
@ -725,29 +731,29 @@ void m6502_Run() {
|
||||
|
||||
m6502.IF = 0;
|
||||
}
|
||||
#endif // INTERRUPR_CHECK_PER_STEP
|
||||
#endif // INTERRUPT_CHECK_PER_STEP
|
||||
|
||||
// dbgPrintf("%llu %04X: ", clktime, m6502.PC);
|
||||
#ifdef SPEEDTEST
|
||||
//#ifdef SPEEDTEST
|
||||
clktime +=
|
||||
#endif
|
||||
//#endif
|
||||
clk = m6502_Step();
|
||||
printDisassembly();
|
||||
printDisassembly( outdev );
|
||||
|
||||
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,
|
||||
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'
|
||||
);
|
||||
// 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,
|
||||
// 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
|
||||
// ee += tick_6502_per_sec * clk;
|
||||
@ -868,21 +874,15 @@ void m6502_ColdReset() {
|
||||
tick_per_sec = e - epoch;
|
||||
tick_6502_per_sec = tick_per_sec / MHz_6502;
|
||||
|
||||
memset( RAM, 0xFF, sizeof(Apple2_64K_RAM) );
|
||||
memset( RAM, 0, 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;
|
||||
|
||||
// N V - B D I Z C
|
||||
// 0 0 1 1 0 1 0 0
|
||||
m6502.SR = 0x34;
|
||||
|
||||
m6502.IF = 0;
|
||||
outdev = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/disassembly_new.log", "w+");
|
||||
if (outdev == NULL) {
|
||||
outdev = stdout;
|
||||
}
|
||||
|
||||
|
||||
// memory size
|
||||
// *((uint16_t*)(&RAM[0x73])) = 0xC000;
|
||||
|
||||
#ifdef FUNCTIONTEST
|
||||
FILE * f = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/6502_functional_test.bin", "rb");
|
||||
@ -900,13 +900,29 @@ void m6502_ColdReset() {
|
||||
// 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);
|
||||
read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DISK_II_C600.ROM", 0xC600);
|
||||
|
||||
// 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");
|
||||
|
||||
// read_woz("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Merlin-8 v2.48 (DOS 3.3).woz");
|
||||
// read_woz("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DOS3.3.Launcher.2.2.woz");
|
||||
read_woz("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Apple DOS 3.3 January 1983.woz");
|
||||
|
||||
m6502.A = m6502.X = m6502.Y = 0xFF;
|
||||
// reset vector
|
||||
m6502.SP = 0xFF; //-3;
|
||||
|
||||
// N V - B D I Z C
|
||||
// 0 0 1 0 0 1 0 0
|
||||
m6502.SR = 0x24;
|
||||
|
||||
m6502.IF = 0;
|
||||
|
||||
// memory size
|
||||
//*((uint16_t*)(&RAM[0x73])) = 0xC000;
|
||||
|
||||
m6502.PC = memread16( RESET_VECTOR );
|
||||
#endif
|
||||
|
||||
|
@ -11,10 +11,14 @@
|
||||
|
||||
#import <stdint.h>
|
||||
|
||||
extern unsigned long long MHz_6502;
|
||||
extern unsigned long long clk_6502_per_frm;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
//#define dbgPrintf(format, ...) printf (format, ## __VA_ARGS__)
|
||||
#define dbgPrintf(format, ...)
|
||||
#define dbgPrintf2(format, ...) printf (format, ## __VA_ARGS__)
|
||||
#define dbgPrintf2(format, ...) if(outdev) fprintf(outdev, format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define dbgPrintf(format, ...)
|
||||
#define dbgPrintf2(format, ...)
|
||||
|
@ -12,9 +12,22 @@
|
||||
#include "common.h"
|
||||
#include "6502.h"
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t latch;
|
||||
uint8_t shift;
|
||||
};
|
||||
struct {
|
||||
uint16_t lower15 : 15;
|
||||
uint16_t valid : 1;
|
||||
};
|
||||
uint16_t shift16;
|
||||
} WOZread_t;
|
||||
|
||||
uint8_t Apple2_64K_RAM[ 64 * KB ] = {0};
|
||||
uint8_t * RAM = Apple2_64K_RAM;
|
||||
WOZread_t WOZread = {0};
|
||||
|
||||
|
||||
enum slot {
|
||||
SLOT0 = 0x00,
|
||||
@ -153,28 +166,106 @@ typedef union address16_u {
|
||||
return 0;
|
||||
|
||||
|
||||
static const minDiskPhaseNum = 0;
|
||||
static const maxDiskPhaseNum = 80;
|
||||
static int trackPhase = maxDiskPhaseNum;
|
||||
static const int minDiskPhaseNum = 0;
|
||||
static const int maxDiskPhaseNum = 79;
|
||||
|
||||
struct phase_t {
|
||||
uint8_t current : 2;
|
||||
uint8_t last : 2;
|
||||
} phase = {0};
|
||||
uint8_t lastMagnet : 4;
|
||||
uint8_t magnet : 4;
|
||||
int count;
|
||||
} phase = { 0, 0, 0 };
|
||||
|
||||
static const int8_t phaseTransition[4][4] = {
|
||||
{ 0, -1, 0, +1 },
|
||||
{ +1, 0, -1, 0 },
|
||||
{ 0, +1, 0, -1 },
|
||||
{ -1, 0, +1, 0 },
|
||||
//static const int8_t phaseTransition[4][4] = {
|
||||
// { 0, -1, 0, +1 },
|
||||
// { +1, 0, -1, 0 },
|
||||
// { 0, +1, 0, -1 },
|
||||
// { -1, 0, +1, 0 },
|
||||
//};
|
||||
|
||||
//static const int phaseTransition[16][16] = {
|
||||
//// 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0000
|
||||
// { 0, 0, -2, -1, 0, 0, 0, 0, +2, +1, 0, 0, 0, 0, 0, 0 }, // 0001
|
||||
// { 0, +2, 0, +1, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0010
|
||||
// { 0, +1, -1, 0, 0, 0, -2, 0, 0, +2, 0, 0, 0, 0, 0, 0 }, // 0011
|
||||
// { 0, 0, +2, 0, 0, 0, +1, 0, -2, 0, 0, 0, -1, 0, 0, 0 }, // 0100
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0101
|
||||
// { 0, 0, +1, +2, -1, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0 }, // 0110
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0111
|
||||
// { 0, -2, 0, 0, +2, 0, 0, 0, 0, -1, 0, 0, +1, 0, 0, 0 }, // 1000
|
||||
// { 0, -1, 0, -2, 0, 0, 0, 0, +1, 0, 0, 0, +2, 0, 0, 0 }, // 1001
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1010
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1011
|
||||
// { 0, 0, 0, 0, +1, 0, +2, 0, -1, -2, 0, 0, 0, 0, 0, 0 }, // 1100
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1101
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1110
|
||||
// { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1111
|
||||
//};
|
||||
|
||||
|
||||
// Magnet States --> Stepper Motor Position
|
||||
//
|
||||
// N
|
||||
// 0001
|
||||
// NW | NE
|
||||
// 1001 | 0011
|
||||
// |
|
||||
// W 1000 ------- o ------- 0010 E
|
||||
// |
|
||||
// 1100 | 0110
|
||||
// SW | SE
|
||||
// 0100
|
||||
// S
|
||||
|
||||
// motor position from the magnet state
|
||||
// -1 means invalid, not supported
|
||||
static const int magnet_to_Poistion[16] = {
|
||||
// 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
|
||||
-1, 0, 2, 1, 4, -1, 3, -1, 6, 7, -1, -1, 5, -1, -1, -1
|
||||
};
|
||||
|
||||
static const int position_to_direction[8][8] = {
|
||||
// N NE E SE S SW W NW
|
||||
// 0 1 2 3 4 5 6 7
|
||||
{ 0, 1, 2, 3, 0, -3, -2, -1 }, // 0 N
|
||||
{ -1, 0, 1, 2, 3, 0, -3, -2 }, // 1 NE
|
||||
{ -2, -1, 0, 1, 2, 3, 0, -3 }, // 2 E
|
||||
{ -3, -2, -1, 0, 1, 2, 3, 0 }, // 3 SE
|
||||
{ 0, -3, -2, -1, 0, 1, 2, 3 }, // 4 S
|
||||
{ 3, 0, -3, -2, -1, 0, 1, 2 }, // 5 SW
|
||||
{ 2, 3, 0, -3, -2, -1, 0, 1 }, // 6 W
|
||||
{ 1, 2, 3, 0, -3, -2, -1, 0 }, // 7 NW
|
||||
};
|
||||
|
||||
|
||||
INLINE void diskII_phase() {
|
||||
|
||||
int position = magnet_to_Poistion[phase.magnet];
|
||||
if ( position >= 0 ) {
|
||||
int lastPosition = phase.count & 7;
|
||||
int direction = position_to_direction[lastPosition][position];
|
||||
|
||||
phase.count += direction;
|
||||
if ( phase.count < minDiskPhaseNum ) {
|
||||
phase.count = minDiskPhaseNum;
|
||||
}
|
||||
else if ( phase.count > maxDiskPhaseNum ) {
|
||||
phase.count = maxDiskPhaseNum;
|
||||
}
|
||||
|
||||
printf(", p:%d d:%d l:%d: ph:%u trk:%u)", position, direction, lastPosition, phase.count, woz_tmap.phase[phase.count]);
|
||||
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
INLINE uint8_t ioRead( uint16_t addr ) {
|
||||
dbgPrintf("mmio read:%04X\n", addr);
|
||||
|
||||
uint8_t currentMagnet = 0;
|
||||
|
||||
switch (addr) {
|
||||
case io_KBD:
|
||||
// if ( RAM[io_KBD] > 0x7F ) printf("io_KBD:%04X\n", addr);
|
||||
@ -192,51 +283,80 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
||||
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;
|
||||
currentMagnet = (addr - io_DISK_PHASE0_OFF - SLOT6) / 2;
|
||||
phase.magnet &= ~(1 << currentMagnet);
|
||||
printf("io_DISK_PHASE%u_OFF (S%u, ps:%X) ", currentMagnet, 6, phase.magnet);
|
||||
|
||||
diskII_phase();
|
||||
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);
|
||||
currentMagnet = (addr - io_DISK_PHASE0_ON - SLOT6) / 2;
|
||||
phase.magnet |= 1 << currentMagnet;
|
||||
printf("io_DISK_PHASE%u_ON (S%u, ps:%X) ", currentMagnet, 6, phase.magnet);
|
||||
|
||||
diskII_phase();
|
||||
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;
|
||||
int track = woz_tmap.phase[phase.count];
|
||||
if (outdev) fprintf(outdev, "track: %d (%d) ", track, phase.count);
|
||||
if ( track >= 40 ) {
|
||||
printf("TRCK TOO HIGH!\n");
|
||||
return rand();
|
||||
}
|
||||
printf("offs:%u\n", trackOffset);
|
||||
return woz_trks[track].data[trackOffset++];
|
||||
// to avoid infinite loop and to search for bit 7 high
|
||||
for ( int i = 0; i < WOZ_TRACK_BYTE_COUNT * 8; i++ ) {
|
||||
if ( ++bitOffset >= 8 ) {
|
||||
bitOffset = 0;
|
||||
if ( ++trackOffset >= WOZ_TRACK_BYTE_COUNT ) {
|
||||
trackOffset = 0;
|
||||
}
|
||||
// printf("offs:%u\n", trackOffset);
|
||||
WOZread.latch = woz_trks[track].data[trackOffset];
|
||||
}
|
||||
|
||||
WOZread.shift16 <<= 1;
|
||||
if ( WOZread.valid ) {
|
||||
uint8_t byte = WOZread.shift;
|
||||
// printf("%02X ", byte);
|
||||
WOZread.shift = 0;
|
||||
if (outdev) fprintf(outdev, "byte: %02X\n", byte);
|
||||
return byte;
|
||||
}
|
||||
}
|
||||
if (outdev) fprintf(outdev, "TIME OUT!\n");
|
||||
return rand();
|
||||
|
||||
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;
|
||||
@ -392,6 +512,7 @@ INLINE uint8_t fetch() {
|
||||
**/
|
||||
INLINE uint16_t fetch16() {
|
||||
uint16_t word = memread16( m6502.PC );
|
||||
// disPrintf(disassembly.comment, "fetch16:%04X", word);
|
||||
m6502.PC += 2;
|
||||
disHexW( disassembly.pOpcode, word );
|
||||
return word;
|
||||
@ -424,6 +545,7 @@ INLINE uint16_t abs_addr() {
|
||||
}
|
||||
INLINE uint16_t ind_addr() {
|
||||
disPrintf(disassembly.oper, "($%04X)", memread16(m6502.PC))
|
||||
disPrintf(disassembly.comment, "ind_addr:%04X", memread16(memread16(m6502.PC)))
|
||||
return memread16( fetch16() );
|
||||
}
|
||||
|
||||
@ -433,7 +555,7 @@ 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.oper, "$%04X,X", memread16(m6502.PC))
|
||||
disPrintf(disassembly.oper, "$%04X,X", memread16(m6502.PC));
|
||||
return fetch16() + m6502.X;
|
||||
}
|
||||
INLINE uint8_t src_abs_X() {
|
||||
@ -487,7 +609,8 @@ 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.oper, "($%02X) {$%04X}", memread8(m6502.PC), memread16( memread8(m6502.PC) ) )
|
||||
disPrintf(disassembly.oper, "($%02X)", memread8(m6502.PC) );
|
||||
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) ) );
|
||||
return memread16(addr);
|
||||
}
|
||||
|
||||
@ -498,7 +621,8 @@ 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.oper, "($%02X,X) {$%04X}", memread8(m6502.PC), memread16( memread8(m6502.PC) + m6502.X) )
|
||||
disPrintf(disassembly.oper, "($%02X,X)", memread8(m6502.PC) )
|
||||
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) + m6502.X) );
|
||||
return memread16( fetch() + m6502.X );
|
||||
}
|
||||
INLINE uint8_t src_X_ind() {
|
||||
@ -516,7 +640,8 @@ 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.oper, "($%02X),Y {$%04X}", memread8(m6502.PC), memread16( memread8(m6502.PC) ) + m6502.Y)
|
||||
disPrintf(disassembly.oper, "($%02X),Y", memread8(m6502.PC) )
|
||||
disPrintf(disassembly.comment, "ind_addr:%04X", memread16( memread8(m6502.PC) ) + m6502.Y );
|
||||
return memread16( fetch() ) + m6502.Y;
|
||||
}
|
||||
INLINE uint8_t src_ind_Y() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
@ -641,8 +641,8 @@
|
||||
<action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menuItem title="Zoom" keyEquivalent="z" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
@ -782,6 +782,102 @@
|
||||
</connections>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LlM-EV-ruZ" customClass="HiRes" customModule="A2Mac" customModuleProvider="target">
|
||||
<rect key="frame" x="16" y="8" width="568" height="384"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Fb7-Jc-jmt">
|
||||
<rect key="frame" x="598" y="186" width="74" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="17" id="xCE-LE-hVy"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="left" title="CPU Speed" id="b3T-0k-ama">
|
||||
<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>
|
||||
<stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" fixedFrame="YES" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lVP-FP-u6x">
|
||||
<rect key="frame" x="600" y="44" width="52" height="136"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7Pw-e8-92m">
|
||||
<rect key="frame" x="-1" y="119" width="55" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="1.023" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="AgQ-Np-TYQ">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="speedSelected:" target="XfG-lQ-9wD" id="fJr-cu-aeu"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hU1-g7-CCX">
|
||||
<rect key="frame" x="-1" y="95" width="30" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="2" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="nfH-ww-Ofp">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="speedSelected:" target="XfG-lQ-9wD" id="5xI-Hq-xGm"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hfg-DD-meM">
|
||||
<rect key="frame" x="-1" y="71" width="31" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="4" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="dqL-yg-qaX">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="speedSelected:" target="XfG-lQ-9wD" id="uCS-5C-ahW"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OsQ-RW-v8K">
|
||||
<rect key="frame" x="-1" y="47" width="37" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="10" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="3Ve-WW-CIS">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="speedSelected:" target="XfG-lQ-9wD" id="QzE-hT-Qif"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vGb-dz-KHi">
|
||||
<rect key="frame" x="-1" y="23" width="45" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="100" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="BUX-kX-vwG">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="speedSelected:" target="XfG-lQ-9wD" id="fc9-ai-wSN"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="umb-DW-vGc">
|
||||
<rect key="frame" x="-1" y="-1" width="47" height="18"/>
|
||||
<buttonCell key="cell" type="radio" title="666" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="8VU-4B-7Pe">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="speedSelected:" target="XfG-lQ-9wD" id="Viq-Dy-2or"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<visibilityPriorities>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
</visibilityPriorities>
|
||||
<customSpacing>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
</customSpacing>
|
||||
</stackView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FZk-VW-alq">
|
||||
<rect key="frame" x="631" y="20" width="41" height="17"/>
|
||||
<constraints>
|
||||
@ -793,10 +889,6 @@
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LlM-EV-ruZ" customClass="HiRes" customModule="A2Mac" customModuleProvider="target">
|
||||
<rect key="frame" x="16" y="8" width="568" height="384"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="mfd-12-bcR" secondAttribute="trailing" constant="10" id="3NC-0i-OPC"/>
|
||||
@ -840,5 +932,18 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="723" y="320"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="Awv-7G-CRH">
|
||||
<objects>
|
||||
<viewController id="0CG-mQ-xR3" sceneMemberID="viewController">
|
||||
<view key="view" id="MW2-U3-obl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<customObject id="OhC-VN-jKp" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="241" y="1071"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
@ -137,7 +137,7 @@ class HiRes: NSView {
|
||||
scaleUnitSquare(to: NSSize(width: scaleSizeW, height: scaleSizeH))
|
||||
|
||||
// create smaller box views for draw optimization
|
||||
// createHiRes()
|
||||
//createHiRes()
|
||||
|
||||
#if METAL_YES
|
||||
initMetal()
|
||||
|
@ -6,8 +6,20 @@
|
||||
// Copyright © 2019 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
import Cocoa
|
||||
|
||||
let K : Double = 1000.0
|
||||
let M : Double = (K * K)
|
||||
let G : Double = (M * K)
|
||||
let T : Double = (G * K)
|
||||
|
||||
let KB : Double = 1024.0
|
||||
let MB : Double = (KB * KB)
|
||||
let GB : Double = (MB * KB)
|
||||
let TB : Double = (GB * KB)
|
||||
|
||||
|
||||
#if METAL_YES
|
||||
import Metal
|
||||
#endif
|
||||
@ -285,7 +297,7 @@ class ViewController: NSViewController {
|
||||
self.display.stringValue = txt
|
||||
// self.display.stringValue = "testing\nit\nout"
|
||||
|
||||
if ( mhz < 10 ) {
|
||||
if ( (mhz < 10) && (mhz != floor(mhz)) ) {
|
||||
self.speedometer.stringValue = String(format: "%0.3lf MHz", mhz);
|
||||
}
|
||||
else {
|
||||
@ -366,11 +378,23 @@ class ViewController: NSViewController {
|
||||
// #endif
|
||||
}
|
||||
|
||||
override var representedObject: Any? {
|
||||
didSet {
|
||||
// Update the view, if already loaded.
|
||||
}
|
||||
|
||||
|
||||
func setCPUClockSpeed( freq : Double ) {
|
||||
mhz = freq
|
||||
MHz_6502 = UInt64(mhz * M)
|
||||
clk_6502_per_frm = MHz_6502 / UInt64(fps)
|
||||
}
|
||||
|
||||
@IBAction func speedSelected(_ sender: NSButton) {
|
||||
if ( sender.title == "Max" ) {
|
||||
clk_6502_per_frm = UINT64_MAX
|
||||
}
|
||||
else if let freq = Double( sender.title ) {
|
||||
setCPUClockSpeed(freq: freq)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
#ifdef DISASSEMBLER
|
||||
|
||||
extern unsigned long long int clktime;
|
||||
unsigned long long discnt = 0;
|
||||
|
||||
#define disHexB( to, b ) \
|
||||
if ( m6502.dbgLevel.trace ) { \
|
||||
snprintf((to), 4, "%02X ", (b)); \
|
||||
@ -47,15 +50,43 @@
|
||||
} \
|
||||
}
|
||||
|
||||
INLINE void printDisassembly() {
|
||||
if ( m6502.dbgLevel.trace ) {
|
||||
printf("%s: %-14s%-6s%-14s%s\n",
|
||||
disassembly.addr,
|
||||
disassembly.opcode,
|
||||
disassembly.inst,
|
||||
disassembly.oper,
|
||||
disassembly.comment
|
||||
);
|
||||
INLINE void printDisassembly( FILE * f ) {
|
||||
if ( m6502.dbgLevel.trace && f ) {
|
||||
// fprintf( f, "%s: %-14s%-6s%-14s%-16s A:%02X X:%02X Y:%02X S:%02X P:%02X (%c%c%c%c%c%c%c%c)\n",
|
||||
// disassembly.addr,
|
||||
// disassembly.opcode,
|
||||
// disassembly.inst,
|
||||
// disassembly.oper,
|
||||
// disassembly.comment,
|
||||
// m6502.A,
|
||||
// m6502.X,
|
||||
// m6502.Y,
|
||||
// m6502.SP,
|
||||
// m6502.SR,
|
||||
// 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'
|
||||
// );
|
||||
|
||||
fprintf( f, "%llu\t%llu %s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t;\t%s\n", // Virtual ][ style
|
||||
++discnt,
|
||||
clktime,
|
||||
disassembly.addr,
|
||||
disassembly.opcode,
|
||||
disassembly.inst,
|
||||
disassembly.oper,
|
||||
m6502.A,
|
||||
m6502.X,
|
||||
m6502.Y,
|
||||
m6502.SR,
|
||||
m6502.SP,
|
||||
disassembly.comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
INLINE void JMP( uint16_t addr ) {
|
||||
dbgPrintf("JMP %04X ", addr);
|
||||
disPrintf(disassembly.inst, "JMP");
|
||||
// disPrintf(disassembly.comment, "to:%04X", addr)
|
||||
#ifdef DEBUG
|
||||
if ( addr == m6502.PC - 3 ) {
|
||||
dbgPrintf("Infinite Loop at %04X!\n", m6502.PC);
|
||||
|
@ -91,9 +91,8 @@ char * charConv =
|
||||
**/
|
||||
INLINE void STR( uint8_t * dst, uint8_t src ) {
|
||||
dbgPrintf("STR [%04X], %02X ", (int)(dst - RAM), src );
|
||||
*dst = src;
|
||||
|
||||
// uint16_t addr = dst - RAM;
|
||||
|
||||
uint16_t addr = dst - RAM;
|
||||
// if ( ( addr >= 0x400 ) && ( addr < 0x800 ) ) {
|
||||
// char c = charConv[src];
|
||||
//// if ( c == '?' ) {
|
||||
@ -103,11 +102,19 @@ INLINE void STR( uint8_t * dst, uint8_t src ) {
|
||||
// if (( src > ' ' ) && ( c < 0x7F ))
|
||||
// printf("*** PRINT: %04X: t:%02X '%c'\n", addr, src, isprint(c) ? c : ' ');
|
||||
// }
|
||||
// else if ( ( addr >= 0xC000 ) && ( addr < 0xD000 ) ) {
|
||||
// else
|
||||
if ( ( addr >= 0xC000 ) && ( addr < 0xD000 ) ) {
|
||||
// printf("mmio write:[%04X] = %02X\n", addr, src);
|
||||
// }
|
||||
//
|
||||
//
|
||||
}
|
||||
// Need to protect ROM!!!
|
||||
else if ( ( addr >= 0xE000 ) && ( addr < 0xF000 ) ) {
|
||||
// printf("mmio write:[%04X] = %02X\n", addr, src);
|
||||
}
|
||||
else {
|
||||
*dst = src;
|
||||
}
|
||||
|
||||
|
||||
// else switch ( addr ) {
|
||||
// case 0x36:
|
||||
// case 0x37:
|
||||
|
15
A2Mac/woz.h
15
A2Mac/woz.h
@ -9,6 +9,12 @@
|
||||
#ifndef woz_h
|
||||
#define woz_h
|
||||
|
||||
#define DISKII_MAXTRACKS 80
|
||||
#define DISKII_PHASES 4
|
||||
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct woz_header_s {
|
||||
uint32_t magic;
|
||||
@ -34,11 +40,12 @@ typedef struct woz_info_s {
|
||||
|
||||
// chunk data only
|
||||
typedef struct woz_tmap_s {
|
||||
uint8_t phase [80 * 4];
|
||||
uint8_t phase [DISKII_MAXTRACKS * DISKII_PHASES];
|
||||
} woz_tmap_t;
|
||||
|
||||
#define WOZ_TRACK_BYTE_COUNT 6646
|
||||
// chunk data only
|
||||
|
||||
typedef struct woz_track_s {
|
||||
uint8_t data [WOZ_TRACK_BYTE_COUNT];
|
||||
uint16_t bytes_used;
|
||||
@ -49,8 +56,10 @@ typedef struct woz_track_s {
|
||||
uint16_t reserved;
|
||||
} woz_track_t;
|
||||
|
||||
// chunk data only
|
||||
typedef woz_track_t woz_trks_t[80];
|
||||
|
||||
// chunk data only
|
||||
typedef woz_track_t woz_trks_t[DISKII_MAXTRACKS];
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif /* woz_h */
|
||||
|
Loading…
x
Reference in New Issue
Block a user