mirror of
https://github.com/livingcomputermuseum/Darkstar.git
synced 2026-03-07 11:50:02 +00:00
39 lines
29 KiB
Plaintext
39 lines
29 KiB
Plaintext
head 1.1;
|
|
branch 1.1.1;
|
|
access ;
|
|
symbols start:1.1.1.1 Xerox:1.1.1;
|
|
locks ; strict;
|
|
comment @# @;
|
|
|
|
|
|
1.1
|
|
date 2001.08.12.22.22.18; author freier; state Exp;
|
|
branches 1.1.1.1;
|
|
next ;
|
|
|
|
1.1.1.1
|
|
date 2001.08.12.22.22.18; author freier; state Exp;
|
|
branches ;
|
|
next ;
|
|
|
|
|
|
desc
|
|
@@
|
|
|
|
|
|
|
|
1.1
|
|
log
|
|
@Initial revision
|
|
@
|
|
text
|
|
@{
|
|
File name: BandBLT.mc
|
|
Description: Mesa byte-code to convert bandlist entries to bits in a bandbuffer
|
|
Author: Patrick PXO
|
|
Created: June 10, 1980 2:48 PM
|
|
LOG
|
|
CRF, 14-Jul-86 16:28:47: Treat trapezoid band list entries as NOPs; also
|
|
deleted remains of old bitmap band list entry code.
|
|
Dennis DEG , 1-Sep-84 19:07:43: Add copyright notice.
|
|
AEF AEF , 18-Nov-83 11:22:39: Added click to Rectangle and Character because of register conflict with Xfer.
|
|
AXD , 16-Aug-83 13:49:04: RRot1 uPPMask because of new PSB format.
|
|
AEF AEF , 2-Aug-83 16:35:44: Change at NoCross3+1 for 32-bit comtrol links changes.
|
|
Jim JXF , February 11, 1981 11:05 AM: use symbol to call SavebbRegs.
|
|
PXO , March 19, 1981 8:55 PM: total re-work of levels, inks, and leftovers.
|
|
PXO , March 23, 1981 4:17 PM: Changed spellings of all occurrences of "uregMumble" to "uMumble."
|
|
PXO , April 20, 1981 5:35 PM: Change a "reReadRets" to "ReadRets."
|
|
PXO , April 21, 1981 4:48 PM: Fix comparison when deciding whether to switch lists on finding SetLevel bandlist entry.
|
|
Jim JXF , August 20, 1981 3:47 PM: changes for new assembler.
|
|
JGS , November 16, 1981 12:17 PM: new instruction set.
|
|
CRF, July 6, 1982 3:04 PM: pass source WORDS per line instead of BITS per
|
|
line to BandBLTBBInit; skip objects starting beyond the scan line end.
|
|
CRF, 8-Oct-82 9:27:05: restore uVirtPage when skipping objects beyond the
|
|
scan line end.
|
|
}
|
|
|
|
{ Copyright (C) 1980, 1981, 1982, 1983 by Xerox Corporation. All rights reserved.}
|
|
|
|
|
|
@@BandBLT:
|
|
ULsave ¬ L, L2 ¬ Savebb.BANDBLT, c1, at[3,10,ESC8n];
|
|
{
|
|
Save R and RH registers.
|
|
}
|
|
rhType ¬ Type.LSEP{For BITBLT}, CALL[SavebbRegs] ,c2;
|
|
|
|
{SavebbRegs subroutine here for 2-2/3 clicks ,c3-c1;}
|
|
{
|
|
SavebbRegs returns to BitBlt code that checks the stack pointer to determine
|
|
whether we're returning from an interrupt. If so, control stays with BitBlt. If not,
|
|
this is a normal entry to BandBLT, and control resumes here.
|
|
}
|
|
|
|
{
|
|
The top stack entry is an MDS-relative pointer to the parameter block for this byte-code; we first fetch the parameters into
|
|
U-registers. The parameters wind up butted up against the high end of a 16-member bank of U-regs, i.e., in registers ...C, D,
|
|
E, F (MOD 10). The exception is the last parameter word, which is left in an R-register and never stored into a U-register; thus
|
|
we have parameter words 1 through n-1 loaded into U-registers as follows:
|
|
Parameter Word U-reg address (MOD 10)
|
|
1 F - (n - 2)
|
|
2 F - (n - 3)
|
|
3 F - (n - 4)
|
|
... ...
|
|
n-3 F - 2
|
|
n-2 F - 1
|
|
n-1 F
|
|
n not stored
|
|
}
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This call to Read will translate the parameter block virtual address to real, leaving the result in rhReadP,,rReadP, and return the
|
|
first word of the block in rTemp, in preparation for the loop below which loads the parameter blocks into U-registers.
|
|
}
|
|
|
|
NormalEntry:
|
|
rUindex ¬ Arg0, push, pCall2 ,c1, at[hbs.1, 10, HowBigStack];
|
|
rReadV ¬ STK, fXpop, fZpop ,c2, at[Read.0, 10];
|
|
rhReadV ¬ TOS LRot0{rhMDS}, CALL[Read] ,c3;
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This loop loads the parameters from memory into the U-registers; note that the U-register is loaded with the contents of the
|
|
R-register rTemp, which holds the word fetched in the previous pass through the loop. This is why the last parameter word
|
|
ends up not getting stored in a U-register (see the code at label suDone).
|
|
}
|
|
suLoop:
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1] ,c1, at[Read.0, 10, ReadRets];
|
|
Ybus ¬ rUindex, rUindex ¬ rUindex + 1, AltUaddr, NibCarryBr, CancelPgCross[$] ,c2;
|
|
uyBlk ¬ rTemp, rTemp ¬ MD, BRANCH[suLoop, suDone] ,c3;
|
|
|
|
{
|
|
End of parameter loop. Leave last parameter word in rTemp for subroutine PageNumToPtr. This code assumes that the last
|
|
parameter word is the page number of the caller's inkwells.
|
|
}
|
|
suDone:
|
|
rScratch ¬ RRot1 uPPMask{7000: forward, disjoint, disjointItems, gray, null, null}, pCall2{last parameter word (rTemp) is ink page #} ,c1, at[Read.1, 10, suLoop];
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Save the virtual address of the caller's gray blocks ("inkwells"). This page contains inkwells at 0-MOD-10 addresses. We
|
|
convert the virtual page number to a LONG POINTER and store it in uInkHigh,,uInkLow. Note that only the low 8 bits of
|
|
uInkHigh are valid; this U-register will later be loaded into an RH-register.
|
|
We also zero the stack pointer here. The reason for this is as follows: When BandBLT returns, it leaves a LONG POINTER on the
|
|
stack; this pointer is either the address of the end-of-band entry causing the return or , in the case of end-of-band, NIL. Thus the
|
|
stack pointer must be set to 2. The problem is that it's very hard to fit "stackP ¬ 2" into the return sequence code, whereas two
|
|
"pushes" fit nicely. This only works, however, if the stack pointer is known to be zero. BITBLT zeroes the stack pointer, but there
|
|
is no guarantee that a call to BandBLT will ever call BITBLT. Note also that this code assumes that BITBLT can handle being called
|
|
with stackP equal to zero.
|
|
}
|
|
|
|
uCurrentFlags ¬ rScratch{7000}, stackP ¬ rScratch{0: low nybble of 7000}, CALL[PageNumToPtr] ,c2, at[PageNumToPtr.0, 10];
|
|
|
|
uInkHigh ¬ rTemp ,c2, at[PageNumToPtr.0, 10, PageNumToPtrRets];
|
|
uInkLow ¬ rJunk, pCall2 ,c3;
|
|
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This code takes the input parameter uBitmapMemPage, the virtual page number of the memory containing
|
|
the font rasters (as opposed to the font pointers and font displacements), and saves it as a LONG POINTER (virtual)
|
|
in uBitmapMemHigh,,uBitmapMemLow. Subsequently, when processing characters, this address will be indexed
|
|
by a character's font displacement value to find the appropriate rasters. Note that only the low 8 bits of uBitmapMemHigh
|
|
are valid; this U-register will later be loaded into an RH-register.
|
|
}
|
|
rTemp ¬ uBitmapMemPage, CALL[PageNumToPtr] ,c1, at[PageNumToPtr.1, 10];
|
|
|
|
uBitmapMemHigh ¬ rTemp ,c1, at[PageNumToPtr.1, 10, PageNumToPtrRets];
|
|
uBitmapMemLow ¬ rJunk, pCall2 ,c2;
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This call to reRead translates the virtual page number of the Font Pointer Table (uFPTPage) to a real address,
|
|
which is stored in uFPTHigh,,uFPTLow. Subsequently, when processing characters, this table will be indexed
|
|
by a character's Font value to find a pointer to its Font Vector Table.
|
|
|
|
This code also loads garbage into uSaveLOwritePHigh,,uSaveLOwritePLow, the pointer to
|
|
the output leftover list. The reason for doing this is to set up for when we need to
|
|
write a leftover. The way it's done is to take a known safe physical address (the
|
|
address of the Font Pointer Table), OR it with 0FF, and save the result in
|
|
uSaveLOwritePHigh,,uSaveLOwritePLow. This will cause a page-cross and a remap
|
|
the first time an attempt is made to write a leftover; the virtual page number we
|
|
use then will be uLOwriteV, the output leftover list page number.
|
|
}
|
|
rTemp ¬ uFPTPage, CALL[reRead] ,c3, at[reRead.8, 10];
|
|
|
|
uFPTLow ¬ rReadP ,c1, at[reRead.8, 10, ReadRets];
|
|
|
|
{
|
|
The low 8 bits of uSaveLOwritePLow are turned on to force a page-cross and remap the very first time an attempt is made to write
|
|
a leftover list entry.
|
|
}
|
|
rReadP ¬ rReadP or 0FF ,c2;
|
|
uSaveLOwritePLow ¬ rReadP ,c3;
|
|
|
|
rReadP ¬ rhReadP ,c1;
|
|
uFPTHigh ¬ rReadP ,c2;
|
|
uSaveLOwritePHigh ¬ rReadP ,c3;
|
|
|
|
uOtherFlags ¬ rScratch{7000: forward, disjoint, disjointItems, gray, null, null} ,c1;
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This call to Read translates the virtual address (in uBLreadHigh,,uBLreadLow) of the input bandlist to a real address, which
|
|
is saved in uOtherListHigh,,uOtherListLow.
|
|
}
|
|
{L2 = 5 is used for call to Read and for call to TempRot12.}
|
|
rReadV ¬ uBLreadLow, pCall2 ,c2;
|
|
rhReadV ¬ uBLreadHigh, CALL[Read] ,c3, at[Read.5, 10];
|
|
|
|
uOtherVirtPage ¬ rJunk {uVirtPage}, ,c1, at[Read.5, 10, ReadRets];
|
|
rTemp ¬ SetInk, L2Disp, CALL[TempRot12] ,c2;
|
|
{rTemp ¬ rTemp LRot12 {Set Ink 0, flags 0} ,c3;}
|
|
|
|
uLastInkLOwritten ¬ rTemp{Set Ink 0, flags 0} ,c1, at[Rot12.5, 10, Rot12Ret];
|
|
uCurrentInkCmd ¬ rTemp{Set Ink 0, flags 0} ,c2;
|
|
uOtherInkCmd ¬ rTemp{Set Ink 0, flags 0} ,c3;
|
|
|
|
uOtherListLow ¬ rReadP ,c1;
|
|
rReadP ¬ rhReadP ,c2;
|
|
uOtherListHigh ¬ rReadP ,c3;
|
|
|
|
rTemp ¬ uInkLow ,c1;
|
|
uCurrentInkwell ¬ rTemp ,c2;
|
|
uOtherInkwell ¬ rTemp, L2 ¬ Rot12.2 ,c3;
|
|
|
|
rTemp ¬ SetLevel, L2Disp, CALL[TempRot12] ,c1;
|
|
{rTemp ¬ rTemp LRot12{Set level 0} ,c2;}
|
|
uCurrentLevelCmd ¬ rTemp{Set level 0}, pCall2 ,c3, at[Rot12.2, 10, Rot12Ret];
|
|
|
|
uOtherLevelCmd ¬ rTemp{Set level 0}, L3 ¬ LOlist ,c1, at[reRead.3, 10];
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
At this point, we're ready to start processing the input leftover list: all the necessary housekeeping has been done, including
|
|
setting L3 to indicate that we're now in the leftover list. (When an end-of-band is found in this list, we'll start processing the
|
|
input bandlist, and L3 will be set to indicate that.) The call to reRead translates uLOreadV, the virtual page number of the input
|
|
leftover list, to a real address in rhReadP,,rReadP, and returns in rTemp the first word in that list. We then decide whether that
|
|
word indicates a character, rectangle, etc., and then begin the real processing. Switch is the label to which control is passed
|
|
when we're done handling a character, rectangle, etc., and need to read the next item in the list currently being read.
|
|
}
|
|
uLastLevelLOwritten ¬ rTemp{Set level 0} ,c2;
|
|
rTemp ¬ uLOreadV, CALL[reRead] ,c3;
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
If the sign bit is off, then this entry is a character descriptor (or a character leftover, if we're in the leftover list). If the sign bit is on,
|
|
a dispatch is needed to determine whether the entry is a rectangle, command, etc.
|
|
}
|
|
|
|
Switch:
|
|
[] ¬ rTemp, NegBr ,c1, at[reRead.3, 10, ReadRets];
|
|
Xbus ¬ rTemp BLentryTypeRot, XDisp, BRANCH[Char, $] ,c2;
|
|
{Noop, }ListFlagDisp, BLentryDISP[EntryType] ,c3;
|
|
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
End-of-page.
|
|
End-of-page command found in leftover list should probably be an error, but we'll simply clean up and return.
|
|
}
|
|
PageEnd:
|
|
TOS ¬ Nil, CANCELBR[$] ,c1, at[EndOfPage, 10, EntryType];
|
|
uStack2 ¬ Nil, pCall0 ,c2;
|
|
stackP ¬ 2, CALL[RestoreRandRHRegs] ,c3, at[restore.BandBLT, 10];
|
|
|
|
{
|
|
End-of-band code also returns here from RestoreRandRHRegs.
|
|
}
|
|
Noop ,c2, at[restore.BandBLT, 10, RestoreCallers];
|
|
Noop, GOTO[BBExit] ,c3;
|
|
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
End-of-band -- find out which list we're in.
|
|
}
|
|
BandEnd:
|
|
Noop, BRANCH[eobLO, $] ,c1, at[EndOfBand, 10, EntryType];
|
|
{
|
|
End-of-band command found in bandlist; save bandlist pointer for building the return value later.
|
|
}
|
|
rJunk ¬ uVirtPage ,c2;
|
|
uRetPage ¬ rJunk ,c3;
|
|
|
|
uRetWord ¬ rReadP, GOTO[eobLO] ,c1;
|
|
eobLO:
|
|
Xbus ¬ uOtherLevelCmd, XHDisp ,c2;
|
|
uCurrentLevelCmd ¬ ~rJunk xor rJunk, BRANCH[$, seenEob, 1] ,c3;
|
|
|
|
rTemp ¬ rReadP, ListFlagDisp, GOTO[MoreChangeLists] ,c1;
|
|
|
|
seenEob:
|
|
uRect2 ¬ rTemp{word to be written}, pCall1 ,c1;
|
|
rReadP ¬ uRetWord{writeLO had better not touch} ,c2, at[writeLO.2, 10];
|
|
rJunk ¬ OneWordLO{single-word leftover list entry}, CALL[writeLO] ,c3;
|
|
|
|
{
|
|
Here we use uRetPage (the virtual page number saved upon finding an end-of-band while reading the bandlist) and uRetWord
|
|
(the real address used to read in the bandlist) to construct the virtual address of the last word read from the bandlist. This is the
|
|
value returned by this byte-code.
|
|
The purpose of the two "pushes" is to set stackP to 2; stackP is known to be zero since the init sequence zeroes it, as does every
|
|
call to BITBLT.
|
|
}
|
|
push, TOS ¬ uRetPage ,c1, at[writeLO.2, 10, writeLORets];
|
|
push, TOS ¬ TOS - 1{current virtual page number} ,c2;
|
|
rhMDS ¬ TOS ¬ TOS LRot8 ,c3;
|
|
|
|
{
|
|
This instruction sets TOS to the low 16 bits of the virtual address, getting the high byte from TOS and the low byte from rReadP.
|
|
We don't really want to read memory; we just want the side effects of the "MAR ¬." The "Map ¬" clause is included to cause the
|
|
read to be from the Map, rather than from real memory. This avoids reading random, possibly non-existent, real memory. Note that
|
|
this click may be aborted and re-executed if rhMDS is zero; the processor thinks it needs to make us wait for access to the display
|
|
bank.
|
|
}
|
|
TOS ¬ MAR ¬ Map ¬ [rhMDS, rReadP + 0] ,c1;
|
|
STK ¬ TOS, pCall0 ,c2;
|
|
TOS ¬ rhMDS, CALL[RestoreRandRHRegs]{Returns to the end-of-page code} ,c3, at[restore.BandBLT, 10];
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------}
|
|
|
|
SetLevel:
|
|
rJunk ¬ uOtherLevelCmd, CANCELBR[$] ,c1, at[SetLevel, 10, EntryType];
|
|
[] ¬ rTemp - rJunk - 1, PgCarryBr ,c2;
|
|
uCurrentLevelCmd ¬ rTemp{new level cmd}, BRANCH[$, ChangeLists] ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2, GOTO[GetNextWordc2] ,c1;
|
|
|
|
|
|
|
|
{
|
|
This code is used to switch between the bandlist and leftover list. It first increments rhReadP,,rReadP (remapping if necessary);
|
|
this is to avoid repeatedly reading SetLevel bandlist entries. It then swaps rhReadP,,rReadP with uOtherListHigh,,uOtherListLow,
|
|
swaps uVirtPage with uOtherListVirtPage, swaps uCurrentInkwell with uOtherInkwell, swaps uCurrentLevelCmd with uOtherLevelCmd, swaps uCurrentInkCmd with uOtherInkCmd, swaps uCurrentFlags with uOtherFlags, and toggles L3 from LOlist <--> BL.
|
|
}
|
|
|
|
ChangeLists:
|
|
rReadP ¬ rReadP + 1, PgCarryBr ,c1;
|
|
{Noop, }pCall2, BRANCH[NoCross1, $] ,c2;
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3, at[reRead.D, 10];
|
|
NoCross1:
|
|
Noop ,c3;
|
|
|
|
rTemp ¬ rReadP, ListFlagDisp ,c1, at[reRead.D, 10, ReadRets];
|
|
MoreChangeLists:
|
|
rReadP ¬ rhReadP, BRANCH[InLOlist, InBandList] ,c2;
|
|
InBandList:
|
|
L3 ¬ LOlist ,c3;
|
|
|
|
rhReadP ¬ uOtherListHigh, GOTO[Contin] ,c1;
|
|
InLOlist:
|
|
L3 ¬ BL ,c3;
|
|
|
|
rhReadP ¬ uOtherListHigh ,c1;
|
|
Contin:
|
|
uOtherListHigh ¬ rReadP ,c2;
|
|
rReadP ¬ uOtherListLow ,c3;
|
|
|
|
uOtherListLow ¬ rTemp ,c1;
|
|
{-------}
|
|
rTemp ¬ uCurrentInkwell ,c2;
|
|
rDest ¬ uOtherInkwell ,c3;
|
|
|
|
uOtherInkwell ¬ rTemp ,c1;
|
|
uCurrentInkwell ¬ rDest ,c2;
|
|
{-------}
|
|
rTemp ¬ uCurrentLevelCmd ,c3;
|
|
|
|
rDest ¬ uOtherLevelCmd ,c1;
|
|
uOtherLevelCmd ¬ rTemp ,c2;
|
|
uCurrentLevelCmd ¬ rDest ,c3;
|
|
{-------}
|
|
|
|
rTemp ¬ uCurrentInkCmd ,c1;
|
|
rDest ¬ uOtherInkCmd ,c2;
|
|
uOtherInkCmd ¬ rTemp ,c3;
|
|
|
|
uCurrentInkCmd ¬ rDest ,c1;
|
|
{-------}
|
|
rTemp ¬ uCurrentFlags ,c2;
|
|
rDest ¬ uOtherFlags ,c3;
|
|
|
|
uOtherFlags ¬ rTemp ,c1;
|
|
uCurrentFlags ¬ rDest ,c2;
|
|
{-------}
|
|
rTemp ¬ uVirtPage ,c3;
|
|
|
|
rDest ¬ uOtherVirtPage ,c1;
|
|
uOtherVirtPage ¬ rTemp ,c2;
|
|
uVirtPage ¬ rDest ,c3;
|
|
|
|
MAR ¬ [rhReadP, rReadP + 0], GOTO[GetNextWordc2] ,c1;
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------}
|
|
|
|
SetInk:
|
|
uCurrentInkCmd ¬ rTemp, CANCELBR[$] ,c1, at[SetInk, 10, EntryType];
|
|
rJunk ¬ rTemp and 00FF{new inkwell number} ,c2;
|
|
rTemp ¬ rTemp LRot8 ,c3;
|
|
|
|
rTemp ¬ rTemp and 0E{bitblt srcfunc,,dstfunc,,0} ,c1;
|
|
rTemp ¬ rTemp or 70{forward(0), disjoint(1), disjointItems(1), gray(1)} ,c2;
|
|
rTemp ¬ rTemp LRot8 ,c3;
|
|
|
|
uCurrentFlags ¬ rTemp ,c1;
|
|
rJunk ¬ rJunk LRot4{new inkwell number * 16} ,c2;
|
|
rTemp ¬ uInkLow ,c3;
|
|
|
|
rJunk ¬ rJunk + rTemp{inks must all live within same 64-K virtual bank} ,c1;
|
|
uCurrentInkwell ¬ rJunk ,c2;
|
|
Noop, GOTO[GetNextWord] ,c3;
|
|
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Rulette entry.
|
|
}
|
|
Roulette:
|
|
rYloc ¬ ~000F, CANCELBR[$] ,c1, at[Roulette, 10, EntryType];
|
|
rYloc ¬ rYloc LRot12{0FFF} ,c2;
|
|
rYloc ¬ rTemp and rYloc ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2 ,c1;
|
|
uRect2 ¬ 0{no leftover to write}, PgCrBRANCH[NoCross0, $] ,c2, at[reRead.E, 10];
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
NoCross0:
|
|
rTemp ¬ MD ,c3;
|
|
|
|
{L2 = 3 is used for call to SaveReadPtr and for call to TempRot12.}
|
|
Q ¬ rTemp and 0F {xloc}, pCall2 ,c1, at[reRead.E, 10, ReadRets];
|
|
rTemp ¬ rTemp xor Q, CALL[SaveReadPtr] ,c2, at[SaveReadPtr.3, 10];
|
|
|
|
rNlines ¬ 1, L2Disp, CALL[TempRot12] ,c2, at[SaveReadPtr.3, 10, SaveReadPtrRets];
|
|
{rTemp ¬ rTemp LRot12 ,c3;}
|
|
|
|
UWidth ¬ rTemp{For BITBLT}, GOTO[RectRuletteCommon] ,c1, at[Rot12.3, 10, Rot12Ret];
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This code reads the next word in the current list and passes control to label Switch, where a dispatch on the entry type is
|
|
executed. The fact that this code is "at[0F, 10, EntryType]" means that a bandlist entry with type field equal to 0F is specifically
|
|
ignored, with no leftover being generated.
|
|
}
|
|
GetNextWord:
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2, CANCELBR[$] ,c1, at[Nop, 10, EntryType];
|
|
GetNextWordc2:
|
|
Noop, PgCrBRANCH[GetNextWordc3, $] ,c2, at[reRead.3, 10];
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
GetNextWordc3:
|
|
rTemp ¬ MD, GOTO[Switch] ,c3;
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Rectangle entry found. Cancel the dispatch set up for command entries, save the first word of the rectangle descriptor, and
|
|
process the rectangle.
|
|
}
|
|
Rectangle:
|
|
rYloc ¬ rTemp, CANCELBR[$] ,c1, at[Rectangle, 10, EntryType];
|
|
uRect0 ¬ rTemp ,c2;
|
|
Noop ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2, ,c1;
|
|
Noop, PgCrBRANCH[NoCross2, $] ,c2, at[reRead.B, 10];
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
NoCross2:
|
|
rTemp ¬ MD ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2 ,c1, at[reRead.B, 10, ReadRets];
|
|
uRect1 ¬ rTemp, rYheight ¬ rTemp, PgCrBRANCH[NoCross3, $] ,c2, at[reRead.4, 10];
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
NoCross3:
|
|
rTemp ¬ MD ,c3;
|
|
|
|
{
|
|
Break the rectangle entry down into its individual parts.
|
|
}
|
|
Q ¬ u1FFF ,c1, at[reRead.4, 10, ReadRets];
|
|
rYloc ¬ rYloc and Q ,c2;
|
|
Noop ,c3;
|
|
|
|
pCall2 ,c1;
|
|
|
|
{
|
|
Save the current real bandlist/leftover list pointer. Also save the bandlist/leftover list virtual page number. This is not necessary
|
|
for rectangles, since they involve no calls to Read or reRead, but it's done here so that uVirtPage can be restored, after processing
|
|
a character, with one piece of code.
|
|
}
|
|
Q ¬ rTemp and 0F {xloc}, CALL[SaveReadPtr] ,c2, at[SaveReadPtr.0, 10];
|
|
|
|
rTemp ¬ rTemp and ~0F ,c2, at[SaveReadPtr.0, 10, SaveReadPtrRets];
|
|
rXwidth ¬ rTemp LRot12 ,c3;
|
|
|
|
rTemp ¬ Bandwidth - Q{lines available in band} ,c1;
|
|
Ybus ¬ rTemp - rXwidth, NegBr ,c2;
|
|
UWidth ¬ rYheight{For BITBLT}, BRANCH[$, Neg0] ,c3;
|
|
|
|
rNlines ¬ rXwidth, GOTO[skip] ,c1;
|
|
Neg0:
|
|
rNlines ¬ rTemp, GOTO[skip] ,c1;
|
|
skip:
|
|
rXwidth ¬ rXwidth - rNlines ,c2;
|
|
rTemp ¬ rXwidth LRot4 ,c3;
|
|
|
|
uRect2 ¬ rTemp, rTemp ¬ Q {xloc} ,c1;
|
|
rTemp ¬ rTemp LRot8 ,c2;
|
|
rTemp ¬ rTemp or 000F {gray brick, 16 lines high} ,c3;
|
|
|
|
UGray ¬ rTemp{For BITBLT} ,c1;
|
|
RectRuletteCommon:
|
|
UHeight ¬ rNlines{For BITBLT} ,c2;
|
|
rTemp ¬ rYloc and 000F ,c3;
|
|
|
|
USrcBit ¬ rTemp{For BITBLT} ,c1;
|
|
rTemp ¬ uCurrentFlags ,c2;
|
|
UFlags ¬ rTemp{For BITBLT} ,c3;
|
|
|
|
rTemp ¬ uInkHigh ,c1;
|
|
UrhVS ¬ rTemp{For BITBLT} ,c2;
|
|
rTemp ¬ uCurrentInkwell ,c3;
|
|
|
|
rTemp ¬ rTemp + Q ,c1;
|
|
USrcVALo ¬ rTemp{For BITBLT} ,c2;
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
This is where the processing for characters merges with the processing of rectangles.
|
|
}
|
|
{
|
|
Compute the destination address; the rectangle's word offset into the band buffer is xloc*256 + yloc/16. Its bit offset into this
|
|
word is yloc MOD 16. If the origin of the rectangle, rulette, or character is beyond the end of the scan line, skip it (i.e. clip it).
|
|
[Rectangles, rulettes, or characters starting within the scan line but extending past the end are clipped by the bit transfer
|
|
routines in BandBLTBBLoops.]
|
|
}
|
|
RectCharCommon:
|
|
rDest ¬ Q{xloc} ,c3;
|
|
|
|
rDest ¬ rDest LRot8{xloc * 256 words per scanline} ,c1;
|
|
rTemp ¬ uBandBufLow ,c2;
|
|
rDest ¬ rDest + rTemp{not allowed to cross banks} ,c3;
|
|
|
|
TOS ¬ rYloc and ~0F ,c1;
|
|
UDstBit ¬ rYloc xor TOS{For BITBLT}, L2 ¬ Rot12.6 ,c2;
|
|
rTemp ¬ TOS, L2Disp, CALL[TempRot12] ,c3;
|
|
|
|
{rTemp ¬ rTemp LRot12 ,c1;}
|
|
rDest ¬ rDest + rTemp, PgCarryBr ,c2, at[Rot12.6, 10, Rot12Ret];
|
|
UDstVALo ¬ rDest{For BITBLT}, BRANCH[$, BeyondScanLineEnd] ,c3;
|
|
|
|
rTemp ¬ uBandBufHigh ,c1;
|
|
UrhVD ¬ rTemp{For BITBLT} ,c2;
|
|
L2 ¬ Rot12.8 ,c3;
|
|
|
|
rTemp ¬ 1, L2Disp, CALL[TempRot12] ,c1;
|
|
{rTemp ¬ rTemp LRot12{256*16 bits per scanline} ,c2;}
|
|
UDstBpl ¬ rTemp{For BITBLT}, ListFlagDisp ,c3, at[Rot12.8, 10, Rot12Ret];
|
|
|
|
rhType ¬ Type.LSEP{For BITBLT}, BRANCH[inLO, inBL] ,c1;
|
|
inLO:
|
|
rTemp ¬ LOlist, GOTO[saveList] ,c2;
|
|
inBL:
|
|
rTemp ¬ BL, GOTO[saveList] ,c2;
|
|
|
|
saveList:
|
|
uSaveList ¬ rTemp, GOTO[BandBLTNormEntry] {Call BITBLT} ,c3;
|
|
|
|
BitBltReturn:
|
|
Xbus ¬ uSaveList, XDisp ,c3, at[3, 8, LSEPReturn];
|
|
|
|
Xbus ¬ dtRet.L4{retnum}, pCall3, XDisp, DISP4[dT] ,c1;
|
|
rTemp ¬ uSaveVirtPage {restore uVirtPage} ,c3, at[dtRet.L4, 10, dTRets];
|
|
|
|
uVirtPage ¬ rTemp, pCall1 ,c1;
|
|
{
|
|
Rectangle or character done. Decide whether to write a leftover.
|
|
}
|
|
[] ¬ uRect2, ZeroBr ,c2, at[writeLO.1, 10];
|
|
rJunk ¬ ThreeWordLO, BRANCH[writeLO, noLO] ,c3;
|
|
|
|
BeyondScanLineEnd:
|
|
rTemp ¬ uSaveVirtPage {restore uVirtPage} ,c1;
|
|
uVirtPage ¬ rTemp, ,c2;
|
|
GOTO[noLO] ,c3;
|
|
noLO:
|
|
Noop ,c1, at[writeLO.1, 10, writeLORets];
|
|
rhReadP ¬ uSaveReadPHigh ,c2;
|
|
rReadP ¬ uSaveReadPLow, GOTO[GetNextWord] ,c3;
|
|
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
Processing for a character. Control reaches here from the code beginning at Switch upon finding a bandlist (or leftover list) entry
|
|
with the sign bit off.
|
|
}
|
|
|
|
Char:
|
|
rCC ¬ rTemp, CancelDisp[$], c3;
|
|
|
|
uChar0 ¬ rTemp, c1;
|
|
Noop, c2;
|
|
Noop, c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2 ,c1;
|
|
rFont ¬ rTemp LRot8, PgCrBRANCH[NoCross4, $] ,c2, at[reRead.C, 10];
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
NoCross4:
|
|
rTemp ¬ MD ,c3;
|
|
|
|
uChar1 ¬ rTemp, rYloc ¬ rTemp, ListFlagDisp ,c1, at[reRead.C, 10, ReadRets];
|
|
uChar2 ¬ 0, BRANCH[CharLO, CharBL] ,c2;
|
|
CharLO:
|
|
Noop ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1], pCall2 ,c1;
|
|
Q ¬ 0 {xloc}, PgCrBRANCH[NoCross5, $] ,c2, at[reRead.6, 10];
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
NoCross5:
|
|
rTemp ¬ MD ,c3;
|
|
|
|
uChar2 ¬ rTemp, rXDisp ¬ rTemp ,c1, at[reRead.6, 10, ReadRets];
|
|
Noop, GOTO[CharCom] ,c2;
|
|
|
|
CharBL:
|
|
rTemp ¬ rTemp LRot4 ,c3;
|
|
|
|
Q ¬ rTemp and 0F {xloc}, L2 ¬ Rot12.7 ,c1;
|
|
rTemp ¬ rTemp and ~000F, L2Disp, CALL[TempRot12] ,c2;
|
|
{rTemp ¬ rTemp LRot12 ,c3;}
|
|
|
|
uChar1 ¬ rTemp, rYloc ¬ rTemp ,c1, at[Rot12.7, 10, Rot12Ret];
|
|
rXDisp ¬ 0, GOTO[CharCom] ,c2;
|
|
|
|
CharCom:
|
|
rCC ¬ rCC and 00FF, pCall2 ,c3;
|
|
|
|
rFont ¬ LShift1 rFont, SE ¬ 0{2*Font}, CALL[SaveReadPtr] ,c1, at[SaveReadPtr.1, 10];
|
|
|
|
rhReadP ¬ uFPTHigh ,c1, at[SaveReadPtr.1, 10, SaveReadPtrRets];
|
|
rReadP ¬ uFPTLow ,c2;
|
|
Noop ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, rFont + 0] ,c1;
|
|
USrcBit ¬ 0{For BITBLT}{may be changed if this is a leftover char} ,c2;
|
|
rReadV ¬ MD {Font Vector Table ptr low word} ,c3;
|
|
|
|
MAR ¬ [rhReadP, rFont + 1], pCall2 ,c1;
|
|
{
|
|
Here it's assumed that Font Vector Tables (FVT's) are page-aligned, so cc can be added into the table without worrying about
|
|
carries or page-crosses.
|
|
}
|
|
rReadV ¬ rReadV + rCC, CancelPgCross[$, 0] ,c2, at[Read.2, 10];
|
|
rhReadV ¬ MD{FVT ptr high word}, CALL[Read] {get displacement from FVT} ,c3;
|
|
|
|
rReadV ¬ uBitmapMemLow ,c1, at[Read.2, 10, ReadRets];
|
|
rTemp ¬ rTemp + rTemp, CarryBr {2 * displacement} ,c2;
|
|
rCC ¬ uBitmapMemHigh, BRANCH[$, CarryFromDisp] ,c3;
|
|
|
|
Noop, GOTO[LowAdd] ,c1;
|
|
CarryFromDisp:
|
|
rCC ¬ rCC + 1, GOTO[LowAdd] ,c1;
|
|
LowAdd:
|
|
rReadV ¬ rReadV + rTemp, CarryBr ,c2;
|
|
uRasterLow ¬ rReadV, BRANCH[$, CarryFromAdd] ,c3;
|
|
|
|
{Noop, }pCall2, GOTO[SaveRh] ,c1;
|
|
CarryFromAdd:
|
|
rCC ¬ rCC + 1, pCall2, GOTO[SaveRh] ,c1;
|
|
SaveRh:
|
|
rhReadV ¬ rCC LRot0 ,c2, at[Read.7, 10];
|
|
uRasterHigh ¬ rCC, CALL[Read] {get bbdx} ,c3;
|
|
|
|
{
|
|
Since the displacement into the rasters is even, there cannot be a page-cross between bbdx and bbdy.
|
|
}
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 1] ,c1, at[Read.7, 10, ReadRets];
|
|
rTemp ¬ rTemp - rXDisp{# of lines remaining}, CancelPgCross[$, 0] ,c2;
|
|
rJunk ¬ MD{bbdy} ,c3;
|
|
|
|
rLoop ¬ Bandwidth - Q{# of lines that fit in band} ,c1;
|
|
[] ¬ rLoop - rTemp, NegBr ,c2;
|
|
UWidth ¬ rJunk{For BITBLT}{bbdy}, BRANCH[fits, tooBig] ,c3;
|
|
|
|
fits:
|
|
UHeight ¬ rTemp{For BITBLT} ,c1;
|
|
uChar2 ¬ 0{no leftover to be generated}, GOTO[cont] ,c2;
|
|
|
|
tooBig:
|
|
UHeight ¬ rLoop{For BITBLT} ,c1;
|
|
rTemp ¬ uChar2 {old xdisp} ,c2;
|
|
rTemp ¬ rTemp + rLoop {new xdisp} ,c3;
|
|
|
|
uChar2 ¬ rTemp ,c1;
|
|
Noop, GOTO[cont] ,c2;
|
|
cont:
|
|
rTemp ¬ 64 ,c3;
|
|
|
|
rTemp ¬ rTemp LRot8 {forward, disjoint, disjointItems, not gray, null, or} ,c1;
|
|
UFlags ¬ rTemp{For BITBLT} ,c2;
|
|
rTemp ¬ UWidth{bbdy} ,c3;
|
|
|
|
{
|
|
For .ac fonts, the rasters are padded to full-word boundaries. Thus we supply words per line,
|
|
not bits per line, to the bit transfer ucode.
|
|
}
|
|
|
|
rTemp ¬ rTemp + 000F ,c1;
|
|
rTemp ¬ rTemp and ~000F ,c2;
|
|
rJunk ¬ rTemp LRot12 {rTemp is used below as BITS per line} ,c3;
|
|
|
|
multTest:
|
|
[] ¬ rXDisp, ZeroBr ,c1;
|
|
USrcBpl ¬ rJunk{For BITBLT}, BRANCH[DispNonZ, DispZ] ,c2;
|
|
|
|
DispZ:
|
|
rTemp ¬ 2{bbdx & bbdy}, GOTO[AddDisp] ,c3;
|
|
{
|
|
This is a leftover character, not a new one; this code computes the address of the resumption point in the rasters.
|
|
The multiplication assumes that the multiplier and multiplicand are both 12-bit numbers. The product is accumulated in the
|
|
doubleword pair rXDisp,,Q; because there are only 12 shifts done, the result is a factor of 16 too large. Note that Q must be inverted
|
|
at the end (after which the low 4 bits of Q are 'F'), since all shifts into Q are complemented. This code was stolen from the
|
|
emulator's multiply byte-code.
|
|
}
|
|
DispNonZ:
|
|
rJunk ¬ Q {save xloc} ,c3;
|
|
|
|
Q ¬ rXDisp ,c1;
|
|
rXDisp ¬ 20 {preset to two words (bbdx and bbdy)} ,c2;
|
|
rLoop ¬ 12'd {twelve-bit multiply} ,c3;
|
|
|
|
mLoop:
|
|
[] ¬ Q and 1, NZeroBr ,c1;
|
|
rLoop ¬ rLoop - 1, ZeroBr, BRANCH[shiftOnly, shiftAndAdd] ,c2;
|
|
shiftOnly:
|
|
rXDisp ¬ DARShift1 (rXDisp + 0), BRANCH[mLoop, mDone] ,c3;
|
|
shiftAndAdd:
|
|
rXDisp ¬ DARShift1 (rXDisp + rTemp), BRANCH[mLoop, mDone] ,c3;
|
|
|
|
mDone:
|
|
rTemp ¬ ~Q {low nybble now 0F}, {0 Disp} CALL[TempRot12] ,c1;
|
|
{ rTemp ¬ rTemp LRot12 {high nybble now 0F} ,c2;}
|
|
USrcBit ¬ rTemp{For BITBLT} {BitBlt only looks at low four bits} ,c3, at[Rot12.0, 10, Rot12Ret];
|
|
|
|
rXDisp ¬ rXDisp LRot8, L2 ¬ Rot12.4 ,c1;
|
|
rLoop ¬ rXDisp and ~00FF {middle byte of word part}, L2Disp, CALL[TempRot12] ,c2;
|
|
{rTemp ¬ rTemp LRot12 {get word part of BitAddress} ,c3;}
|
|
|
|
rTemp ¬ rTemp and 00FF {low byte of word part} ,c1, at[Rot12.4, 10, Rot12Ret];
|
|
rTemp ¬ rTemp or rLoop {low word of word part} ,c2;
|
|
rXDisp ¬ rXDisp and 00FF {high byte of word part} ,c3;
|
|
|
|
Q ¬ rJunk {restore xloc}, GOTO[GetRasterAddr] ,c1;
|
|
|
|
AddDisp:
|
|
Noop ,c1;
|
|
GetRasterAddr:
|
|
rReadV ¬ uRasterLow ,c2;
|
|
rLoop ¬ uRasterHigh ,c3;
|
|
|
|
rReadV ¬ rReadV + rTemp, CarryBr ,c1;
|
|
rLoop ¬ rLoop + rXDisp, BRANCH[NoCarry0, Carry0] ,c2;
|
|
NoCarry0:
|
|
Noop, GOTO[common0] ,c3;
|
|
Carry0:
|
|
rLoop ¬ rLoop + 1, GOTO[common0] ,c3;
|
|
|
|
common0:
|
|
USrcVALo ¬ rReadV{For BITBLT} ,c1;
|
|
UrhVS ¬ rLoop{For BITBLT}, GOTO[RectCharCommon] ,c2;
|
|
|
|
|
|
{-----------------------------------------------------------------------------------------------------------------------------------------------------------------}
|
|
{ Trapezoids are unimplemented on the DLion, so they are treated as Noops.
|
|
The code below just skips over the trapezoid band list entry. This
|
|
provides backward compatibility in the sense that the client of BandBLT
|
|
can experiment to see if trapezoids are implemented by the underlying
|
|
microcode.
|
|
}
|
|
|
|
TrapezoidNOP:
|
|
rReadP ¬ MAR ¬ [rhReadP, rReadP + 0A], pCall2, CANCELBR[$] ,c1, at[Trapezoid, 10, EntryType];
|
|
Q ¬ rReadP, PgCrBRANCH[$, TPgCross] ,c2, at[reRead.9, 10];
|
|
rTemp ¬ MD, GOTO[Switch] ,c3;
|
|
|
|
TPgCross:
|
|
rTemp ¬ uVirtPage, CALL[reRead] ,c3;
|
|
|
|
rReadP ¬ MAR ¬ [rhReadP, Q + 0], pCall2, GOTO[GetNextWordc2] ,c1, at[reRead.9, 10, ReadRets];
|
|
|
|
@
|
|
|
|
|
|
1.1.1.1
|
|
log
|
|
@first add
|
|
@
|
|
text
|
|
@@
|