mirror of
https://github.com/trudnai/Steve2.git
synced 2024-05-29 03:41:28 +00:00
- Disk read acceleration
- Source code organization 1
This commit is contained in:
parent
e33c1dc34b
commit
7e2d93f043
|
@ -9,6 +9,9 @@
|
|||
/* Begin PBXBuildFile section */
|
||||
32439F8722ECD8AD0077AAE0 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; };
|
||||
32439F8822ECD8AD0077AAE0 /* apple.rom in Resources */ = {isa = PBXBuildFile; fileRef = 32439F8422ECD8AD0077AAE0 /* apple.rom */; };
|
||||
325EB62F23F8856F00C6B4A4 /* woz.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB62E23F8856F00C6B4A4 /* woz.c */; };
|
||||
325EB63623F8F78300C6B4A4 /* disk.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB63523F8F78300C6B4A4 /* disk.c */; };
|
||||
325EB63923F9E48100C6B4A4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB63823F9E48100C6B4A4 /* common.c */; };
|
||||
3262F37623E169F8008BDB95 /* spk_dn.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3262F37423E169F8008BDB95 /* spk_dn.wav */; };
|
||||
3262F37723E169F8008BDB95 /* spk_up.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3262F37523E169F8008BDB95 /* spk_up.wav */; };
|
||||
326ED2EF232D7A0000A41337 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */; };
|
||||
|
@ -84,11 +87,15 @@
|
|||
32439F8422ECD8AD0077AAE0 /* apple.rom */ = {isa = PBXFileReference; lastKnownFileType = file; path = apple.rom; sourceTree = "<group>"; };
|
||||
32439F8522ECD8AD0077AAE0 /* 6502.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 6502.h; sourceTree = "<group>"; };
|
||||
32439F8622ECD8AD0077AAE0 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
|
||||
325EB62D23F8856F00C6B4A4 /* woz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = woz.h; sourceTree = "<group>"; };
|
||||
325EB62E23F8856F00C6B4A4 /* woz.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = woz.c; sourceTree = "<group>"; };
|
||||
325EB63423F8F78300C6B4A4 /* disk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = disk.h; sourceTree = "<group>"; };
|
||||
325EB63523F8F78300C6B4A4 /* disk.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = disk.c; sourceTree = "<group>"; };
|
||||
325EB63823F9E48100C6B4A4 /* common.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = common.c; sourceTree = "<group>"; };
|
||||
3262F37423E169F8008BDB95 /* spk_dn.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = spk_dn.wav; sourceTree = "<group>"; };
|
||||
3262F37523E169F8008BDB95 /* spk_up.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = spk_up.wav; sourceTree = "<group>"; };
|
||||
3264261023284F6F008B615F /* Apple2_mmio_8bit_ioaddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Apple2_mmio_8bit_ioaddr.h; sourceTree = "<group>"; };
|
||||
326426112328ADF4008B615F /* Apple_II_ROM.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = Apple_II_ROM.s; sourceTree = "<group>"; };
|
||||
326C50802383CC0B00A05420 /* woz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = woz.h; sourceTree = "<group>"; };
|
||||
326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = SOURCE_ROOT; };
|
||||
32B18435233F10BC00DBB4AB /* Shaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = "<group>"; };
|
||||
32B18438233FAB3900DBB4AB /* verticies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = verticies.swift; sourceTree = "<group>"; };
|
||||
|
@ -177,6 +184,43 @@
|
|||
path = instructions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
325EB63123F8861A00C6B4A4 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
325EB63723F9492200C6B4A4 /* util */,
|
||||
325EB63223F8862A00C6B4A4 /* dev */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
325EB63223F8862A00C6B4A4 /* dev */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
325EB63323F8863100C6B4A4 /* disk */,
|
||||
);
|
||||
path = dev;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
325EB63323F8863100C6B4A4 /* disk */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
325EB62D23F8856F00C6B4A4 /* woz.h */,
|
||||
325EB62E23F8856F00C6B4A4 /* woz.c */,
|
||||
325EB63423F8F78300C6B4A4 /* disk.h */,
|
||||
325EB63523F8F78300C6B4A4 /* disk.c */,
|
||||
);
|
||||
path = disk;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
325EB63723F9492200C6B4A4 /* util */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
32439F8622ECD8AD0077AAE0 /* common.h */,
|
||||
325EB63823F9E48100C6B4A4 /* common.c */,
|
||||
);
|
||||
path = util;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3262F37823E17013008BDB95 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -214,6 +258,7 @@
|
|||
32BFFB5922EACC630003B53F /* A2Mac */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
325EB63123F8861A00C6B4A4 /* src */,
|
||||
3262F37823E17013008BDB95 /* Resources */,
|
||||
32439F7522ECD8AD0077AAE0 /* instructions */,
|
||||
32439F8522ECD8AD0077AAE0 /* 6502.h */,
|
||||
|
@ -224,7 +269,6 @@
|
|||
32B18438233FAB3900DBB4AB /* verticies.swift */,
|
||||
32439F7322ECD8AD0077AAE0 /* Apple2_mmio.h */,
|
||||
3264261023284F6F008B615F /* Apple2_mmio_8bit_ioaddr.h */,
|
||||
32439F8622ECD8AD0077AAE0 /* common.h */,
|
||||
32BFFB5A22EACC630003B53F /* AppDelegate.swift */,
|
||||
32BFFB5C22EACC630003B53F /* ViewController.swift */,
|
||||
32B18435233F10BC00DBB4AB /* Shaders.metal */,
|
||||
|
@ -238,7 +282,6 @@
|
|||
32BFFB6322EACC660003B53F /* Info.plist */,
|
||||
32BFFB6422EACC660003B53F /* A2Mac.entitlements */,
|
||||
32439F7222ECD8AC0077AAE0 /* A2Mac-Bridging-Header.h */,
|
||||
326C50802383CC0B00A05420 /* woz.h */,
|
||||
);
|
||||
path = A2Mac;
|
||||
sourceTree = "<group>";
|
||||
|
@ -459,8 +502,11 @@
|
|||
files = (
|
||||
32439F8722ECD8AD0077AAE0 /* 6502.c in Sources */,
|
||||
32DBF7642334657900DD50E7 /* HiRes.swift in Sources */,
|
||||
325EB63623F8F78300C6B4A4 /* disk.c in Sources */,
|
||||
325EB63923F9E48100C6B4A4 /* common.c in Sources */,
|
||||
32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */,
|
||||
32C4532E233345430000EBA1 /* MonitorView.swift in Sources */,
|
||||
325EB62F23F8856F00C6B4A4 /* woz.c in Sources */,
|
||||
32BFFB5B22EACC630003B53F /* AppDelegate.swift in Sources */,
|
||||
32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */,
|
||||
);
|
||||
|
|
102
A2Mac/6502.c
102
A2Mac/6502.c
|
@ -13,37 +13,14 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "6502.h"
|
||||
#include "woz.h"
|
||||
|
||||
#define WOZ1_MAGIC 0x315A4F57
|
||||
#define WOZ2_MAGIC 0x325A4F57
|
||||
#define WOZ_INFO_CHUNK_ID 0x4F464E49
|
||||
#define WOZ_TMAP_CHUNK_ID 0x50414D54
|
||||
#define WOZ_TRKS_CHUNK_ID 0x534B5254
|
||||
#define WOZ_META_CHUNK_ID 0x4154454D
|
||||
|
||||
woz_header_t woz_header;
|
||||
woz_chunk_header_t woz_chunk_header;
|
||||
woz_tmap_t woz_tmap;
|
||||
woz_trks_t woz_trks;
|
||||
|
||||
uint64_t clklast = 0;
|
||||
uint64_t clkelpased = 0;
|
||||
uint16_t trackOffset = 0;
|
||||
uint8_t bitOffset = 0;
|
||||
|
||||
FILE * outdev = NULL;
|
||||
|
||||
void ViewController_spk_up_play(void);
|
||||
void ViewController_spk_dn_play(void);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define INLINE
|
||||
#else
|
||||
#define INLINE static __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
|
@ -80,9 +57,9 @@ m6502_t m6502 = {
|
|||
0, // PC
|
||||
0, // SP
|
||||
|
||||
// 0, // clk
|
||||
0, // clktime
|
||||
|
||||
0, // clklast
|
||||
|
||||
0, // trace
|
||||
0, // step
|
||||
0, // brk
|
||||
|
@ -91,7 +68,8 @@ m6502_t m6502 = {
|
|||
0, // bra_true
|
||||
0, // bra_false
|
||||
0, // compile
|
||||
HLT // IF
|
||||
HLT, // IF
|
||||
|
||||
};
|
||||
|
||||
disassembly_t disassembly;
|
||||
|
@ -791,7 +769,7 @@ void m6502_Run() {
|
|||
// mhz = clktime / (execution_time * M);
|
||||
}
|
||||
|
||||
void read_rom( const char * filename, const uint8_t * rom, const uint16_t addr ) {
|
||||
void read_rom( const char * filename, uint8_t * rom, const uint16_t addr ) {
|
||||
FILE * f = fopen(filename, "rb");
|
||||
if (f == NULL) {
|
||||
perror("Failed: ");
|
||||
|
@ -808,64 +786,6 @@ void read_rom( const char * filename, const uint8_t * rom, const uint16_t addr )
|
|||
}
|
||||
|
||||
|
||||
void read_woz( const char * filename ) {
|
||||
FILE * f = fopen(filename, "rb");
|
||||
if (f == NULL) {
|
||||
perror("Failed: ");
|
||||
return;
|
||||
}
|
||||
|
||||
fread( &woz_header, 1, sizeof(woz_header_t), f);
|
||||
if ( woz_header.magic != WOZ1_MAGIC ) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ( ! feof(f) ) {
|
||||
// beginning of the chunk, so we can skip it later
|
||||
|
||||
long r = fread( &woz_chunk_header, 1, sizeof(woz_chunk_header_t), f);
|
||||
if ( r != sizeof(woz_chunk_header_t) ) {
|
||||
break;
|
||||
}
|
||||
long foffs = ftell(f);
|
||||
|
||||
void * buf = NULL;
|
||||
|
||||
switch ( woz_chunk_header.magic ) {
|
||||
case WOZ_INFO_CHUNK_ID:
|
||||
break;
|
||||
|
||||
case WOZ_TMAP_CHUNK_ID:
|
||||
buf = &woz_tmap;
|
||||
break;
|
||||
|
||||
case WOZ_TRKS_CHUNK_ID:
|
||||
buf = woz_trks;
|
||||
break;
|
||||
|
||||
case WOZ_META_CHUNK_ID:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
r = fread( buf, 1, woz_chunk_header.size, f);
|
||||
if ( r != woz_chunk_header.size ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we are skipping unhandled chunks correctly
|
||||
fseek(f, foffs + woz_chunk_header.size, SEEK_SET);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void m6502_ColdReset() {
|
||||
inst_cnt = 0;
|
||||
mhz = (double)MHz_6502 / M;
|
||||
|
@ -906,12 +826,12 @@ void m6502_ColdReset() {
|
|||
read_rom("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DISK_II_C600.ROM", Apple2_64K_RAM, 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");
|
||||
// woz_loadFile("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DOS 3.3 System Master.woz");
|
||||
// woz_loadFile("/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");
|
||||
// woz_loadFile("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Merlin-8 v2.48 (DOS 3.3).woz");
|
||||
// woz_loadFile("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/DOS3.3.Launcher.2.2.woz");
|
||||
woz_loadFile("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/Apple DOS 3.3 January 1983.woz");
|
||||
|
||||
m6502.A = m6502.X = m6502.Y = 0xFF;
|
||||
// reset vector
|
||||
|
|
59
A2Mac/6502.h
59
A2Mac/6502.h
|
@ -9,21 +9,14 @@
|
|||
#ifndef __6502_H__
|
||||
#define __6502_H__
|
||||
|
||||
#import <stdint.h>
|
||||
#include <stdint.h>
|
||||
#include "common.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, ...) if(outdev) fprintf(outdev, format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define dbgPrintf(format, ...)
|
||||
#define dbgPrintf2(format, ...)
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NO_INT,
|
||||
HLT,
|
||||
|
@ -33,6 +26,7 @@ typedef enum {
|
|||
SOFTRESET,
|
||||
} interrupt_t;
|
||||
|
||||
|
||||
typedef struct debugLevel_s {
|
||||
uint8_t trace : 1;
|
||||
uint8_t step : 1;
|
||||
|
@ -44,6 +38,7 @@ typedef struct debugLevel_s {
|
|||
uint8_t compile : 1;
|
||||
} debugLevel_t;
|
||||
|
||||
|
||||
typedef struct m6502_s {
|
||||
uint8_t A; // Accumulator
|
||||
uint8_t X; // X index register
|
||||
|
@ -74,6 +69,7 @@ typedef struct m6502_s {
|
|||
|
||||
// unsigned clk; // Clock Counter
|
||||
uint64_t clktime;
|
||||
uint64_t clklast;
|
||||
|
||||
debugLevel_t dbgLevel; // 0: No Debug, 1: Disassembly Only, 2: Run till BRK, 3: StepByStep
|
||||
|
||||
|
@ -110,4 +106,47 @@ extern void m6502_ColdReset(void);
|
|||
extern void m6502_Run(void);
|
||||
extern void kbdInput ( uint8_t code );
|
||||
|
||||
|
||||
INLINE void set_flags_N( const uint8_t test ) {
|
||||
m6502.N = BITTEST(test, 7);
|
||||
}
|
||||
|
||||
INLINE void set_flags_V( const uint8_t test ) {
|
||||
m6502.V = BITTEST(test, 6);
|
||||
}
|
||||
|
||||
INLINE void set_flags_Z( const uint8_t test ) {
|
||||
m6502.Z = test == 0;
|
||||
}
|
||||
|
||||
INLINE void set_flags_C( const int16_t test ) {
|
||||
m6502.C = test >= 0;
|
||||
}
|
||||
|
||||
INLINE void set_flags_NZ( const uint8_t test ) {
|
||||
set_flags_N(test);
|
||||
set_flags_Z(test);
|
||||
}
|
||||
|
||||
INLINE void set_flags_NV( const uint8_t test ) {
|
||||
set_flags_N(test);
|
||||
set_flags_V(test);
|
||||
}
|
||||
|
||||
INLINE void set_flags_NVZ( const uint8_t test ) {
|
||||
set_flags_NZ(test);
|
||||
set_flags_V(test);
|
||||
}
|
||||
|
||||
INLINE void set_flags_NZC( const int16_t test ) {
|
||||
set_flags_NZ(test);
|
||||
set_flags_C(test);
|
||||
}
|
||||
|
||||
//INLINE void set_flags_NZCV( int test ) {
|
||||
// set_flags_NZC(test);
|
||||
// set_flags_V(test);
|
||||
//}
|
||||
|
||||
|
||||
#endif /* __6502_H__ */
|
||||
|
|
|
@ -11,20 +11,8 @@
|
|||
|
||||
#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;
|
||||
|
||||
WOZread_t WOZread = {0};
|
||||
#include "disk.h"
|
||||
#include "woz.h"
|
||||
|
||||
|
||||
typedef union address16_u {
|
||||
|
@ -226,202 +214,12 @@ enum mmio {
|
|||
#define PAGESIZE 256
|
||||
#define PAGES 16
|
||||
|
||||
//uint8_t ram_0[PAGESIZE];
|
||||
//uint8_t ram_1[PAGESIZE];
|
||||
//uint8_t ram_2[PAGESIZE];
|
||||
//uint8_t ram_3[PAGESIZE];
|
||||
//uint8_t ram_4[PAGESIZE];
|
||||
//uint8_t ram_5[PAGESIZE];
|
||||
//uint8_t ram_6[PAGESIZE];
|
||||
//uint8_t ram_7[PAGESIZE];
|
||||
//uint8_t ram_8[PAGESIZE];
|
||||
//uint8_t ram_9[PAGESIZE];
|
||||
//uint8_t ram_A[PAGESIZE];
|
||||
//uint8_t ram_B[PAGESIZE];
|
||||
//uint8_t aui_C[PAGESIZE];
|
||||
//uint8_t rom_D[PAGESIZE];
|
||||
//uint8_t rom_E[PAGESIZE];
|
||||
//uint8_t rom_F[PAGESIZE];
|
||||
//
|
||||
//uint8_t * ram[PAGES] = {
|
||||
// ram_0,
|
||||
// ram_1,
|
||||
// ram_2,
|
||||
// ram_3,
|
||||
// ram_4,
|
||||
// ram_5,
|
||||
// ram_6,
|
||||
// ram_7,
|
||||
// ram_8,
|
||||
// ram_9,
|
||||
// ram_A,
|
||||
// ram_B,
|
||||
// aui_C,
|
||||
// rom_D,
|
||||
// rom_E,
|
||||
// rom_F,
|
||||
//};
|
||||
|
||||
//uint8_t ( * mmio_read [ 64 * KB ] )( uint16_t addr );
|
||||
|
||||
|
||||
#define CASE_DISKII(x) \
|
||||
case io_DISK_PHASE0_OFF + SLOT##x: \
|
||||
printf("io_DISK_PHASE0_OFF (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE0_ON + SLOT##x: \
|
||||
printf("io_DISK_PHASE0_ON (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE1_OFF + SLOT##x: \
|
||||
printf("io_DISK_PHASE1_OFF (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE1_ON + SLOT##x: \
|
||||
printf("io_DISK_PHASE1_ON (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE2_OFF + SLOT##x: \
|
||||
printf("io_DISK_PHASE2_OFF (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE2_ON + SLOT##x: \
|
||||
printf("io_DISK_PHASE2_ON (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE3_OFF + SLOT##x: \
|
||||
printf("io_DISK_PHASE3_OFF (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_PHASE3_ON + SLOT##x: \
|
||||
printf("io_DISK_PHASE3_ON (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_POWER_OFF + SLOT##x: \
|
||||
printf("io_DISK_POWER_OFF (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_POWER_ON + SLOT##x: \
|
||||
printf("io_DISK_POWER_ON (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_SELECT_1 + SLOT##x: \
|
||||
printf("io_DISK_SELECT_1 (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_SELECT_2 + SLOT##x: \
|
||||
printf("io_DISK_SELECT_2 (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_READ + SLOT##x: \
|
||||
printf("io_DISK_READ (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_WRITE + SLOT##x: \
|
||||
printf("io_DISK_WRITE (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_CLEAR + SLOT##x: \
|
||||
printf("io_DISK_CLEAR (S%u)\n", x); \
|
||||
return 0; \
|
||||
case io_DISK_SHIFT + SLOT##x: \
|
||||
printf("io_DISK_SHIFT (S%u)\n", x); \
|
||||
return 0;
|
||||
|
||||
|
||||
static const int minDiskTrackNum = 0;
|
||||
static const int maxDiskTrackNum = 39;
|
||||
static const int minDiskPhaseStates = 8; // 4 quarters * 2 because of two neighbouring magnets can be activated at the same time which gets you a half quarter movement
|
||||
static const int minDiskPhaseNum = 0;
|
||||
static const int maxDiskPhaseNum = minDiskPhaseStates * maxDiskTrackNum;
|
||||
|
||||
struct phase_t {
|
||||
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 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]);
|
||||
|
||||
}
|
||||
else {
|
||||
// invalid magnet config
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
INLINE uint8_t ioRead( uint16_t addr ) {
|
||||
dbgPrintf("mmio read:%04X\n", addr);
|
||||
|
||||
uint8_t currentMagnet = 0;
|
||||
int clk = 0;
|
||||
|
||||
switch (addr) {
|
||||
case io_KBD:
|
||||
|
@ -441,8 +239,6 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
|||
|
||||
return RAM[io_SPKR];
|
||||
|
||||
// CASE_DISKII(6)
|
||||
|
||||
case io_MEM_RDRAM_NOWR_2:
|
||||
case io_MEM_RDROM_WRAM_2:
|
||||
case io_MEM_RDROM_NOWR_2:
|
||||
|
@ -523,10 +319,10 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
|||
case io_DISK_PHASE2_OFF + SLOT6:
|
||||
case io_DISK_PHASE3_OFF + SLOT6:
|
||||
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);
|
||||
disk.phase.magnet &= ~(1 << currentMagnet);
|
||||
printf("io_DISK_PHASE%u_OFF (S%u, ps:%X) ", currentMagnet, 6, disk.phase.magnet);
|
||||
|
||||
diskII_phase();
|
||||
disk_phase();
|
||||
return 0;
|
||||
|
||||
case io_DISK_PHASE0_ON + SLOT6:
|
||||
|
@ -534,10 +330,10 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
|||
case io_DISK_PHASE2_ON + SLOT6:
|
||||
case io_DISK_PHASE3_ON + SLOT6: {
|
||||
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);
|
||||
disk.phase.magnet |= 1 << currentMagnet;
|
||||
printf("io_DISK_PHASE%u_ON (S%u, ps:%X) ", currentMagnet, 6, disk.phase.magnet);
|
||||
|
||||
diskII_phase();
|
||||
disk_phase();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -558,49 +354,9 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
|||
return 0;
|
||||
|
||||
case io_DISK_READ + SLOT6:
|
||||
dbgPrintf("io_DISK_READ (S%u)\n", 6);
|
||||
int track = woz_tmap.phase[phase.count];
|
||||
if (outdev) fprintf(outdev, "track: %d (%d) ", track, phase.count);
|
||||
if ( track >= 40 ) {
|
||||
dbgPrintf("TRCK TOO HIGH!\n");
|
||||
return rand();
|
||||
}
|
||||
return disk_read();
|
||||
|
||||
|
||||
clkelpased = m6502.clktime - clklast;
|
||||
clklast = m6502.clktime;
|
||||
|
||||
if ( clkelpased > 100 ) {
|
||||
bitOffset = (clkelpased % 32) / 4;
|
||||
trackOffset += (clkelpased / 32) % WOZ_TRACK_BYTE_COUNT;
|
||||
WOZread.latch = 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;
|
||||
// }
|
||||
trackOffset++;
|
||||
trackOffset %= WOZ_TRACK_BYTE_COUNT;
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
//
|
||||
// common.h
|
||||
// 6502
|
||||
//
|
||||
// Created by Tamas Rudnai on 7/14/19.
|
||||
// Copyright © 2019 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include "6502.h"
|
||||
|
||||
|
||||
#define K 1000ULL
|
||||
#define M (K * K)
|
||||
#define G (M * K)
|
||||
#define T (G * K)
|
||||
|
||||
#define PG 256ULL
|
||||
#define KB 1024ULL
|
||||
#define MB (KB * KB)
|
||||
#define GB (MB * KB)
|
||||
#define TB (GB * KB)
|
||||
|
||||
|
||||
typedef
|
||||
union {
|
||||
uint8_t bits;
|
||||
struct {
|
||||
uint8_t b0:1;
|
||||
uint8_t b1:1;
|
||||
uint8_t b2:1;
|
||||
uint8_t b3:1;
|
||||
uint8_t b4:1;
|
||||
uint8_t b5:1;
|
||||
uint8_t b6:1;
|
||||
uint8_t b7:1;
|
||||
};
|
||||
} bits_t;
|
||||
|
||||
|
||||
#define BITTEST(n,x) ((bits_t)(n)).b##x
|
||||
|
||||
INLINE void set_flags_N( const uint8_t test ) {
|
||||
m6502.N = BITTEST(test, 7);
|
||||
}
|
||||
|
||||
INLINE void set_flags_V( const uint8_t test ) {
|
||||
m6502.V = BITTEST(test, 6);
|
||||
}
|
||||
|
||||
INLINE void set_flags_Z( const uint8_t test ) {
|
||||
m6502.Z = test == 0;
|
||||
}
|
||||
|
||||
INLINE void set_flags_C( const int16_t test ) {
|
||||
m6502.C = test >= 0;
|
||||
}
|
||||
|
||||
INLINE void set_flags_NZ( const uint8_t test ) {
|
||||
set_flags_N(test);
|
||||
set_flags_Z(test);
|
||||
}
|
||||
|
||||
INLINE void set_flags_NV( const uint8_t test ) {
|
||||
set_flags_N(test);
|
||||
set_flags_V(test);
|
||||
}
|
||||
|
||||
INLINE void set_flags_NVZ( const uint8_t test ) {
|
||||
set_flags_NZ(test);
|
||||
set_flags_V(test);
|
||||
}
|
||||
|
||||
INLINE void set_flags_NZC( const int16_t test ) {
|
||||
set_flags_NZ(test);
|
||||
set_flags_C(test);
|
||||
}
|
||||
|
||||
//INLINE void set_flags_NZCV( int test ) {
|
||||
// set_flags_NZC(test);
|
||||
// set_flags_V(test);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __COMMON_H__
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
INLINE void BRA( int8_t reladdr ) {
|
||||
m6502.PC += reladdr;
|
||||
m6502.clktime++;
|
||||
#ifdef DEBUG
|
||||
if ( reladdr == -2 ) {
|
||||
dbgPrintf2("Infinite Loop at %04X!\n", m6502.PC);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
--------------------------------------------
|
||||
implied BRK 00 1 7
|
||||
**/
|
||||
INLINE void BRK() {
|
||||
INLINE int BRK() {
|
||||
dbgPrintf("BRK ");
|
||||
disPrintf(disassembly.inst, "BRK");
|
||||
PUSH_addr(m6502.PC +1); // PC +2, however, fetch already incremented it by 1
|
||||
|
@ -29,6 +29,8 @@ INLINE void BRK() {
|
|||
PUSH(m6502.SR);
|
||||
m6502.I = 1;
|
||||
m6502.PC = memread16(IRQ_VECTOR);
|
||||
|
||||
return 7;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
73
A2Mac/src/dev/disk/disk.c
Normal file
73
A2Mac/src/dev/disk/disk.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// disk.c
|
||||
// A2Mac
|
||||
//
|
||||
// Created by Tamas Rudnai on 2/15/20.
|
||||
// Copyright © 2020 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#include "disk.h"
|
||||
#include "6502.h"
|
||||
#include "common.h"
|
||||
#include "woz.h"
|
||||
|
||||
|
||||
disk_t disk = {
|
||||
{ 0, 0, 0 }, // phase
|
||||
};
|
||||
|
||||
|
||||
|
||||
// motor position from the magnet state
|
||||
// -1 means invalid, not supported
|
||||
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
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
void disk_phase() {
|
||||
|
||||
int position = magnet_to_Poistion[disk.phase.magnet];
|
||||
if ( position >= 0 ) {
|
||||
int lastPosition = disk.phase.count & 7;
|
||||
int direction = position_to_direction[lastPosition][position];
|
||||
|
||||
disk.phase.count += direction;
|
||||
if( disk.phase.count < minDiskPhaseNum ) {
|
||||
disk.phase.count = minDiskPhaseNum;
|
||||
}
|
||||
else
|
||||
if( disk.phase.count > maxDiskPhaseNum ) {
|
||||
disk.phase.count = maxDiskPhaseNum;
|
||||
}
|
||||
|
||||
// printf(", p:%d d:%d l:%d: ph:%u trk:%u)", position, direction, lastPosition, phase.count, woz_tmap.phase[phase.count]);
|
||||
|
||||
}
|
||||
else {
|
||||
// invalid magnet config
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
uint8_t disk_read() {
|
||||
dbgPrintf("io_DISK_READ (S%u)\n", 6);
|
||||
return woz_read();
|
||||
}
|
||||
|
55
A2Mac/src/dev/disk/disk.h
Normal file
55
A2Mac/src/dev/disk/disk.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// disk.h
|
||||
// A2Mac
|
||||
//
|
||||
// Created by Tamas Rudnai on 2/15/20.
|
||||
// Copyright © 2020 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef disk_h
|
||||
#define disk_h
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#define minDiskTrackNum 0
|
||||
#define maxDiskTrackNum 39
|
||||
#define minDiskPhaseStates 8 // 4 quarters * 2 because of two neighbouring magnets can be activated at the same time which leaves motor in a half quarter movement
|
||||
#define minDiskPhaseNum 0
|
||||
#define maxDiskPhaseNum (minDiskPhaseStates * maxDiskTrackNum)
|
||||
|
||||
typedef struct phase_s {
|
||||
uint8_t lastMagnet : 4;
|
||||
uint8_t magnet : 4;
|
||||
int count;
|
||||
} phase_t;
|
||||
|
||||
typedef struct disk_s {
|
||||
phase_t phase;
|
||||
} disk_t;
|
||||
|
||||
extern disk_t disk;
|
||||
|
||||
|
||||
// Magnet States --> Stepper Motor Position
|
||||
//
|
||||
// N
|
||||
// 0001
|
||||
// NW | NE
|
||||
// 1001 | 0011
|
||||
// |
|
||||
// W 1000 ------- o ------- 0010 E
|
||||
// |
|
||||
// 1100 | 0110
|
||||
// SW | SE
|
||||
// 0100
|
||||
// S
|
||||
|
||||
extern const int magnet_to_Poistion[16];
|
||||
extern const int position_to_direction[8][8];
|
||||
|
||||
extern void disk_phase();
|
||||
extern uint8_t disk_read();
|
||||
|
||||
|
||||
#endif /* disk_h */
|
303
A2Mac/src/dev/disk/woz.c
Normal file
303
A2Mac/src/dev/disk/woz.c
Normal file
|
@ -0,0 +1,303 @@
|
|||
//
|
||||
// woz.c
|
||||
// A2Mac
|
||||
//
|
||||
// Created by Tamas Rudnai on 2/15/20.
|
||||
// Copyright © 2020 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "woz.h"
|
||||
#include "disk.h"
|
||||
#include "6502.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
WOZread_t WOZread = {0};
|
||||
uint8_t WOZlatch = 0;
|
||||
|
||||
int trackOffset = 0;
|
||||
int bitOffset = 0;
|
||||
uint64_t clkelpased;
|
||||
|
||||
|
||||
woz_header_t woz_header;
|
||||
woz_chunk_header_t woz_chunk_header;
|
||||
woz_tmap_t woz_tmap;
|
||||
woz_trks_t woz_trks;
|
||||
|
||||
|
||||
uint8_t woz_read() {
|
||||
|
||||
int track = woz_tmap.phase[disk.phase.count];
|
||||
if (outdev) fprintf(outdev, "track: %d (%d) ", track, disk.phase.count);
|
||||
if ( track >= 40 ) {
|
||||
dbgPrintf("TRCK TOO HIGH!\n");
|
||||
return rand();
|
||||
}
|
||||
|
||||
#ifdef WOZ_REAL_SPIN
|
||||
|
||||
WOZread.shift32 = 0;
|
||||
bitOffset = (m6502.clktime >> 2) & 7;
|
||||
trackOffset = (m6502.clktime >> 5) % WOZ_TRACK_BYTE_COUNT;
|
||||
WOZread.next = woz_trks[track].data[ (trackOffset +1) % WOZ_TRACK_BYTE_COUNT ];
|
||||
WOZread.data = woz_trks[track].data[ trackOffset ];
|
||||
WOZread.prev = woz_trks[track].data[ (trackOffset -1) % WOZ_TRACK_BYTE_COUNT ];
|
||||
WOZread.shift = woz_trks[track].data[ (trackOffset -2) % WOZ_TRACK_BYTE_COUNT ];
|
||||
|
||||
printf("clk:%llu bo:%u to:%u W:%08X\n", m6502.clktime, bitOffset, trackOffset, WOZread.shift32);
|
||||
|
||||
uint8_t state = 0;
|
||||
// simulating the continous shift register in Disk ][
|
||||
for (int i = bitOffset + 16; i; --i) {
|
||||
|
||||
WOZread.shift32 <<= 1;
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
WOZlatch = WOZread.shift;
|
||||
if ( WOZread.valid ) {
|
||||
state = 1;
|
||||
WOZread.shift = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// we do not latch the shift register for one 4us cycle
|
||||
state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
// this should not happen
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("shft1: W:%08X L:%02X\n", WOZread.shift32, WOZlatch);
|
||||
|
||||
}
|
||||
|
||||
printf("clk:%llu bo:%u to:%u W:%08X B:%02X\n", m6502.clktime, bitOffset, trackOffset, WOZread.shift32, WOZlatch);
|
||||
if ( WOZlatch & 0x80 ) {
|
||||
printf("WOZlatch: %02X\n", WOZlatch);
|
||||
|
||||
static int readState = 0;
|
||||
static int vol = 0;
|
||||
static int trk = 0;
|
||||
static int sec = 0;
|
||||
|
||||
switch (readState) {
|
||||
case 0:
|
||||
if ( 0xD5 == WOZlatch ) readState = 1;
|
||||
else readState = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if ( 0xAA == WOZlatch ) readState = 2;
|
||||
else readState = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if ( 0x96 == WOZlatch ) {
|
||||
readState = 3;
|
||||
printf("sector header marker\n");
|
||||
}
|
||||
else if ( 0xAD == WOZlatch ) {
|
||||
readState = 10;
|
||||
printf("sector data marker\n");
|
||||
}
|
||||
else readState = 0;
|
||||
break;
|
||||
|
||||
case 3: // sector header, vol number 1
|
||||
readState++;
|
||||
vol = (WOZlatch << 1) | 1;
|
||||
break;
|
||||
|
||||
case 4: // sector header, vol number 2
|
||||
readState++;
|
||||
vol &= WOZlatch;
|
||||
printf("vol:%u ", vol);
|
||||
break;
|
||||
|
||||
case 5: // sector header, trk number 1
|
||||
readState++;
|
||||
trk = (WOZlatch << 1) | 1;
|
||||
break;
|
||||
|
||||
case 6: // sector header, trk number 2
|
||||
readState++;
|
||||
trk &= WOZlatch;
|
||||
printf("trk:%u ", trk);
|
||||
break;
|
||||
|
||||
case 7: // sector header, sec number 1
|
||||
readState++;
|
||||
sec = (WOZlatch << 1) | 1;
|
||||
break;
|
||||
|
||||
case 8: // sector header, sec number 2
|
||||
readState = 0;
|
||||
sec &= WOZlatch;
|
||||
printf("sec:%u\n", sec);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
readState = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// switch ( WOZlatch ) {
|
||||
// case 0xAA:
|
||||
// case 0x96:
|
||||
//// printf("%02X ", WOZlatch);
|
||||
// printf("clk:%llu bo:%u to:%u B:%02X\n", m6502.clktime, bitOffset, trackOffset, WOZlatch);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
return WOZlatch;
|
||||
|
||||
|
||||
#elif defined( WOZ_REAL_SPIN2 )
|
||||
clkelpased = m6502.clktime - clklast;
|
||||
clklast = m6502.clktime & ~3;
|
||||
|
||||
bitOffset = (clkelpased >> 2) & 7;
|
||||
trackOffset += (clkelpased >> 5) % WOZ_TRACK_BYTE_COUNT;
|
||||
WOZread.data = 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;
|
||||
// }
|
||||
trackOffset++;
|
||||
trackOffset %= WOZ_TRACK_BYTE_COUNT;
|
||||
|
||||
// printf("offs:%u\n", trackOffset);
|
||||
WOZread.data = 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();
|
||||
|
||||
|
||||
|
||||
#else // WOZ_REAL_SPIN
|
||||
clkelpased = m6502.clktime - m6502.clklast;
|
||||
m6502.clklast = m6502.clktime;
|
||||
|
||||
if ( clkelpased > 100 ) {
|
||||
// printf("NEED SYNC : %llu\n", clkelpased);
|
||||
bitOffset = (clkelpased >> 2) & 7;
|
||||
trackOffset += ((clkelpased >> 5) +64) % WOZ_TRACK_BYTE_COUNT;
|
||||
WOZread.data = 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;
|
||||
// }
|
||||
trackOffset++;
|
||||
trackOffset %= WOZ_TRACK_BYTE_COUNT;
|
||||
|
||||
// printf("offs:%u\n", trackOffset);
|
||||
WOZread.data = 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();
|
||||
|
||||
#endif // WOZ_REAL_SPIN
|
||||
|
||||
}
|
||||
|
||||
|
||||
void woz_loadFile( const char * filename ) {
|
||||
FILE * f = fopen(filename, "rb");
|
||||
if (f == NULL) {
|
||||
perror("Failed: ");
|
||||
return;
|
||||
}
|
||||
|
||||
fread( &woz_header, 1, sizeof(woz_header_t), f);
|
||||
if ( woz_header.magic != WOZ1_MAGIC ) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ( ! feof(f) ) {
|
||||
// beginning of the chunk, so we can skip it later
|
||||
|
||||
long r = fread( &woz_chunk_header, 1, sizeof(woz_chunk_header_t), f);
|
||||
if ( r != sizeof(woz_chunk_header_t) ) {
|
||||
break;
|
||||
}
|
||||
long foffs = ftell(f);
|
||||
|
||||
void * buf = NULL;
|
||||
|
||||
switch ( woz_chunk_header.magic ) {
|
||||
case WOZ_INFO_CHUNK_ID:
|
||||
break;
|
||||
|
||||
case WOZ_TMAP_CHUNK_ID:
|
||||
buf = &woz_tmap;
|
||||
break;
|
||||
|
||||
case WOZ_TRKS_CHUNK_ID:
|
||||
buf = woz_trks;
|
||||
break;
|
||||
|
||||
case WOZ_META_CHUNK_ID:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
r = fread( buf, 1, woz_chunk_header.size, f);
|
||||
if ( r != woz_chunk_header.size ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we are skipping unhandled chunks correctly
|
||||
fseek(f, foffs + woz_chunk_header.size, SEEK_SET);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +1,28 @@
|
|||
//
|
||||
// woz1.h
|
||||
// woz.h
|
||||
// A2Mac
|
||||
//
|
||||
// Created by Tamas Rudnai on 11/18/19.
|
||||
// Copyright © 2019 GameAlloy. All rights reserved.
|
||||
// Created by Tamas Rudnai on 2/15/20.
|
||||
// Copyright © 2020 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef woz_h
|
||||
#define woz_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#define DISKII_MAXTRACKS 80
|
||||
#define DISKII_PHASES 4
|
||||
|
||||
#define WOZ1_MAGIC 0x315A4F57
|
||||
#define WOZ2_MAGIC 0x325A4F57
|
||||
#define WOZ_INFO_CHUNK_ID 0x4F464E49
|
||||
#define WOZ_TMAP_CHUNK_ID 0x50414D54
|
||||
#define WOZ_TRKS_CHUNK_ID 0x534B5254
|
||||
#define WOZ_META_CHUNK_ID 0x4154454D
|
||||
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
@ -62,4 +73,53 @@ typedef woz_track_t woz_trks_t[DISKII_MAXTRACKS];
|
|||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
|
||||
#define __NO__WOZ_REAL_SPIN2
|
||||
#ifdef WOZ_REAL_SPIN
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t next;
|
||||
uint8_t data;
|
||||
uint8_t prev;
|
||||
uint8_t shift;
|
||||
};
|
||||
struct {
|
||||
uint32_t lower : 31;
|
||||
uint32_t valid : 1;
|
||||
};
|
||||
uint32_t shift32;
|
||||
} WOZread_t;
|
||||
|
||||
#else // WOZ_REAL_SPIN
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t data;
|
||||
uint8_t shift;
|
||||
};
|
||||
struct {
|
||||
uint16_t lower15 : 15;
|
||||
uint16_t valid : 1;
|
||||
};
|
||||
uint16_t shift16;
|
||||
} WOZread_t;
|
||||
|
||||
#endif // WOZ_REAL_SPIN
|
||||
|
||||
|
||||
extern WOZread_t WOZread;
|
||||
extern uint8_t WOZlatch;
|
||||
|
||||
//extern woz_header_t woz_header;
|
||||
//extern woz_chunk_header_t woz_chunk_header;
|
||||
//extern woz_tmap_t woz_tmap;
|
||||
//extern woz_trks_t woz_trks;
|
||||
|
||||
|
||||
extern uint8_t woz_read();
|
||||
extern void woz_loadFile( const char * filename );
|
||||
|
||||
|
||||
#endif /* woz_h */
|
15
A2Mac/src/util/common.c
Normal file
15
A2Mac/src/util/common.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// common.c
|
||||
// A2Mac
|
||||
//
|
||||
// Created by Tamas Rudnai on 2/16/20.
|
||||
// Copyright © 2020 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
|
||||
|
||||
FILE * outdev = NULL;
|
||||
|
||||
|
67
A2Mac/src/util/common.h
Normal file
67
A2Mac/src/util/common.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// common.h
|
||||
// 6502
|
||||
//
|
||||
// Created by Tamas Rudnai on 7/14/19.
|
||||
// Copyright © 2019 GameAlloy. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define INLINE
|
||||
#else
|
||||
#define INLINE static __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
//#define dbgPrintf(format, ...) printf (format, ## __VA_ARGS__)
|
||||
#define dbgPrintf(format, ...)
|
||||
#define dbgPrintf2(format, ...) if(outdev) fprintf(outdev, format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define dbgPrintf(format, ...)
|
||||
#define dbgPrintf2(format, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#define K 1000ULL
|
||||
#define M (K * K)
|
||||
#define G (M * K)
|
||||
#define T (G * K)
|
||||
|
||||
#define PG 256ULL
|
||||
#define KB 1024ULL
|
||||
#define MB (KB * KB)
|
||||
#define GB (MB * KB)
|
||||
#define TB (GB * KB)
|
||||
|
||||
|
||||
typedef
|
||||
union {
|
||||
uint8_t bits;
|
||||
struct {
|
||||
uint8_t b0:1;
|
||||
uint8_t b1:1;
|
||||
uint8_t b2:1;
|
||||
uint8_t b3:1;
|
||||
uint8_t b4:1;
|
||||
uint8_t b5:1;
|
||||
uint8_t b6:1;
|
||||
uint8_t b7:1;
|
||||
};
|
||||
} bits_t;
|
||||
|
||||
|
||||
#define BITTEST(n,x) ((bits_t)(n)).b##x
|
||||
|
||||
|
||||
extern FILE * outdev;
|
||||
|
||||
|
||||
#endif // __COMMON_H__
|
Loading…
Reference in New Issue
Block a user