MTOS MultiTasking Operation System
The MTOS is a set of programs that uses
a program called "Split Personality" from
Nibble magazine. Most of the code in Split
Personality is intact. We've added the
ability to add more banks to the system
with a Ramworks III card, added cross bank
transfer ability, interrupt handler for
multitasking (auto-switching), interrupt
enabler, and a Z80 programmable interrupt
generator.
Download the DSK.
This is an old version of the code without
the interrupt code, no PRODOS compatibility.
I've helped beta-test and improve the code
for an apple II "multitasker". It interests
me for use on my robot. Wozbot currently
multitasks several programs in his memory.
The MTOS system stores different programs
(along with the STACK for that process)
in different banks of auxillary
memory.
The 6502 processor has a 64k address range
(16bit address). To add more memory to the
computer, companies "bank switched RAM".
RAM is stuck on an interface card. It is
switched out in chunks into the address space
of the 6502. The Apple lets you switch
different parts out at different times.
You can switch the stack/Language Card
(upper 16k), page zero and 1 (zero page and
the stack), and page 2 to DFFF (the area
between the stack and $C000, which is the
beginning of the "softswitches" and other
Apple II I/O area.
Here is an article that will give you better
idea how the Softswitches work.
THe MTOS works by running a program for a
short time, a mouse card interrupt occurs.
The interrupt triggers the switching code.
The code saves the processor status,
program counter, stack pointer, etc (all
6502 registers). It then switches in the
next bank of Auxillary memory. The control
is passed to the switching code in the
selected bank. The code loads the processor
status for that task, and runs the task.
Another interrupt occurs, and the code
switches to the next task.
COMING SOON:
Memory map animations of how the transfer
between banks occurs.
RJ
The Setup program gets loaded into $8200.
It then copies data around the banks as
mentioned and described below.
A small BASIC program is used to add more
active banks. Up to 16 banks can be used
with a RAMWORKS III card.
Once the banks are setup, you POKE the
number of the bank you want to get to and
CALL768. Split Pers determines if you are
in Aux or MAIN. If in AUX, it switches to
MAIN. If in MAIN, it switches to the bank
you POKED.
No automation of program loading has been
made. You must go into each bank seperately
and load the appropriate BASIC/Assembly files.
You must also BLOAD the interrupt handler
into any bank you wish to multitask.
Once all the interrupt handlers are installed,
interrupts are turnedON. I wrote a small driver
for my Z80 computer that sets the interrupt
interval and turns them ON.
The Apple II will begin multitasking.
Needed is screen output for aux banks higher
than AUX0. We could add code into MAIN RAM
to copy from AUX the screen data and store it
in MAIN RAM screen area. This would be slow.
How about a RAM card that allows you to
display text from any bank?
Step 1:
a)Set to read/write all main memory.
b)Set to Read ROM/Write RAM
---c)Copy ROM to upper 16k main RAM
---d)Copy $00-$1FF (zero pg, stack) to $8000-$81FF
---e)Load Split Pers to $300
Step 2:
a)Set to read $200-$BFFF main memory.
b)Set to write $200-$BFFF Aux memory
---c)Copy $200-$BFFF from main to aux memory
Step 3:
a)Set to READ/WRITE Aux. $0-$1ff and upper 16k.
b)Set to Read ROM/WRITE RAM
---c)Copy ROM into Aux RAM top 16k
Step 4:
a)Set to read $200-$BFFF main memory.
b)Set to READ/Write Aux memory $00-$1FF and top 16k
---c)Copy $8000-$81FF from main to aux memory $00-$1FF (see step1)
TEMP EQU $0000
STARTSOU EQU $3C
ENDSOU EQU $3E
DEST EQU $42
STATUS EQU $48
BANK EQU $3CE
APPLEID EQU $3CF
RDMAINRM EQU $C002
WRMAINRM EQU $C004
SETSTDZP EQU $C008
SETALTZP EQU $C009
READRAM EQU $C080
RROMWRAM EQU $C081
READROM EQU $C082
RDWRTLC EQU $C083
AUXMOVE EQU $C311
IDBYTE EQU $FBB3
HOME EQU $FC58
COUT EQU $FDED
MOVE EQU $FE2C
BELL EQU $FF3A
SAVE EQU $FF4A
*
***************************
*
ORG $8200
*
*
*THE FIRST SECTION OF THIS PROGRAM IS A
*CONTROLLING CODE THAT CALLS SUBROUTINES TO DO ALMOST
*EVERYTHING. THIS SHOULD MAKE THE CODE EASY TO FOLLOW
*AND MODIFY
*
*****************************
*
CLI ; CLEAR INTERRUPTS
CLD ; CLEAR DECIMAL MODE
CLC ; CLEAR CARRY
JSR SAVE ; AND SAVE REGISTER VALUES
SEI ;DISABLE INTERRUPTS- WITH THE SOFT
;SWITCHES TO BE HIT THEY COULD BE
;FATAL
JSR NORMAL ;INITIALIZE RAM STATUS TO KNOWN
;SETTINGS TO READ/WRITE ROM UPPER
;16K AND MAIN RAM
NOP
NOP
NOP
* ;JSR CKMEMSIZ MAKE SURE WE HAVE EXPANDED RAM
JSR ZPSETUP ;DO VECTORS. ETC BEFORE ZPPISAVE
JSR ZPP1SAVE ;SAVE A "VIRGIN" COPY OF THE ZERO
;PAGE AND 6502'S STACK (PAGE ONE)
JSR INSTALSW ;PUT RAM GATE IN AT $300
JSR LCLOAD ;COPY ROM TO LANGUAGE CARD
NOP
NOP
NOP
* ;JSR CKBIGMEM HOOK IN HERE TO LOOK FOR A BIG
;MEMORY RAM CARD USING THE IIE'S
;RENDUNDANT RAM STRUCTURE. THE
;EXAMPLE SUPPLIED HERE IS FOR AN
;APPLIED ENGINEERING MEMORYMASTER
DOBANK2 LDA #$02 ;BEGIN SETUP OF THE 2ND 64K BANK
STA BANK ;BY PUTTING AN ID BYTE (03CE)
JSR MAINLOAD ;IN PLACE AND COPYING THE $200
;TO $BFFF DATA TO ALT. THIS WILL
;INCLUDE THE RAM GATE SWITCH.
;DOS VECTORS, LOADED APPLESOFT/BINARY
;PROGRAMS, DOS, ETC
STA SETALTZP ;SWITCH ON TOP 16K, ZP AND PG1
JSR LCLOAD ;AND DO LC LOAD IN THAT RAM
STA SETSTDZP ;THEN TURN THE ROM BACK ON
JSR ZPP1COPY ;COPY NORMAL PAGE 0 AND 1 INTO
;WHATEVER ALTERNATE RAM AVAILABLE
* +-----------------------------------------+
* | SPECIAL NOTE |
* | AT THIS POINT WE ARE |
* | ALMOST FINISHED FOR A NORMAL 128K |
* | EXPANDED RAM IIE SO ANY LARGE MEMORY |
* | CARDS THAT WERE FOUND IN CKBIGMEM |
* | ABOVE THAT NEED ATTENTION MUYST NOW BE |
* | HANDLED . THE EXAMPLE GIVE IS FOR AN |
* | AE MEMORY MASTER (192K)--SUBSITTUE |
* | ROUTINES FOR THE SPECIFIC CARD OF |
* | YOUR CHOICE HERE. IN CKBIGMEM AND IN |
* | THE SECTION NOW TITLED MEMASTER |
* +-----------------------------------------+
LDA APPLEID ;IS THIS A MEMORY MASTER IIE?
CMP #$81 ;IF SO WE DO 2ND ALT 64K BANK
BEQ MEMASTER ;COPYING STUFF
END LDA #$01 ;PUT A "1" IN THE MAIN RAM'S
STA BANK ;BANK IDENTIFICATION BYTE
JSR HOME ;NEATEN THINGS UP A LITTLE
JMP $3D0 ;AND EXIT TO APPLESOFT
MEMASTER STA $C05E ;SWITCH TO 2ND ALTERNATE 64K RAM
STA $C05F
LDA #$03 ;PUT A THREE IN THE 3RD BANKS
STA BANK ;ID BYTE WHEN THE $200-$BFFF
JSR MAINLOAD ;RANGE IS COPIED
STA SETALTZP ;REPEAT LOADING OF TOP 16K WITH
JSR LCLOAD ;APPLESOFT AND MONITOR BUT IN THE
STA SETSTDZP ;MEMORYMASTER'S 2ND ALT 64K BANK
JSR ZPP1COPY ;ZEROPG AND PG1 COPY
STA $C05E ;HITMEMORY MASTER SWITCHES AGAIN
STA $C05F ;TO RETURN TO BANK #2
JSR END ;NOW EXIT
* END OF GENERAL CONTROLLING PROGRAM
* FOLLOWING ARE SUBROUTINES CALLED FROM ABOVE
* APPLE ID AND SPLIT PERS ARE ACCESSED
NORMAL STA WRMAINRM ;WRITEMOTHER RAM
STA RDMAINRM ;READ MOTHER RAM
LDA READROM ;READ ROM IN LC/WRITE PROTECT RAM
STA SETSTDZP ;MAKE ANY ALT. RAM UNAVAILABLE
JSR MSGOUT ;CLEAR THE SCREEN AND
HEX 8D04 ;TURN ON 80 COL CARD
ASC "PR#3"
HEX 8D00 ;MAKE SURE I/O VECTORS INSTALLED
JSR INTRO ;GIVE CREDITS
RTS
*
CKMEMSIZ JSR MSGOUT ;LOAD THE APPLEID PGM
HEX 8D04
ASC "BLOAD APPLE.ID"
HEX 8D00
JSR $D24 ;CALL THE PROGRAM
LDA APPLEID ;USE APPLE'S OWN ROUTINE TO SEE
CMP #$80 ;IF WE HAVE EXPANDED RAM
BNE NORAM ;IF NOT GOTO BAD NEWS CENTRAL
JSR HOME ;CLEAR THE SCREEN
JSR MSGOUT ;IF SO NOTIFY THAT PROCESS IS ON
ASC "EXPANDED RAM AVAILABLE--SETUP IN PROGRESS"
HEX 8D00
RTS
NORAM JSR HOME ;CLEAR SCREEN
JSR MSGOUT ;NO EXTRA RAM- GIVE 'EM
HEX 8D ;BAD NEWS
ASC "THE APPLE MACHINE IDENTIFICATION"
HEX 8D
ASC "PROGRAM HAS NOT FOUND THEIS COMPUTER"
HEX 8D
ASC "TO BE EQUIPPED WITH EXPANDED RAM."
HEX 8D8D8D
ASC "SETUP IS TERMINATED"
HEX 8D8D00
JSR NORMAL
JSR BELL
JMP $3D0 ;EXIT VIA DOS
ZPSETUP LDA #$FF ;SIGNAL IMMEDIATE MODE WITH $FF
STA $76 ;IN CURLIN+1
LDA $49 ;GET STACK POINTER FOR ALT RAM USE
STA $101 ;AND INITIALIZE STACKPOINTER VALUE
;<- ADD NEEDED ZEROPAGE STUFF HERE
RTS ;AND RETURN
LCLOAD ;SET TO READ ROM/WRITE RAM
;IN LC AREA--IF ALTZP IS ON
;THIS GIVES THE TOP OF AN
;ALTERNATE 64K BANK INSTEAD
LDA RROMWRAM ;SET TOP 16K TO READ ROM AND
LDA RROMWRAM ; WRITE RAM FOR COPY TRANSFER
;2 LDA'S REQUIRED (NOT IN MANUAL)
LDY #$00 ;SET UP THE $D000 STARTING
LDA #$D0 ;ADDRESS IN DEST AND
STA DEST+1 ;LEAVE Y HOLDING #$00
STY DEST
LCLOOP LDA (DEST),Y ;USE POST INDEXED INDIRECT
STA (DEST),Y ;ADDRESSING TO CREAT A VERY
DEY ;F-A-S-T
BNE LCLOOP ;ROUTINE TO COPY AN IMAGE OF
INC DEST+1 ;APPLESOFT AND THE MONITOR
BNE LCLOOP ;FROM FROM TO AVAILABLE RAM
LDA READROM ;WHEN FINISHED RESET ROM
RTS ;AND RETURN
INSTALSW JSR MSGOUT ;PRINT RETURN ($8D) AND CTL-D
HEX 8D04 ;TO GETT UNCLE DOS'S ATTENTION
ASC "BLOAD SPLIT.PERS"
HEX 8D00 ;PRINT RETURN, MARK MESSAGE END
RTS ;ALL DONE--CONTINUE
ZPP1SAVE LDA #$00 ;MOVE PAGE ZERO AND PAGE 1
STA DEST ;TO $8000 TO $81FF
LDA #$80 ;USING THE APPLE'S BUILT IN
STA DEST+1 ;MOVE ROUTINE AT $FE2C
LDA #$00
STA STARTSOU
STA STARTSOU+1
LDA #$FF
STA ENDSOU
LDA #$01
STA ENDSOU+1
JSR MOVE
LDX $49 ;GET STACK POINTER SAVED AT $101
INX ;IT WILL BE INCREMENTED BEFORE THE
LDA STATUS ;STATUS BYTE IS PULLED ON TO IT SO
STA $8100,X ;PUT THE STATUS BYTE WHERE NEEDED
;NOTE : CAN'T BE DONE IN ZPSETUP
RTS
ZPP1COPY STA SETALTZP ;TURN ON AUX TOP 16 + PG0-1
LDX #$00 ;BUILD A COUPLE OF SIMPLE
PUTZPG LDA $8000,X ;LOOPS TO TAKE THE PAGES
STA $00,X ;STORED AT $8000-$81FF AND
DEX ;PUT THEN IN ALT RAM PG 0-1
BNE PUTZPG ;--EASIER TO DO THIS THAN
PUTPG1 LDA $8100,X ;SET UP "MOVE" ROUTINE
STA $100,X
DEX
BNE PUTPG1
LDA READROM
STA SETSTDZP
RTS
MAINLOAD LDA #$00 ;AUXMOVE IS SET UP MUCH LIKE
STA DEST ;THE MOVE ROUTINE
STA STARTSOU
LDA #$02
STA DEST+1
STA STARTSOU+1
LDA #$FF
STA ENDSOU
LDA #$BF
STA ENDSOU+1
SEC ;SIGNAL MAIN TO AUX MOVE
JSR AUXMOVE ;PROVIDED BY APPLE AT $C311
RTS
* +-----------------------------------------+
* | NOTE: THE CODE IN CKBIGMEM BELOW |
* | IS FOR EXAMPLE. CODE IN THIS |
* | AREA MUST BE SPECIFIC FOR A GIVEN |
* | TYPE OF RAM CARD IN CONSIDERATION |
* | OF ITS SIZE, SWITCHING PROCEDURE |
* | AND RAM ARCHITECTURE. THE CODE |
* | HERE IS FOR AN A.E. MEMORY MASTER. |
* +-----------------------------------------+
CKBIGMEM LDA RDWRTLC ;MAKE SURE WE READ AND WRITE
LDA RDWRTLC ;THE LC (UPPER 16K) AREA
STA SETALTZP ;IN THE ALTERNATE RAM
LDA IDBYTE ;GET A BYTE TO TEST
STA $C05E ;THESE INSTRUCTION ARE THE SWITCH
STA $C05F ;TO CHANGE MEMORY ALT 64K
CMP IDBYTE ;IS IT THE SAME AS BEFORE WE HIT
;THE MEMORY MASTER ALTERNATE RAM
;BANK SWITCH SEQUENCE?
BNE PREPLUS ;IF NET WE HAVE ADDITIONAL BANK
;BUT IF SO WE STILL DON'T KNOW SO
INC IDBYTE ;WE CHANGE THE IDBYTE AND THEN
STA $C05E ;WE HIT THE MEMORY MASTER BANK
STA $C05F ;SWITCH SEQUENCE. IF OUR COMPARISON
CMP IDBYTE ;SAYS ACC=IDBYTE WE HAVE AN EXTRA
;BANK TO SETUP. IF NOT WE GIVE
STA SETSTDZP ;UP, TURN OFF THE ALT. UPPER RAM
LDA READROM ;AND SELECT ROM, LEAVING $80 IN
RTS ;THE APPLEID WHEN WE RETURN
PREPLUS STA $C05E ;AESTHETIC CONSIDERATION-IT DOESN'T
STA $C05F ;REALLY MATTER WHICH IS "2" OR "3"
PLUSBANK STA IDBYTE ;CORRECT IDBYTE
LDA READROM ;READ ROM AND TURN OFF
STA SETSTDZP ;THE ALTERNATE RAM
LDA #$81
STA APPLEID ;SET APPLEID BYTE TO HOLD $81
RTS
*
*
*THE ANDY HERTZFELD STRING PRINTING ROUTINE FROM
*CALL - A.P.P.L.E
*
MSGOUT PLA ;FETCH THE RETURN ADDRESSES
STA TEMP ;FROM THE 6502'S STACK
PLA ;AND SAVE THEM WHERE WE CAN
STA TEMP+1 ;GET TO THEM LATER
LDY #0 ;CLEAR THE STRING INDEX AND
LOOP INC TEMP ;INCREMENT RETURN ADDRESS FOR
BNE SKIPADD ;EACH CHR+HI BYTE IF TEMP=0
INC TEMP+1 ;FOR "BOUNDARY" CROSSINGS
SKIPADD LDA (TEMP),Y ;GET THE NEXST CHAR FOR PRINTING
BEQ MSGRTS ;AND IF CHR=0 WE EXIT
ORA #$80 ;TURN ON HIGH BIT FOR COUT
JSR COUT ;AND PRINT VIA MONITOR ROUTINE
JMP LOOP ;GO BACK FOR NEXT CHARACTER
MSGRTS LDA TEMP+1 ;EXITING SO RECOVER THE
PHA ;ADJUSTED RETURN ADDRESS
LDA TEMP ;AND PUT IT ON THE STACK
PHA ;FOR RETURN PAST END OF STRING
RTS ;TO NEXT PROGRAM INSTRUCTION
*
*
INTRO JSR BELL ;TOOT THE HORN
JSR HOME ; AND CLEAR THE SCREEN
JSR MSGOUT ;GIVE CRIDIT WHERE
HEX 8D ;CREDIT IS DUE
ASC "APPLE SPLIT PERSONALITY"
HEX 8D
ASC "BY JOHN A. OAKEY"
HEX 8D
ASC "COPYRIGHT (C)1986"
HEX 8D
ASC "BY MICROSPARC, INC."
HEX 8D
ASC "CONCORD, MA 01742"
HEX 8D8D8D
ASC "TWO MOMENTS PLEASE."
HEX 8D8D00606F616B6579
ORG $2000
BankSel EQU $C073
MaxMem EQU 16 ;Maximum desired, 3 megabytes in this example
*Write bank number to each bank
STA $C009 ;Store in alternate zero page
LDY #$7F ;Valid banks range $00 to $7F
FindBanks
STY BankSel ;Go through each bank
STY $00 ;Store the bank number
TYA
EOR #$FF
STA $01 ;Second self-check
DEY
BPL FindBanks
*Read them back to find valid banks and save in table
LDA #$00
TAY
TAX
FindThem
STY BankSel ;Search through all banks
STA BankSel+3
CPY $00
BNE NotOne ;Check bank number
TYA
EOR #$FF
CMP $01 ;Check second double-check
BNE NotOne
INX
TYA ;Found valid bank-save in table
STA BankTbl,X
CPX #MaxMem ;Found all banks to be used
BCS Done
NotOne
INY ;Go through all valid bank ranges
BPL FindThem
*Ending routine
Done
LDA #$00 ;Reset to video bank
STA BankSel
STA $C008
STX BankTbl ;Size of Ram card
LDA #$FF
STA BankTbl+1,X ;Mark end of table
RTS
BankTbl DS MaxMem+2