2016-11-06 07:53:43 +00:00
# include <cstdlib>
2018-08-07 19:21:43 +00:00
# include <cassert>
2016-12-07 02:24:11 +00:00
# include <cmath>
2016-11-09 11:46:26 +00:00
# include <cstring>
2020-12-11 01:19:39 +00:00
# include <array>
2016-11-06 20:37:19 +00:00
# include <string>
# include <set>
2016-11-07 18:44:29 +00:00
# include <chrono>
# include <thread>
# include <ratio>
2016-11-08 05:22:21 +00:00
# include <iostream>
2016-11-12 21:20:10 +00:00
# include <deque>
# include <map>
2016-11-17 00:16:10 +00:00
# include <thread>
2018-07-20 23:09:59 +00:00
# include <functional>
2016-11-08 05:22:21 +00:00
# include <signal.h>
2020-12-17 07:03:43 +00:00
# include <unistd.h>
2016-11-06 20:37:19 +00:00
2020-12-06 01:19:21 +00:00
# ifndef M_PI
# define M_PI 3.14159
# endif
2020-12-17 07:03:43 +00:00
typedef uint64_t clk_t ;
struct system_clock
{
clk_t clock_cpu = 0 ; // Actual CPU and memory clocks, variable rate
clk_t clock_14mhz = 0 ; // Fixed 14.31818MHz clock
clk_t phase_hpe = 0 ; // Phase of CPU clock within horizontal lines
operator clk_t ( ) const { return clock_14mhz ; }
void add_cpu_cycles ( clk_t elapsed_cpu )
{
clock_cpu + = elapsed_cpu ;
clock_14mhz + = elapsed_cpu * 14 + ( elapsed_cpu + phase_hpe ) / 65 * 2 ;
phase_hpe = ( phase_hpe + elapsed_cpu ) % 65 ;
if ( 0 ) printf ( " added %llu, new cpu clock %llu, 14mhz clock %llu, phase %llu \n " , elapsed_cpu , clock_cpu , clock_14mhz , phase_hpe ) ;
}
} clk ;
2020-12-20 22:49:46 +00:00
#if 0
2020-12-17 07:03:43 +00:00
# define printf PrintToLine3
clk_t clockRangeStart = 2427489692 - 100000 ;
clk_t clockRangeEnd = 2427489692 + 1000 ;
void PrintToLine3 ( const char * fmt , . . . )
{
if ( clk < clockRangeStart ) {
return ;
}
if ( clk > clockRangeEnd ) {
abort ( ) ;
}
static char buffer [ 36 ] ;
va_list args ;
va_start ( args , fmt ) ;
vsnprintf ( buffer , sizeof ( buffer ) , fmt , args ) ;
va_end ( args ) ;
write ( 0 , buffer , strlen ( buffer ) ) ;
}
2020-12-20 22:49:46 +00:00
# endif
2020-12-17 07:03:43 +00:00
2018-09-09 00:36:16 +00:00
// Brad's 6502
# include "cpu6502.h"
2016-11-17 00:16:10 +00:00
2020-12-06 01:19:21 +00:00
# undef SUPPORT_FAKE_6502
2018-09-09 00:36:16 +00:00
// Mike Chambers' 6502
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2016-11-11 23:18:08 +00:00
# include "fake6502.h"
2020-12-06 01:19:21 +00:00
# endif
2016-11-11 23:18:08 +00:00
2016-11-06 20:37:19 +00:00
using namespace std ;
2016-11-06 07:53:43 +00:00
# include "emulator.h"
2016-11-08 05:22:21 +00:00
# include "dis6502.h"
2016-11-17 00:16:10 +00:00
# include "interface.h"
2016-11-06 07:53:43 +00:00
2020-12-06 01:31:46 +00:00
# define LK_HACK 0
2018-08-02 22:20:59 +00:00
2020-12-17 07:03:43 +00:00
constexpr uint32_t DEBUG_ERROR = 0x01 ;
constexpr uint32_t DEBUG_WARN = 0x02 ;
constexpr uint32_t DEBUG_DECODE = 0x04 ;
constexpr uint32_t DEBUG_STATE = 0x08 ;
constexpr uint32_t DEBUG_RW = 0x10 ;
constexpr uint32_t DEBUG_BUS = 0x20 ;
constexpr uint32_t DEBUG_FLOPPY = 0x40 ;
constexpr uint32_t DEBUG_SWITCH = 0x80 ;
constexpr uint32_t DEBUG_CLOCK = 0x100 ;
2020-12-31 19:00:09 +00:00
volatile uint32_t debug = DEBUG_ERROR | DEBUG_WARN ; // | DEBUG_STATE | DEBUG_DECODE;
2016-11-11 13:54:59 +00:00
2018-07-21 02:37:49 +00:00
bool delete_is_left_arrow = true ;
2016-11-11 23:18:08 +00:00
volatile bool exit_on_banking = false ;
volatile bool exit_on_memory_fallthrough = true ;
2016-11-17 06:50:09 +00:00
volatile bool run_fast = false ;
2016-11-23 18:53:56 +00:00
volatile bool pause_cpu = false ;
2016-11-06 07:53:43 +00:00
2018-08-08 23:18:16 +00:00
bool run_rate_limited = false ;
int rate_limit_millis ;
2018-08-01 07:42:31 +00:00
// XXX - this should be handled through a function passed to MAINboard
APPLE2Einterface : : ModeHistory mode_history ;
2016-11-30 06:17:17 +00:00
const float paddle_max_pulse_seconds = .00282 ;
2018-08-02 23:07:42 +00:00
// Map from memory address to name of function (from the ld65 map file).
static map < int , string > address_to_function_name ;
2018-07-30 23:01:39 +00:00
const int machine_clock_rate = 14318180 ;
2016-11-24 07:29:23 +00:00
2020-12-17 07:03:43 +00:00
bool read_blob ( const char * name , uint8_t * b , size_t sz )
2016-11-26 22:51:14 +00:00
{
FILE * fp = fopen ( name , " rb " ) ;
if ( fp = = NULL ) {
fprintf ( stderr , " failed to open %s for reading \n " , name ) ;
fclose ( fp ) ;
return false ;
}
size_t length = fread ( b , 1 , sz , fp ) ;
if ( length < sz ) {
fprintf ( stderr , " File read from %s was unexpectedly short (%zd bytes, expected %zd) \n " , name , length , sz ) ;
perror ( " read_blob " ) ;
fclose ( fp ) ;
return false ;
}
fclose ( fp ) ;
return true ;
}
2018-08-02 23:07:42 +00:00
/**
* Parse a map entry from an ld65 map file and add it to the address_to_function_name map .
*/
static void add_map_entry ( char * line )
{
// Find end of function name and terminate it.
char * s = line ;
while ( * s ! = ' ' ) {
s + + ;
}
* s = ' \0 ' ;
string function_name = string ( line ) ;
// Parse hex address.
int address = strtol ( line + 26 , NULL , 16 ) ;
// See if we have a duplicate. We define our own symbols (like _pushax) as aliases
// to cc65-defined ones (like pushax) so we can access them from C.
string old_function_name = address_to_function_name [ address ] ;
if ( old_function_name . size ( ) ! = 0 & & old_function_name . size ( ) < function_name . size ( ) ) {
// Skip this one, we already have one that's shorter (probably without
// leading underscore).
} else {
// Add to map.
address_to_function_name [ address ] = line ;
}
}
/**
* Read a map file generated by ld65 . Puts symbols into the address_to_function_name map .
*/
2020-12-06 01:19:21 +00:00
static bool read_map ( const char * name )
2018-08-02 23:07:42 +00:00
{
char line [ 100 ] ;
FILE * fp = fopen ( name , " r " ) ;
int state = 0 ;
while ( state ! = 3 & & fgets ( line , sizeof ( line ) , fp ) ! = NULL ) {
switch ( state ) {
case 0 :
if ( strncmp ( line , " Exports list by name: " , 21 ) = = 0 ) {
// Found header.
state = 1 ;
}
break ;
case 1 :
// Skip line with dashes.
state = 2 ;
break ;
case 2 :
// Parse table.
if ( strlen ( line ) < = 76 ) {
// End of table.
state = 3 ;
}
add_map_entry ( line ) ;
add_map_entry ( line + 40 ) ;
break ;
}
}
fclose ( fp ) ;
return true ;
}
2016-11-06 20:37:19 +00:00
struct SoftSwitch
{
string name ;
int clear_address ;
int set_address ;
int read_address ;
bool read_also_changes ;
2020-12-27 07:03:13 +00:00
bool enabled ;
2016-11-08 21:22:46 +00:00
bool implemented ;
2020-12-27 07:03:13 +00:00
SoftSwitch ( const char * name_ , int clear , int on , int read , bool read_changes , vector < SoftSwitch * > & s , bool initialValue , bool implemented_ = false ) :
2016-11-06 20:37:19 +00:00
name ( name_ ) ,
clear_address ( clear ) ,
set_address ( on ) ,
read_address ( read ) ,
2016-11-08 21:22:46 +00:00
read_also_changes ( read_changes ) ,
2020-12-27 07:03:13 +00:00
enabled ( initialValue ) ,
2016-11-08 21:22:46 +00:00
implemented ( implemented_ )
2016-11-06 20:37:19 +00:00
{
s . push_back ( this ) ;
}
operator bool ( ) const
{
2016-11-11 13:54:59 +00:00
return enabled ;
2016-11-06 20:37:19 +00:00
}
} ;
2016-11-08 21:35:35 +00:00
struct region
{
2016-11-09 00:41:30 +00:00
string name ;
2016-11-08 21:35:35 +00:00
int base ;
int size ;
bool contains ( int addr ) const
{
2020-12-11 01:19:39 +00:00
return ( addr > = base ) & & ( addr < base + size ) ;
2016-11-08 21:35:35 +00:00
}
} ;
2016-11-09 00:41:30 +00:00
typedef std : : function < bool ( ) > enabled_func ;
2016-11-09 05:43:01 +00:00
enum MemoryType { RAM , ROM } ;
2016-11-08 21:35:35 +00:00
struct backed_region : region
{
2020-12-17 07:03:43 +00:00
vector < uint8_t > memory ;
2016-11-09 05:43:01 +00:00
MemoryType type ;
2016-11-11 03:33:27 +00:00
enabled_func read_enabled ;
enabled_func write_enabled ;
2016-11-08 21:35:35 +00:00
2016-11-26 22:51:14 +00:00
backed_region ( const char * name , int base , int size , MemoryType type_ , vector < backed_region * > * regions , enabled_func enabled_ ) :
2016-11-09 00:41:30 +00:00
region { name , base , size } ,
memory ( size ) ,
2016-11-09 05:43:01 +00:00
type ( type_ ) ,
2016-11-11 03:33:27 +00:00
read_enabled ( enabled_ ) ,
write_enabled ( enabled_ )
2016-11-09 00:41:30 +00:00
{
2016-11-11 03:33:27 +00:00
std : : fill ( memory . begin ( ) , memory . end ( ) , 0x00 ) ;
2016-11-26 22:51:14 +00:00
if ( regions )
regions - > push_back ( this ) ;
2016-11-11 03:33:27 +00:00
}
2016-11-26 22:51:14 +00:00
backed_region ( const char * name , int base , int size , MemoryType type_ , vector < backed_region * > * regions , enabled_func read_enabled_ , enabled_func write_enabled_ ) :
2016-11-11 03:33:27 +00:00
region { name , base , size } ,
memory ( size ) ,
type ( type_ ) ,
read_enabled ( read_enabled_ ) ,
write_enabled ( write_enabled_ )
{
std : : fill ( memory . begin ( ) , memory . end ( ) , 0x00 ) ;
2016-11-26 22:51:14 +00:00
if ( regions )
regions - > push_back ( this ) ;
2016-11-09 00:41:30 +00:00
}
2016-11-08 21:35:35 +00:00
2016-11-08 21:22:46 +00:00
bool contains ( int addr ) const
{
2020-12-11 01:19:39 +00:00
return ( addr > = base ) & & ( addr < base + size ) ;
2016-11-08 21:22:46 +00:00
}
2016-11-08 21:35:35 +00:00
2020-12-17 07:03:43 +00:00
bool read ( int addr , uint8_t & data )
2016-11-08 21:35:35 +00:00
{
2016-11-11 03:33:27 +00:00
if ( contains ( addr ) & & read_enabled ( ) ) {
2016-11-08 21:35:35 +00:00
data = memory [ addr - base ] ;
return true ;
}
return false ;
}
2020-12-17 07:03:43 +00:00
bool write ( int addr , uint8_t data )
2016-11-08 21:35:35 +00:00
{
2016-11-11 03:33:27 +00:00
if ( ( type = = RAM ) & & contains ( addr ) & & write_enabled ( ) ) {
2016-11-08 21:35:35 +00:00
memory [ addr - base ] = data ;
return true ;
}
return false ;
}
2016-11-08 21:22:46 +00:00
} ;
2016-11-09 00:41:30 +00:00
const region io_region = { " io " , 0xC000 , 0x100 } ;
2016-11-08 21:22:46 +00:00
2020-12-31 19:00:09 +00:00
namespace DiskII
2020-12-12 16:38:58 +00:00
{
/*
2020-12-12 17:44:44 +00:00
5 1 / 2 " floppy disk images are 70 tracks of 16 sectors of 256 bytes
But DOS and ProDOS only read even tracks , so floppy images saved on disk contain only even tracks ,
and a " .dsk " floppy image is only 143360 bytes .
2020-12-12 16:38:58 +00:00
*/
constexpr int sectorSize = 256 ;
constexpr int sectorsPerTrack = 16 ;
2020-12-31 19:00:09 +00:00
constexpr int headDiscretePositions = 140 ;
// constexpr int tracksPerFloppy = headDiscretePositions / 4;
2020-12-12 16:38:58 +00:00
2020-12-17 07:03:43 +00:00
const uint8_t sectorHeader [ 21 ] =
2020-12-12 17:44:44 +00:00
{
0xD5 , 0xAA , 0x96 , 0xFF , 0xFE , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0xDE , 0xAA , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xD5 , 0xAA , 0xAD
} ;
const int sectorSkewDOS [ 16 ] =
{
0x0 , 0x7 , 0xE , 0x6 , 0xD , 0x5 , 0xC , 0x4 , 0xB , 0x3 , 0xA , 0x2 , 0x9 , 0x1 , 0x8 , 0xF
} ;
const int sectorSkewProDOS [ 16 ] =
{
0x0 , 0x8 , 0x1 , 0x9 , 0x2 , 0xA , 0x3 , 0xB , 0x4 , 0xC , 0x5 , 0xD , 0x6 , 0xE , 0x7 , 0xF
} ;
2020-12-17 07:03:43 +00:00
const uint8_t sectorFooter [ 48 ] =
2020-12-12 17:44:44 +00:00
{
0xDE , 0xAA , 0xEB , 0xFF , 0xEB , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF
} ;
2020-12-17 07:03:43 +00:00
const uint8_t SixBitsToBytes [ 0x40 ] =
2020-12-12 17:44:44 +00:00
{
0x96 , 0x97 , 0x9A , 0x9B , 0x9D , 0x9E , 0x9F , 0xA6 ,
0xA7 , 0xAB , 0xAC , 0xAD , 0xAE , 0xAF , 0xB2 , 0xB3 ,
0xB4 , 0xB5 , 0xB6 , 0xB7 , 0xB9 , 0xBA , 0xBB , 0xBC ,
0xBD , 0xBE , 0xBF , 0xCB , 0xCD , 0xCE , 0xCF , 0xD3 ,
0xD6 , 0xD7 , 0xD9 , 0xDA , 0xDB , 0xDC , 0xDD , 0xDE ,
0xDF , 0xE5 , 0xE6 , 0xE7 , 0xE9 , 0xEA , 0xEB , 0xEC ,
0xED , 0xEE , 0xEF , 0xF2 , 0xF3 , 0xF4 , 0xF5 , 0xF6 ,
0xF7 , 0xF9 , 0xFA , 0xFB , 0xFC , 0xFD , 0xFE , 0xFF
} ;
2020-12-12 06:02:52 +00:00
2020-12-12 16:38:58 +00:00
constexpr size_t trackGapSize = 64 ;
2020-12-12 06:02:52 +00:00
constexpr size_t nybblizedSectorSize = 21 + 343 + 48 ;
2020-12-12 16:38:58 +00:00
constexpr size_t nybblizedTrackSize = trackGapSize + sectorsPerTrack * nybblizedSectorSize ;
2020-12-12 06:02:52 +00:00
void nybblizeSector ( int trackIndex , int sectorIndex , const uint8_t * sectorBytes , uint8_t * sectorNybblized )
{
2020-12-27 07:03:13 +00:00
// memset(sectorNybblized, 0xFF, nybblizedSectorSize); // Doesn't matter if 00s or FFs...
2020-12-12 06:02:52 +00:00
uint8_t * p = sectorNybblized ;
2020-12-12 17:44:44 +00:00
memcpy ( p , sectorHeader , sizeof ( sectorHeader ) ) ; // Set up the sectorIndex header
2020-12-12 06:02:52 +00:00
2020-12-12 17:44:44 +00:00
p [ 5 ] = ( ( trackIndex > > 1 ) & 0x55 ) | 0xAA ;
p [ 6 ] = ( trackIndex & 0x55 ) | 0xAA ;
2020-12-12 06:02:52 +00:00
p [ 7 ] = ( ( sectorIndex > > 1 ) & 0x55 ) | 0xAA ;
p [ 8 ] = ( sectorIndex & 0x55 ) | 0xAA ;
p [ 9 ] = ( ( ( trackIndex ^ sectorIndex ^ 0xFE ) > > 1 ) & 0x55 ) | 0xAA ;
p [ 10 ] = ( ( trackIndex ^ sectorIndex ^ 0xFE ) & 0x55 ) | 0xAA ;
p + = 21 ;
// Convert the 256 8-bit bytes into 342 6-bit bytes.
for ( int i = 0 ; i < 0x56 ; i + + )
{
p [ i ] = ( ( sectorBytes [ ( i + 0xAC ) & 0xFF ] & 0x01 ) < < 7 )
| ( ( sectorBytes [ ( i + 0xAC ) & 0xFF ] & 0x02 ) < < 5 )
| ( ( sectorBytes [ ( i + 0x56 ) & 0xFF ] & 0x01 ) < < 5 )
| ( ( sectorBytes [ ( i + 0x56 ) & 0xFF ] & 0x02 ) < < 3 )
| ( ( sectorBytes [ ( i + 0x00 ) & 0xFF ] & 0x01 ) < < 3 )
| ( ( sectorBytes [ ( i + 0x00 ) & 0xFF ] & 0x02 ) < < 1 ) ;
}
p [ 0x54 ] & = 0x3F ;
p [ 0x55 ] & = 0x3F ;
memcpy ( p + 0x56 , sectorBytes , 256 ) ;
// XOR the data block with itself, offset by one byte,
2020-12-27 07:03:13 +00:00
// creating a 343rd byte which is used as a checksum.
2020-12-12 06:02:52 +00:00
p [ 342 ] = 0x00 ;
for ( int i = 342 ; i > 0 ; i - - )
p [ i ] = p [ i ] ^ p [ i - 1 ] ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
2020-12-12 06:02:52 +00:00
// Using a lookup table, convert the 6-bit bytes into disk bytes.
for ( int i = 0 ; i < 343 ; i + + )
2020-12-12 16:38:58 +00:00
p [ i ] = SixBitsToBytes [ p [ i ] > > 2 ] ;
2020-12-12 06:02:52 +00:00
p + = 343 ;
// Done with the nybblization, now for the epilogue...
2020-12-12 16:38:58 +00:00
memcpy ( p , sectorFooter , sizeof ( sectorFooter ) ) ;
2020-12-12 06:02:52 +00:00
}
2020-12-17 07:03:43 +00:00
bool nybblizeTrackFromFile ( FILE * floppyImageFile , int trackIndex , uint8_t * nybblizedTrack , const int * skew )
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
{
2020-12-12 17:44:44 +00:00
memset ( nybblizedTrack , 0xFF , trackGapSize ) ; // Write gap 1, 64 bytes (self-sync)
2020-12-12 06:02:52 +00:00
2020-12-17 07:03:43 +00:00
for ( int sectorIndex = 0 ; sectorIndex < 16 ; sectorIndex + + )
2020-12-12 06:02:52 +00:00
{
2020-12-17 07:03:43 +00:00
uint32_t sectorOffset = ( skew [ sectorIndex ] + trackIndex * sectorsPerTrack ) * sectorSize ;
2020-12-12 17:44:44 +00:00
int seeked = fseek ( floppyImageFile , sectorOffset , SEEK_SET ) ;
if ( seeked = = - 1 ) {
fprintf ( stderr , " failed to seek to sector in floppy disk image \n " ) ;
return false ;
}
2020-12-12 16:38:58 +00:00
2020-12-17 07:03:43 +00:00
uint8_t sectorBytes [ 256 ] ;
2020-12-12 17:44:44 +00:00
size_t wasRead = fread ( sectorBytes , 1 , sectorSize , floppyImageFile ) ;
if ( wasRead ! = sectorSize ) {
fprintf ( stderr , " failed to read sector from floppy disk image \n " ) ;
2020-12-20 22:49:46 +00:00
printf ( " track %d, sectorIndex %d, skew %d, offset %d, read %zd \n " , trackIndex , sectorIndex , skew [ sectorIndex ] , sectorOffset , wasRead ) ;
2020-12-12 17:44:44 +00:00
return false ;
2020-12-12 06:02:52 +00:00
}
2020-12-12 17:44:44 +00:00
2020-12-27 07:03:13 +00:00
uint8_t * sectorDest = nybblizedTrack + trackGapSize + sectorIndex * nybblizedSectorSize ;
nybblizeSector ( trackIndex , sectorIndex , sectorBytes , sectorDest ) ;
2020-12-12 06:02:52 +00:00
}
2020-12-12 16:38:58 +00:00
return true ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2020-12-31 19:00:09 +00:00
enum MotorAction
{
MOTOR_RIGHT_ONE , /* headPosition += 1; */
MOTOR_RIGHT_TWO , /* headPosition += 2; */
MOTOR_LEFT_ONE , /* headPosition -= 1; */
MOTOR_LEFT_TWO , /* headPosition -= 2; */
MOTOR_NONE , /* nothing */
MOTOR_SNAP , /* calculate which way head moves from magnet and head position */
MOTOR_STATE_NEVER , /* should never get this transition */
} ;
MotorAction motorActions [ 256 ] =
{
MOTOR_NONE , // 0x00, 0,0,0,0 to 0,0,0,0
MOTOR_SNAP , // 0x01, 0,0,0,0 to 0,0,0,1
MOTOR_SNAP , // 0x02, 0,0,0,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x03, 0,0,0,0 to 0,0,1,1
MOTOR_SNAP , // 0x04, 0,0,0,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x05, 0,0,0,0 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x06, 0,0,0,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x07, 0,0,0,0 to 0,1,1,1
MOTOR_SNAP , // 0x08, 0,0,0,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x09, 0,0,0,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x0A, 0,0,0,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x0B, 0,0,0,0 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x0C, 0,0,0,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x0D, 0,0,0,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x0E, 0,0,0,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x0F, 0,0,0,0 to 1,1,1,1
MOTOR_NONE , // 0x10, 0,0,0,1 to 0,0,0,0
MOTOR_NONE , // 0x11, 0,0,0,1 to 0,0,0,1
MOTOR_LEFT_TWO , // 0x12, 0,0,0,1 to 0,0,1,0
MOTOR_LEFT_ONE , // 0x13, 0,0,0,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0x14, 0,0,0,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x15, 0,0,0,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x16, 0,0,0,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x17, 0,0,0,1 to 0,1,1,1
MOTOR_RIGHT_TWO , // 0x18, 0,0,0,1 to 1,0,0,0
MOTOR_RIGHT_ONE , // 0x19, 0,0,0,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x1A, 0,0,0,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x1B, 0,0,0,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x1C, 0,0,0,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x1D, 0,0,0,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x1E, 0,0,0,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x1F, 0,0,0,1 to 1,1,1,1
MOTOR_NONE , // 0x20, 0,0,1,0 to 0,0,0,0
MOTOR_RIGHT_TWO , // 0x21, 0,0,1,0 to 0,0,0,1
MOTOR_NONE , // 0x22, 0,0,1,0 to 0,0,1,0
MOTOR_RIGHT_ONE , // 0x23, 0,0,1,0 to 0,0,1,1
MOTOR_LEFT_TWO , // 0x24, 0,0,1,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x25, 0,0,1,0 to 0,1,0,1
MOTOR_LEFT_ONE , // 0x26, 0,0,1,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x27, 0,0,1,0 to 0,1,1,1
MOTOR_STATE_NEVER , // 0x28, 0,0,1,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x29, 0,0,1,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x2A, 0,0,1,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x2B, 0,0,1,0 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x2C, 0,0,1,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x2D, 0,0,1,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x2E, 0,0,1,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x2F, 0,0,1,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0x30, 0,0,1,1 to 0,0,0,0
MOTOR_RIGHT_ONE , // 0x31, 0,0,1,1 to 0,0,0,1
MOTOR_LEFT_ONE , // 0x32, 0,0,1,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x33, 0,0,1,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0x34, 0,0,1,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x35, 0,0,1,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x36, 0,0,1,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x37, 0,0,1,1 to 0,1,1,1
MOTOR_STATE_NEVER , // 0x38, 0,0,1,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x39, 0,0,1,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x3A, 0,0,1,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x3B, 0,0,1,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x3C, 0,0,1,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x3D, 0,0,1,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x3E, 0,0,1,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x3F, 0,0,1,1 to 1,1,1,1
MOTOR_NONE , // 0x40, 0,1,0,0 to 0,0,0,0
MOTOR_STATE_NEVER , // 0x41, 0,1,0,0 to 0,0,0,1
MOTOR_RIGHT_TWO , // 0x42, 0,1,0,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x43, 0,1,0,0 to 0,0,1,1
MOTOR_NONE , // 0x44, 0,1,0,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x45, 0,1,0,0 to 0,1,0,1
MOTOR_RIGHT_ONE , // 0x46, 0,1,0,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x47, 0,1,0,0 to 0,1,1,1
MOTOR_LEFT_TWO , // 0x48, 0,1,0,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x49, 0,1,0,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x4A, 0,1,0,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x4B, 0,1,0,0 to 1,0,1,1
MOTOR_LEFT_ONE , // 0x4C, 0,1,0,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x4D, 0,1,0,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x4E, 0,1,0,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x4F, 0,1,0,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0x50, 0,1,0,1 to 0,0,0,0
MOTOR_STATE_NEVER , // 0x51, 0,1,0,1 to 0,0,0,1
MOTOR_STATE_NEVER , // 0x52, 0,1,0,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x53, 0,1,0,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0x54, 0,1,0,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x55, 0,1,0,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x56, 0,1,0,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x57, 0,1,0,1 to 0,1,1,1
MOTOR_STATE_NEVER , // 0x58, 0,1,0,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x59, 0,1,0,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x5A, 0,1,0,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x5B, 0,1,0,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x5C, 0,1,0,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x5D, 0,1,0,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x5E, 0,1,0,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x5F, 0,1,0,1 to 1,1,1,1
MOTOR_STATE_NEVER , // 0x60, 0,1,1,0 to 0,0,0,0
MOTOR_STATE_NEVER , // 0x61, 0,1,1,0 to 0,0,0,1
MOTOR_RIGHT_ONE , // 0x62, 0,1,1,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x63, 0,1,1,0 to 0,0,1,1
MOTOR_LEFT_ONE , // 0x64, 0,1,1,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x65, 0,1,1,0 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x66, 0,1,1,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x67, 0,1,1,0 to 0,1,1,1
MOTOR_STATE_NEVER , // 0x68, 0,1,1,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x69, 0,1,1,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x6A, 0,1,1,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x6B, 0,1,1,0 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x6C, 0,1,1,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x6D, 0,1,1,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x6E, 0,1,1,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x6F, 0,1,1,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0x70, 0,1,1,1 to 0,0,0,0
MOTOR_STATE_NEVER , // 0x71, 0,1,1,1 to 0,0,0,1
MOTOR_STATE_NEVER , // 0x72, 0,1,1,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x73, 0,1,1,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0x74, 0,1,1,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x75, 0,1,1,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x76, 0,1,1,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x77, 0,1,1,1 to 0,1,1,1
MOTOR_STATE_NEVER , // 0x78, 0,1,1,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x79, 0,1,1,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x7A, 0,1,1,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x7B, 0,1,1,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x7C, 0,1,1,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x7D, 0,1,1,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x7E, 0,1,1,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x7F, 0,1,1,1 to 1,1,1,1
MOTOR_NONE , // 0x80, 1,0,0,0 to 0,0,0,0
MOTOR_LEFT_TWO , // 0x81, 1,0,0,0 to 0,0,0,1
MOTOR_STATE_NEVER , // 0x82, 1,0,0,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x83, 1,0,0,0 to 0,0,1,1
MOTOR_RIGHT_TWO , // 0x84, 1,0,0,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x85, 1,0,0,0 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x86, 1,0,0,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x87, 1,0,0,0 to 0,1,1,1
MOTOR_NONE , // 0x88, 1,0,0,0 to 1,0,0,0
MOTOR_LEFT_ONE , // 0x89, 1,0,0,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x8A, 1,0,0,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x8B, 1,0,0,0 to 1,0,1,1
MOTOR_RIGHT_ONE , // 0x8C, 1,0,0,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x8D, 1,0,0,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x8E, 1,0,0,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x8F, 1,0,0,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0x90, 1,0,0,1 to 0,0,0,0
MOTOR_LEFT_ONE , // 0x91, 1,0,0,1 to 0,0,0,1
MOTOR_STATE_NEVER , // 0x92, 1,0,0,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0x93, 1,0,0,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0x94, 1,0,0,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0x95, 1,0,0,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0x96, 1,0,0,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0x97, 1,0,0,1 to 0,1,1,1
MOTOR_RIGHT_ONE , // 0x98, 1,0,0,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0x99, 1,0,0,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0x9A, 1,0,0,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0x9B, 1,0,0,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0x9C, 1,0,0,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0x9D, 1,0,0,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0x9E, 1,0,0,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0x9F, 1,0,0,1 to 1,1,1,1
MOTOR_STATE_NEVER , // 0xA0, 1,0,1,0 to 0,0,0,0
MOTOR_STATE_NEVER , // 0xA1, 1,0,1,0 to 0,0,0,1
MOTOR_STATE_NEVER , // 0xA2, 1,0,1,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0xA3, 1,0,1,0 to 0,0,1,1
MOTOR_STATE_NEVER , // 0xA4, 1,0,1,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0xA5, 1,0,1,0 to 0,1,0,1
MOTOR_STATE_NEVER , // 0xA6, 1,0,1,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0xA7, 1,0,1,0 to 0,1,1,1
MOTOR_STATE_NEVER , // 0xA8, 1,0,1,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0xA9, 1,0,1,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0xAA, 1,0,1,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0xAB, 1,0,1,0 to 1,0,1,1
MOTOR_STATE_NEVER , // 0xAC, 1,0,1,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0xAD, 1,0,1,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0xAE, 1,0,1,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0xAF, 1,0,1,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0xB0, 1,0,1,1 to 0,0,0,0
MOTOR_STATE_NEVER , // 0xB1, 1,0,1,1 to 0,0,0,1
MOTOR_STATE_NEVER , // 0xB2, 1,0,1,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0xB3, 1,0,1,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0xB4, 1,0,1,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0xB5, 1,0,1,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0xB6, 1,0,1,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0xB7, 1,0,1,1 to 0,1,1,1
MOTOR_STATE_NEVER , // 0xB8, 1,0,1,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0xB9, 1,0,1,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0xBA, 1,0,1,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0xBB, 1,0,1,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0xBC, 1,0,1,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0xBD, 1,0,1,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0xBE, 1,0,1,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0xBF, 1,0,1,1 to 1,1,1,1
MOTOR_STATE_NEVER , // 0xC0, 1,1,0,0 to 0,0,0,0
MOTOR_STATE_NEVER , // 0xC1, 1,1,0,0 to 0,0,0,1
MOTOR_STATE_NEVER , // 0xC2, 1,1,0,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0xC3, 1,1,0,0 to 0,0,1,1
MOTOR_RIGHT_ONE , // 0xC4, 1,1,0,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0xC5, 1,1,0,0 to 0,1,0,1
MOTOR_STATE_NEVER , // 0xC6, 1,1,0,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0xC7, 1,1,0,0 to 0,1,1,1
MOTOR_LEFT_ONE , // 0xC8, 1,1,0,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0xC9, 1,1,0,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0xCA, 1,1,0,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0xCB, 1,1,0,0 to 1,0,1,1
MOTOR_STATE_NEVER , // 0xCC, 1,1,0,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0xCD, 1,1,0,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0xCE, 1,1,0,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0xCF, 1,1,0,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0xD0, 1,1,0,1 to 0,0,0,0
MOTOR_STATE_NEVER , // 0xD1, 1,1,0,1 to 0,0,0,1
MOTOR_STATE_NEVER , // 0xD2, 1,1,0,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0xD3, 1,1,0,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0xD4, 1,1,0,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0xD5, 1,1,0,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0xD6, 1,1,0,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0xD7, 1,1,0,1 to 0,1,1,1
MOTOR_STATE_NEVER , // 0xD8, 1,1,0,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0xD9, 1,1,0,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0xDA, 1,1,0,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0xDB, 1,1,0,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0xDC, 1,1,0,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0xDD, 1,1,0,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0xDE, 1,1,0,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0xDF, 1,1,0,1 to 1,1,1,1
MOTOR_STATE_NEVER , // 0xE0, 1,1,1,0 to 0,0,0,0
MOTOR_STATE_NEVER , // 0xE1, 1,1,1,0 to 0,0,0,1
MOTOR_STATE_NEVER , // 0xE2, 1,1,1,0 to 0,0,1,0
MOTOR_STATE_NEVER , // 0xE3, 1,1,1,0 to 0,0,1,1
MOTOR_STATE_NEVER , // 0xE4, 1,1,1,0 to 0,1,0,0
MOTOR_STATE_NEVER , // 0xE5, 1,1,1,0 to 0,1,0,1
MOTOR_STATE_NEVER , // 0xE6, 1,1,1,0 to 0,1,1,0
MOTOR_STATE_NEVER , // 0xE7, 1,1,1,0 to 0,1,1,1
MOTOR_STATE_NEVER , // 0xE8, 1,1,1,0 to 1,0,0,0
MOTOR_STATE_NEVER , // 0xE9, 1,1,1,0 to 1,0,0,1
MOTOR_STATE_NEVER , // 0xEA, 1,1,1,0 to 1,0,1,0
MOTOR_STATE_NEVER , // 0xEB, 1,1,1,0 to 1,0,1,1
MOTOR_STATE_NEVER , // 0xEC, 1,1,1,0 to 1,1,0,0
MOTOR_STATE_NEVER , // 0xED, 1,1,1,0 to 1,1,0,1
MOTOR_STATE_NEVER , // 0xEE, 1,1,1,0 to 1,1,1,0
MOTOR_STATE_NEVER , // 0xEF, 1,1,1,0 to 1,1,1,1
MOTOR_STATE_NEVER , // 0xF0, 1,1,1,1 to 0,0,0,0
MOTOR_STATE_NEVER , // 0xF1, 1,1,1,1 to 0,0,0,1
MOTOR_STATE_NEVER , // 0xF2, 1,1,1,1 to 0,0,1,0
MOTOR_STATE_NEVER , // 0xF3, 1,1,1,1 to 0,0,1,1
MOTOR_STATE_NEVER , // 0xF4, 1,1,1,1 to 0,1,0,0
MOTOR_STATE_NEVER , // 0xF5, 1,1,1,1 to 0,1,0,1
MOTOR_STATE_NEVER , // 0xF6, 1,1,1,1 to 0,1,1,0
MOTOR_STATE_NEVER , // 0xF7, 1,1,1,1 to 0,1,1,1
MOTOR_STATE_NEVER , // 0xF8, 1,1,1,1 to 1,0,0,0
MOTOR_STATE_NEVER , // 0xF9, 1,1,1,1 to 1,0,0,1
MOTOR_STATE_NEVER , // 0xFA, 1,1,1,1 to 1,0,1,0
MOTOR_STATE_NEVER , // 0xFB, 1,1,1,1 to 1,0,1,1
MOTOR_STATE_NEVER , // 0xFC, 1,1,1,1 to 1,1,0,0
MOTOR_STATE_NEVER , // 0xFD, 1,1,1,1 to 1,1,0,1
MOTOR_STATE_NEVER , // 0xFE, 1,1,1,1 to 1,1,1,0
MOTOR_STATE_NEVER , // 0xFF, 1,1,1,1 to 1,1,1,1
} ;
typedef std : : array < bool , 4 > MagnetState ;
int calculateMotorSnapLocation ( int headLocation /* 0 to headDiscretePositions - 1 */ , int alignedHeadLocation /* 0 to 7 */ )
{
// energized phase 3 from no other magnets, track stepper motor snapped from 0 to 4
int below = headLocation / 8 * 8 - 8 + alignedHeadLocation ;
int above = headLocation / 8 * 8 + alignedHeadLocation ;
int closest = ( ( headLocation - below ) < = ( above - headLocation ) ) ? below : above ;
int actual = std : : max ( 0 , std : : min ( closest , headDiscretePositions - 1 ) ) ;
if ( debug & DEBUG_FLOPPY ) {
printf ( " headLocation = %d, aligned = %d, below = %d, above = %d, closest = %d, actual = %d \n " ,
headLocation , alignedHeadLocation , below , above , closest , actual ) ;
}
return actual ;
}
2020-12-12 16:38:58 +00:00
} ;
2020-12-07 04:08:03 +00:00
// XXX readonly at this time
2016-11-26 22:51:14 +00:00
struct DISKIIboard : board_base
{
2020-12-11 01:19:39 +00:00
static constexpr int CA0 = 0xC0E0 ; // stepper phase 0 / control line 0
static constexpr int CA1 = 0xC0E2 ; // stepper phase 1 / control line 1
static constexpr int CA2 = 0xC0E4 ; // stepper phase 2 / control line 2
static constexpr int CA3 = 0xC0E6 ; // stepper phase 3 / control strobe
static constexpr int ENABLE = 0xC0E8 ; // disk drive off/on
static constexpr int SELECT = 0xC0EA ; // select drive 1/2
static constexpr int Q6L = 0xC0EC ; // IO strobe for read
static constexpr int Q6H = 0xC0ED ; // IO strobe for write
static constexpr int Q7L = 0xC0EE ; // IO strobe for clear
static constexpr int Q7H = 0xC0EF ; // IO strobe for shift
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
2020-12-17 07:03:43 +00:00
const map < uint32_t , string > io = {
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
{ 0xC0E0 , " CA0OFF " } ,
{ 0xC0E1 , " CA0ON " } ,
{ 0xC0E2 , " CA1OFF " } ,
{ 0xC0E3 , " CA1ON " } ,
{ 0xC0E4 , " CA2OFF " } ,
{ 0xC0E5 , " CA2ON " } ,
{ 0xC0E6 , " CA3OFF " } ,
{ 0xC0E7 , " CA3ON " } ,
{ 0xC0E8 , " DISABLE " } ,
{ 0xC0E9 , " ENABLE " } ,
{ 0xC0EA , " SELECT0 " } ,
{ 0xC0EB , " SELECT1 " } ,
{ 0xC0EC , " Q6L " } ,
{ 0xC0ED , " Q6H " } ,
{ 0xC0EE , " Q7L " } ,
{ 0xC0EF , " Q7H " } ,
} ;
2016-11-26 22:51:14 +00:00
backed_region rom_C600 = { " rom_C600 " , 0xC600 , 0x0100 , ROM , nullptr , [ & ] { return true ; } } ;
2020-12-20 22:49:46 +00:00
bool floppyPresent [ 2 ] = { false , false } ;
2020-12-12 17:44:44 +00:00
std : : string floppyImageNames [ 2 ] ;
2020-12-12 16:38:58 +00:00
FILE * floppyImageFiles [ 2 ] = { nullptr , nullptr } ;
2020-12-20 22:49:46 +00:00
const int * floppySectorSkew [ 2 ] = { nullptr , nullptr } ;
2016-11-26 22:51:14 +00:00
2020-12-12 17:44:44 +00:00
// Floppy drive control
int driveSelected = 0 ;
2020-12-20 22:49:46 +00:00
bool driveMotorEnabled [ 2 ] = { false , false } ;
2020-12-12 17:44:44 +00:00
enum { READ , WRITE } headMode = READ ;
2020-12-17 07:03:43 +00:00
uint8_t dataLatch = 0x00 ;
2020-12-31 19:00:09 +00:00
DiskII : : MagnetState driveMagnetState [ 2 ] = { { false , false , false , false } , { false , false , false , false } } ;
int currentHeadLocation [ 2 ] = { 0 , 0 } ; // XXXFLOPPY normalize this to head location 0-(headDiscretePositions - 1)
2020-12-12 17:44:44 +00:00
// track data
2020-12-31 19:00:09 +00:00
uint8_t trackBytes [ DiskII : : nybblizedTrackSize ] ;
2020-12-13 23:44:22 +00:00
bool trackBytesOutOfDate = true ;
2020-12-12 18:17:13 +00:00
int nybblizedTrackIndex = - 1 ;
int nybblizedDriveIndex = - 1 ;
2020-12-17 07:03:43 +00:00
uint32_t trackByteIndex = 0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
2020-12-06 01:19:21 +00:00
void set_floppy ( int number , const char * name ) / / number 0 or 1 ; name = NULL to eject
2016-11-26 22:51:14 +00:00
{
2020-12-12 17:44:44 +00:00
floppyPresent [ number ] = false ;
floppyImageNames [ number ] = " " ;
2020-12-12 18:17:13 +00:00
if ( nybblizedDriveIndex = = number ) {
nybblizedTrackIndex = - 1 ;
nybblizedDriveIndex = - 1 ;
}
2020-12-12 16:38:58 +00:00
2016-11-26 22:51:14 +00:00
if ( name ) {
2020-12-12 16:38:58 +00:00
if ( floppyImageFiles [ number ] ) {
fclose ( floppyImageFiles [ number ] ) ;
}
floppyImageFiles [ number ] = fopen ( name , " rb " ) ;
if ( ! floppyImageFiles [ number ] ) {
fprintf ( stderr , " Couldn't open floppy disk image \" %s \" \n " , name ) ;
2020-12-12 06:02:52 +00:00
} else {
2020-12-12 16:38:58 +00:00
if ( strcmp ( name + strlen ( name ) - 3 , " .po " ) = = 0 ) {
printf ( " ProDOS floppy \n " ) ;
2020-12-31 19:00:09 +00:00
floppySectorSkew [ number ] = DiskII : : sectorSkewProDOS ;
2020-12-12 16:38:58 +00:00
} else {
2020-12-31 19:00:09 +00:00
floppySectorSkew [ number ] = DiskII : : sectorSkewDOS ;
2020-12-12 16:38:58 +00:00
}
2020-12-12 17:44:44 +00:00
floppyPresent [ number ] = true ;
floppyImageNames [ number ] = name ;
2020-12-12 06:02:52 +00:00
}
2016-11-26 22:51:14 +00:00
}
}
2016-12-02 18:42:22 +00:00
typedef std : : function < void ( int number , bool activity ) > floppy_activity_func ;
floppy_activity_func floppy_activity ;
2020-12-17 07:03:43 +00:00
DISKIIboard ( const uint8_t diskII_rom [ 256 ] , const char * floppy0_name , const char * floppy1_name , floppy_activity_func floppy_activity_ ) :
2016-12-02 18:42:22 +00:00
floppy_activity ( floppy_activity_ )
2016-11-26 22:51:14 +00:00
{
std : : copy ( diskII_rom , diskII_rom + 0x100 , rom_C600 . memory . begin ( ) ) ;
2020-12-11 01:19:39 +00:00
if ( floppy0_name ) {
2020-12-12 06:02:52 +00:00
set_floppy ( 0 , floppy0_name ) ;
2020-12-11 01:19:39 +00:00
}
if ( floppy1_name ) {
2020-12-12 06:02:52 +00:00
set_floppy ( 1 , floppy1_name ) ;
2020-12-11 01:19:39 +00:00
}
2016-11-26 22:51:14 +00:00
}
2020-12-17 07:03:43 +00:00
uint8_t readNextTrackByte ( )
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
{
2020-12-27 07:03:13 +00:00
// bool dataValid = (headMode != READ || !driveMotorEnabled[driveSelected] || !floppyPresent[driveSelected]);
bool dataValid = floppyPresent [ driveSelected ] ;
if ( ! dataValid ) {
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
return 0x00 ;
2020-12-27 07:03:13 +00:00
}
2020-12-12 17:44:44 +00:00
2020-12-13 23:44:22 +00:00
if ( trackBytesOutOfDate ) {
readDriveTrack ( ) ;
trackBytesOutOfDate = false ;
}
2020-12-12 18:17:13 +00:00
uint8_t data = trackBytes [ trackByteIndex ] ;
2020-12-12 17:44:44 +00:00
2020-12-27 07:03:13 +00:00
if ( false ) {
2020-12-31 19:00:09 +00:00
printf ( " read track %d byte %d (sector %ld byte %ld), yields %d (%02X) \n " , nybblizedTrackIndex , trackByteIndex , trackByteIndex / DiskII : : nybblizedSectorSize , trackByteIndex % DiskII : : nybblizedSectorSize , data , data ) ;
2020-12-27 07:03:13 +00:00
}
2020-12-31 19:00:09 +00:00
trackByteIndex = ( trackByteIndex + 1 ) % DiskII : : nybblizedTrackSize ;
2020-12-12 17:44:44 +00:00
return data ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2020-12-12 17:44:44 +00:00
bool readDriveTrack ( )
{
if ( ! floppyPresent [ driveSelected ] ) {
return false ;
}
2020-12-31 19:00:09 +00:00
if ( currentHeadLocation [ driveSelected ] % 4 ! = 0 ) {
fprintf ( stderr , " current head location %d was unexpectedly not aligned with Disk II track (%% 4 = %d) \n " , currentHeadLocation [ driveSelected ] , currentHeadLocation [ driveSelected ] % 4 ) ;
2020-12-12 18:17:13 +00:00
return true ;
}
2020-12-31 19:00:09 +00:00
if ( ( nybblizedTrackIndex = = currentHeadLocation [ driveSelected ] ) & & ( nybblizedDriveIndex = = driveSelected ) ) {
return true ;
}
bool success = DiskII : : nybblizeTrackFromFile ( floppyImageFiles [ driveSelected ] , currentHeadLocation [ driveSelected ] / 4 , trackBytes , floppySectorSkew [ driveSelected ] ) ;
2020-12-12 17:44:44 +00:00
if ( ! success ) {
fprintf ( stderr , " unexpected failure reading track from disk \" %s \" \n " , floppyImageNames [ driveSelected ] . c_str ( ) ) ;
return false ;
}
2020-12-31 19:00:09 +00:00
nybblizedTrackIndex = currentHeadLocation [ driveSelected ] / 4 ;
2020-12-12 18:17:13 +00:00
nybblizedDriveIndex = driveSelected ;
2020-12-27 07:03:13 +00:00
trackByteIndex = 0 ;
2020-12-12 18:17:13 +00:00
2020-12-12 17:44:44 +00:00
return true ;
}
2020-12-31 19:00:09 +00:00
/* brainstorming over stepper magnet control: */
/* only magnet ((motor / 2 +- 1) % 4) can be energized or deenergized in normal operation */
/* if (motor % 2 == 0), only valid new state is that ((motor / 2 +- 1) % 4) magnets are energized */
/* if (motor / 2 - 1) % 4 is energized, motor -= 1 */
/* if (motor / 2 + 1) % 4 is energized, motor += 1 */
/* if (motor % 2 == 1), only valid new state is that ((motor / 2 +- 1) % 4) magnets are deenergized */
/* if (motor / 2 - 1) % 4 is deenergized, motor += 1 */
/* if (motor / 2 + 1) % 4 is deenergized, motor -= 1 */
/* if all are deenergized then one is energized, head snaps to that magnet from where it is */
/* magnet = 0 and (head % 8) in {0,1,2,3}, head moves to right */
/* magnet = 0 and (head % 8) == 4 head snaps randomly? (or always to left?) */
/* magnet = 0 and (head % 8) in {5,6,7}, head moves to left */
/* could print an error if head wasn't at that magnet */
static uint8_t magnetStateToTransitionIndex ( DiskII : : MagnetState oldState , DiskII : : MagnetState newState )
{
return
( oldState [ 0 ] < < 7 ) |
( oldState [ 1 ] < < 6 ) |
( oldState [ 2 ] < < 5 ) |
( oldState [ 3 ] < < 4 ) |
( newState [ 0 ] < < 3 ) |
( newState [ 1 ] < < 2 ) |
( newState [ 2 ] < < 1 ) |
( newState [ 3 ] < < 0 ) ;
}
2020-12-17 07:03:43 +00:00
void controlTrackMotor ( uint32_t addr )
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
{
int phase = ( addr & 0x7 ) > > 1 ;
2020-12-31 19:00:09 +00:00
bool state = addr & 0x1 ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
const DiskII : : MagnetState & oldMagnetState = driveMagnetState [ driveSelected ] ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
DiskII : : MagnetState newMagnetState = oldMagnetState ;
newMagnetState [ phase ] = state ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
DiskII : : MotorAction action = DiskII : : motorActions [ magnetStateToTransitionIndex ( oldMagnetState , newMagnetState ) ] ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
switch ( action ) {
case DiskII : : MOTOR_RIGHT_ONE :
currentHeadLocation [ driveSelected ] = std : : min ( currentHeadLocation [ driveSelected ] + 1 , DiskII : : headDiscretePositions - 1 ) ;
trackBytesOutOfDate = true ;
break ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
case DiskII : : MOTOR_RIGHT_TWO :
currentHeadLocation [ driveSelected ] = std : : min ( currentHeadLocation [ driveSelected ] + 2 , DiskII : : headDiscretePositions - 1 ) ;
2020-12-13 23:44:22 +00:00
trackBytesOutOfDate = true ;
2020-12-31 19:00:09 +00:00
break ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
case DiskII : : MOTOR_LEFT_ONE :
currentHeadLocation [ driveSelected ] = std : : max ( currentHeadLocation [ driveSelected ] - 1 , 0 ) ;
trackBytesOutOfDate = true ;
break ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
case DiskII : : MOTOR_LEFT_TWO :
currentHeadLocation [ driveSelected ] = std : : max ( currentHeadLocation [ driveSelected ] - 2 , 0 ) ;
2020-12-13 23:44:22 +00:00
trackBytesOutOfDate = true ;
2020-12-31 19:00:09 +00:00
break ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
case DiskII : : MOTOR_NONE :
// nothing;
break ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
case DiskII : : MOTOR_SNAP : {
/* calculate which way head moves from magnet and head position */
int headLocationAlignedWithPhaseMagnet = phase * 2 ;
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
if ( currentHeadLocation [ driveSelected ] = = headLocationAlignedWithPhaseMagnet ) {
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
/* just reenergized magnet last deenergized, do nothing */
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
} else {
int old = currentHeadLocation [ driveSelected ] ;
currentHeadLocation [ driveSelected ] = DiskII : : calculateMotorSnapLocation ( currentHeadLocation [ driveSelected ] , headLocationAlignedWithPhaseMagnet ) ;
if ( debug & DEBUG_FLOPPY ) {
printf ( " energized phase %d from no other magnets, track stepper motor snapped from %d to %d \n " , phase , old , currentHeadLocation [ driveSelected ] ) ;
}
trackBytesOutOfDate = true ;
}
break ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2020-12-12 17:44:44 +00:00
2020-12-31 19:00:09 +00:00
case DiskII : : MOTOR_STATE_NEVER :
if ( debug & DEBUG_WARN ) {
fprintf ( stderr , " unexpected track stepper motor transition: %d,%d,%d,%d to %d,%d,%d,%d \n " ,
oldMagnetState [ 0 ] ? 1 : 0 , oldMagnetState [ 1 ] ? 1 : 0 , oldMagnetState [ 2 ] ? 1 : 0 , oldMagnetState [ 3 ] ? 1 : 0 ,
newMagnetState [ 0 ] ? 1 : 0 , newMagnetState [ 1 ] ? 1 : 0 , newMagnetState [ 2 ] ? 1 : 0 , newMagnetState [ 3 ] ? 1 : 0 ) ;
}
break ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2020-12-31 19:00:09 +00:00
driveMagnetState [ driveSelected ] = newMagnetState ;
if ( debug & DEBUG_FLOPPY ) printf ( " stepper %04X, phase %d, state %d, so stepper motor state now: %d, %d, %d, %d \n " ,
addr , phase , state ,
newMagnetState [ 0 ] ? 1 : 0 , newMagnetState [ 1 ] ? 1 : 0 , newMagnetState [ 2 ] ? 1 : 0 , newMagnetState [ 3 ] ? 1 : 0 ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2020-12-17 07:03:43 +00:00
virtual bool write ( int addr , uint8_t data )
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
{
if ( addr < 0xC0E0 | | addr > 0xC0EF )
return false ;
2020-12-12 17:44:44 +00:00
if ( debug & DEBUG_WARN ) printf ( " DISK II unhandled write of %02X to %04X (%s) \n " , data , addr , io . at ( addr ) . c_str ( ) ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
return false ;
}
2020-12-12 17:44:44 +00:00
2020-12-17 07:03:43 +00:00
virtual bool read ( int addr , uint8_t & data )
2016-11-26 22:51:14 +00:00
{
if ( rom_C600 . read ( addr , data ) ) {
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( debug & DEBUG_RW ) printf ( " DiskII read 0x%04X -> %02X \n " , addr , data ) ;
2016-11-26 22:51:14 +00:00
return true ;
}
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( addr < 0xC0E0 | | addr > 0xC0EF ) {
return false ;
}
if ( addr > = CA0 & & addr < = ( CA3 + 1 ) ) {
if ( debug & DEBUG_FLOPPY ) printf ( " floppy control track motor \n " ) ;
2020-12-12 17:44:44 +00:00
controlTrackMotor ( addr ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
data = 0 ;
return true ;
} else if ( addr = = Q6L ) { // 0xC0EC
2020-12-12 17:44:44 +00:00
data = readNextTrackByte ( ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( debug & DEBUG_FLOPPY ) printf ( " floppy read byte : %02X \n " , data ) ;
return true ;
} else if ( addr = = Q6H ) { // 0xC0ED
if ( debug & DEBUG_FLOPPY ) printf ( " floppy read latch \n " ) ;
2020-12-12 17:44:44 +00:00
data = dataLatch ; // XXX do something with the latch - e.g. set write-protect bit
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
data = 0 ;
return true ;
} else if ( addr = = Q7L ) { // 0xC0EE
if ( debug & DEBUG_FLOPPY ) printf ( " floppy set read \n " ) ;
2020-12-12 17:44:44 +00:00
headMode = READ ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
data = 0 ;
return true ;
} else if ( addr = = Q7H ) { // 0xC0EF
if ( debug & DEBUG_FLOPPY ) printf ( " floppy set write \n " ) ;
2020-12-12 17:44:44 +00:00
headMode = WRITE ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
data = 0 ;
return true ;
} else if ( addr = = SELECT ) {
if ( debug & DEBUG_FLOPPY ) printf ( " floppy select first drive \n " ) ;
2021-01-02 15:53:46 +00:00
if ( driveSelected ! = 0 ) {
driveSelected = 0 ;
trackBytesOutOfDate = true ;
}
2020-12-27 07:03:13 +00:00
data = 0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
return true ;
} else if ( addr = = SELECT + 1 ) {
if ( debug & DEBUG_FLOPPY ) printf ( " floppy select second drive \n " ) ;
2021-01-02 15:53:46 +00:00
if ( driveSelected ! = 1 ) {
driveSelected = 1 ;
trackBytesOutOfDate = true ;
}
2020-12-27 07:03:13 +00:00
data = 0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
return true ;
} else if ( addr = = ENABLE ) {
if ( debug & DEBUG_FLOPPY ) printf ( " floppy switch off \n " ) ;
2020-12-12 17:44:44 +00:00
driveMotorEnabled [ driveSelected ] = false ;
floppy_activity ( driveSelected , false ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
// go disable reading
// disable other drive?
2020-12-27 07:03:13 +00:00
data = 0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
return true ;
} else if ( addr = = ENABLE + 1 ) {
if ( debug & DEBUG_FLOPPY ) printf ( " floppy switch on \n " ) ;
2020-12-12 17:44:44 +00:00
driveMotorEnabled [ driveSelected ] = true ;
floppy_activity ( driveSelected , true ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
// go enable reading
// disable other drive?
2020-12-27 07:03:13 +00:00
data = 0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
return true ;
}
2020-12-12 17:44:44 +00:00
if ( debug & DEBUG_WARN ) printf ( " DISK II unhandled read from %04X (%s) \n " , addr , io . at ( addr ) . c_str ( ) ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
data = 0 ;
return true ;
2016-11-26 22:51:14 +00:00
}
2020-12-15 03:48:17 +00:00
virtual void reset ( void )
{
2020-12-27 07:03:13 +00:00
driveMotorEnabled [ 0 ] = false ; // Is this what the drive HW does?
driveMotorEnabled [ 1 ] = false ; // Is this what the drive HW does?
2020-12-15 03:48:17 +00:00
driveSelected = 0 ;
trackBytesOutOfDate = true ;
floppy_activity ( 0 , false ) ;
floppy_activity ( 1 , false ) ;
}
2016-11-26 22:51:14 +00:00
} ;
2018-07-31 21:31:36 +00:00
struct Mockingboard : board_base
{
Mockingboard ( )
{
}
2020-12-17 07:03:43 +00:00
virtual bool write ( int addr , uint8_t data )
2018-07-31 21:31:36 +00:00
{
if ( ( addr > = 0xC400 ) & & ( addr < = 0xC4FF ) ) {
if ( debug & DEBUG_RW ) printf ( " Mockingboard write 0x%02X to 0x%04X ignored \n " , data , addr ) ;
return true ;
}
return false ;
}
2020-12-17 07:03:43 +00:00
virtual bool read ( int addr , uint8_t & data )
2018-07-31 21:31:36 +00:00
{
if ( ( addr > = 0xC400 ) & & ( addr < = 0xC4FF ) ) {
if ( debug & DEBUG_RW ) printf ( " Mockingboard read at 0x%04X ignored \n " , addr ) ;
data = 0 ;
return true ;
}
return false ;
}
virtual void reset ( void ) { }
} ;
2016-12-07 22:42:28 +00:00
const int waveform_length = 44100 / 1000 / 2 ; // half of a wave at 4000 Hz
2016-12-07 02:24:11 +00:00
const float waveform_max_amplitude = .35f ;
2020-12-17 07:03:43 +00:00
static uint8_t waveform [ waveform_length ] ;
2016-12-07 02:24:11 +00:00
static void initialize_audio_waveform ( ) __attribute__ ( ( constructor ) ) ;
void initialize_audio_waveform ( )
{
for ( int i = 0 ; i < waveform_length ; i + + ) {
float theta = ( float ( i ) / ( waveform_length - 1 ) - .5f ) * M_PI ;
waveform [ i ] = 127.5 + waveform_max_amplitude * 127.5 * sin ( theta ) ;
}
}
2018-07-31 21:31:36 +00:00
int hires_blanking_address_base [ 262 ] ;
2020-12-27 07:03:13 +00:00
extern const int hires_visible_address_base [ 262 ] ;
2018-07-31 21:31:36 +00:00
static void generate_hires_scanout_addresses ( ) __attribute__ ( ( constructor ) ) ;
void generate_hires_scanout_addresses ( )
{
for ( int i = 0 ; i < 262 ; i + + )
if ( i < 64 )
hires_blanking_address_base [ i ] = hires_visible_address_base [ i ] + 0x68 ;
else
hires_blanking_address_base [ i ] = hires_visible_address_base [ i ] - 0x18 ;
}
int get_hires_scanout_address ( int byte_in_frame )
{
int line_in_frame = byte_in_frame / 65 ;
int byte_in_line = byte_in_frame % 65 ;
if ( byte_in_line < 25 )
2018-07-31 21:51:51 +00:00
return 0x2000 + ( hires_blanking_address_base [ line_in_frame ] + byte_in_line ) % 0x2000 ;
2018-07-31 21:31:36 +00:00
2018-07-31 21:51:51 +00:00
return 0x2000 + ( hires_visible_address_base [ line_in_frame ] + byte_in_line - 25 ) % 0x2000 ;
2018-07-31 21:31:36 +00:00
}
2020-12-27 07:03:13 +00:00
const static int text_blanking_address_base [ ] =
2018-07-31 21:31:36 +00:00
{
0x1468 ,
0x14E8 ,
0x1568 ,
0x15E8 ,
0x1668 ,
0x16E8 ,
0x1768 ,
0x17E8 ,
0x1410 ,
0x1490 ,
0x1510 ,
0x1590 ,
0x1610 ,
0x1690 ,
0x1710 ,
0x1790 ,
0x1438 ,
0x14B8 ,
0x1538 ,
0x15B8 ,
0x1638 ,
0x16B8 ,
0x1738 ,
0x17B8 ,
0x1460 ,
0x14E0 ,
0x1560 ,
0x15E0 ,
0x1660 ,
0x16E0 ,
0x1760 ,
0x17E0 ,
0x17E0 , // last text line is actually scanned 14 times so add another row
} ;
2020-12-27 07:03:13 +00:00
const static int text_visible_address_base [ ] =
2018-07-31 21:31:36 +00:00
{
0x0400 ,
0x0480 ,
0x0500 ,
0x0580 ,
0x0600 ,
0x0680 ,
0x0700 ,
0x0780 ,
0x0428 ,
0x04A8 ,
0x0528 ,
0x05A8 ,
0x0628 ,
0x06A8 ,
0x0728 ,
0x07A8 ,
0x0450 ,
0x04D0 ,
0x0550 ,
0x05D0 ,
0x0650 ,
0x06D0 ,
0x0750 ,
0x07D0 ,
0x0478 ,
0x04F8 ,
0x0578 ,
0x05F8 ,
0x0678 ,
0x06F8 ,
0x0778 ,
0x07F8 ,
0x07F8 , // last text line is actually scanned 14 times so add another row
} ;
int get_text_scanout_address ( int byte_in_frame )
{
int text_line_in_frame = byte_in_frame / ( 8 * 65 ) ;
int byte_in_line = byte_in_frame % 65 ;
if ( byte_in_line < 25 )
return text_blanking_address_base [ text_line_in_frame ] + byte_in_line ;
return text_visible_address_base [ text_line_in_frame ] + byte_in_line - 25 ;
}
2016-11-06 07:53:43 +00:00
struct MAINboard : board_base
{
2016-11-23 23:29:47 +00:00
system_clock & clk ;
2016-11-26 22:51:14 +00:00
vector < board_base * > boards ;
2016-11-06 20:37:19 +00:00
vector < SoftSwitch * > switches ;
2016-11-18 06:05:02 +00:00
SoftSwitch * switches_by_address [ 256 ] ;
2020-12-11 01:19:39 +00:00
// Inside the Apple //e, page 379
2020-12-27 07:03:13 +00:00
SoftSwitch SLOTCXROM { " SLOTCXROM " , 0xC007 , 0xC006 , 0xC015 , false , switches , false , true } ;
SoftSwitch STORE80 { " STORE80 " , 0xC000 , 0xC001 , 0xC018 , false , switches , false , true } ;
SoftSwitch RAMRD { " RAMRD " , 0xC002 , 0xC003 , 0xC013 , false , switches , false , true } ;
SoftSwitch RAMWRT { " RAMWRT " , 0xC004 , 0xC005 , 0xC014 , false , switches , false , true } ;
SoftSwitch ALTZP { " ALTZP " , 0xC008 , 0xC009 , 0xC016 , false , switches , false , true } ;
SoftSwitch C3ROM { " C3ROM " , 0xC00A , 0xC00B , 0xC017 , false , switches , false , true } ;
SoftSwitch ALTCHAR { " ALTCHAR " , 0xC00E , 0xC00F , 0xC01E , false , switches , false , true } ;
SoftSwitch VID80 { " VID80 " , 0xC00C , 0xC00D , 0xC01F , false , switches , false , true } ;
SoftSwitch TEXT { " TEXT " , 0xC050 , 0xC051 , 0xC01A , true , switches , false , true } ;
SoftSwitch MIXED { " MIXED " , 0xC052 , 0xC053 , 0xC01B , true , switches , false , true } ;
SoftSwitch PAGE2 { " PAGE2 " , 0xC054 , 0xC055 , 0xC01C , true , switches , false , true } ;
SoftSwitch HIRES { " HIRES " , 0xC056 , 0xC057 , 0xC01D , true , switches , false , true } ;
2016-11-08 21:22:46 +00:00
2021-01-02 17:45:49 +00:00
std : : array < bool , 4 > AN = { false , false , false , false } ;
2016-11-09 00:41:30 +00:00
vector < backed_region * > regions ;
2020-12-11 01:19:39 +00:00
std : : array < backed_region * , 256 > read_regions_by_page ;
std : : array < backed_region * , 256 > write_regions_by_page ;
void repage_regions ( const char * reason )
{
std : : fill ( read_regions_by_page . begin ( ) , read_regions_by_page . end ( ) , nullptr ) ;
std : : fill ( write_regions_by_page . begin ( ) , write_regions_by_page . end ( ) , nullptr ) ;
for ( auto * r : regions ) {
int firstpage = r - > base / 256 ;
int lastpage = ( r - > base + r - > size - 1 ) / 256 ;
if ( ( r - > type = = RAM ) & & r - > write_enabled ( ) ) {
for ( int i = firstpage ; i < = lastpage ; i + + ) {
2020-12-28 06:03:56 +00:00
if ( write_regions_by_page [ i ] ) {
2020-12-28 04:55:26 +00:00
if ( false ) {
printf ( " warning, write region for 0x%02X00 setting for \" %s \" but was already filled by \" %s \" ; repaged because \" %s \" \n " ,
i , r - > name . c_str ( ) , write_regions_by_page [ i ] - > name . c_str ( ) , reason ) ;
}
2020-12-11 01:19:39 +00:00
} else {
write_regions_by_page [ i ] = r ;
}
}
}
if ( r - > read_enabled ( ) ) {
for ( int i = firstpage ; i < = lastpage ; i + + ) {
2020-12-28 06:03:56 +00:00
if ( read_regions_by_page [ i ] ) {
2020-12-28 04:55:26 +00:00
if ( false ) {
printf ( " warning, read region for 0x%02X00 setting for \" %s \" but was already filled by \" %s \" ; repaged because \" %s \" \n " ,
i , r - > name . c_str ( ) , read_regions_by_page [ i ] - > name . c_str ( ) , reason ) ;
}
2020-12-11 01:19:39 +00:00
} else {
read_regions_by_page [ i ] = r ;
}
}
}
}
}
2016-11-18 05:50:09 +00:00
2016-11-26 22:51:14 +00:00
backed_region szp = { " szp " , 0x0000 , 0x0200 , RAM , & regions , [ & ] ( ) { return ! ALTZP ; } } ; // stack and zero page
backed_region aszp = { " aszp " , 0x0000 , 0x0200 , RAM , & regions , [ & ] ( ) { return ALTZP ; } } ; // alternate stack and zero page
2016-11-11 03:33:27 +00:00
2020-12-11 01:19:39 +00:00
enabled_func always_disabled = [ ] { return false ; } ;
2020-12-20 22:49:46 +00:00
bool internal_C800_ROM_selected = false ;
2020-12-27 07:03:13 +00:00
backed_region rom_C100 = { " rom_C100 " , 0xC100 , 0x0200 , ROM , & regions , [ & ] { return ! SLOTCXROM ; } , always_disabled } ;
backed_region rom_C300 = { " rom_C300 " , 0xC300 , 0x0100 , ROM , & regions , [ & ] { return ! SLOTCXROM | | ( SLOTCXROM & & ! C3ROM ) ; } , always_disabled } ;
backed_region rom_C400 = { " rom_C400 " , 0xC400 , 0x0400 , ROM , & regions , [ & ] { return ! SLOTCXROM ; } , always_disabled } ;
backed_region rom_C800 = { " rom_C800 " , 0xC800 , 0x0800 , ROM , & regions , [ & ] { return ! SLOTCXROM | | ( SLOTCXROM & & ! C3ROM & & internal_C800_ROM_selected ) ; } , always_disabled } ;
2020-12-11 01:19:39 +00:00
backed_region rom_CXXX_default = { " rom_CXXX_default " , 0xC100 , 0x0F00 , ROM , & regions , [ & ] { return true ; } , always_disabled } ;
2016-11-11 03:33:27 +00:00
enabled_func read_from_aux_ram = [ & ] { return RAMRD ; } ;
enabled_func write_to_aux_ram = [ & ] { return RAMWRT ; } ;
enabled_func read_from_main_ram = [ & ] { return ! read_from_aux_ram ( ) ; } ;
enabled_func write_to_main_ram = [ & ] { return ! write_to_aux_ram ( ) ; } ;
2016-11-26 22:51:14 +00:00
backed_region ram_0200 = { " ram_0200 " , 0x0200 , 0x0200 , RAM , & regions , read_from_main_ram , write_to_main_ram } ;
backed_region ram_0200_x = { " ram_0200_x " , 0x0200 , 0x0200 , RAM , & regions , read_from_aux_ram , write_to_aux_ram } ;
backed_region ram_0C00 = { " ram_0C00 " , 0x0C00 , 0x1400 , RAM , & regions , read_from_main_ram , write_to_main_ram } ;
backed_region ram_0C00_x = { " ram_0C00_x " , 0x0C00 , 0x1400 , RAM , & regions , read_from_aux_ram , write_to_aux_ram } ;
backed_region ram_6000 = { " ram_6000 " , 0x6000 , 0x6000 , RAM , & regions , read_from_main_ram , write_to_main_ram } ;
backed_region ram_6000_x = { " ram_6000_x " , 0x6000 , 0x6000 , RAM , & regions , read_from_aux_ram , write_to_aux_ram } ;
2016-11-11 03:33:27 +00:00
2020-12-20 22:49:46 +00:00
bool C08X_read_RAM = false ;
bool C08X_write_RAM = false ;
enum { BANK1 , BANK2 } C08X_bank = BANK1 ;
2020-12-06 01:19:21 +00:00
2020-12-11 01:19:39 +00:00
backed_region rom_D000 = { " rom_D000 " , 0xD000 , 0x1000 , ROM , & regions , [ & ] { return ! C08X_read_RAM ; } , always_disabled } ;
backed_region rom_E000 = { " rom_E000 " , 0xE000 , 0x2000 , ROM , & regions , [ & ] { return ! C08X_read_RAM ; } , always_disabled } ;
2020-12-06 01:19:21 +00:00
backed_region ram1_main_D000 = { " ram1_main_D000 " , 0xD000 , 0x1000 , RAM , & regions , [ & ] { return ! ALTZP & & C08X_read_RAM & & ( C08X_bank = = BANK1 ) ; } , [ & ] { return ! ALTZP & & C08X_write_RAM & & ( C08X_bank = = BANK1 ) ; } } ;
backed_region ram2_main_D000 = { " ram2_main_D000 " , 0xD000 , 0x1000 , RAM , & regions , [ & ] { return ! ALTZP & & C08X_read_RAM & & ( C08X_bank = = BANK2 ) ; } , [ & ] { return ! ALTZP & & C08X_write_RAM & & ( C08X_bank = = BANK2 ) ; } } ;
backed_region ram_main_E000 = { " ram1_main_E000 " , 0xE000 , 0x2000 , RAM , & regions , [ & ] { return C08X_read_RAM ; } , [ & ] { return ! ALTZP & & C08X_write_RAM ; } } ;
backed_region ram1_main_D000_x = { " ram1_main_D000_x " , 0xD000 , 0x1000 , RAM , & regions , [ & ] { return ALTZP & & C08X_read_RAM & & ( C08X_bank = = BANK1 ) ; } , [ & ] { return ALTZP & & C08X_write_RAM & & ( C08X_bank = = BANK1 ) ; } } ;
backed_region ram2_main_D000_x = { " ram2_main_D000_x " , 0xD000 , 0x1000 , RAM , & regions , [ & ] { return ALTZP & & C08X_read_RAM & & ( C08X_bank = = BANK2 ) ; } , [ & ] { return ALTZP & & C08X_write_RAM & & ( C08X_bank = = BANK2 ) ; } } ;
backed_region ram_main_E000_x = { " ram1_main_E000_x " , 0xE000 , 0x2000 , RAM , & regions , [ & ] { return ALTZP & & C08X_read_RAM ; } , [ & ] { return ALTZP & & C08X_write_RAM ; } } ;
2020-12-28 04:55:26 +00:00
enabled_func read_from_aux_text1 = [ & ] { return ( ! STORE80 & & RAMRD ) | | ( STORE80 & & ! HIRES & & PAGE2 ) ; } ;
enabled_func write_to_aux_text1 = [ & ] { return ( ! STORE80 & & RAMWRT ) | | ( STORE80 & & ! HIRES & & PAGE2 ) ; } ;
2016-11-11 03:33:27 +00:00
enabled_func read_from_main_text1 = [ & ] { return ! read_from_aux_text1 ( ) ; } ;
enabled_func write_to_main_text1 = [ & ] { return ! write_to_aux_text1 ( ) ; } ;
2016-11-26 22:51:14 +00:00
backed_region text_page1 = { " text_page1 " , 0x0400 , 0x0400 , RAM , & regions , read_from_main_text1 , write_to_main_text1 } ;
backed_region text_page1x = { " text_page1x " , 0x0400 , 0x0400 , RAM , & regions , read_from_aux_text1 , write_to_aux_text1 } ;
backed_region text_page2 = { " text_page2 " , 0x0800 , 0x0400 , RAM , & regions , read_from_main_ram , write_to_main_ram } ;
backed_region text_page2x = { " text_page2x " , 0x0800 , 0x0400 , RAM , & regions , read_from_aux_ram , write_to_aux_ram } ;
2016-11-11 03:33:27 +00:00
2021-01-02 17:45:49 +00:00
// Understanding the IIe by Sather:
// if 80Store is set and hires is cleared, then page2 switches text between main and aux
// if 80Store is set and hires is set, then page2 switches text AND hires between main and aux
// if 80Store is cleared, then RAMRD and RAMWRT switch text AND hires AND 200-BFFF between main and aux
// enabled_func read_from_aux_hires1 = [&]{return HIRES && RAMRD && ((!STORE80) || (STORE80 && PAGE2));};
// enabled_func write_to_aux_hires1 = [&]{return HIRES && RAMWRT && ((!STORE80) || (STORE80 && PAGE2));};
enabled_func read_from_aux_hires1 = [ & ] { return ( STORE80 & & HIRES & & PAGE2 ) | | ( ! STORE80 & & RAMRD ) ; } ;
enabled_func write_to_aux_hires1 = [ & ] { return ( STORE80 & & HIRES & & PAGE2 ) | | ( ! STORE80 & & RAMWRT ) ; } ;
2016-11-11 03:33:27 +00:00
enabled_func read_from_main_hires1 = [ & ] { return ! read_from_aux_hires1 ( ) ; } ;
enabled_func write_to_main_hires1 = [ & ] { return ! write_to_aux_hires1 ( ) ; } ;
2016-11-26 22:51:14 +00:00
backed_region hires_page1 = { " hires_page1 " , 0x2000 , 0x2000 , RAM , & regions , read_from_main_hires1 , write_to_main_hires1 } ;
backed_region hires_page1x = { " hires_page1x " , 0x2000 , 0x2000 , RAM , & regions , read_from_aux_hires1 , write_to_aux_hires1 } ;
backed_region hires_page2 = { " hires_page2 " , 0x4000 , 0x2000 , RAM , & regions , read_from_main_ram , write_to_main_ram } ;
backed_region hires_page2x = { " hires_page2x " , 0x4000 , 0x2000 , RAM , & regions , read_from_aux_ram , write_to_aux_ram } ;
2016-11-11 03:33:27 +00:00
2020-12-31 19:00:09 +00:00
static std : : map < uint16_t , std : : string > MMIO_named_locations ;
2020-12-27 07:03:13 +00:00
set < int > ignore_mmio = {
0xC060 , // TAPEIN through Apple //e
0xC061 , // RDBTN0 Open Apple on and after Apple //e
0xC062 , // BUTN1 Solid Apple on and after Apple //e
2020-12-31 19:00:09 +00:00
} ;
2016-11-11 13:54:59 +00:00
set < int > banking_read_switches = {
2020-12-27 07:03:13 +00:00
0xC080 ,
0xC081 ,
0xC082 ,
0xC083 ,
0xC084 ,
0xC085 ,
0xC086 ,
0xC087 ,
0xC088 ,
0xC089 ,
0xC08A ,
0xC08B ,
0xC08C ,
0xC08D ,
0xC08E ,
0xC08F ,
2016-11-11 13:54:59 +00:00
} ;
set < int > banking_write_switches = {
2020-12-27 07:03:13 +00:00
0xC006 ,
0xC007 ,
0xC000 ,
0xC001 ,
0xC002 ,
0xC003 ,
0xC004 ,
0xC005 ,
0xC008 ,
0xC009 ,
0xC00A ,
0xC00B ,
2016-11-11 13:54:59 +00:00
} ;
2016-11-08 21:22:46 +00:00
2020-12-17 07:03:43 +00:00
deque < uint8_t > keyboard_buffer ;
2016-11-12 21:20:10 +00:00
2016-11-24 07:29:23 +00:00
static const int sample_rate = 44100 ;
2018-08-04 06:58:10 +00:00
static const size_t audio_buffer_size = sample_rate / 100 ;
2020-12-17 07:03:43 +00:00
uint8_t audio_buffer [ audio_buffer_size ] ;
uint64_t audio_buffer_start_sample = 0 ;
uint64_t audio_buffer_next_sample = 0 ;
uint8_t speaker_level ;
2016-12-07 02:24:11 +00:00
bool speaker_transitioning_to_high = false ;
int where_in_waveform = 0 ;
2016-11-24 07:29:23 +00:00
2018-08-02 22:20:59 +00:00
# if LK_HACK
2020-12-17 07:03:43 +00:00
uint8_t * disassemble_buffer = 0 ;
2018-08-06 07:18:38 +00:00
int disassemble_state = 0 ;
2018-08-02 22:20:59 +00:00
int disassemble_index = 0 ;
int disassemble_size = 0 ;
2018-08-06 07:18:38 +00:00
int disassemble_addr = 0 ;
2018-08-02 22:20:59 +00:00
# endif
2016-11-24 07:29:23 +00:00
void fill_flush_audio ( )
{
2020-12-17 07:03:43 +00:00
uint64_t current_sample = clk * sample_rate / machine_clock_rate ;
2016-12-07 02:24:11 +00:00
2020-12-17 07:03:43 +00:00
for ( uint64_t i = audio_buffer_next_sample ; i < current_sample ; i + + ) {
2016-12-07 02:24:11 +00:00
if ( where_in_waveform < waveform_length ) {
2020-12-17 07:03:43 +00:00
uint8_t level = waveform [ where_in_waveform + + ] ;
2016-12-07 02:24:11 +00:00
speaker_level = speaker_transitioning_to_high ? level : ( 255 - level ) ;
}
audio_buffer [ i % audio_buffer_size ] = speaker_level ;
2016-11-24 07:29:23 +00:00
if ( i - audio_buffer_start_sample = = audio_buffer_size - 1 ) {
audio_flush ( audio_buffer , audio_buffer_size ) ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
2016-11-24 07:29:23 +00:00
audio_buffer_start_sample = i + 1 ;
}
}
audio_buffer_next_sample = current_sample ;
}
2016-12-02 18:42:22 +00:00
clk_t open_apple_down_ends = 0 ;
void momentary_open_apple ( clk_t how_long )
{
open_apple_down_ends = clk + how_long ;
}
2016-11-24 07:29:23 +00:00
// flush anything needing flushing
void sync ( )
{
fill_flush_audio ( ) ;
}
2020-12-17 07:03:43 +00:00
void enqueue_key ( uint8_t k )
2016-11-12 21:20:10 +00:00
{
keyboard_buffer . push_back ( k ) ;
}
2016-11-28 21:27:52 +00:00
2018-08-01 07:42:31 +00:00
APPLE2Einterface : : ModeSettings convert_switches_to_mode_settings ( )
{
APPLE2Einterface : : DisplayMode mode = TEXT ? APPLE2Einterface : : TEXT : ( HIRES ? APPLE2Einterface : : HIRES : APPLE2Einterface : : LORES ) ;
int page = ( PAGE2 & & ! STORE80 ) ? 1 : 0 ;
2021-01-02 17:45:49 +00:00
bool dhgr = ( ! AN [ 3 ] ) & & VID80 ;
if ( 0 ) printf ( " mode %s, mixed %s, page %d, vid80 %s, dhgr %s, altchar %s \n " ,
2018-08-01 07:42:31 +00:00
( mode = = APPLE2Einterface : : TEXT ) ? " TEXT " : ( ( mode = = APPLE2Einterface : : LORES ) ? " LORES " : " HIRES " ) ,
MIXED ? " true " : " false " ,
page ,
VID80 ? " true " : " false " ,
2021-01-02 17:45:49 +00:00
dhgr ? " true " : " false " ,
2018-08-01 07:42:31 +00:00
ALTCHAR ? " true " : " false " ) ;
2021-01-02 17:45:49 +00:00
return APPLE2Einterface : : ModeSettings ( mode , MIXED , page , VID80 , dhgr , ALTCHAR ) ;
2018-08-01 07:42:31 +00:00
}
APPLE2Einterface : : ModeSettings old_mode_settings ;
void post_soft_switch_mode_change ( )
{
APPLE2Einterface : : ModeSettings settings = convert_switches_to_mode_settings ( ) ;
if ( settings ! = old_mode_settings ) {
mode_history . push_back ( make_tuple ( clk . clock_cpu , settings ) ) ;
old_mode_settings = settings ;
}
}
2020-12-17 07:03:43 +00:00
typedef std : : function < bool ( int addr , bool aux , uint8_t data ) > display_write_func ;
2016-11-19 04:54:19 +00:00
display_write_func display_write ;
2020-12-17 07:03:43 +00:00
typedef std : : function < void ( uint8_t * audiobuffer , size_t dist ) > audio_flush_func ;
2016-11-24 07:29:23 +00:00
audio_flush_func audio_flush ;
2016-11-30 06:17:17 +00:00
typedef std : : function < tuple < float , bool > ( int num ) > get_paddle_func ;
get_paddle_func get_paddle ;
clk_t paddles_clock_out [ 4 ] ;
2020-12-17 07:03:43 +00:00
MAINboard ( system_clock & clk_ , const uint8_t rom_image [ 32768 ] , display_write_func display_write_ , audio_flush_func audio_flush_ , get_paddle_func get_paddle_ ) :
2016-11-23 23:29:47 +00:00
clk ( clk_ ) ,
2016-11-17 02:46:32 +00:00
internal_C800_ROM_selected ( true ) ,
2016-12-07 02:24:11 +00:00
speaker_level ( waveform [ 0 ] ) ,
2016-11-24 07:29:23 +00:00
display_write ( display_write_ ) ,
2016-11-30 06:17:17 +00:00
audio_flush ( audio_flush_ ) ,
get_paddle ( get_paddle_ )
2016-11-06 07:53:43 +00:00
{
2016-11-11 03:33:27 +00:00
std : : copy ( rom_image + rom_D000 . base - 0x8000 , rom_image + rom_D000 . base - 0x8000 + rom_D000 . size , rom_D000 . memory . begin ( ) ) ;
std : : copy ( rom_image + rom_E000 . base - 0x8000 , rom_image + rom_E000 . base - 0x8000 + rom_E000 . size , rom_E000 . memory . begin ( ) ) ;
2016-11-11 13:54:59 +00:00
std : : copy ( rom_image + rom_C100 . base - 0x8000 , rom_image + rom_C100 . base - 0x8000 + rom_C100 . size , rom_C100 . memory . begin ( ) ) ;
std : : copy ( rom_image + rom_C300 . base - 0x8000 , rom_image + rom_C300 . base - 0x8000 + rom_C300 . size , rom_C300 . memory . begin ( ) ) ;
2016-11-11 23:18:08 +00:00
std : : copy ( rom_image + rom_C400 . base - 0x8000 , rom_image + rom_C400 . base - 0x8000 + rom_C400 . size , rom_C400 . memory . begin ( ) ) ;
std : : copy ( rom_image + rom_C800 . base - 0x8000 , rom_image + rom_C800 . base - 0x8000 + rom_C800 . size , rom_C800 . memory . begin ( ) ) ;
2016-11-18 05:50:09 +00:00
2020-12-11 01:19:39 +00:00
repage_regions ( " init " ) ;
2020-12-28 04:55:26 +00:00
for ( int i = 0 ; i < 256 ; i + + ) {
switches_by_address [ i ] = nullptr ;
}
2017-01-05 06:09:31 +00:00
for ( auto sw : switches ) {
2016-11-19 04:54:19 +00:00
switches_by_address [ sw - > clear_address - 0xC000 ] = sw ;
switches_by_address [ sw - > set_address - 0xC000 ] = sw ;
switches_by_address [ sw - > read_address - 0xC000 ] = sw ;
2016-11-18 05:50:09 +00:00
}
2020-12-28 04:55:26 +00:00
2018-08-01 04:50:36 +00:00
// TEXT.enabled = true;
2018-08-01 07:42:31 +00:00
old_mode_settings = convert_switches_to_mode_settings ( ) ;
2016-11-06 22:37:20 +00:00
}
2016-11-08 21:22:46 +00:00
2020-12-06 01:19:21 +00:00
~ MAINboard ( )
2016-11-06 22:37:20 +00:00
{
2016-11-06 07:53:43 +00:00
}
2016-11-15 18:39:38 +00:00
2020-12-06 01:19:21 +00:00
void reset ( )
2016-11-15 18:39:38 +00:00
{
// Partially from Apple //e Technical Reference
// XXX need to double-check these against the actual hardware
ALTZP . enabled = false ;
2020-12-27 07:03:13 +00:00
SLOTCXROM . enabled = false ;
2016-11-15 18:39:38 +00:00
RAMRD . enabled = false ;
RAMWRT . enabled = false ;
C3ROM . enabled = false ;
2016-12-06 01:27:57 +00:00
VID80 . enabled = false ;
2016-11-15 18:39:38 +00:00
C08X_bank = BANK2 ;
C08X_read_RAM = false ;
C08X_write_RAM = true ;
internal_C800_ROM_selected = true ;
2020-12-11 01:19:39 +00:00
repage_regions ( " reset " ) ;
2020-12-15 03:48:17 +00:00
for ( auto b : boards ) {
b - > reset ( ) ;
}
2016-11-15 18:39:38 +00:00
}
2020-12-17 07:03:43 +00:00
bool read ( int addr , uint8_t & data )
2016-11-06 07:53:43 +00:00
{
if ( debug & DEBUG_RW ) printf ( " MAIN board read \n " ) ;
2017-01-05 06:09:31 +00:00
for ( auto b : boards ) {
2016-11-26 22:51:14 +00:00
if ( b - > read ( addr , data ) ) {
return true ;
}
}
2020-12-11 01:19:39 +00:00
auto * r = read_regions_by_page [ addr / 256 ] ;
if ( r ) {
data = r - > memory [ addr - r - > base ] ;
if ( debug & DEBUG_RW ) printf ( " read %02X from 0x%04X in %s \n " , addr , data , r - > name . c_str ( ) ) ;
2020-12-06 01:19:21 +00:00
return true ;
}
2016-11-08 21:22:46 +00:00
if ( io_region . contains ( addr ) ) {
2016-11-11 23:18:08 +00:00
if ( exit_on_banking & & ( banking_read_switches . find ( addr ) ! = banking_read_switches . end ( ) ) ) {
2016-11-11 13:54:59 +00:00
printf ( " bank switch control %04X, aborting \n " , addr ) ;
exit ( 1 ) ;
}
2016-11-19 04:54:19 +00:00
SoftSwitch * sw = switches_by_address [ addr - 0xC000 ] ;
2020-12-28 04:55:26 +00:00
if ( sw ) {
2018-08-01 07:42:31 +00:00
2020-12-17 07:03:43 +00:00
uint8_t result = 0xFF ;
2018-08-01 07:42:31 +00:00
// Special case for floating bus for reading video scanout
// XXX doesn't handle 80-column nor AUX
if ( ( addr = = 0xC050 ) | | ( addr = = 0xC051 ) ) {
bool page1 = ( PAGE2 & & ! STORE80 ) ? false : true ;
// 65 bytes per line, 262 lines per frame (aka "field")
int byte_in_frame = clk . clock_cpu % 17030 ;
int line_in_frame = byte_in_frame / 65 ;
if ( 0 ) printf ( " TEXT %s, HIRES %s, MIXED %s, line_in_frame = %d \n " ,
TEXT ? " true " : " false " ,
HIRES ? " true " : " false " ,
MIXED ? " true " : " false " ,
line_in_frame ) ;
bool mixed_text_scanout =
( ( line_in_frame > = 160 ) & & ( line_in_frame < 192 ) ) | |
( line_in_frame > = 224 ) ;
if ( TEXT | | ! HIRES | | ( MIXED & & mixed_text_scanout ) ) {
// TEXT or GR mode; they read the same addresses.
int addr2 = get_text_scanout_address ( byte_in_frame ) + ( page1 ? 0 : 0x0400 ) ;
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " got text scanout address $%04X \n " , addr2 ) ;
2018-08-01 07:42:31 +00:00
if ( addr2 > 0xC00 ) {
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " read 0C00 floating bus \n " ) ;
2018-08-01 07:42:31 +00:00
ram_0C00 . read ( addr2 , result ) ;
} else {
if ( page1 ) {
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " read text page1 floating bus \n " ) ;
2018-08-01 07:42:31 +00:00
text_page1 . read ( addr2 , result ) ;
} else {
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " read text page2 floating bus \n " ) ;
2018-08-01 07:42:31 +00:00
text_page2 . read ( addr2 , result ) ;
}
}
} else {
// HGR mode and not in text region if MIXED
int addr2 = get_hires_scanout_address ( byte_in_frame ) + ( page1 ? 0 : 0x2000 ) ;
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " got hires scanout address $%04X \n " , addr2 ) ;
2018-08-01 07:42:31 +00:00
if ( page1 ) {
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " read hires page1 floating bus \n " ) ;
2018-08-01 07:42:31 +00:00
hires_page1 . read ( addr2 , result ) ;
} else {
2018-08-01 18:26:49 +00:00
if ( 0 ) printf ( " read hires page2 floating bus \n " ) ;
2018-08-01 07:42:31 +00:00
hires_page2 . read ( addr2 , result ) ;
}
}
}
2016-11-06 20:37:19 +00:00
if ( addr = = sw - > read_address ) {
2016-11-11 13:54:59 +00:00
data = sw - > enabled ? 0x80 : 0x00 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( debug & DEBUG_SWITCH ) printf ( " Read status of %s = %02X \n " , sw - > name . c_str ( ) , data ) ;
2016-11-06 07:53:43 +00:00
return true ;
2020-12-27 07:03:13 +00:00
} else if ( sw - > read_also_changes & & ( addr = = sw - > set_address ) ) {
2016-11-09 00:41:30 +00:00
if ( ! sw - > implemented ) { printf ( " %s ; set is unimplemented \n " , sw - > name . c_str ( ) ) ; fflush ( stdout ) ; exit ( 0 ) ; }
2018-08-01 07:42:31 +00:00
data = result ;
2020-12-28 06:03:56 +00:00
if ( ! sw - > enabled ) {
sw - > enabled = true ;
if ( debug & DEBUG_SWITCH ) printf ( " Set %s \n " , sw - > name . c_str ( ) ) ;
post_soft_switch_mode_change ( ) ;
static char reason [ 512 ] ; sprintf ( reason , " set %s " , sw - > name . c_str ( ) ) ;
repage_regions ( reason ) ;
}
2016-11-06 20:37:19 +00:00
return true ;
2020-12-27 07:03:13 +00:00
} else if ( sw - > read_also_changes & & ( addr = = sw - > clear_address ) ) {
2016-11-11 13:54:59 +00:00
if ( ! sw - > implemented ) { printf ( " %s ; unimplemented \n " , sw - > name . c_str ( ) ) ; fflush ( stdout ) ; exit ( 0 ) ; }
2018-08-01 07:42:31 +00:00
data = result ;
2020-12-28 06:03:56 +00:00
if ( sw - > enabled ) {
sw - > enabled = false ;
if ( debug & DEBUG_SWITCH ) printf ( " Clear %s \n " , sw - > name . c_str ( ) ) ;
post_soft_switch_mode_change ( ) ;
static char reason [ 512 ] ; sprintf ( reason , " clear %s " , sw - > name . c_str ( ) ) ;
repage_regions ( reason ) ;
}
2016-11-06 20:37:19 +00:00
return true ;
}
}
2016-11-11 03:33:27 +00:00
if ( ( addr & 0xFFF0 ) = = 0xC080 ) {
C08X_bank = ( ( addr > > 3 ) & 1 ) ? BANK1 : BANK2 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
C08X_write_RAM = addr & 1 ;
int read_ROM = ( ( addr > > 1 ) & 1 ) ^ C08X_write_RAM ;
C08X_read_RAM = ! read_ROM ;
if ( debug & DEBUG_SWITCH ) printf ( " write %04X switch, %s, %d write_RAM, %d read_RAM \n " , addr , ( C08X_bank = = BANK1 ) ? " BANK1 " : " BANK2 " , C08X_write_RAM , C08X_read_RAM ) ;
data = 0x00 ;
2020-12-11 01:19:39 +00:00
repage_regions ( " C08x write " ) ;
2016-11-11 03:33:27 +00:00
return true ;
2016-11-30 06:17:17 +00:00
} else if ( addr = = 0xC011 ) {
2016-11-11 03:33:27 +00:00
data = ( C08X_bank = = BANK2 ) ? 0x80 : 0x0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
data = 0x00 ;
if ( debug & DEBUG_SWITCH ) printf ( " read BSRBANK2, return 0x%02X \n " , data ) ;
2016-11-11 03:33:27 +00:00
return true ;
2016-11-30 06:17:17 +00:00
} else if ( addr = = 0xC012 ) {
2016-11-11 03:33:27 +00:00
data = C08X_read_RAM ? 0x80 : 0x0 ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( debug & DEBUG_SWITCH ) printf ( " read BSRREADRAM, return 0x%02X \n " , data ) ;
2016-11-11 03:33:27 +00:00
return true ;
2016-11-30 06:17:17 +00:00
} else if ( addr = = 0xC000 ) {
2016-11-12 21:20:10 +00:00
if ( ! keyboard_buffer . empty ( ) ) {
data = 0x80 | keyboard_buffer [ 0 ] ;
} else {
data = 0x00 ;
}
2016-11-06 22:37:20 +00:00
if ( debug & DEBUG_RW ) printf ( " read KBD, return 0x%02X \n " , data ) ;
2016-11-06 20:37:19 +00:00
return true ;
2016-11-30 06:17:17 +00:00
} else if ( addr = = 0xC020 ) {
if ( debug & DEBUG_RW ) printf ( " read TAPE, force 0x00 \n " ) ;
data = 0x00 ;
return true ;
} else if ( addr = = 0xC030 ) {
2016-11-06 21:27:01 +00:00
if ( debug & DEBUG_RW ) printf ( " read SPKR, force 0x00 \n " ) ;
2016-11-24 07:29:23 +00:00
fill_flush_audio ( ) ;
2016-11-06 20:44:32 +00:00
data = 0x00 ;
2016-12-07 02:24:11 +00:00
where_in_waveform = 0 ;
speaker_transitioning_to_high = ! speaker_transitioning_to_high ;
2016-11-06 20:44:32 +00:00
return true ;
2016-11-30 06:17:17 +00:00
} else if ( addr = = 0xC010 ) {
2016-11-06 20:37:19 +00:00
// reset keyboard latch
2016-11-12 21:20:10 +00:00
if ( ! keyboard_buffer . empty ( ) ) {
keyboard_buffer . pop_front ( ) ;
}
data = 0x0 ;
2016-11-06 22:37:20 +00:00
if ( debug & DEBUG_RW ) printf ( " read KBDSTRB, return 0x%02X \n " , data ) ;
2016-11-06 20:37:19 +00:00
return true ;
2016-11-30 06:17:17 +00:00
} else if ( addr = = 0xC070 ) {
for ( int i = 0 ; i < 4 ; i + + ) {
float value ;
bool button ;
tie ( value , button ) = get_paddle ( i ) ;
paddles_clock_out [ i ] = clk + value * paddle_max_pulse_seconds * machine_clock_rate ;
}
data = 0x0 ;
return true ;
} else if ( addr > = 0xC064 & & addr < = 0xC067 ) {
int num = addr - 0xC064 ;
data = ( clk < paddles_clock_out [ num ] ) ? 0xff : 0x00 ;
return true ;
} else if ( addr > = 0xC061 & & addr < = 0xC063 ) {
int num = addr - 0xC061 ;
2016-12-02 18:42:22 +00:00
if ( num = = 0 & & ( open_apple_down_ends > clk ) ) {
data = 0xff ;
return true ;
}
2016-11-30 06:17:17 +00:00
float value ;
bool button ;
tie ( value , button ) = get_paddle ( num ) ;
data = button ? 0xff : 0x0 ;
return true ;
2021-01-02 17:45:49 +00:00
} else if ( addr > = 0xC058 & & addr < = 0xC05F ) {
/* annunciators & DHGR enable */
int num = ( addr - 0xC058 ) / 2 ;
bool set = addr & 1 ;
2021-01-12 04:25:55 +00:00
if ( debug & DEBUG_RW ) printf ( " read %04X, %s annunciator %d \n " , addr , set ? " set " : " clear " , num ) ;
2021-01-02 17:45:49 +00:00
AN [ num ] = set ;
// Should also do something here if we are emulating something attached to AN{0,1,2,3}
data = 0 ;
return true ;
2016-11-30 06:17:17 +00:00
}
if ( ignore_mmio . find ( addr ) ! = ignore_mmio . end ( ) ) {
if ( debug & DEBUG_RW ) printf ( " read %04X, ignored, return 0x00 \n " , addr ) ;
data = 0x00 ;
return true ;
2016-11-06 20:37:19 +00:00
}
2020-12-31 19:00:09 +00:00
if ( MMIO_named_locations . count ( addr ) > 0 ) {
printf ( " unhandled MMIO Read at %04X (%s) \n " , addr , MMIO_named_locations . at ( addr ) . c_str ( ) ) ;
} else {
printf ( " unhandled MMIO Read at %04X \n " , addr ) ;
}
data = 0x00 ;
return true ;
// fflush(stdout); exit(0);
2016-11-06 07:53:43 +00:00
}
2016-11-11 23:18:08 +00:00
if ( ( addr & 0xFF00 ) = = 0xC300 ) {
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( debug & DEBUG_SWITCH ) printf ( " read 0x%04X, enabling internal C800 ROM \n " , addr ) ;
2020-12-11 01:19:39 +00:00
if ( ! internal_C800_ROM_selected ) {
internal_C800_ROM_selected = true ;
repage_regions ( " C3xx write " ) ;
}
2016-11-11 23:18:08 +00:00
}
if ( addr = = 0xCFFF ) {
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( debug & DEBUG_SWITCH ) printf ( " read 0xCFFF, disabling internal C800 ROM \n " ) ;
2020-12-11 01:19:39 +00:00
if ( internal_C800_ROM_selected ) {
internal_C800_ROM_selected = false ;
repage_regions ( " C3FF write " ) ;
}
2016-11-11 23:18:08 +00:00
}
2016-11-11 13:54:59 +00:00
if ( debug & DEBUG_WARN ) printf ( " unhandled memory read at %04X \n " , addr ) ;
2016-11-11 23:18:08 +00:00
if ( exit_on_memory_fallthrough ) {
2016-11-11 13:54:59 +00:00
printf ( " unhandled memory read at %04X, aborting \n " , addr ) ;
printf ( " Switches: \n " ) ;
2017-01-05 06:09:31 +00:00
for ( auto sw : switches ) {
2016-11-11 13:54:59 +00:00
printf ( " %s: %s \n " , sw - > name . c_str ( ) , sw - > enabled ? " enabled " : " disabled " ) ;
}
exit ( 1 ) ;
}
2016-11-06 07:53:43 +00:00
return false ;
}
2020-12-17 07:03:43 +00:00
bool write ( int addr , uint8_t data )
2016-11-06 07:53:43 +00:00
{
2018-08-02 22:20:59 +00:00
# if LK_HACK
if ( addr = = 0xBFFE ) {
2018-08-06 07:18:38 +00:00
// Reset protocol.
2018-08-02 22:20:59 +00:00
if ( disassemble_buffer ! = 0 ) {
delete [ ] disassemble_buffer ;
disassemble_buffer = 0 ;
}
2018-08-06 07:18:38 +00:00
disassemble_state = 0 ;
2018-08-02 22:20:59 +00:00
return true ;
} else if ( addr = = 0xBFFF ) {
2018-08-06 07:18:38 +00:00
// We dribble our meta-data in one byte at a time.
switch ( disassemble_state ) {
case 0 :
// LSB of size.
disassemble_size = data ;
disassemble_state + + ;
break ;
case 1 :
// MSB of size.
disassemble_size | = data < < 8 ;
2020-12-17 07:03:43 +00:00
disassemble_buffer = new uint8_t [ disassemble_size ] ;
2018-08-06 07:18:38 +00:00
disassemble_index = 0 ;
printf ( " Size of buffer: %d bytes \n " , disassemble_size ) ;
disassemble_state + + ;
break ;
case 2 :
// LSB of address.
disassemble_addr = data ;
disassemble_state + + ;
break ;
case 3 :
// MSB of address.
disassemble_addr | = data < < 8 ;
disassemble_state + + ;
break ;
case 4 :
// Add byte to disassembly buffer. Disassemble if full.
if ( disassemble_buffer ! = 0 ) {
disassemble_buffer [ disassemble_index + + ] = data ;
if ( disassemble_index = = disassemble_size ) {
int bytes ;
string dis ;
2018-08-07 19:27:44 +00:00
for ( int i = 0 ; i < disassemble_size ;
2018-08-06 07:18:38 +00:00
i + = bytes , disassemble_addr + = bytes ) {
tie ( bytes , dis ) = disassemble_6502 ( disassemble_addr ,
disassemble_buffer + i ) ;
printf ( " %-32s " , dis . c_str ( ) ) ;
if ( bytes = = 3 ) {
// Print function name if we have it.
int jump_address = disassemble_buffer [ i + 1 ] +
( disassemble_buffer [ i + 2 ] < < 8 ) ;
auto search = address_to_function_name . find ( jump_address ) ;
if ( search ! = address_to_function_name . end ( ) ) {
printf ( " ; %s " , search - > second . c_str ( ) ) ;
}
}
printf ( " \n " ) ;
2018-08-02 23:07:42 +00:00
}
2018-08-06 07:18:38 +00:00
printf ( " --- \n " ) ;
delete [ ] disassemble_buffer ;
disassemble_buffer = 0 ;
2018-08-02 23:07:42 +00:00
}
2018-08-02 22:20:59 +00:00
}
2018-08-06 07:18:38 +00:00
break ;
2018-08-02 22:20:59 +00:00
}
return true ;
}
# endif
2021-01-02 17:45:49 +00:00
if ( ( addr > = 0x400 ) & & ( addr < = 0xBFF ) ) {
2016-12-05 06:07:00 +00:00
display_write ( addr , write_to_aux_text1 ( ) , data ) ;
2016-11-06 07:53:43 +00:00
}
2021-01-02 17:45:49 +00:00
if ( ( addr > = 0x2000 ) & & ( addr < = 0x5FFF ) ) {
display_write ( addr , write_to_aux_hires1 ( ) , data ) ;
}
2017-01-05 06:09:31 +00:00
for ( auto b : boards ) {
2016-11-26 22:51:14 +00:00
if ( b - > write ( addr , data ) ) {
return true ;
}
}
2020-12-11 01:19:39 +00:00
auto * r = write_regions_by_page [ addr / 256 ] ;
if ( r ) {
if ( debug & DEBUG_RW ) printf ( " wrote %02X to 0x%04X in %s \n " , addr , data , r - > name . c_str ( ) ) ;
if ( ( addr - r - > base < 0 ) | | ( addr - r - > base > r - > size ) ) {
printf ( " write to %d outside region \" %s \" , base %d, size %d \n " , addr , r - > name . c_str ( ) , r - > base , r - > size ) ;
2020-12-06 01:19:21 +00:00
}
2020-12-11 01:19:39 +00:00
r - > memory [ addr - r - > base ] = data ;
return true ;
2020-12-06 01:19:21 +00:00
}
2016-11-08 21:22:46 +00:00
if ( io_region . contains ( addr ) ) {
2016-11-11 23:18:08 +00:00
if ( exit_on_banking & & ( banking_write_switches . find ( addr ) ! = banking_write_switches . end ( ) ) ) {
2016-11-12 22:41:11 +00:00
printf ( " bank switch control %04X, exiting \n " , addr ) ;
2016-11-11 13:54:59 +00:00
exit ( 1 ) ;
}
2016-11-19 04:54:19 +00:00
SoftSwitch * sw = switches_by_address [ addr - 0xC000 ] ;
2020-12-28 04:55:26 +00:00
if ( sw ) {
2016-11-06 20:37:19 +00:00
if ( addr = = sw - > set_address ) {
2016-11-09 00:41:30 +00:00
if ( ! sw - > implemented ) { printf ( " %s ; set is unimplemented \n " , sw - > name . c_str ( ) ) ; fflush ( stdout ) ; exit ( 0 ) ; }
2016-11-06 20:37:19 +00:00
data = 0xff ;
2020-12-07 04:08:03 +00:00
if ( ! sw - > enabled ) {
sw - > enabled = true ;
if ( debug & DEBUG_SWITCH ) printf ( " Set %s \n " , sw - > name . c_str ( ) ) ;
post_soft_switch_mode_change ( ) ;
2020-12-11 01:19:39 +00:00
static char reason [ 512 ] ; sprintf ( reason , " set %s " , sw - > name . c_str ( ) ) ;
repage_regions ( reason ) ;
2020-12-07 04:08:03 +00:00
}
2016-11-06 20:37:19 +00:00
return true ;
} else if ( addr = = sw - > clear_address ) {
2016-11-09 00:41:30 +00:00
// if(!sw->implemented) { printf("%s ; unimplemented\n", sw->name.c_str()); fflush(stdout); exit(0); }
2016-11-06 20:37:19 +00:00
data = 0xff ;
2020-12-07 04:08:03 +00:00
if ( sw - > enabled ) {
sw - > enabled = false ;
if ( debug & DEBUG_SWITCH ) printf ( " Clear %s \n " , sw - > name . c_str ( ) ) ;
post_soft_switch_mode_change ( ) ;
2020-12-11 01:19:39 +00:00
static char reason [ 512 ] ; sprintf ( reason , " clear %s " , sw - > name . c_str ( ) ) ;
repage_regions ( reason ) ;
2020-12-07 04:08:03 +00:00
}
2016-11-06 20:37:19 +00:00
return true ;
}
2016-11-06 07:53:43 +00:00
}
2016-11-28 21:27:52 +00:00
if ( ( addr & 0xFFF0 ) = = 0xC080 ) {
C08X_bank = ( ( addr > > 3 ) & 1 ) ? BANK1 : BANK2 ;
C08X_write_RAM = addr & 1 ;
int read_ROM = ( ( addr > > 1 ) & 1 ) ^ C08X_write_RAM ;
C08X_read_RAM = ! read_ROM ;
if ( debug & DEBUG_SWITCH ) printf ( " write %04X switch, %s, %d write_RAM, %d read_RAM \n " , addr , ( C08X_bank = = BANK1 ) ? " BANK1 " : " BANK2 " , C08X_write_RAM , C08X_read_RAM ) ;
data = 0x00 ;
2020-12-11 01:19:39 +00:00
repage_regions ( " C08x write " ) ;
2016-11-28 21:27:52 +00:00
return true ;
}
2016-11-06 20:37:19 +00:00
if ( addr = = 0xC010 ) {
2016-11-06 21:27:01 +00:00
if ( debug & DEBUG_RW ) printf ( " write KBDSTRB \n " ) ;
2016-11-12 21:20:10 +00:00
if ( ! keyboard_buffer . empty ( ) ) {
keyboard_buffer . pop_front ( ) ;
}
2016-11-06 20:37:19 +00:00
// reset keyboard latch
return true ;
}
2016-11-06 20:44:32 +00:00
if ( addr = = 0xC030 ) {
2016-11-06 21:27:01 +00:00
if ( debug & DEBUG_RW ) printf ( " write SPKR \n " ) ;
2016-11-28 22:22:22 +00:00
fill_flush_audio ( ) ;
data = 0x00 ;
2016-12-07 02:24:11 +00:00
where_in_waveform = 0 ;
speaker_transitioning_to_high = ! speaker_transitioning_to_high ;
2016-11-06 20:44:32 +00:00
return true ;
}
2021-01-02 17:45:49 +00:00
if ( addr > = 0xC058 & & addr < = 0xC05F ) {
/* annunciators & DHGR enable */
int num = ( addr - 0xC058 ) / 2 ;
bool set = addr & 1 ;
2021-01-12 04:25:55 +00:00
if ( debug & DEBUG_RW ) printf ( " write %04X, %s annunciator %d \n " , addr , set ? " set " : " clear " , num ) ;
2021-01-02 17:45:49 +00:00
AN [ num ] = set ;
// Should also do something here if we are emulating something attached to AN{0,1,2,3}
return true ;
}
2020-12-31 19:00:09 +00:00
if ( MMIO_named_locations . count ( addr ) > 0 ) {
printf ( " unhandled MMIO Write at %04X (%s) \n " , addr , MMIO_named_locations . at ( addr ) . c_str ( ) ) ;
} else {
printf ( " unhandled MMIO Write at %04X \n " , addr ) ;
}
return false ;
// fflush(stdout); exit(0);
2016-11-06 07:53:43 +00:00
}
2016-11-11 13:54:59 +00:00
if ( debug & DEBUG_WARN ) printf ( " unhandled memory write to %04X \n " , addr ) ;
2016-11-11 23:18:08 +00:00
if ( exit_on_memory_fallthrough ) {
2016-11-12 22:41:11 +00:00
printf ( " unhandled memory write to %04X, exiting \n " , addr ) ;
2016-11-11 13:54:59 +00:00
exit ( 1 ) ;
}
2016-11-06 07:53:43 +00:00
return false ;
}
} ;
2020-12-31 19:00:09 +00:00
std : : map < uint16_t , std : : string > MAINboard : : MMIO_named_locations =
{
{ 0xC068 , " STATEREG " } ,
{ 0xC05C , " CLRAN2 " } ,
{ 0xC05E , " CLRAN3 " } ,
{ 0xC05F , " SETAN3 " } ,
} ;
2016-11-26 22:51:14 +00:00
struct bus_frontend
2016-11-06 07:53:43 +00:00
{
2020-12-06 01:19:21 +00:00
MAINboard * board ;
2020-12-17 07:03:43 +00:00
map < int , vector < uint8_t > > writes ;
map < int , vector < uint8_t > > reads ;
2016-11-26 22:51:14 +00:00
2020-12-17 07:03:43 +00:00
uint8_t read ( uint16_t addr )
2016-11-06 07:53:43 +00:00
{
2020-12-17 07:03:43 +00:00
uint8_t data = 0xaa ;
2018-08-02 23:49:51 +00:00
if ( board - > read ( addr & 0xFFFF , data ) ) {
2020-12-17 07:03:43 +00:00
if ( debug & DEBUG_BUS )
{
2020-12-20 22:49:46 +00:00
printf ( " R %04X %02X \n " , addr & 0xFFFF , data ) ;
2020-12-17 07:03:43 +00:00
}
2018-08-02 23:49:51 +00:00
// reads[addr & 0xFFFF].push_back(data);
2016-11-26 22:51:14 +00:00
return data ;
2016-11-06 07:53:43 +00:00
}
2020-12-17 07:03:43 +00:00
if ( debug & DEBUG_ERROR ) {
2018-08-02 23:49:51 +00:00
fprintf ( stderr , " no ownership of read at %04X \n " , addr & 0xFFFF ) ;
2020-12-17 07:03:43 +00:00
}
2016-11-06 07:53:43 +00:00
return 0xAA ;
}
2020-12-17 07:03:43 +00:00
void write ( uint16_t addr , uint8_t data )
2016-11-06 07:53:43 +00:00
{
2018-08-02 23:49:51 +00:00
if ( board - > write ( addr & 0xFFFF , data ) ) {
2020-12-17 07:03:43 +00:00
if ( debug & DEBUG_BUS )
{
2020-12-20 22:49:46 +00:00
printf ( " W %04X %02X \n " , addr & 0xFFFF , data ) ;
2020-12-17 07:03:43 +00:00
}
2018-08-02 23:49:51 +00:00
// writes[addr & 0xFFFF].push_back(data);
2016-11-26 22:51:14 +00:00
return ;
2016-11-06 07:53:43 +00:00
}
2020-12-17 07:03:43 +00:00
if ( debug & DEBUG_ERROR ) {
2018-08-02 23:49:51 +00:00
fprintf ( stderr , " no ownership of write %02X at %04X \n " , data , addr & 0xFFFF ) ;
2020-12-17 07:03:43 +00:00
}
2016-11-06 07:53:43 +00:00
}
2016-11-15 18:39:38 +00:00
void reset ( )
{
2016-11-26 22:51:14 +00:00
board - > reset ( ) ;
2016-11-15 18:39:38 +00:00
}
2016-11-06 07:53:43 +00:00
} ;
2016-11-26 22:51:14 +00:00
bus_frontend bus ;
2016-11-06 07:53:43 +00:00
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2016-11-11 23:18:08 +00:00
extern " C " {
uint8_t read6502 ( uint16_t address )
{
return bus . read ( address ) ;
}
void write6502 ( uint16_t address , uint8_t value )
{
bus . write ( address , value ) ;
}
} ;
2020-12-06 01:19:21 +00:00
# endif /* SUPPORT_FAKE_6502 */
void usage ( const char * progname )
2016-11-06 07:53:43 +00:00
{
printf ( " \n " ) ;
2018-09-26 01:21:58 +00:00
printf ( " usage: %s [options] ROM.bin \n " , progname ) ;
printf ( " options: \n " ) ;
printf ( " -mute disable audio output \n " ) ;
printf ( " -debugger start in the debugger \n " ) ;
printf ( " -d MASK enable various debug states \n " ) ;
printf ( " -fast run full speed (not real time) \n " ) ;
printf ( " -diskII ROM.bin floppy1 floppy2 \n " ) ;
printf ( " insert two floppies (or \" - \" for none) \n " ) ;
printf ( " -map ld65.map specify ld65 map file for debug output \n " ) ;
printf ( " -backspace-is-delete map delete key to backspace instead of left arrow \n " ) ;
2016-11-06 07:53:43 +00:00
printf ( " \n " ) ;
printf ( " \n " ) ;
}
2016-11-09 11:46:26 +00:00
bool debugging = false ;
void cleanup ( void )
{
2016-11-12 21:20:10 +00:00
fflush ( stdout ) ;
fflush ( stderr ) ;
2016-11-09 11:46:26 +00:00
}
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2016-12-09 21:06:50 +00:00
bool use_fake6502 = false ;
2020-12-06 01:19:21 +00:00
# endif
2016-11-30 17:26:19 +00:00
2016-11-26 22:51:14 +00:00
string read_bus_and_disassemble ( bus_frontend & bus , int pc )
2016-11-11 23:18:08 +00:00
{
int bytes ;
string dis ;
2020-12-17 07:03:43 +00:00
uint8_t buf [ 4 ] ;
2016-11-11 23:18:08 +00:00
buf [ 0 ] = bus . read ( pc + 0 ) ;
buf [ 1 ] = bus . read ( pc + 1 ) ;
buf [ 2 ] = bus . read ( pc + 2 ) ;
buf [ 3 ] = bus . read ( pc + 3 ) ;
2020-12-27 07:03:13 +00:00
tie ( bytes , dis ) = disassemble_6502 ( pc , buf ) ;
2016-11-12 21:20:10 +00:00
return dis ;
2016-11-11 23:18:08 +00:00
}
2016-11-14 21:41:57 +00:00
int millis_per_slice = 16 ;
2016-11-17 00:16:10 +00:00
struct key_to_ascii
{
2020-12-17 07:03:43 +00:00
uint8_t no_shift_no_control ;
uint8_t yes_shift_no_control ;
uint8_t no_shift_yes_control ;
uint8_t yes_shift_yes_control ;
2016-11-17 00:16:10 +00:00
} ;
map < int , key_to_ascii > interface_key_to_apple2e =
{
{ ' A ' , { 97 , 65 , 1 , 1 } } ,
{ ' B ' , { 98 , 66 , 2 , 2 } } ,
{ ' C ' , { 99 , 67 , 3 , 3 } } ,
{ ' D ' , { 100 , 68 , 4 , 4 } } ,
{ ' E ' , { 101 , 69 , 5 , 5 } } ,
{ ' F ' , { 102 , 70 , 6 , 6 } } ,
{ ' G ' , { 103 , 71 , 7 , 7 } } ,
{ ' H ' , { 104 , 72 , 8 , 8 } } ,
{ ' I ' , { 105 , 73 , 9 , 9 } } ,
{ ' J ' , { 106 , 74 , 10 , 10 } } ,
{ ' K ' , { 107 , 75 , 11 , 11 } } ,
{ ' L ' , { 108 , 76 , 12 , 12 } } ,
{ ' M ' , { 109 , 77 , 13 , 13 } } ,
{ ' N ' , { 110 , 78 , 14 , 14 } } ,
{ ' O ' , { 111 , 79 , 15 , 15 } } ,
{ ' P ' , { 112 , 80 , 16 , 16 } } ,
{ ' Q ' , { 113 , 81 , 17 , 17 } } ,
{ ' R ' , { 114 , 82 , 18 , 18 } } ,
{ ' S ' , { 115 , 83 , 19 , 19 } } ,
{ ' T ' , { 116 , 84 , 20 , 20 } } ,
{ ' U ' , { 117 , 85 , 21 , 21 } } ,
{ ' V ' , { 118 , 86 , 22 , 22 } } ,
{ ' W ' , { 119 , 87 , 23 , 23 } } ,
{ ' X ' , { 120 , 88 , 24 , 24 } } ,
{ ' Y ' , { 121 , 89 , 25 , 25 } } ,
{ ' Z ' , { 122 , 90 , 26 , 26 } } ,
{ ' 1 ' , { ' 1 ' , ' ! ' , 0 , 0 } } ,
{ ' 2 ' , { ' 2 ' , ' @ ' , 0 , 0 } } ,
{ ' 3 ' , { ' 3 ' , ' # ' , 0 , 0 } } ,
{ ' 4 ' , { ' 4 ' , ' $ ' , 0 , 0 } } ,
{ ' 5 ' , { ' 5 ' , ' % ' , 0 , 0 } } ,
{ ' 6 ' , { ' 6 ' , ' ^ ' , 0 , 0 } } ,
{ ' 7 ' , { ' 7 ' , ' & ' , 0 , 0 } } ,
{ ' 8 ' , { ' 8 ' , ' * ' , 0 , 0 } } ,
{ ' 9 ' , { ' 9 ' , ' ( ' , 0 , 0 } } ,
{ ' 0 ' , { ' 0 ' , ' ) ' , 0 , 0 } } ,
{ ' - ' , { ' - ' , ' _ ' , 0 , 0 } } ,
{ ' = ' , { ' = ' , ' + ' , 0 , 0 } } ,
{ ' [ ' , { ' [ ' , ' { ' , 0 , 0 } } ,
{ ' ] ' , { ' ] ' , ' } ' , 0 , 0 } } ,
{ ' \\ ' , { ' \\ ' , ' | ' , 0 , 0 } } ,
{ ' ; ' , { ' ; ' , ' : ' , 0 , 0 } } ,
{ ' \' ' , { ' \' ' , ' " ' , 0 , 0 } } ,
{ ' , ' , { ' , ' , ' < ' , 0 , 0 } } ,
{ ' . ' , { ' . ' , ' > ' , 0 , 0 } } ,
{ ' / ' , { ' / ' , ' ? ' , 0 , 0 } } ,
{ ' ` ' , { ' ` ' , ' ~ ' , 0 , 0 } } ,
{ ' ' , { ' ' , ' ' , 0 , 0 } } ,
} ;
2016-12-02 18:42:22 +00:00
DISKIIboard * diskIIboard ;
2018-07-31 21:31:36 +00:00
Mockingboard * mockingboard ;
2016-12-02 18:42:22 +00:00
2018-09-09 00:17:09 +00:00
enum APPLE2Einterface : : EventType process_events ( MAINboard * board , bus_frontend & bus , CPU6502 < system_clock , bus_frontend > & cpu )
2016-11-17 00:16:10 +00:00
{
static bool shift_down = false ;
static bool control_down = false ;
2016-11-28 22:22:22 +00:00
static bool caps_down = false ;
2016-11-17 00:16:10 +00:00
2016-11-19 04:54:19 +00:00
while ( APPLE2Einterface : : event_waiting ( ) ) {
APPLE2Einterface : : event e = APPLE2Einterface : : dequeue_event ( ) ;
2016-12-02 18:42:22 +00:00
if ( e . type = = APPLE2Einterface : : EJECT_FLOPPY ) {
diskIIboard - > set_floppy ( e . value , NULL ) ;
} else if ( e . type = = APPLE2Einterface : : INSERT_FLOPPY ) {
diskIIboard - > set_floppy ( e . value , e . str ) ;
free ( e . str ) ;
} else if ( e . type = = APPLE2Einterface : : PASTE ) {
2020-12-17 07:03:43 +00:00
for ( uint32_t i = 0 ; i < strlen ( e . str ) ; i + + )
2016-11-19 08:45:39 +00:00
if ( e . str [ i ] = = ' \n ' )
board - > enqueue_key ( ' \r ' ) ;
else
board - > enqueue_key ( e . str [ i ] ) ;
free ( e . str ) ;
2016-11-19 04:54:19 +00:00
} else if ( e . type = = APPLE2Einterface : : KEYDOWN ) {
if ( ( e . value = = APPLE2Einterface : : LEFT_SHIFT ) | | ( e . value = = APPLE2Einterface : : RIGHT_SHIFT ) )
2016-11-17 00:16:10 +00:00
shift_down = true ;
2016-11-19 04:54:19 +00:00
else if ( ( e . value = = APPLE2Einterface : : LEFT_CONTROL ) | | ( e . value = = APPLE2Einterface : : RIGHT_CONTROL ) )
2016-11-17 00:16:10 +00:00
control_down = true ;
2016-11-28 22:22:22 +00:00
else if ( e . value = = APPLE2Einterface : : CAPS_LOCK ) {
caps_down = true ;
} else if ( e . value = = APPLE2Einterface : : ENTER ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( 141 - 128 ) ;
2016-11-19 04:54:19 +00:00
} else if ( e . value = = APPLE2Einterface : : TAB ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( ' ' ) ;
2016-11-19 04:54:19 +00:00
} else if ( e . value = = APPLE2Einterface : : ESCAPE ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( ' ' ) ;
2018-07-21 02:37:49 +00:00
} else if ( e . value = = APPLE2Einterface : : BACKSPACE ) {
if ( delete_is_left_arrow ) {
board - > enqueue_key ( 136 - 128 ) ;
} else {
board - > enqueue_key ( 255 - 128 ) ;
}
2016-11-19 04:54:19 +00:00
} else if ( e . value = = APPLE2Einterface : : RIGHT ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( 149 - 128 ) ;
2016-11-19 04:54:19 +00:00
} else if ( e . value = = APPLE2Einterface : : LEFT ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( 136 - 128 ) ;
2016-11-19 04:54:19 +00:00
} else if ( e . value = = APPLE2Einterface : : DOWN ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( 138 - 128 ) ;
2016-11-19 04:54:19 +00:00
} else if ( e . value = = APPLE2Einterface : : UP ) {
2016-11-17 00:16:10 +00:00
board - > enqueue_key ( 139 - 128 ) ;
} else {
auto it = interface_key_to_apple2e . find ( e . value ) ;
if ( it ! = interface_key_to_apple2e . end ( ) ) {
const key_to_ascii & k = ( * it ) . second ;
2016-11-28 22:22:22 +00:00
if ( ! shift_down ) {
if ( ! control_down ) {
if ( caps_down & & ( e . value > = ' A ' ) & & ( e . value < = ' Z ' ) )
board - > enqueue_key ( k . yes_shift_no_control ) ;
else
board - > enqueue_key ( k . no_shift_no_control ) ;
} else
board - > enqueue_key ( k . no_shift_yes_control ) ;
} else {
if ( ! control_down )
board - > enqueue_key ( k . yes_shift_no_control ) ;
else
board - > enqueue_key ( k . yes_shift_yes_control ) ;
}
2016-11-17 00:16:10 +00:00
}
}
2016-11-19 04:54:19 +00:00
} else if ( e . type = = APPLE2Einterface : : KEYUP ) {
if ( ( e . value = = APPLE2Einterface : : LEFT_SHIFT ) | | ( e . value = = APPLE2Einterface : : RIGHT_SHIFT ) )
2016-11-17 00:16:10 +00:00
shift_down = false ;
2016-11-19 04:54:19 +00:00
else if ( ( e . value = = APPLE2Einterface : : LEFT_CONTROL ) | | ( e . value = = APPLE2Einterface : : RIGHT_CONTROL ) )
2016-11-17 00:16:10 +00:00
control_down = false ;
2016-11-28 22:22:22 +00:00
else if ( e . value = = APPLE2Einterface : : CAPS_LOCK ) {
caps_down = false ;
}
2016-11-23 00:09:48 +00:00
} if ( e . type = = APPLE2Einterface : : RESET ) {
bus . reset ( ) ;
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2016-12-05 18:04:38 +00:00
if ( use_fake6502 )
reset6502 ( ) ;
else
2020-12-06 01:19:21 +00:00
# endif
2018-09-09 00:23:38 +00:00
cpu . reset ( ) ;
2016-11-23 00:09:48 +00:00
} else if ( e . type = = APPLE2Einterface : : REBOOT ) {
bus . reset ( ) ;
2018-07-30 23:01:39 +00:00
board - > momentary_open_apple ( machine_clock_rate / ( 5 * 14 ) ) ;
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2016-12-05 18:04:38 +00:00
if ( use_fake6502 )
reset6502 ( ) ;
else
2020-12-06 01:19:21 +00:00
# endif
2018-09-09 00:23:38 +00:00
cpu . reset ( ) ;
2016-11-23 18:53:56 +00:00
} else if ( e . type = = APPLE2Einterface : : PAUSE ) {
pause_cpu = e . value ;
2016-11-23 04:02:49 +00:00
} else if ( e . type = = APPLE2Einterface : : SPEED ) {
2016-11-23 18:53:56 +00:00
run_fast = e . value ;
2018-08-08 23:18:16 +00:00
} else if ( e . type = = APPLE2Einterface : : QUIT ) {
return e . type ;
} else if ( e . type = = APPLE2Einterface : : REQUEST_ITERATION_PERIOD_IN_MILLIS ) {
run_rate_limited = true ;
rate_limit_millis = e . value ;
} else if ( e . type = = APPLE2Einterface : : WITHDRAW_ITERATION_PERIOD_REQUEST ) {
run_rate_limited = false ;
}
2016-11-17 00:16:10 +00:00
}
2016-11-19 04:54:19 +00:00
return APPLE2Einterface : : NONE ;
2016-11-17 00:16:10 +00:00
}
2018-07-28 09:50:09 +00:00
extern uint16_t pc ;
2016-11-26 22:51:14 +00:00
2018-09-09 00:36:16 +00:00
template < class CLK , class BUS >
void print_cpu_state ( const CPU6502 < CLK , BUS > & cpu )
{
printf ( " 6502: A:%02X X:%02X Y:%02X P: " , cpu . a , cpu . x , cpu . y ) ;
printf ( " %s " , ( cpu . p & cpu . N ) ? " N " : " n " ) ;
printf ( " %s " , ( cpu . p & cpu . V ) ? " V " : " v " ) ;
printf ( " - " ) ;
printf ( " %s " , ( cpu . p & cpu . B ) ? " B " : " b " ) ;
printf ( " %s " , ( cpu . p & cpu . D ) ? " D " : " d " ) ;
printf ( " %s " , ( cpu . p & cpu . I ) ? " I " : " i " ) ;
printf ( " %s " , ( cpu . p & cpu . Z ) ? " Z " : " z " ) ;
printf ( " %s " , ( cpu . p & cpu . C ) ? " C " : " c " ) ;
2020-12-20 22:49:46 +00:00
// uint8_t s0 = bus.read(0x100 + cpu.s + 0);
// uint8_t s1 = bus.read(0x100 + cpu.s + 1);
// uint8_t s2 = bus.read(0x100 + cpu.s + 2);
// uint8_t pc0 = bus.read(cpu.pc + 0);
// uint8_t pc1 = bus.read(cpu.pc + 1);
// uint8_t pc2 = bus.read(cpu.pc + 2);
// printf("S:%02X (%02X %02X %02X ...) ", cpu.s, s0, s1, s2);
// printf("PC:%04X (%02X %02X %02X ...)\n", cpu.pc, pc0, pc1, pc2);
printf ( " S:%02X " , cpu . s ) ;
printf ( " PC:%04X \n " , cpu . pc ) ;
2018-09-09 00:36:16 +00:00
}
2020-12-17 07:03:43 +00:00
template < class TYPE , uint32_t LENGTH >
2019-02-18 16:11:22 +00:00
struct averaged_sequence
{
int where ;
TYPE sum ;
TYPE list [ LENGTH ] ;
averaged_sequence ( ) :
where ( - 1 )
{
2020-12-17 07:03:43 +00:00
for ( uint32_t i = 0 ; i < LENGTH ; i + + )
2019-02-18 16:11:22 +00:00
list [ i ] = 0 ;
sum = 0 ;
}
void add ( TYPE value )
{
if ( where = = - 1 ) {
2020-12-17 07:03:43 +00:00
for ( uint32_t i = 0 ; i < LENGTH ; i + + )
2019-02-18 16:11:22 +00:00
list [ i ] = value ;
sum = value * LENGTH ;
where = 0 ;
} else {
sum - = list [ where ] ;
list [ where ] = value ;
sum + = list [ where ] ;
where = ( where + 1 ) % LENGTH ;
}
}
TYPE get ( ) const
{
return sum / LENGTH ;
}
} ;
2016-11-06 07:53:43 +00:00
int main ( int argc , char * * argv )
{
2020-12-06 01:19:21 +00:00
const char * progname = argv [ 0 ] ;
2016-11-06 07:53:43 +00:00
argc - = 1 ;
argv + = 1 ;
2020-12-06 01:19:21 +00:00
const char * diskII_rom_name = NULL , * floppy1_name = NULL , * floppy2_name = NULL ;
const char * map_name = NULL ;
2018-08-02 23:49:51 +00:00
bool mute = false ;
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
2016-11-06 07:53:43 +00:00
while ( ( argc > 0 ) & & ( argv [ 0 ] [ 0 ] = = ' - ' ) ) {
2018-08-02 23:49:51 +00:00
if ( strcmp ( argv [ 0 ] , " -mute " ) = = 0 ) {
mute = true ;
argv + + ;
argc - - ;
} else if ( strcmp ( argv [ 0 ] , " -debugger " ) = = 0 ) {
2018-08-06 07:11:33 +00:00
debugging = true ;
2016-11-09 05:43:01 +00:00
argv + + ;
argc - - ;
2016-11-26 22:51:14 +00:00
} else if ( strcmp ( argv [ 0 ] , " -diskII " ) = = 0 ) {
if ( argc < 4 ) {
2018-09-26 01:21:58 +00:00
fprintf ( stderr , " -diskII option requires a ROM image filename and two floppy image names (or \" - \" for no floppy image). \n " ) ;
2016-11-26 22:51:14 +00:00
exit ( EXIT_FAILURE ) ;
}
diskII_rom_name = argv [ 1 ] ;
floppy1_name = argv [ 2 ] ;
floppy2_name = argv [ 3 ] ;
argv + = 4 ;
argc - = 4 ;
2018-07-21 02:37:49 +00:00
} else if ( strcmp ( argv [ 0 ] , " -backspace-is-delete " ) = = 0 ) {
delete_is_left_arrow = false ;
argv + = 1 ;
argc - = 1 ;
2016-11-20 20:23:42 +00:00
} else if ( strcmp ( argv [ 0 ] , " -fast " ) = = 0 ) {
run_fast = true ;
argv + = 1 ;
argc - = 1 ;
2016-11-09 11:46:26 +00:00
} else if ( strcmp ( argv [ 0 ] , " -d " ) = = 0 ) {
debug = atoi ( argv [ 1 ] ) ;
2016-11-26 22:51:14 +00:00
if ( argc < 2 ) {
fprintf ( stderr , " -d option requires a debugger mask value. \n " ) ;
exit ( EXIT_FAILURE ) ;
}
2016-11-09 11:46:26 +00:00
argv + = 2 ;
argc - = 2 ;
2018-08-02 23:07:42 +00:00
} else if ( strcmp ( argv [ 0 ] , " -map " ) = = 0 ) {
if ( argc < 2 ) {
fprintf ( stderr , " -map option requires an ld65 map filename. \n " ) ;
exit ( EXIT_FAILURE ) ;
}
map_name = argv [ 1 ] ;
argv + = 2 ;
argc - = 2 ;
2016-11-09 05:43:01 +00:00
} else if (
2016-11-06 07:53:43 +00:00
( strcmp ( argv [ 0 ] , " -help " ) = = 0 ) | |
( strcmp ( argv [ 0 ] , " -h " ) = = 0 ) | |
( strcmp ( argv [ 0 ] , " -? " ) = = 0 ) )
{
usage ( progname ) ;
exit ( EXIT_SUCCESS ) ;
} else {
fprintf ( stderr , " unknown parameter \" %s \" \n " , argv [ 0 ] ) ;
usage ( progname ) ;
exit ( EXIT_FAILURE ) ;
}
}
if ( argc < 1 ) {
usage ( progname ) ;
exit ( EXIT_FAILURE ) ;
}
2020-12-06 01:19:21 +00:00
const char * romname = argv [ 0 ] ;
2020-12-17 07:03:43 +00:00
uint8_t b [ 32768 ] ;
2016-11-06 07:53:43 +00:00
2020-12-11 01:19:39 +00:00
if ( ! read_blob ( romname , b , sizeof ( b ) ) ) {
2016-11-06 07:53:43 +00:00
exit ( EXIT_FAILURE ) ;
2020-12-11 01:19:39 +00:00
}
2016-11-26 22:51:14 +00:00
2020-12-17 07:03:43 +00:00
uint8_t diskII_rom [ 256 ] ;
2016-11-26 22:51:14 +00:00
if ( diskII_rom_name ! = NULL ) {
if ( ! read_blob ( diskII_rom_name , diskII_rom , sizeof ( diskII_rom ) ) )
exit ( EXIT_FAILURE ) ;
2016-11-06 07:53:43 +00:00
}
2018-08-02 23:07:42 +00:00
if ( map_name ! = NULL ) {
if ( ! read_map ( map_name ) )
exit ( EXIT_FAILURE ) ;
}
2016-11-12 21:20:10 +00:00
MAINboard * mainboard ;
2020-12-17 07:03:43 +00:00
MAINboard : : display_write_func display = [ ] ( uint16_t addr , bool aux , uint8_t data ) - > bool { return APPLE2Einterface : : write ( addr , aux , data ) ; } ;
2016-12-27 06:28:45 +00:00
2016-11-30 06:17:17 +00:00
MAINboard : : get_paddle_func paddle = [ ] ( int num ) - > tuple < float , bool > { return APPLE2Einterface : : get_paddle ( num ) ; } ;
2016-12-27 06:28:45 +00:00
2018-08-02 23:49:51 +00:00
MAINboard : : audio_flush_func audio ;
if ( mute )
2020-12-17 07:03:43 +00:00
audio = [ ] ( uint8_t * buf , size_t sz ) { } ;
2018-08-02 23:49:51 +00:00
else
2020-12-17 07:03:43 +00:00
audio = [ ] ( uint8_t * buf , size_t sz ) { if ( ! run_fast ) APPLE2Einterface : : enqueue_audio_samples ( buf , sz ) ; } ;
2016-12-27 06:28:45 +00:00
2016-11-30 06:17:17 +00:00
mainboard = new MAINboard ( clk , b , display , audio , paddle ) ;
2016-11-26 22:51:14 +00:00
bus . board = mainboard ;
2016-11-15 18:39:38 +00:00
bus . reset ( ) ;
2016-11-06 07:53:43 +00:00
2016-11-26 22:51:14 +00:00
if ( diskII_rom_name ! = NULL ) {
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( ( strcmp ( floppy1_name , " - " ) = = 0 ) | |
( strcmp ( floppy1_name , " none " ) = = 0 ) | |
( strcmp ( floppy1_name , " " ) = = 0 ) )
floppy1_name = NULL ;
if ( ( strcmp ( floppy2_name , " - " ) = = 0 ) | |
( strcmp ( floppy2_name , " none " ) = = 0 ) | |
( strcmp ( floppy2_name , " " ) = = 0 ) )
floppy2_name = NULL ;
2016-11-26 22:51:14 +00:00
try {
2016-12-02 18:42:22 +00:00
DISKIIboard : : floppy_activity_func activity = [ ] ( int num , bool activity ) { APPLE2Einterface : : show_floppy_activity ( num , activity ) ; } ;
2020-12-13 23:44:22 +00:00
diskIIboard = new ( std : : nothrow ) DISKIIboard ( diskII_rom , floppy1_name , floppy2_name , activity ) ;
if ( ! diskIIboard ) {
printf ( " failed to new DISKIIboard \n " ) ;
}
2016-12-02 18:42:22 +00:00
mainboard - > boards . push_back ( diskIIboard ) ;
2018-07-31 21:31:36 +00:00
mockingboard = new Mockingboard ( ) ;
mainboard - > boards . push_back ( mockingboard ) ;
2016-11-26 22:51:14 +00:00
} catch ( const char * msg ) {
cerr < < msg < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2018-09-09 00:23:38 +00:00
CPU6502 < system_clock , bus_frontend > cpu ( clk , bus ) ;
2016-11-06 07:53:43 +00:00
2016-11-19 04:54:19 +00:00
atexit ( cleanup ) ;
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2016-11-11 23:18:08 +00:00
if ( use_fake6502 )
reset6502 ( ) ;
2020-12-06 01:19:21 +00:00
# endif
2016-11-30 17:26:19 +00:00
2016-12-02 18:42:22 +00:00
APPLE2Einterface : : start ( run_fast , diskII_rom_name ! = NULL , floppy1_name ! = NULL , floppy2_name ! = NULL ) ;
2016-11-17 06:50:09 +00:00
2016-11-30 06:17:17 +00:00
chrono : : time_point < chrono : : system_clock > then = std : : chrono : : system_clock : : now ( ) ;
2019-02-18 16:11:22 +00:00
chrono : : time_point < chrono : : system_clock > cpu_speed_then = std : : chrono : : system_clock : : now ( ) ;
clk_t cpu_previous_cycles = 0 ;
averaged_sequence < float , 20 > cpu_speed_averaged ;
2016-11-28 22:22:22 +00:00
2020-12-27 07:03:13 +00:00
std : : set < uint16_t > breakpoints ;
2016-11-06 07:53:43 +00:00
while ( 1 ) {
2016-11-08 05:22:21 +00:00
if ( ! debugging ) {
2016-11-23 00:09:48 +00:00
if ( process_events ( mainboard , bus , cpu ) = = APPLE2Einterface : : QUIT ) {
2016-11-17 02:54:56 +00:00
break ;
}
2016-11-17 00:16:10 +00:00
2020-12-13 23:44:22 +00:00
uint32_t clocks_per_slice ;
2016-11-23 18:53:56 +00:00
if ( pause_cpu )
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
clocks_per_slice = 0 ;
2016-11-23 18:53:56 +00:00
else {
2018-08-08 23:18:16 +00:00
if ( run_rate_limited ) {
clocks_per_slice = machine_clock_rate / 1000 * rate_limit_millis ;
} else if ( run_fast ) {
2016-11-28 22:22:22 +00:00
clocks_per_slice = machine_clock_rate / 5 ;
2018-08-08 23:18:16 +00:00
} else {
2016-11-30 06:17:17 +00:00
clocks_per_slice = millis_per_slice * machine_clock_rate / 1000 * 1.05 ;
2018-08-08 23:18:16 +00:00
}
2016-11-23 18:53:56 +00:00
}
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
clk_t prev_clock = clk ;
while ( clk - prev_clock < clocks_per_slice ) {
2016-11-20 20:23:42 +00:00
if ( debug & DEBUG_DECODE ) {
2020-12-06 01:19:21 +00:00
string dis = read_bus_and_disassemble ( bus ,
# ifdef SUPPORT_FAKE_6502
use_fake6502 ? pc :
# endif
cpu . pc ) ;
2016-11-12 21:20:10 +00:00
printf ( " %s \n " , dis . c_str ( ) ) ;
2016-11-20 20:23:42 +00:00
}
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
if ( use_fake6502 ) {
clockticks6502 = 0 ;
2016-11-11 23:18:08 +00:00
step6502 ( ) ;
2018-07-30 23:01:39 +00:00
clk . add_cpu_cycles ( clockticks6502 ) ;
2020-12-06 01:19:21 +00:00
} else
# endif
{
2018-09-09 00:23:38 +00:00
cpu . cycle ( ) ;
2020-12-20 22:49:46 +00:00
if ( debug & DEBUG_STATE ) {
2018-09-09 00:36:16 +00:00
print_cpu_state ( cpu ) ;
2020-12-20 22:49:46 +00:00
}
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2020-12-17 07:03:43 +00:00
if ( debug & DEBUG_CLOCK ) {
2020-12-20 22:49:46 +00:00
printf ( " clock = %u, %u \n " , ( uint32_t ) ( clk / ( 1LLU < < 32 ) ) , ( uint32_t ) ( clk % ( 1LLU < < 32 ) ) ) ;
2020-12-17 07:03:43 +00:00
}
2016-11-11 23:18:08 +00:00
}
2016-11-24 07:29:23 +00:00
mainboard - > sync ( ) ;
2018-07-31 22:33:51 +00:00
2019-02-18 16:11:22 +00:00
chrono : : time_point < chrono : : system_clock > cpu_speed_now = std : : chrono : : system_clock : : now ( ) ;
auto cpu_elapsed_seconds = chrono : : duration_cast < chrono : : duration < float > > ( cpu_speed_now - cpu_speed_then ) ;
cpu_speed_then = cpu_speed_now ;
clk_t cpu_elapsed_cycles = clk . clock_cpu - cpu_previous_cycles ;
cpu_previous_cycles = clk . clock_cpu ;
float cpu_speed = cpu_elapsed_cycles / cpu_elapsed_seconds . count ( ) ;
cpu_speed_averaged . add ( cpu_speed ) ;
APPLE2Einterface : : iterate ( mode_history , clk . clock_cpu , cpu_speed_averaged . get ( ) / 1000000.0f ) ;
2018-08-01 07:42:31 +00:00
mode_history . clear ( ) ;
2018-07-31 22:33:51 +00:00
2016-11-30 06:17:17 +00:00
chrono : : time_point < chrono : : system_clock > now = std : : chrono : : system_clock : : now ( ) ;
2016-11-08 05:22:21 +00:00
auto elapsed_millis = chrono : : duration_cast < chrono : : milliseconds > ( now - then ) ;
2020-12-06 01:19:21 +00:00
if ( ! run_fast | | pause_cpu ) {
2018-08-08 23:18:16 +00:00
this_thread : : sleep_for ( chrono : : milliseconds ( clocks_per_slice * 1000 / machine_clock_rate ) - elapsed_millis ) ;
2020-12-06 01:19:21 +00:00
}
2016-11-28 22:22:22 +00:00
then = now ;
2016-11-17 06:50:09 +00:00
2016-11-08 05:22:21 +00:00
} else {
2016-11-07 18:44:29 +00:00
2020-12-27 07:03:13 +00:00
int steps = 1 ;
2016-11-08 05:22:21 +00:00
printf ( " > " ) ;
char line [ 512 ] ;
2016-11-09 11:46:26 +00:00
if ( fgets ( line , sizeof ( line ) - 1 , stdin ) = = NULL ) {
exit ( 0 ) ;
}
2016-11-08 05:22:21 +00:00
line [ strlen ( line ) - 1 ] = ' \0 ' ;
if ( strcmp ( line , " go " ) = = 0 ) {
printf ( " continuing \n " ) ;
debugging = false ;
continue ;
2020-12-27 07:03:13 +00:00
} else if ( strncmp ( line , " step " , 4 ) = = 0 ) {
if ( line [ 5 ] ! = ' \0 ' ) {
steps = atoi ( line + 5 ) ;
printf ( " run for %d steps \n " , steps ) ;
}
} else if ( strncmp ( line , " break " , 5 ) = = 0 ) {
if ( line [ 6 ] ! = ' \0 ' ) {
uint16_t addr = strtoul ( line + 5 , NULL , 0 ) ;
printf ( " breakpoint at 0x%04X \n " , addr ) ;
breakpoints . insert ( addr ) ;
} else {
printf ( " expected breakpoint address \n " ) ;
}
continue ;
2016-11-17 06:50:09 +00:00
} else if ( strcmp ( line , " fast " ) = = 0 ) {
printf ( " run flat out \n " ) ;
run_fast = true ;
continue ;
2016-11-20 22:21:01 +00:00
} else if ( strcmp ( line , " slow " ) = = 0 ) {
2016-11-17 06:50:09 +00:00
printf ( " run 1mhz \n " ) ;
run_fast = false ;
continue ;
2016-11-11 13:54:59 +00:00
} else if ( strcmp ( line , " banking " ) = = 0 ) {
printf ( " abort on any banking \n " ) ;
2016-11-11 23:18:08 +00:00
exit_on_banking = true ;
2016-11-11 13:54:59 +00:00
continue ;
2016-11-08 05:22:21 +00:00
} else if ( strncmp ( line , " debug " , 5 ) = = 0 ) {
2020-12-17 07:03:43 +00:00
sscanf ( line + 6 , " %u " , & debug ) ;
2016-11-08 05:22:21 +00:00
printf ( " debug set to %02X \n " , debug ) ;
2016-11-09 05:43:01 +00:00
continue ;
2016-11-15 18:39:38 +00:00
} else if ( strcmp ( line , " reset " ) = = 0 ) {
printf ( " machine reset. \n " ) ;
bus . reset ( ) ;
2018-09-09 00:23:38 +00:00
cpu . reset ( ) ;
2016-11-15 18:39:38 +00:00
continue ;
} else if ( strcmp ( line , " reboot " ) = = 0 ) {
printf ( " CPU rebooted (NMI). \n " ) ;
bus . reset ( ) ;
2018-09-09 00:23:38 +00:00
cpu . nmi ( ) ;
2016-11-15 18:39:38 +00:00
continue ;
2016-11-08 05:22:21 +00:00
}
2020-12-27 07:03:13 +00:00
for ( int i = 0 ; i < steps ; i + + ) {
if ( debug & DEBUG_DECODE ) {
string dis = read_bus_and_disassemble ( bus ,
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2020-12-27 07:03:13 +00:00
use_fake6502 ? pc :
2020-12-06 01:19:21 +00:00
# endif
2020-12-27 07:03:13 +00:00
cpu . pc ) ;
printf ( " %s \n " , dis . c_str ( ) ) ;
}
2020-12-06 01:19:21 +00:00
# ifdef SUPPORT_FAKE_6502
2020-12-27 07:03:13 +00:00
if ( use_fake6502 ) {
clockticks6502 = 0 ;
step6502 ( ) ;
clk . add_cpu_cycles ( clockticks6502 ) ;
} else
2020-12-06 01:19:21 +00:00
# endif
2020-12-27 07:03:13 +00:00
{
cpu . cycle ( ) ;
if ( debug & DEBUG_STATE )
print_cpu_state ( cpu ) ;
}
if ( ( i % 10000 ) = = 0 ) {
mainboard - > sync ( ) ;
}
if ( ( i % 100000 ) = = 0 ) {
APPLE2Einterface : : iterate ( mode_history , clk . clock_cpu , 1.023 ) ;
mode_history . clear ( ) ;
}
uint16_t pcnow =
# ifdef SUPPORT_FAKE_6502
use_fake6502 ? pc :
# endif
cpu . pc ;
printf ( " %04X, %zd \n " , pcnow , breakpoints . count ( pcnow ) ) ;
if ( breakpoints . count ( pcnow ) > 0 ) {
printf ( " break at 0x%4X \n " , pcnow ) ;
break ;
}
Partially implement floppy disks
Floppy disks partially work:
apple2e -noaudio -fast -diskII disk2romfile {floppy1name,"none"} {floppy2name,"none"} apple2e.rom
Import nybblizer from Shamus but only DOS
Support floppy hardware
track motor stepper
enable
read
Add -noaudio (otherwise execution is throttled by waits once audio buffer is filled)
Only read ROM at D000 and E000 if C08X_read_RAM isn't turned on
RAMRD, RAMWRT, and ALTZP are implemented, note them as such in constructor
Correctly decode C08X soft switches
Implement a bunch more instructions
INC abs
LDY abs, X
SBC abs, Y
ADC abs
ASL abs
LSR abs, X
ORA abs
ORA abs, X
AND abs, Y
STA (ind, X)
LDX abs
CPX abs
EOR (ind, X)
EOR abs
EOR abs, X
STX abs
Throttle to actual number of clocks per instruction
Temporarily enable "Fake6502" instead of my CPU because there's an obvious difference
Better blink speed in interface.cpp
2016-11-28 01:10:03 +00:00
}
2016-11-19 04:54:19 +00:00
2016-11-08 05:22:21 +00:00
}
2016-11-06 07:53:43 +00:00
}
2016-11-17 00:16:10 +00:00
2016-11-19 04:54:19 +00:00
APPLE2Einterface : : shutdown ( ) ;
2020-12-06 01:19:21 +00:00
return 0 ;
2016-11-06 07:53:43 +00:00
}
2018-07-31 21:31:36 +00:00
2020-12-27 07:03:13 +00:00
const int hires_visible_address_base [ 262 ] =
2018-07-31 21:31:36 +00:00
{
0x0000 , 0x0400 , 0x0800 , 0x0C00 , 0x1000 , 0x1400 , 0x1800 , 0x1C00 ,
0x0080 , 0x0480 , 0x0880 , 0x0C80 , 0x1080 , 0x1480 , 0x1880 , 0x1C80 ,
0x0100 , 0x0500 , 0x0900 , 0x0D00 , 0x1100 , 0x1500 , 0x1900 , 0x1D00 ,
0x0180 , 0x0580 , 0x0980 , 0x0D80 , 0x1180 , 0x1580 , 0x1980 , 0x1D80 ,
0x0200 , 0x0600 , 0x0A00 , 0x0E00 , 0x1200 , 0x1600 , 0x1A00 , 0x1E00 ,
0x0280 , 0x0680 , 0x0A80 , 0x0E80 , 0x1280 , 0x1680 , 0x1A80 , 0x1E80 ,
0x0300 , 0x0700 , 0x0B00 , 0x0F00 , 0x1300 , 0x1700 , 0x1B00 , 0x1F00 ,
0x0380 , 0x0780 , 0x0B80 , 0x0F80 , 0x1380 , 0x1780 , 0x1B80 , 0x1F80 ,
0x0028 , 0x0428 , 0x0828 , 0x0C28 , 0x1028 , 0x1428 , 0x1828 , 0x1C28 ,
0x00A8 , 0x04A8 , 0x08A8 , 0x0CA8 , 0x10A8 , 0x14A8 , 0x18A8 , 0x1CA8 ,
0x0128 , 0x0528 , 0x0928 , 0x0D28 , 0x1128 , 0x1528 , 0x1928 , 0x1D28 ,
0x01A8 , 0x05A8 , 0x09A8 , 0x0DA8 , 0x11A8 , 0x15A8 , 0x19A8 , 0x1DA8 ,
0x0228 , 0x0628 , 0x0A28 , 0x0E28 , 0x1228 , 0x1628 , 0x1A28 , 0x1E28 ,
0x02A8 , 0x06A8 , 0x0AA8 , 0x0EA8 , 0x12A8 , 0x16A8 , 0x1AA8 , 0x1EA8 ,
0x0328 , 0x0728 , 0x0B28 , 0x0F28 , 0x1328 , 0x1728 , 0x1B28 , 0x1F28 ,
0x03A8 , 0x07A8 , 0x0BA8 , 0x0FA8 , 0x13A8 , 0x17A8 , 0x1BA8 , 0x1FA8 ,
0x0050 , 0x0450 , 0x0850 , 0x0C50 , 0x1050 , 0x1450 , 0x1850 , 0x1C50 ,
0x00D0 , 0x04D0 , 0x08D0 , 0x0CD0 , 0x10D0 , 0x14D0 , 0x18D0 , 0x1CD0 ,
0x0150 , 0x0550 , 0x0950 , 0x0D50 , 0x1150 , 0x1550 , 0x1950 , 0x1D50 ,
0x01D0 , 0x05D0 , 0x09D0 , 0x0DD0 , 0x11D0 , 0x15D0 , 0x19D0 , 0x1DD0 ,
0x0250 , 0x0650 , 0x0A50 , 0x0E50 , 0x1250 , 0x1650 , 0x1A50 , 0x1E50 ,
0x02D0 , 0x06D0 , 0x0AD0 , 0x0ED0 , 0x12D0 , 0x16D0 , 0x1AD0 , 0x1ED0 ,
0x0350 , 0x0750 , 0x0B50 , 0x0F50 , 0x1350 , 0x1750 , 0x1B50 , 0x1F50 ,
0x03D0 , 0x07D0 , 0x0BD0 , 0x0FD0 , 0x13D0 , 0x17D0 , 0x1BD0 , 0x1FD0 ,
0x0078 , 0x0478 , 0x0878 , 0x0C78 , 0x1078 , 0x1478 , 0x1878 , 0x1C78 ,
0x00F8 , 0x04F8 , 0x08F8 , 0x0CF8 , 0x10F8 , 0x14F8 , 0x18F8 , 0x1CF8 ,
0x0178 , 0x0578 , 0x0978 , 0x0D78 , 0x1178 , 0x1578 , 0x1978 , 0x1D78 ,
0x01F8 , 0x05F8 , 0x09F8 , 0x0DF8 , 0x11F8 , 0x15F8 , 0x19F8 , 0x1DF8 ,
0x0278 , 0x0678 , 0x0A78 , 0x0E78 , 0x1278 , 0x1678 , 0x1A78 , 0x1E78 ,
0x02F8 , 0x06F8 , 0x0AF8 , 0x0EF8 , 0x12F8 , 0x16F8 , 0x1AF8 , 0x1EF8 ,
0x0378 , 0x0778 , 0x0B78 , 0x0F78 , 0x1378 , 0x1778 , 0x1B78 , 0x1F78 ,
0x03F8 , 0x07F8 , 0x0BF8 , 0x0FF8 , 0x13F8 , 0x17F8 , 0x1BF8 , 0x1FF8 ,
0x0BF8 , 0x0FF8 , 0x13F8 , 0x17F8 , 0x1BF8 , 0x1FF8 ,
} ;