Code copied from 2.0.2 DMG Sources folder

This commit is contained in:
Derek Knight (mac) 2018-05-26 15:52:10 +12:00
parent 3c08889b94
commit 43ec68068e
340 changed files with 64392 additions and 0 deletions

83
ASR33/ASR33.h Normal file
View 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
View 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
View 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
View 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

View 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

View 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
View 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
View 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 */

File diff suppressed because it is too large Load Diff

Binary file not shown.

View 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 &mdash; when the punch is turned on &mdash;
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,&hellip;,7) to signal that
the following code is to be loaded to memory field x.)
</li>
<li>
&ldquo;Copy &amp; Paste&rdquo; and &ldquo;Drag &amp; Drop&rdquo; 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 &ldquo;Flush Typeahead Buffer&rdquo; 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 (&ldquo;Console TTY In&rdquo; 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 &mdash; when the reader is turned off &mdash; because the user
typed a key), the flag is raised again.
</td>