mirror of
https://github.com/DerekK19/PDP-8-E-Simulator.git
synced 2024-09-10 02:54:25 +00:00
Code copied from 2.0.2 DMG Sources folder
This commit is contained in:
parent
3c08889b94
commit
43ec68068e
83
ASR33/ASR33.h
Normal file
83
ASR33/ASR33.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33.h - ASR 33 Teletype for the PDP-8/E Simulator
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#define KBB_CHANGED_NOTIFICATION @"asr33KeyboardBufferChangedNotification"
|
||||
#define TTO_CHANGED_NOTIFICATION @"asr33TeletypeOutputChangedNotification"
|
||||
#define TTY_ONLINE_CHANGED_NOTIFICATION @"asr33TTYOnlineChangedNotification"
|
||||
|
||||
|
||||
@class NSCondition, PaperTapeController, ASR33TextView, ASR33WindowController, TypeaheadBuffer;
|
||||
|
||||
|
||||
@interface ASR33 : PDP8Plugin <NSCoding, InputConsumer>
|
||||
{
|
||||
@public
|
||||
/* The attributes are public, so the C functions implementing the PDP-8 instructions can
|
||||
access them directly. No other Cocoa code should use them directly. To ensure this,
|
||||
the register names are mapped to dummy names with the #defines below. In the source
|
||||
codes files with the instruction C functions, #define USE_ASR33_REGISTERS_DIRECTLY
|
||||
to make the registers available. */
|
||||
unsigned short KBB;
|
||||
unsigned long inflag;
|
||||
unsigned long outflag;
|
||||
unsigned short output;
|
||||
@private
|
||||
unsigned short TTO; // private: not accessed by IOTs
|
||||
short int input; // int: can be EOF == -1
|
||||
unsigned short inAddress;
|
||||
unsigned short outAddress;
|
||||
unsigned short punchMask;
|
||||
IBOutlet PaperTapeController *reader;
|
||||
IBOutlet PaperTapeController *punch;
|
||||
IBOutlet ASR33TextView *textview;
|
||||
IBOutlet ASR33WindowController *windowController;
|
||||
IBOutlet TypeaheadBuffer *typeaheadBuffer;
|
||||
BOOL online;
|
||||
NSConditionLock *inputLock;
|
||||
NSConditionLock *outputLock;
|
||||
NSCondition *outputOnline;
|
||||
BOOL runWithRealtimeSpeed;
|
||||
BOOL playSound;
|
||||
float soundVolume;
|
||||
BOOL isConsoleTTY;
|
||||
}
|
||||
|
||||
- (unsigned short) getKBB;
|
||||
- (void) setKBB:(unsigned short)kbb;
|
||||
- (unsigned short) getTTO;
|
||||
- (void) setTTO:(unsigned short)tto;
|
||||
- (BOOL) getOnline;
|
||||
- (void) setOnline:(BOOL)onlineOffline;
|
||||
- (void) canContinueOutput;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#if ! USE_ASR33_REGISTERS_DIRECTLY
|
||||
#define KBB __dont_use_KBB__
|
||||
#define inflag __dont_use_inflag__
|
||||
#define outflag __dont_use_outflag__
|
||||
#define input __dont_use_input__
|
||||
#define output __dont_use_output__
|
||||
#endif
|
484
ASR33/ASR33.m
Normal file
484
ASR33/ASR33.m
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33.m - ASR 33 Teletype for the PDP-8/E Simulator
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "PluginFramework/PluginAPI.h"
|
||||
#import "PluginFramework/PDP8.h"
|
||||
#import "PluginFramework/Utilities.h"
|
||||
#import "PluginFramework/FileDropControlTargetProtocol.h"
|
||||
#import "PluginFramework/PaperTapeController.h"
|
||||
#import "PluginFramework/InputConsumerProtocol.h"
|
||||
#import "PluginFramework/NSThread+MainThread.h"
|
||||
|
||||
#define USE_ASR33_REGISTERS_DIRECTLY 1
|
||||
|
||||
#import "ASR33.h"
|
||||
#import "ASR33TextView.h"
|
||||
#import "ASR33WindowController.h"
|
||||
#import "ASR33iot.h"
|
||||
#import "ASR33Preferences.h"
|
||||
#import "TypeaheadBuffer.h"
|
||||
|
||||
|
||||
#define ASR33_CONTTY_PLUGIN_NAME NSLocalizedStringFromTableInBundle( \
|
||||
@"ASR 33 Console Teletype.pdp8Plugin", nil, [self bundle], @"")
|
||||
#define ASR33_AUXTTY_IO_INFO_FILENAME @"auxtty-io-info"
|
||||
|
||||
#define CODER_KEY_KBB @"kbb"
|
||||
#define CODER_KEY_TTO @"tto"
|
||||
#define CODER_KEY_INFLAG @"inflag"
|
||||
#define CODER_KEY_INMASK @"inmask"
|
||||
#define CODER_KEY_OUTFLAG @"outflag"
|
||||
#define CODER_KEY_OUTMASK @"outmask"
|
||||
#define CODER_KEY_ONLINE @"online"
|
||||
|
||||
#define NO_OUTPUT 0
|
||||
#define OUTPUT 1
|
||||
#define NO_INPUT 0
|
||||
#define INPUT 1
|
||||
|
||||
#define TELETYPE_DELAY 100000 // 100.000 microseconds = 0.1 second
|
||||
|
||||
#define SOUND_BACKSPACE @"tty-backspace"
|
||||
#define SOUND_BELL @"tty-bell"
|
||||
#define SOUND_CARRIAGE_RETURN @"tty-carriage-return"
|
||||
#define SOUND_KEYSTROKE1 @"tty-keystroke1"
|
||||
#define SOUND_KEYSTROKE2 @"tty-keystroke2"
|
||||
#define SOUND_KEYSTROKE3 @"tty-keystroke3"
|
||||
#define SOUND_KEYSTROKE4 @"tty-keystroke4"
|
||||
#define SOUND_SPACE @"tty-space"
|
||||
#define SOUND_TYPE @"mp3"
|
||||
|
||||
|
||||
@interface NSSound (SetVolume)
|
||||
|
||||
- (void) setVolume:(float)volume; // this is a Leopard method, not available with Tiger
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation ASR33
|
||||
|
||||
|
||||
API_VERSION
|
||||
|
||||
|
||||
#pragma mark Plugin Methods
|
||||
|
||||
|
||||
- (NSString *) ioInformationPlistName
|
||||
{
|
||||
isConsoleTTY = [[self pluginName] isEqualToString:ASR33_CONTTY_PLUGIN_NAME];
|
||||
return isConsoleTTY ? [super ioInformationPlistName] : ASR33_AUXTTY_IO_INFO_FILENAME;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) iotsForAddress:(int)ioAddress
|
||||
{
|
||||
if (inAddress == 0) {
|
||||
inAddress = ioAddress;
|
||||
return [NSArray arrayWithObjects:
|
||||
[NSValue valueWithPointer:i6030],
|
||||
[NSValue valueWithPointer:i6031],
|
||||
[NSValue valueWithPointer:i6032],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:i6034],
|
||||
[NSValue valueWithPointer:i6035],
|
||||
[NSValue valueWithPointer:i6036],
|
||||
[NSValue valueWithPointer:nil],
|
||||
nil];
|
||||
} else {
|
||||
outAddress = ioAddress;
|
||||
return [NSArray arrayWithObjects:
|
||||
[NSValue valueWithPointer:i6040],
|
||||
[NSValue valueWithPointer:i6041],
|
||||
[NSValue valueWithPointer:i6042],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:i6044],
|
||||
[NSValue valueWithPointer:i6045],
|
||||
[NSValue valueWithPointer:i6046],
|
||||
[NSValue valueWithPointer:nil],
|
||||
nil];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) skiptestsForAddress:(int)ioAddress
|
||||
{
|
||||
return ioAddress == inAddress ?
|
||||
[NSArray arrayWithObjects:
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:s6031],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
nil] :
|
||||
[NSArray arrayWithObjects:
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:s6041],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:s6045],
|
||||
[NSValue valueWithPointer:nil],
|
||||
[NSValue valueWithPointer:nil],
|
||||
nil];
|
||||
}
|
||||
|
||||
|
||||
- (void) setIOFlag:(unsigned long)flag forIOFlagName:(NSString *)name;
|
||||
{
|
||||
if (inflag)
|
||||
outflag = flag;
|
||||
else
|
||||
inflag = flag;
|
||||
}
|
||||
|
||||
|
||||
- (void) CAF:(int)ioAddress
|
||||
{
|
||||
if (ioAddress == inAddress) { // CAF is called twice, ignore second call
|
||||
KBB = 0;
|
||||
TTO = 0;
|
||||
[pdp8 setInterruptMaskBits:inflag | outflag];
|
||||
[pdp8 clearIOFlagBits:inflag | outflag];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) clearAllFlags:(int)ioAddress
|
||||
{
|
||||
/* Don't modify the online state - software can't turn the TTY power knob.
|
||||
Don't modify the on/off state of the reader/punch (else the user cannot
|
||||
load BIN tapes as described in the Small Computer Systems Handbook,
|
||||
where he must operate CLEAR/CONT *after* turning on the reader). */
|
||||
if (ioAddress == inAddress) { // CAF is called twice, ignore second call
|
||||
[self setKBB:0];
|
||||
[self setTTO:0];
|
||||
[pdp8 setInterruptMaskBits:inflag | outflag];
|
||||
[pdp8 clearIOFlagBits:inflag | outflag];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) resetDevice
|
||||
{
|
||||
[typeaheadBuffer flush:self];
|
||||
[self setKBB:0];
|
||||
[self setTTO:0];
|
||||
[pdp8 setInterruptMaskBits:inflag | outflag];
|
||||
[pdp8 clearIOFlagBits:inflag | outflag];
|
||||
[self setOnline:YES];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Thread Handling
|
||||
|
||||
|
||||
- (void) playSound:(unsigned short)key
|
||||
{
|
||||
NSString *soundname;
|
||||
|
||||
NSAssertRunningOnMainThread ();
|
||||
key &= 0177;
|
||||
if (playSound || key == '\a') {
|
||||
if (isblank(key))
|
||||
soundname = SOUND_SPACE;
|
||||
else if (key == '\b')
|
||||
soundname = SOUND_BACKSPACE;
|
||||
else if (key == '\a')
|
||||
soundname = SOUND_BELL;
|
||||
else if (key == '\r')
|
||||
soundname = SOUND_CARRIAGE_RETURN;
|
||||
else if (isupper(key))
|
||||
soundname = SOUND_KEYSTROKE1;
|
||||
else if (islower(key))
|
||||
soundname = SOUND_KEYSTROKE2;
|
||||
else if (isdigit(key))
|
||||
soundname = SOUND_KEYSTROKE3;
|
||||
else
|
||||
soundname = SOUND_KEYSTROKE4;
|
||||
NSSound *sound = [[NSSound alloc] initWithContentsOfFile:
|
||||
[[self bundle] pathForResource:soundname ofType:SOUND_TYPE] byReference:YES];
|
||||
[sound autorelease];
|
||||
if ([sound respondsToSelector:@selector(setVolume:)])
|
||||
[sound setVolume:soundVolume];
|
||||
[sound play];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) canContinueInput
|
||||
{
|
||||
if ([inputLock tryLockWhenCondition:NO_INPUT])
|
||||
[inputLock unlockWithCondition:INPUT];
|
||||
/* else
|
||||
User typed so fast that input would be lost, but the typeahead buffer keeps this input. */
|
||||
}
|
||||
|
||||
|
||||
- (void) canContinueOutput
|
||||
{
|
||||
if ([outputLock tryLockWhenCondition:NO_OUTPUT])
|
||||
[outputLock unlockWithCondition:OUTPUT];
|
||||
#if ! defined(NS_BLOCK_ASSERTIONS)
|
||||
else
|
||||
NSLog (@"PDP-8 software bug: TPC or TLS executed before preceding TTY output finished");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
- (void) setTeletypeOutputFlag
|
||||
{
|
||||
NSAssertRunningOnMainThread ();
|
||||
[pdp8 setIOFlagBits:outflag];
|
||||
}
|
||||
|
||||
|
||||
- (void) processInput
|
||||
{
|
||||
NSAssertRunningOnMainThread ();
|
||||
input &= 0377; // strip off Unicode characters etc.
|
||||
if (online) {
|
||||
[self setKBB:input];
|
||||
[pdp8 setIOFlagBits:inflag];
|
||||
} else {
|
||||
[self playSound:input];
|
||||
[punch putChar:input & punchMask handleBackspace:YES];
|
||||
[textview putChar:input & 0177];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) processOutput
|
||||
{
|
||||
NSAssertRunningOnMainThread ();
|
||||
[self playSound:output];
|
||||
[self setTTO:output];
|
||||
[punch putChar:output & punchMask handleBackspace:NO];
|
||||
[textview putChar:output & 0177];
|
||||
}
|
||||
|
||||
|
||||
- (void) getReaderChar
|
||||
{
|
||||
NSAssertRunningOnMainThread ();
|
||||
input = [reader getChar];
|
||||
}
|
||||
|
||||
|
||||
- (uint64_t) realtimeDelay:(uint64_t)maTime
|
||||
{
|
||||
if (runWithRealtimeSpeed) {
|
||||
uint64_t us = absolute2nanoseconds(mach_absolute_time() - maTime) / 1000;
|
||||
if (us < TELETYPE_DELAY)
|
||||
usleep (TELETYPE_DELAY - us);
|
||||
maTime = mach_absolute_time();
|
||||
}
|
||||
return maTime;
|
||||
}
|
||||
|
||||
|
||||
- (void) asr33InputThread:(id)object
|
||||
{
|
||||
[[NSAutoreleasePool alloc] init];
|
||||
for (;;) {
|
||||
[inputLock lockWhenCondition:INPUT];
|
||||
uint64_t maTime = mach_absolute_time();
|
||||
while ((! online || [pdp8 getIOFlagBits:inflag] == 0) &&
|
||||
([self performSelectorOnMainThread:@selector(getReaderChar)
|
||||
withObject:nil waitUntilDone:YES], input != EOF)) {
|
||||
maTime = [self realtimeDelay:maTime];
|
||||
[self performSelectorOnMainThread:@selector(processInput)
|
||||
withObject:nil waitUntilDone:YES];
|
||||
}
|
||||
while ([typeaheadBuffer hasCharacters] &&
|
||||
(! online || [pdp8 isStopped] || [pdp8 getIOFlagBits:inflag] == 0)) {
|
||||
input = [typeaheadBuffer getNextChar] | 0200;
|
||||
maTime = [self realtimeDelay:maTime];
|
||||
[self performSelectorOnMainThread:@selector(processInput)
|
||||
withObject:nil waitUntilDone:YES];
|
||||
}
|
||||
[inputLock unlockWithCondition:NO_INPUT];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) asr33OutputThread:(id)object
|
||||
{
|
||||
[[NSAutoreleasePool alloc] init];
|
||||
[outputOnline lock];
|
||||
for (;;) {
|
||||
if (! online)
|
||||
[outputOnline wait];
|
||||
[outputLock lockWhenCondition:OUTPUT];
|
||||
uint64_t maTime = mach_absolute_time();
|
||||
[self performSelectorOnMainThread:@selector(processOutput)
|
||||
withObject:nil waitUntilDone:YES];
|
||||
[self realtimeDelay:maTime];
|
||||
[outputLock unlockWithCondition:NO_OUTPUT];
|
||||
[self performSelectorOnMainThread:@selector(setTeletypeOutputFlag)
|
||||
withObject:nil waitUntilDone:YES];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Register Access
|
||||
|
||||
|
||||
- (unsigned short) getKBB
|
||||
{
|
||||
return KBB;
|
||||
}
|
||||
|
||||
|
||||
- (void) setKBB:(unsigned short)kbb
|
||||
{
|
||||
NSAssert1 ((kbb & ~0377) == 0, @"Bad KBB: 0%o", kbb);
|
||||
KBB = kbb;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:KBB_CHANGED_NOTIFICATION object:self];
|
||||
}
|
||||
|
||||
|
||||
- (unsigned short) getTTO
|
||||
{
|
||||
return TTO;
|
||||
}
|
||||
|
||||
|
||||
- (void) setTTO:(unsigned short)tto
|
||||
{
|
||||
NSAssert1 ((tto & ~0377) == 0, @"Bad TTO: 0%o", tto);
|
||||
TTO = tto;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:TTO_CHANGED_NOTIFICATION object:self];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) getOnline
|
||||
{
|
||||
return online;
|
||||
}
|
||||
|
||||
|
||||
- (void) setOnline:(BOOL)onlineOffline
|
||||
{
|
||||
online = onlineOffline;
|
||||
[outputOnline signal];
|
||||
if (! online)
|
||||
[self canContinueInput];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:TTY_ONLINE_CHANGED_NOTIFICATION object:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Initialization
|
||||
|
||||
|
||||
- (id) initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
self = [super init];
|
||||
[self setKBB:[coder decodeIntForKey:CODER_KEY_KBB]];
|
||||
[self setTTO:[coder decodeIntForKey:CODER_KEY_TTO]];
|
||||
[coder decodeBoolForKey:CODER_KEY_INFLAG] ?
|
||||
[pdp8 setIOFlagBits:inflag] : [pdp8 clearIOFlagBits:inflag];
|
||||
[coder decodeBoolForKey:CODER_KEY_INMASK] ?
|
||||
[pdp8 setInterruptMaskBits:inflag] : [pdp8 clearInterruptMaskBits:inflag];
|
||||
[coder decodeBoolForKey:CODER_KEY_OUTFLAG] ?
|
||||
[pdp8 setIOFlagBits:outflag] : [pdp8 clearIOFlagBits:outflag];
|
||||
[coder decodeBoolForKey:CODER_KEY_OUTMASK] ?
|
||||
[pdp8 setInterruptMaskBits:outflag] : [pdp8 clearInterruptMaskBits:outflag];
|
||||
[self setOnline:[coder decodeBoolForKey:CODER_KEY_ONLINE]];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
[coder encodeInt:[self getKBB] forKey:CODER_KEY_KBB];
|
||||
[coder encodeInt:[self getTTO] forKey:CODER_KEY_TTO];
|
||||
[coder encodeBool:[pdp8 getIOFlagBits:inflag] ? YES : NO forKey:CODER_KEY_INFLAG];
|
||||
[coder encodeBool:[pdp8 getInterruptMaskBits:inflag] ? YES : NO forKey:CODER_KEY_INMASK];
|
||||
[coder encodeBool:[pdp8 getIOFlagBits:outflag] ? YES : NO forKey:CODER_KEY_OUTFLAG];
|
||||
[coder encodeBool:[pdp8 getInterruptMaskBits:outflag] ? YES : NO forKey:CODER_KEY_OUTMASK];
|
||||
[coder encodeBool:[self getOnline] forKey:CODER_KEY_ONLINE];
|
||||
}
|
||||
|
||||
|
||||
- (void) notifyApplicationWillTerminate:(NSNotification *)notification
|
||||
{
|
||||
// NSLog (@"ASR33 notifyApplicationWillTerminate");
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification
|
||||
object:nil];
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
|
||||
[self encodeWithCoder:archiver];
|
||||
[archiver finishEncoding];
|
||||
[archiver release];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:data forKey:[self pluginName]];
|
||||
}
|
||||
|
||||
|
||||
- (void) notifyPreferencesChanged:(NSNotification *)notification
|
||||
{
|
||||
// NSLog (@"ASR33 notifyPreferencesChanged");
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
runWithRealtimeSpeed = [defaults integerForKey:ASR33_PREFS_SPEED_KEY];
|
||||
playSound = runWithRealtimeSpeed && [defaults boolForKey:ASR33_PREFS_PLAY_SOUND];
|
||||
soundVolume = [defaults objectForKey:ASR33_PREFS_SOUND_VOLUME] ?
|
||||
[defaults floatForKey:ASR33_PREFS_SOUND_VOLUME] : 0.5f;
|
||||
punchMask = [defaults boolForKey:ASR33_PREFS_MASK_HIGHBIT_KEY] ? 0177 : 0377;
|
||||
}
|
||||
|
||||
|
||||
- (void) pluginDidLoad
|
||||
{
|
||||
NSData *data = [[NSUserDefaults standardUserDefaults] dataForKey:[self pluginName]];
|
||||
if (data) {
|
||||
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
|
||||
self = [self initWithCoder:unarchiver];
|
||||
[unarchiver finishDecoding];
|
||||
[unarchiver release];
|
||||
} else
|
||||
[self setOnline:YES];
|
||||
inputLock = [[NSConditionLock alloc] initWithCondition:NO_INPUT];
|
||||
outputLock = [[NSConditionLock alloc] initWithCondition:NO_OUTPUT];
|
||||
outputOnline = [[NSCondition alloc] init];
|
||||
[NSThread detachNewThreadSelector:@selector(asr33InputThread:) toTarget:self withObject:nil];
|
||||
[NSThread detachNewThreadSelector:@selector(asr33OutputThread:) toTarget:self withObject:nil];
|
||||
[windowController setWindowTitle:[[self pluginName] stringByDeletingPathExtension]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(notifyApplicationWillTerminate:)
|
||||
name:NSApplicationWillTerminateNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(notifyPreferencesChanged:)
|
||||
name:NSUserDefaultsDidChangeNotification object:nil];
|
||||
[self notifyPreferencesChanged:nil];
|
||||
}
|
||||
|
||||
|
||||
@end
|
35
ASR33/ASR33TextView.h
Normal file
35
ASR33/ASR33TextView.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33TextView.h - NSTextView for the ASR 33 Teletype
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
@class TypeaheadBuffer;
|
||||
|
||||
|
||||
@interface ASR33TextView : NSTextView {
|
||||
@private
|
||||
IBOutlet TypeaheadBuffer *typeaheadBuffer;
|
||||
}
|
||||
|
||||
- (void) putChar:(unichar)c;
|
||||
|
||||
@end
|
161
ASR33/ASR33TextView.m
Normal file
161
ASR33/ASR33TextView.m
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33TextView.m - NSTextView for the ASR 33 Teletype
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "ASR33TextView.h"
|
||||
#import "TypeaheadBuffer.h"
|
||||
|
||||
|
||||
@implementation ASR33TextView
|
||||
|
||||
|
||||
- (BOOL) validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem >)item
|
||||
{
|
||||
SEL action = [item action];
|
||||
return (action == @selector(copy:) ||
|
||||
action == @selector(paste:) ||
|
||||
action == @selector(selectAll:) ||
|
||||
action == @selector(_learnSpellingFromMenu:) ||
|
||||
action == @selector(spotlight:) ||
|
||||
action == @selector(_searchWithGoogleFromMenu:) ||
|
||||
action == @selector(_lookUpIndefiniteRangeInDictionaryFromMenu:) ||
|
||||
action == @selector(startSpeaking:) ||
|
||||
action == @selector(stopSpeaking:)) ?
|
||||
[super validateUserInterfaceItem:item] : FALSE;
|
||||
}
|
||||
|
||||
|
||||
- (void) doCommandBySelector:(SEL)selector
|
||||
{
|
||||
NSString *selectorName = NSStringFromSelector(selector);
|
||||
// NSLog (@"doCommandByselector %@", selectorName);
|
||||
if (selector == @selector(insertNewline:))
|
||||
[typeaheadBuffer typeahead:@"\r"];
|
||||
else if (selector == @selector(deleteBackward:))
|
||||
[typeaheadBuffer typeahead:@"\b"];
|
||||
else if (selector == @selector(deleteForward:))
|
||||
[typeaheadBuffer typeahead:@"\177"]; // Rubout
|
||||
else if (selector == @selector(cancelOperation:))
|
||||
[typeaheadBuffer typeahead:@"\033"]; // Escape
|
||||
else if (selector == @selector(centerSelectionInVisibleArea:))
|
||||
[typeaheadBuffer typeahead:@"\f"]; // Ctrl-L
|
||||
else if (selector == @selector(pageDown:))
|
||||
[typeaheadBuffer typeahead:@"\026"]; // Ctrl-V
|
||||
else if (selector == @selector(noop:)) {
|
||||
NSEvent *currentEvent = [NSApp currentEvent];
|
||||
unsigned modifierFlags = [currentEvent modifierFlags];
|
||||
unsigned c = [[currentEvent charactersIgnoringModifiers] characterAtIndex:0];
|
||||
if (modifierFlags & NSControlKeyMask) {
|
||||
switch (c) {
|
||||
case 'c' :
|
||||
case 'C' :
|
||||
[typeaheadBuffer typeahead:@"\003"]; // Ctrl-C
|
||||
break;
|
||||
case 'z' :
|
||||
case 'Z' :
|
||||
[typeaheadBuffer typeahead:@"\032"]; // Ctrl-Z
|
||||
break;
|
||||
default :
|
||||
NSLog (@"character %c (%o) ignored", c, c);
|
||||
break;
|
||||
}
|
||||
} else if (modifierFlags & NSFunctionKeyMask) {
|
||||
if (c == 0xf739) // fn-6 = forward delete on notebook keyboards
|
||||
[typeaheadBuffer typeahead:@"\177"]; // Rubout
|
||||
}
|
||||
} else if (selector != @selector(complete:) &&
|
||||
! [selectorName hasPrefix:@"delete"]) // ignore all delete* selectors
|
||||
[super doCommandBySelector:selector];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) readSelectionFromPasteboard:(NSPasteboard *)pasteboard type:(NSString *)type
|
||||
{
|
||||
[pasteboard types]; // required before accessing the pasteboards data
|
||||
if ([type isEqualToString:NSStringPboardType]) {
|
||||
[typeaheadBuffer typeahead:[pasteboard stringForType:type]];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (void) insertText:(NSString *)string
|
||||
{
|
||||
[typeaheadBuffer typeahead:string];
|
||||
}
|
||||
|
||||
|
||||
- (void) putChar:(unichar)c
|
||||
{
|
||||
NSTextStorage *storage = [self textStorage];
|
||||
int length = [storage length];
|
||||
NSRange endOfText = NSMakeRange(length, 0);
|
||||
[self scrollRangeToVisible:endOfText];
|
||||
[self setSelectedRange:endOfText];
|
||||
switch (c) {
|
||||
case '\a' :
|
||||
// NSBeep (); // handled by the ASR33 method playSound:
|
||||
break;
|
||||
case '\b' :
|
||||
if (length && [[storage string] characterAtIndex:length - 1] != '\n')
|
||||
[super deleteBackward:self];
|
||||
break;
|
||||
default :
|
||||
[super insertText:[NSString stringWithCharacters:&c length:1]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) awakeFromNib
|
||||
{
|
||||
// set size of container - to make horizontal scroller appear
|
||||
NSTextContainer *container = [self textContainer];
|
||||
NSSize size = [container containerSize];
|
||||
size.width = UINT_MAX;
|
||||
[container setContainerSize:size];
|
||||
[container setWidthTracksTextView:NO];
|
||||
|
||||
// set default font
|
||||
NSFont *font = [NSFont userFixedPitchFontOfSize:11];
|
||||
[self setFont:font];
|
||||
|
||||
// set tabstop every 8 character
|
||||
NSMutableParagraphStyle *style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
|
||||
[style setTabStops:[NSArray array]];
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
|
||||
NSAttributedString *str =
|
||||
[[[NSAttributedString alloc] initWithString:@" " attributes:attrs] autorelease];
|
||||
[style setDefaultTabInterval:8 * [str size].width /* == 7 */];
|
||||
[self setTypingAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
style, NSParagraphStyleAttributeName, font, NSFontAttributeName, nil]];
|
||||
if ([self respondsToSelector:@selector(setAutomaticTextReplacementEnabled:)])
|
||||
[self performSelector:@selector(setAutomaticTextReplacementEnabled:)
|
||||
withObject:(NSObject *) NO];
|
||||
}
|
||||
|
||||
|
||||
@end
|
46
ASR33/ASR33WindowController.h
Normal file
46
ASR33/ASR33WindowController.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33WindowController.h - ASR 33 Teletype Window Controller
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
@class ASR33, PaperTapeController, ASR33TextView, RegisterFormCell, KeepInMenuWindow;
|
||||
|
||||
|
||||
@interface ASR33WindowController : NSObject
|
||||
{
|
||||
@private
|
||||
IBOutlet ASR33 *asr33;
|
||||
IBOutlet KeepInMenuWindow *window;
|
||||
IBOutlet NSView *ttyToolbarView;
|
||||
IBOutlet NSView *readerToolbarView;
|
||||
IBOutlet NSView *punchToolbarView;
|
||||
IBOutlet NSSegmentedControl *localOnline;
|
||||
IBOutlet RegisterFormCell *kbb;
|
||||
IBOutlet RegisterFormCell *tto;
|
||||
IBOutlet PaperTapeController *readerController;
|
||||
IBOutlet PaperTapeController *punchController;
|
||||
}
|
||||
|
||||
- (IBAction) localOnlineClicked:(id)sender;
|
||||
- (void) setWindowTitle:(NSString *)title;
|
||||
|
||||
@end
|
242
ASR33/ASR33WindowController.m
Normal file
242
ASR33/ASR33WindowController.m
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33WindowController.h - ASR 33 Teletype Window Controller
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "PluginFramework/PluginAPI.h"
|
||||
#import "PluginFramework/KeepInMenuWindow.h"
|
||||
#import "PluginFramework/Utilities.h"
|
||||
#import "PluginFramework/InputConsumerProtocol.h"
|
||||
#import "PluginFramework/RegisterFormCell.h"
|
||||
|
||||
#import "ASR33WindowController.h"
|
||||
#import "ASR33.h"
|
||||
|
||||
|
||||
@implementation ASR33WindowController
|
||||
|
||||
|
||||
#define TTY_TOOLBAR_ITEM_IDENTIFIER @"ttyTBItemIdentifier"
|
||||
#define READER_TOOLBAR_ITEM_IDENTIFIER @"readerTBItemIdentifier"
|
||||
#define PUNCH_TOOLBAR_ITEM_IDENTIFIER @"punchTBItemIdentifier"
|
||||
|
||||
|
||||
#pragma mark Toolbar
|
||||
|
||||
|
||||
- (void) setupToolbar
|
||||
{
|
||||
NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"ASR33WindowToolbar"] autorelease];
|
||||
[toolbar setAllowsUserCustomization:NO];
|
||||
[toolbar setAutosavesConfiguration:YES];
|
||||
[toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel];
|
||||
[toolbar setSizeMode:NSToolbarSizeModeDefault];
|
||||
[toolbar setDelegate:self];
|
||||
[window setToolbar:toolbar];
|
||||
[window setShowsToolbarButton:YES];
|
||||
adjustToolbarControlForTiger ([kbb controlView]);
|
||||
adjustToolbarControlForTiger ([tto controlView]);
|
||||
}
|
||||
|
||||
|
||||
- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdent
|
||||
willBeInsertedIntoToolbar:(BOOL)willBeInserted
|
||||
{
|
||||
NSRect rect;
|
||||
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||
NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease];
|
||||
|
||||
if ([itemIdent isEqual:TTY_TOOLBAR_ITEM_IDENTIFIER]) {
|
||||
[toolbarItem setLabel:NSLocalizedStringFromTableInBundle(
|
||||
@"ASR 33 Teletype", nil, bundle, @"")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedStringFromTableInBundle(
|
||||
@"ASR 33 Teletype", nil, bundle, @"")];
|
||||
[toolbarItem setToolTip:NSLocalizedStringFromTableInBundle(
|
||||
@"This area contains the registers and switches of the ASR 33 teletype",
|
||||
nil, bundle, @"")];
|
||||
[toolbarItem setView:ttyToolbarView];
|
||||
rect = [ttyToolbarView frame];
|
||||
[toolbarItem setMinSize:NSMakeSize(NSWidth(rect), NSHeight(rect))];
|
||||
[toolbarItem setMaxSize:NSMakeSize(NSWidth(rect), NSHeight(rect))];
|
||||
} else if ([itemIdent isEqual:READER_TOOLBAR_ITEM_IDENTIFIER]) {
|
||||
[toolbarItem setLabel:NSLocalizedStringFromTableInBundle(
|
||||
@"Low Speed Paper Tape Reader", nil, bundle, @"")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedStringFromTableInBundle(
|
||||
@"Low Speed Paper Tape Reader", nil, bundle, @"")];
|
||||
[toolbarItem setToolTip:NSLocalizedStringFromTableInBundle(
|
||||
@"This area displays the state of the low speed paper tape reader",
|
||||
nil, bundle, @"")];
|
||||
[toolbarItem setView:readerToolbarView];
|
||||
rect = [readerToolbarView frame];
|
||||
[toolbarItem setMinSize:NSMakeSize(NSWidth(rect), NSHeight(rect))];
|
||||
[toolbarItem setMaxSize:NSMakeSize(NSWidth(rect), NSHeight(rect))];
|
||||
} else if ([itemIdent isEqual:PUNCH_TOOLBAR_ITEM_IDENTIFIER]) {
|
||||
[toolbarItem setLabel:NSLocalizedStringFromTableInBundle(
|
||||
@"Low Speed Paper Tape Punch", nil, bundle, @"")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedStringFromTableInBundle(
|
||||
@"Low Speed Paper Tape Punch", nil, bundle, @"")];
|
||||
[toolbarItem setToolTip:NSLocalizedStringFromTableInBundle(
|
||||
@"This area displays the state of the low speed paper tape punch",
|
||||
nil, bundle, @"")];
|
||||
[toolbarItem setView:punchToolbarView];
|
||||
rect = [punchToolbarView frame];
|
||||
[toolbarItem setMinSize:NSMakeSize(NSWidth(rect), NSHeight(rect))];
|
||||
[toolbarItem setMaxSize:NSMakeSize(NSWidth(rect), NSHeight(rect))];
|
||||
} else
|
||||
toolbarItem = nil;
|
||||
return toolbarItem;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
|
||||
{
|
||||
return [NSArray arrayWithObjects:
|
||||
TTY_TOOLBAR_ITEM_IDENTIFIER, NSToolbarSeparatorItemIdentifier,
|
||||
READER_TOOLBAR_ITEM_IDENTIFIER, NSToolbarSeparatorItemIdentifier,
|
||||
PUNCH_TOOLBAR_ITEM_IDENTIFIER,
|
||||
nil];
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
|
||||
{
|
||||
return [NSArray arrayWithObjects:
|
||||
TTY_TOOLBAR_ITEM_IDENTIFIER, READER_TOOLBAR_ITEM_IDENTIFIER,
|
||||
PUNCH_TOOLBAR_ITEM_IDENTIFIER, NSToolbarSeparatorItemIdentifier,
|
||||
nil];
|
||||
}
|
||||
|
||||
|
||||
- (void) windowDidBecomeMain:(NSNotification *)notification
|
||||
{
|
||||
if (runningOnLionOrNewer()) {
|
||||
[kbb setEnabled:YES];
|
||||
[tto setEnabled:YES];
|
||||
[readerController setEnabled:YES];
|
||||
[punchController setEnabled:YES];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) windowDidResignMain:(NSNotification *)notification
|
||||
{
|
||||
if (runningOnLionOrNewer()) {
|
||||
[kbb setEnabled:NO];
|
||||
[tto setEnabled:NO];
|
||||
[readerController setEnabled:NO];
|
||||
[punchController setEnabled:NO];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Notifications
|
||||
|
||||
|
||||
- (void) windowWillBeginSheet:(NSNotification *)notification
|
||||
{
|
||||
[localOnline setEnabled:NO];
|
||||
[kbb setEnabled:NO];
|
||||
[tto setEnabled:NO];
|
||||
[readerController setEnabled:NO];
|
||||
[punchController setEnabled:NO];
|
||||
}
|
||||
|
||||
|
||||
- (void) windowDidEndSheet:(NSNotification *)notification;
|
||||
{
|
||||
[localOnline setEnabled:YES];
|
||||
[kbb setEnabled:YES];
|
||||
[tto setEnabled:YES];
|
||||
[readerController setEnabled:YES];
|
||||
[punchController setEnabled:YES];
|
||||
}
|
||||
|
||||
|
||||
- (void) notifyPluginsLoaded:(NSNotification *)notification
|
||||
{
|
||||
[self windowDidResignMain:notification];
|
||||
[window orderBackFromDefaults:self];
|
||||
}
|
||||
|
||||
|
||||
- (void) setupNotifications
|
||||
{
|
||||
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(notifyOnlineChanged:) name:TTY_ONLINE_CHANGED_NOTIFICATION object:nil];
|
||||
[defaultCenter addObserver:self selector:@selector(notifyPluginsLoaded:)
|
||||
name:PLUGINS_LOADED_NOTIFICATION object:nil];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Controls
|
||||
|
||||
|
||||
- (IBAction) localOnlineClicked:(id)sender
|
||||
{
|
||||
[asr33 setOnline:[sender selectedSegment]];
|
||||
}
|
||||
|
||||
|
||||
- (void) notifyOnlineChanged:(NSNotification *)notification
|
||||
{
|
||||
[localOnline setSelectedSegment:[asr33 getOnline]];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Initialization
|
||||
|
||||
|
||||
- (void) setWindowTitle:(NSString *)title
|
||||
{
|
||||
BOOL isAuxTTY = ! [[window title] isEqualToString:title];
|
||||
NSRect oldFrame = [window frame];
|
||||
[window setTitle:title];
|
||||
[window setFrameAutosaveName:title];
|
||||
/* this is a hack to move the AuxTTY window away from the exact position of the ConTTY when the
|
||||
simulator starts for the first time without existing preferences file */
|
||||
if (isAuxTTY && NSEqualRects(oldFrame, [window frame]))
|
||||
[window setFrameOrigin:NSMakePoint(oldFrame.origin.x + 20, oldFrame.origin.y - 20)];
|
||||
}
|
||||
|
||||
|
||||
- (void) setupRegisters
|
||||
{
|
||||
[kbb setupRegisterFor:asr33 getRegisterValue:@selector(getKBB) setRegisterValue:@selector(setKBB:)
|
||||
changedNotificationName:KBB_CHANGED_NOTIFICATION mask:0377 base:8];
|
||||
[tto setupRegisterFor:asr33 getRegisterValue:@selector(getTTO) setRegisterValue:@selector(setTTO:)
|
||||
changedNotificationName:TTO_CHANGED_NOTIFICATION mask:0377 base:8];
|
||||
}
|
||||
|
||||
|
||||
- (void) awakeFromNib
|
||||
{
|
||||
[self setupToolbar];
|
||||
[self setupNotifications];
|
||||
[self setupRegisters];
|
||||
}
|
||||
|
||||
|
||||
@end
|
151
ASR33/ASR33iot.c
Normal file
151
ASR33/ASR33iot.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33iot.c - ASR 33 Teletype IOTs
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#define USE_ASR33_REGISTERS_DIRECTLY 1
|
||||
#define USE_PDP8_REGISTERS_DIRECTLY 1
|
||||
|
||||
#import "PluginFramework/PluginAPI.h"
|
||||
#import "PluginFramework/PDP8.h"
|
||||
#import "PluginFramework/InputConsumerProtocol.h"
|
||||
|
||||
#import "ASR33iot.h"
|
||||
#import "ASR33.h"
|
||||
|
||||
|
||||
void i6030 (void) /* KCF 6030 */
|
||||
{
|
||||
pdp8->IOFLAGS &= ~PLUGIN_POINTER(ASR33)->inflag;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6031 (void) /* KSF 6031 */
|
||||
{
|
||||
if (pdp8->IOFLAGS & PLUGIN_POINTER(ASR33)->inflag)
|
||||
pdp8->PC++;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
unsigned s6031 (void) /* KSF 6031 stiptest */
|
||||
{
|
||||
return pdp8->IOFLAGS & PLUGIN_POINTER(ASR33)->inflag;
|
||||
}
|
||||
|
||||
|
||||
void i6032 (void) /* KCC 6032 */
|
||||
{
|
||||
pdp8->IOFLAGS &= ~PLUGIN_POINTER(ASR33)->inflag;
|
||||
pdp8->AC &= 010000;
|
||||
[PLUGIN_POINTER(ASR33) canContinueInput];
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6034 (void) /* KRS 6034 */
|
||||
{
|
||||
pdp8->AC |= PLUGIN_POINTER(ASR33)->KBB;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6035 (void) /* KIE 6035 */
|
||||
{
|
||||
if (pdp8->AC & 1)
|
||||
pdp8->IMASK |= PLUGIN_POINTER(ASR33)->inflag | PLUGIN_POINTER(ASR33)->outflag;
|
||||
else
|
||||
pdp8->IMASK &= ~(PLUGIN_POINTER(ASR33)->inflag | PLUGIN_POINTER(ASR33)->outflag);
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6036 (void) /* KRB 6036 */
|
||||
{
|
||||
pdp8->AC = (pdp8->AC & 010000) | PLUGIN_POINTER(ASR33)->KBB;
|
||||
pdp8->IOFLAGS &= ~PLUGIN_POINTER(ASR33)->inflag;
|
||||
[PLUGIN_POINTER(ASR33) canContinueInput];
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6040 (void) /* TFL 6040 */
|
||||
{
|
||||
pdp8->IOFLAGS |= PLUGIN_POINTER(ASR33)->outflag;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6041 (void) /* TSF 6041 */
|
||||
{
|
||||
if (pdp8->IOFLAGS & PLUGIN_POINTER(ASR33)->outflag)
|
||||
pdp8->PC++;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
unsigned s6041 (void) /* TSF 6041 skiptest */
|
||||
{
|
||||
return pdp8->IOFLAGS & PLUGIN_POINTER(ASR33)->outflag;
|
||||
}
|
||||
|
||||
|
||||
void i6042 (void) /* TCF 6042 */
|
||||
{
|
||||
pdp8->IOFLAGS &= ~PLUGIN_POINTER(ASR33)->outflag;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6044 (void) /* TPC 6044 */
|
||||
{
|
||||
PLUGIN_POINTER(ASR33)->output = (pdp8->AC & 0377);
|
||||
[PLUGIN_POINTER(ASR33) canContinueOutput];
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
void i6045 (void) /* TSK 6045 */
|
||||
{
|
||||
|
||||
if (pdp8->IOFLAGS & pdp8->IMASK & (PLUGIN_POINTER(ASR33)->inflag | PLUGIN_POINTER(ASR33)->outflag))
|
||||
pdp8->PC++;
|
||||
EXECUTION_TIME (12);
|
||||
}
|
||||
|
||||
|
||||
unsigned s6045 (void) /* TSK 6045 skiptest */
|
||||
{
|
||||
return pdp8->IOFLAGS & pdp8->IMASK & (PLUGIN_POINTER(ASR33)->inflag | PLUGIN_POINTER(ASR33)->outflag);
|
||||
}
|
||||
|
||||
|
||||
void i6046 (void) /* TLS 6046 */
|
||||
{
|
||||
PLUGIN_POINTER(ASR33)->output = (pdp8->AC & 0377);
|
||||
pdp8->IOFLAGS &= ~PLUGIN_POINTER(ASR33)->outflag;
|
||||
[PLUGIN_POINTER(ASR33) canContinueOutput];
|
||||
EXECUTION_TIME (12);
|
||||
}
|
39
ASR33/ASR33iot.h
Normal file
39
ASR33/ASR33iot.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* ASR33iot.h - ASR 33 Teletype IOTs
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
extern void i6030 (void); /* KCF 6030 */
|
||||
extern void i6031 (void); /* KSF 6031 */
|
||||
extern unsigned s6031 (void); /* KSF (skip test) */
|
||||
extern void i6032 (void); /* KCC 6032 */
|
||||
extern void i6034 (void); /* KRS 6034 */
|
||||
extern void i6035 (void); /* KIE 6035 */
|
||||
extern void i6036 (void); /* KRB 6036 */
|
||||
extern void i6040 (void); /* TFL 6040 */
|
||||
extern void i6041 (void); /* TSF 6041 */
|
||||
extern unsigned s6041 (void); /* TSF (skip test) */
|
||||
extern void i6042 (void); /* TCF 6042 */
|
||||
extern void i6044 (void); /* TPC 6044 */
|
||||
extern void i6045 (void); /* TSK 6045 */
|
||||
extern unsigned s6045 (void); /* TSK (skip test) */
|
||||
extern void i6046 (void); /* TLS 6046 */
|
1694
ASR33/English.lproj/ASR33.nib/designable.nib
generated
Normal file
1694
ASR33/English.lproj/ASR33.nib/designable.nib
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
ASR33/English.lproj/ASR33.nib/keyedobjects.nib
generated
Normal file
BIN
ASR33/English.lproj/ASR33.nib/keyedobjects.nib
generated
Normal file
Binary file not shown.
307
ASR33/English.lproj/ASR33OnlineHelp/index.html
Normal file
307
ASR33/English.lproj/ASR33OnlineHelp/index.html
Normal file
@ -0,0 +1,307 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<!--
|
||||
* PDP-8/E Simulator
|
||||
*
|
||||
* Copyright © 1994-2015 Bernhard Baehr
|
||||
*
|
||||
* index.html - Online help for the ASR 33 Teletype
|
||||
*
|
||||
* This file is part of PDP-8/E Simulator.
|
||||
*
|
||||
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
|
||||
<title>ASR 33 Teletype Help</title>
|
||||
<meta name="description"
|
||||
content="Describes the functioning and PDP-8 IOTs of the ASR 33 Teletype">
|
||||
<meta name="AppleTitle" content="ASR 33 Teletype Help">
|
||||
<meta name="AppleIcon" content="pdp8e.png">
|
||||
<link href="styles.css" rel="stylesheet" media="all">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>ASR 33 Teletype Help</h1>
|
||||
|
||||
<p>
|
||||
The ASR 33 Teletype can operate under program control or independent of the PDP-8 unter manual
|
||||
control. When operated in manual mode, characters typed at the keyboard are printed by the type
|
||||
writer of the teletype. When additionally the paper tape punch is turned on, the typed
|
||||
characters are punched on the papter tape, too. When a paper tape is loaded into the reader and
|
||||
the reader is turned on, the teletype ignores the keyboard input and reads characters to print
|
||||
or punch from the reader paper tape.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When the teletype is used in online mode, characters typed at the keyboard or read from the reader paper
|
||||
tape are not printed or punched, but their ASCII value is transferred into the keyboard buffer register
|
||||
KBB, from where the PDP-8 can read it into the accumulator AC. The PDP-8 then can use teletype output
|
||||
IOTs to write the character to the teletype output buffer register TTO to initiate the printing or
|
||||
punching of the character.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The teletypes of the PDP-8/E Simulator have the following improvements compared to hardware ASR 33
|
||||
Teletypes:
|
||||
<p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Backspace handling: When the teletype is operated in local mode, typing the backspace key causes the
|
||||
last character to be removed from the output display and — when the punch is turned on —
|
||||
from the punch paper tape. The Macintosh clear key (at the top left of the numeric key pad or fn-6 on
|
||||
notebook keyboards) has the function of the ASR 33 rubout key.
|
||||
</li>
|
||||
<li>
|
||||
Tabulator handling: The teletype handles the output of tabulator characters with tabulator stops at every
|
||||
8th column. (Tab characters are punched to paper tapes unaltered.)
|
||||
</li>
|
||||
<li>
|
||||
Speed: The simulated teletype can run with the speed of a hardware ASR 33 teletype (about ten characters
|
||||
per second) or as fast as possible. Use the ASR 33 preference pane to change the speed of the teletype.
|
||||
</li>
|
||||
<li>
|
||||
High bit masking for the punch: When this feature is enabled (in the ASR 33 preference pane), the paper
|
||||
tape punch masks the most significant bit of the punched characters. This is useful when you run PDP-8
|
||||
software that use the 8th bit as a checksum and save the output to a paper tape. When the MSB is
|
||||
masked out, you can open and read the paper tape file with any Mac text editor. (When punching BIN or
|
||||
RIM format paper tapes, you normally won't have to disable the MSB masking because these formats use
|
||||
the 8th bit only for punching leaders or trailers, which are not needed with paper tapes stored in
|
||||
files. One exception: BIN format with field settings uses values 3x0 (x=0,…,7) to signal that
|
||||
the following code is to be loaded to memory field x.)
|
||||
</li>
|
||||
<li>
|
||||
“Copy & Paste” and “Drag & Drop” is supported for the teletype:
|
||||
When you paste text into the teletype window, the text is inserted into a typeahead buffer
|
||||
from where the teletype reads it sccessively as if the characters were typed at the keyboard.
|
||||
New keyboard input is appended at the end of the typeahead buffer. While the typeahead buffer is not
|
||||
empty, a button “Flush Typeahead Buffer” appears in the toolbar of the ASR 33 window that
|
||||
you can use to clear the buffer prematurely.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Console Teletype</h2>
|
||||
|
||||
<p>
|
||||
The console teletype uses I/O address 03 for the keyboard and reader and 04 for the printer
|
||||
and punch and supports the following IOTs:
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Mnemonic<br>Symbol</th>
|
||||
<th>Octal<br>Code</th>
|
||||
<th class="left"><br>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>KCF</td>
|
||||
<td>6030</td>
|
||||
<td class="left">
|
||||
Clear the keyboard/reader I/O flag (“Console TTY In” in the CPU window).
|
||||
Do not start the reader to read the next tape character.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>KSF</td>
|
||||
<td>6031</td>
|
||||
<td class="left">
|
||||
Skip the next instruction when the keyboard/reader I/O flag is raised, i. e. a new
|
||||
character is loaded into the keyboard buffer register KBB.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>KCC</td>
|
||||
<td>6032</td>
|
||||
<td class="left">
|
||||
Clear AC and the keyboard/reader I/O flag. When the paper tape reader is turned on,
|
||||
start to read the next character from the tape. When a new value is loaded into KBB
|
||||
(from the tape or — when the reader is turned off — because the user
|
||||
typed a key), the flag is raised again.
|
||||
</td>
|
||||