:IF[WithUIB]; *********************************************

TITLE[DUIB];
%
Tom Rich September 8, 1982: WithTor => WithUIB.
Ed Fiala 26 April 1982: Absorb DUIBDefs; use WithTOR conditional;
eliminate uibNotifyInterruptPage; pick up ESS changes from Tom Rich as
conditional assembly.
Villano February 26, 1981 9:32 AM changed DoInt to NotifyInterrupt
rej January 9, 1981 2:21 PM output gotcha: removed task in cursLoad;add nops in curschec
rej September 22, 1980 11:19 AM bypass gotcha on CursBitmapPtr in curs loading
rej September 22, 1980 10:02 AM update CSB cursorLoadControl with PSTORE1
rej September 22, 1980 8:53 AM IOCBscanlines ← IOCBscanlines-2
rej September 18, 1980 3:30 PM correct offset in init of cursor quad
rej September 11, 1980 3:58 PM change cursor, buttons, keys as per spec
rej August 21, 1980 10:04 AM init InterruptLine to be -1
rej August 21, 1980 9:59 AM move taskout in VSnotify - loadpage gotcha
rej August 15, 1980 3:38 PM set uibWordsPerLine and uibIOCBparms to be same reg
rej August 15, 1980 1:54 PM tempreg2 instead of 1 in scanline interrupt setup
rej July 18, 1980 9:31 AM one IOFetch16 per line cursload; flag for zero width IOCB
rej June 25, 1980 1:47 PM adjust CursY by one; sub 1 from interruptline in uibDCBdone
rej June 20, 1980 1:49 PM fix CursY problem created in previous mod
rej June 20, 1980 8:57 AM fix nocursor test in displaysetup, adjust cursY
rej June 19, 1980 2:26 PM two IOfetch16s per line for cursorload
rej June 19, 1980 12:42 PM fix field set in cursorload
rej June 17, 1980 1:24 PM zerobase fetch of cursIOCB in curs loading
rej June 17, 1980 9:41 AM wait text line before cursor load; for debug only
rej June 17, 1980 9:05 AM cursor loading - move cursorX changes to after PSTORE4
rej June 16, 1980 2:07 PM cursor field fix in loading, one IOFetch 16
rej June 16, 1980 11:38 AM set to 32 bit cursor in uibNextDCB
rej June 13, 1980 3:26 PM bypass gotcha in uibCursLoadLoop
rej June 12, 1980 5:15 PM make sure uibCSBuiStatus gets fetched before update
rej June 11, 1980 11:03 AM bypass problem in uibD0vsInterrupt
rej June 6, 1980 9:11 AM increment uibVideoBitmapPtr after last fetch
rej June 5, 1980 4:24 PM add "uibVideoUnloadPtr ← uibBufferSize" to uibDCBdone and uibCheckIOCBhead
rej June 5, 1980 10:15 AM mod for uiCSB and cursorIOCB format change
rej April 9, 1980 1:21 PM csbBase init in initcode; CursBitmapBase in curs load
rej April 9, 1980 9:12 AM fix cursor setup; finish waitscanline
rej April 8, 1980 5:05 PM setup for waitscanline
rej April 8, 1980 4:37 PM csbbase init in endfield;fix mousedelxy
rej March 27, 1980 5:08 PM zerobase
rej March 27, 1980 1:45 PM wait scanline
rej March 25, 1980 2:20 PM last IOFETCH16 covers new dcb
%
SET[uibTASKL, LSHIFT[uibTASK,4]]; *FOR DEVICE ADDRESSES

SET[uibClearAddr,0]; *OUTPUT DEVICE ADDRESSES
SET[uibDATABUFaddr,ADD[uibTASKL,1]];
SET[uibControlRegAddr,2];
SET[uibMESAregAddr,3];
SET[uibCursorPointerAddr,4];
SET[uibHTABaddr,5];
SET[uibBPREG,6];
SET[AuibCursMemAddr,7];
SET[uibCursMemAddr,ADD[uibTASKL,7]];
SET[uibOutChannelBuffAddr,ADD[uibTASKL,10]];

SET[uibDeviceIDregAddr, 0]; *INPUT DEVICE ADDRESSES
*new INPUT decodes
SET[uibInChannelBuffAddr,ADD[uibTASKL,1]];
SET[uibStatusReg1Addr, 2];
SET[uibUIBdataAddr, 3];

SET[uibFifoCommandsDispLoc, OR[LSHIFT[uibPage,10],100]];
SET[uibFifoDataTypesDispLoc, OR[LSHIFT[uibPage,10],120]];

MC[uibAllowWU,220];
*control register for init (old was 222)

MC[uiblhLinesPerField,400]; *617B this is 2 less than actual count (R<0 adds 2 more)
MC[uibrhLinesPerField,217];
MC[uibNonDisplayCount,41];*4 less than retrace time; 1 to sync; 1 for R<0; 2 not counted(int&setup)
SET[uibFifoEntriesPerScanLine,3];
MC[uibStartFifoEntryCount,SUB[uibFifoEntriesPerScanLine,2]];

MC[uibTurnOffCursor,2000];
*cursor control
MC[uibLargePositiveNumber,10000];
MC[uibCursFieldBump,40000];
MC[uibCursLinesPerFrame,42];
MC[uibCursXeven,100000];
MC[uibCursBitmapFieldOffset,200];*uibmode - 128d nibbles/field

SET[uibDisplayCSB, uibTask];
SET[uibSCBcsb, 17];
SET[uibKEYcsb, 16];
SET[uibCSBpage, 377];
SET[uibCSBbank, 0];
MC[uiblhCSBbase,LSHIFT[uibCSBpage,10]];
*uib CSB base addresses
MC[uibrhCSBbase,LSHIFT[uibDisplayCSB,4]];
MC[uiblhCSBbase1,LSHIFT[uibCSBbank,10]];
MC[uibrhCSBbase1,ADD[uibCSBbank,1]];

SET[uibMouseXcoordOffset,0];
*uib display CSB constants
SET[uibTouchOffset,2];
SET[uibCSBLineInterruptMaskOffset,4];
SET[uibD0vsInterruptMaskOffset,6];
SET[uibCSBuiStatusOffset,7];
SET[uibCursBitmapBaseOffset,10];
SET[uibCursXOffset,12];
SET[uibIOCBheadOffset,14];
SET[uibCursLoadControlOffset,15];
SET[uibBitmapBaseOffset,16];

SET[uibSCBcsbOffset, LSHIFT[SUB[uibSCBcsb,uibDisplayCSB], 4]];
SET[uibKEYcsbOffset, LSHIFT[SUB[uibKEYcsb,uibDisplayCSB], 4]];

MC[uibKeyBitsQuad0Offset,ADD[uibKEYcsbOffset,0]];
*KEY CSB constants
MC[uibKeyBitsQuad1Offset,ADD[uibKEYcsbOffset,4]];
MC[uibKeyBitsQuad2Offset,ADD[uibKEYcsbOffset,10]];
MC[uibMouseButtonWordOffset,ADD[uibKEYcsbOffset,3]];

MC[uibSCBcsbQuad0offset,ADD[uibSCBcsbOffset,0]];
*SCB CSB constants
MC[uibSCBcsbQuad1offset,ADD[uibSCBcsbOffset,4]];
MC[uibChannelIOCBbaseOffset,ADD[uibSCBcsbOffset,10]];
MC[uibSCBinterruptMaskOffset,ADD[uibSCBcsbOffset,12]];
MC[uibChannelTransferFlagsOffset,ADD[uibSCBcsbOffset,13]];
MC[uibSCBsavedQuadOffset,ADD[uibSCBcsbOffset,14]];

MC[uibInputChannelFlag,1];*flag indicates transfer type: INPUT(1), OUTPUT(0)
MC[uibExecuteChannelTransfer,100000];*flag causes transfer rather than FIFO read

MC[uibUIstatusKeyMask,
100000];*Display status masks (bits in lh byte)
MC[uibUIstatusTouchMask,
40000];*who changed
MC[uibUIstatusMouseXYMask, 20000];
MC[uibUIstatusButtonMask,
10000];

MC[uibBufferSize,377];
*buffer parameters
MC[uibBuffLessOneBlk,357];

MC[uibButtonsUp,377];

SetTask[uibTask];
*REGISTER PARAMETERS
Set[uibRbase, AND[60, uibTASKL]];
*TEMPORARY REGISTERS

RV[uibTempReg1,ADD[uibRbase,0]];
RV[uibTempReg2,ADD[uibRbase,1]];
RV[uibTempReg3,ADD[uibRbase,2]];
RV[uibTempReg4,ADD[uibRbase,3]];


*REGISTERS AND CONSTANTS USED BY UIB TASK DURING DISPLAY PERIOD
* registers 0 and 1 are also used by NotifyInterrupt
RV[uibHTAB,ADD[uibRbase,0]];
RV[uibIOCBhead,ADD[uibRbase,0]];
RV[uibVideoLoopControl,ADD[uibRbase,0]];
RV[uibCursLoadControl,ADD[uibRbase,1]];
RV[uibBitmapBase,ADD[uibRbase,2]];
RV[uibBitmapBase1,ADD[uibRbase,3]];

RV[uibIOCBlink,ADD[uibRbase,4]]; *IOCB WORD 0
RV[uibIOCBparms,ADD[uibRbase,5]]; *IOCB WORD 1
RV[uibWordsPerLine,ADD[uibRbase,5]]; *IOCB WORD 1
RV[uibVideoBitmapPtr,ADD[uibRbase,6]]; *IOCB WORD 2
RV[uibIOCBscanlines,ADD[uibRbase,7]]; *IOCB WORD 3

RV[uibScanLineNotifyMask,ADD[uibRbase,10]];
RV[uibInterruptLine,ADD[uibRbase,11]];
RV[uibCursX,ADD[uibRbase,12]];
RV[uibCursY,ADD[uibRbase,13]];

RV[uibVideoUnloadPtr,ADD[uibRbase,14]];
RV[uibVideoPtrs,ADD[uibRbase,14]];
RV[uibZeroBase,ADD[uibRbase,15]];
RV[uibScanLineCount,ADD[uibRbase,16]];
RV[uibStatusReg1,ADD[uibRbase,17]];


*REGISTERS USED BY UIB TASK DURING FIFO PERIOD
* registers 0 and 1 are also used by NotifyInterrupt
RV[uibTempReg1,ADD[uibRbase,0]];
RV[uibTempReg2,ADD[uibRbase,1]];
RV[uibUIBdata,ADD[uibRbase,2]];
RV[uibControlReg,ADD[uibRbase,3]];
RV[uibFifoEntryCount,ADD[uibRbase,3]];

RV[uibMouseButtonWord,ADD[uibRbase,4]];
RV[uibUIstatus,ADD[uibRbase,5]];
RV[uibChannelTransferFlags,ADD[uibRbase,7]];


RV[uibMouseDelXY,ADD[uibRbase,12]];

RV[uibMouseXcoord,ADD[uibRbase,10]];
RV[uibMouseYcoord,ADD[uibRbase,11]];


RV[uibTouchX,ADD[uibRbase,10]];
RV[uibTouchY,ADD[uibRbase,11]];

RV[uibQuadWord0,ADD[uibRbase,10]];
RV[uibQuadWord1,ADD[uibRbase,11]];
RV[uibQuadWord2,ADD[uibRbase,12]];
RV[uibQuadWord3,ADD[uibRbase,13]];

RV[uibScanLineNotifyMask,ADD[uibRbase,10]];
RV[uibInterruptLine,ADD[uibRbase,11]];
RV[uibD0vsInterruptMask,ADD[uibRbase,12]];
RV[uibCSBuiStatus,ADD[uibRbase,13]];

RV[uibSCBinterruptMask,ADD[uibRbase,10]];

RV[uibChannelIOCBbase,ADD[uibRbase,10]];

RV[uibChannelBuffBase,ADD[uibRbase,10]];
RV[uibChannelBuffBase1,ADD[uibRbase,11]];
RV[uibChannelBlockCnt,ADD[uibRbase,12]];
RV[uibChannelBuffPtr,ADD[uibRbase,13]];

RV[uibCSBbase,ADD[uibRbase,14]]; *BASE REGISTER PAIR
RV[uibCSBbase1,ADD[uibRbase,15]];
RV[uibScanLineCount,ADD[uibRbase,16]];
RV[uibStatusReg1,ADD[uibRbase,17]];

*REGISTERS USED DURING CURSOR LOADING

RV[uibIOCBhead,ADD[uibRbase,0]];
RV[uibCursLoadControl,ADD[uibRbase,1]];
RV[uibBitmapBase,ADD[uibRbase,2]];
RV[uibBitmapBase1,ADD[uibRbase,3]];

RV[uibCursLineCount,ADD[uibRbase,4]];
RV[uibCursZeroBase,ADD[uibRbase,5]];
RV[uibCursBitmapPtr,ADD[uibRbase,5]];

RV[uibCursBitmapBase,ADD[uibRbase,10]];
RV[uibCursBitmapBase1,ADD[uibRbase,11]];
RV[uibCursX,ADD[uibRbase,12]];
RV[uibCursY,ADD[uibRbase,13]];

RV[uibCSBbase,ADD[uibRbase,14]]; *BASE REGISTER PAIR
RV[uibCSBbase1,ADD[uibRbase,15]];
RV[uibScanLineCount,ADD[uibRbase,16]];
RV[uibStatusReg1,ADD[uibRbase,17]];
**********************************************
*INIT CODE
**********************************************
SetTask[uibTask];

uibInit:
uibControlReg ← (uibAllowWU), At[UIBInitLoc];
OUTPUT[uibControlReg,uibControlRegAddr]; *ALLOW WAKEUPS
uibCSBbase←uibrhCSBbase;
uibCSBbase←(uibCSBbase) OR (uiblhCSBbase);
uibCSBbase1←uibrhCSBbase1;
uibCSBbase1←(uibCSBbase1) OR (uiblhCSBbase1);
*set keyboard words to -1 (key up)
uibTempReg4 ← (ZERO)-1;
uibTempReg2← (ZERO)-1;
uibTempReg3 ← (ZERO)-1;
uibTempReg1 ← (ZERO)-1;
*init CSBs and KeyBits --store ones
t←uibSCBsavedQuadOffset;
PSTORE4[uibCSBbase, uibTempReg1];
t←uibKeyBitsQuad0Offset;
PSTORE4[uibCSBbase,uibTempReg1];*keys up
t←uibKeyBitsQuad1Offset;
PSTORE4[uibCSBbase,uibTempReg1];*keys up
:IF[ESSMode]; **************************************
t←uibKeyBitsQuad2Offset;
PSTORE4[uibCSBbase,uibTempReg1];*keys up
:ENDIF; ********************************************
PSTORE4[uibCSBbase,uibTempReg1,uibMouseXcoordOffset];*no touch; mouse at origin
*init CSBs --store zeros
uibTempReg4 ← zero;
uibTempReg2← zero;
uibTempReg3 ← zero;
uibTempReg1 ← zero;
t←uibSCBcsbQuad0offset;
PSTORE4[uibCSBbase, uibTempReg1];
t←uibSCBcsbQuad1offset;
PSTORE4[uibCSBbase, uibTempReg1];
t←uibChannelIOCBbaseOffset;
PSTORE4[uibCSBbase, uibTempReg1];
PSTORE4[uibCSBbase,uibTempReg1,uibIOCBheadOffset];
uibTempReg2← (ZERO)-1;*init InterruptLine
nop;*so PSTORE gets updated uibTempReg2
PSTORE4[uibCSBbase,uibTempReg1,uibCSBLineInterruptMaskOffset];
uibTempReg3← (7000c);*turn off cursor display
nop;*so PSTORE gets updated uibTempReg3
PSTORE4[uibCSBbase,uibTempReg1,uibCursBitmapBaseOffset];

SETTASK[uibTASK];
LOADPAGE[uibPage] ;
gotop[.+1];
ONPAGE[uibPage];
CALL[uibTaskOut];
GOTO[uibENDFIELD];
************************************************
*First wakeup at uibENDFIELD
************************************************

**********************************************
*
END DISPLAY
**********************************************
uibENDFIELD:
uibVideoUnloadPtr ← uibBufferSize;
call[uibCheckCursor], OUTPUT[uibVideoUnloadPtr,uibBPREG];

uibHTAB←200C; *send black background
OUTPUT[uibHTAB,uibHTABaddr];
uibCSBbase←uibrhCSBbase;
uibCSBbase←(uibCSBbase) OR (uiblhCSBbase);
uibCSBbase1←uibrhCSBbase1;
CALL[uibSyncWithVS], uibCSBbase1←(uibCSBbase1) OR (uiblhCSBbase1);
**********************************************
*VERTICAL SYNC
**********************************************
uibSyncWithVS:
INPUT[uibStatusReg1, uibStatusReg1Addr];
LU←LDF[uibStatusReg1, 15,1] ;*vertical ?
GOTO[uibSleep,ALU=0], uibScanLineCount←uibNonDisplayCount;
**********************************************
*CURSOR LOADING
**********************************************
uibD0cursor:
uibInitCursorLoading:
PFETCH1[uibCSBbase, uibCursLoadControl,uibCursLoadControlOffset];*fetch uibCursLoadControl
uibCursBitmapPtr←zero;*offset into cursor bitmap
uibCursLineCount←(17c);
SKIP[R<0], LU←uibCursLoadControl;* check need for load
GOTO[uibCursOff1], uibCursX←(uibTurnOffCursor);
PFETCH2[uibCSBbase, uibCursBitmapBase,uibCursBitmapBaseOffset];

t←LDF[uibCursLoadControl,2,2]; *or in XC8 and XC9 selecting 1 of 4 cursors
uibCursX←t;
LU←LDF[uibStatusReg1,14,1];*check field
GOTO[.+3, ALU#0], uibCursX←(uibCursX) OR (100000c);
uibCursBitmapPtr←(uibCursBitmapPtr)+(uibCursBitmapFieldOffset);
uibCursX←(uibCursX) AND NOT (100000c);*select upper or lower half of RAM
OUTPUT[uibCursX, uibCursorPointerAddr];

uibCursLoadLoop:
CALL[uibSleep], t←uibCursBitmapPtr;
GOTO[uibCursEndLoad,R<0], uibCursLineCount←(uibCursLineCount)-(2c);
******************* for 2 IOFETCH16s per scanline
*
GOTO[uibCursOff,R<0], uibCursLineCount←(uibCursLineCount)-(4c);
*
IOFETCH20[uibCursBitmapBase, uibCursMemAddr];
*
CALL[uibTaskOut], t←(uibCursBitmapPtr)←(uibCursBitmapPtr)+(20c);
******************* for 2 IOFETCH16s per scanline
IOFETCH20[uibCursBitmapBase, uibCursMemAddr];
GOTO[uibCursLoadLoop], uibCursBitmapPtr←(uibCursBitmapPtr)+(20c);

uibCursEndLoad:
uibCursLoadControl←(uibCursLoadControl) + (uibCursFieldBump);* add one per field
PSTORE1[uibCSBbase, uibCursLoadControl,uibCursLoadControlOffset];*STORE uibCursLoadControl
uibCursOff:
uibCursX←(uibTurnOffCursor);
uibCursOff1:
OUTPUT[uibCursX, uibCursorPointerAddr]; *turn off cursor


**********************************************
*FIFO
**********************************************
**********************************************
*restore state:
*
1) retrieve saved quad from CSB
*
2) retrieve ChannelTransferFlags word from CSB
**********************************************
uibFifo:
uibFIFOstateRestore:
t←uibChannelTransferFlagsOffset;
PFETCH1[uibCSBbase, uibChannelTransferFlags];
uibUIstatus←(zero);
uibFifoEntryCount←(zero);*will execute loop twice
t←uibSCBsavedQuadOffset;
GOTO[uibPreEntryLoop], PFETCH4[uibCSBbase, uibQuadWord0];

**********************************************
*process fifo entries
**********************************************
uibProcessFifo:
uibFifoScanLineLoop:
*** do untill time for display (uibScanlineCount<0)
CALL[uibSleep];
GOTO[uibFIFOstateSave, R<0], LU←(uibScanLineCount);
GOTO[uibEntryLoop], uibFifoEntryCount←(uibStartFifoEntryCount);
uibEntryLoopEnd:
GOTO[uibFifoScanLineLoop,R<0], uibFifoEntryCount←(uibFifoEntryCount)-1;
NOP;*placement
uibPreEntryLoop:
CALL[uibTaskOut];*task at end of each entry
uibEntryLoop:
*** do while entry in Fifo(IOATTEN) or channel transfer and entryCount >=0
GOTO[uibChannelTransfer, R<0], LU←uibChannelTransferFlags;*channel transfer
SKIP[IOATTEN];
GOTO[uibFifoScanLineLoop];*FIFO empty
INPUT[uibUIBdata,uibUIBdataAddr];*FIFO entry
SKIP[R<0], DISPATCH[uibUIBdata,3,4], LU←uibUIBdata;
DISP[uibFifoCommands], t←RHMASK[uibUIBdata];
DISP[uibFifoDataTypes], t←RHMASK[uibUIBdata];
**********************************************
*fifo state save
**********************************************
uibFIFOstateSave:
t←uibSCBsavedQuadOffset;
PSTORE4[uibCSBbase, uibQuadWord0];
TASK, t←uibChannelTransferFlagsOffset;
PSTORE1[uibCSBbase, uibChannelTransferFlags];
**********************************************
*VS interrupt
**********************************************
uibD0vsInterrupt:
PFETCH4[uibCSBbase,uibScanLineNotifyMask,uibCSBLineInterruptMaskOffset];
t←uibUIstatus;
uibCSBuiStatus←uibCSBuiStatus;*make sure its there
uibCSBuiStatus←t;
t←uibD0vsInterruptMask;* set t here to avoid bypass gotcha (3rd inst is in NotifyInterrupt)
LOADPAGE[NotifyInterruptPage] ;
CALLp[NotifyInterrupt],PSTORE4[uibCSBbase,uibScanLineNotifyMask,uibCSBLineInterruptMaskOffset];
CALL[uibSleep], PFETCH4[uibCSBbase, uibIOCBhead,uibIOCBheadOffset];*fetch display control

**********************************************
*
DISPLAY SETUP
**********************************************
uibLastNonDisplayLine:
PFETCH2[uibCSBbase, uibCursX, uibCursXOffset];*fetch cursor x and y
uibSetScanLineCount:
uibScanLineCount←uiblhLinesPerField;
uibScanLineCount ← (uibScanLineCount) OR (uibrhLinesPerField);
t←uibInterruptLine, GOTO[uibCursorSet, R<0];*no scanline interrupt
uibTempReg2←t;*save uibInterruptLine
t←uibScanLineCount;
uibInterruptLine←t;
t←uibTempReg2;
uibInterruptLine←(uibInterruptLine)-t;* uibInterruptLine←total-uibInterruptLine
*save remainder
uibScanLineCount←t;*set count for uibInterruptLine before notify
uibScanLineCount←(uibScanLineCount)-(2c);*two lines sent for count of 0
uibCursorSet:
uibCursY←(uibCursY)+(1c);
TASK, t←(uibCursX)-(3c);*kludge
uibCursX←(zero) - t;*negate x value
t ← LDF[uibStatusReg1,14,1];*check for even/odd field
t←(LDF[uibCursY,17,1] ) XOR t;
GOTO[.+3,ALU#0], uibCursX←LDF[uibCursX,5,13];
uibCursX←(uibCursX) OR (uibCursXeven);
uibCursY←(uibCursY)-1;
uibCheckIOCBhead:
uibZeroBase←zero;
t←uibIOCBhead;
GOTO[uibGetFirstDCB, ALU#0], uibVideoUnloadPtr ← uibBufferSize;
OUTPUT[uibVideoUnloadPtr,uibBPREG];
call[uibCheckCursor],IOSTROBE;
goto[uibNoMoreDCBs];
uibGetFirstDCB:
CALL[uibTaskOut], ODDPFETCH4[uibZeroBase,uibIOCBlink]; *Fetch IOCB
GOTO[uibNextDCB],IOSTROBE;

**********************************************
*VIDEO
**********************************************
**********************************************
*last thing you do after processing a scan line which is not the last of a DCB
**********************************************
uibNormalVideoExit:
call[uibCheckCursor], uibVideoBitmapPtr←(uibVideoBitmapPtr)+(20C);*update after last fetch
uibVideoData:
t←(uibWordsPerLine)-(21c);*-1 since loop terminates on negative count
uibVideoLoopControl←t ;* set up count so last fetch16 is not in loop
CALL[uibVideoLoop], t ←uibVideoBitmapPtr;
uibVideoLoop:
GOTO[uibVideoLastIOFetch, R<0], uibVideoLoopControl←(uibVideoLoopControl)-(20c);
IOFETCH16[uibBitmapBase,uibDATABUFaddr];
RETURN, uibVideoBitmapPtr←t←(uibVideoBitmapPtr)+(20C);
**********************************************
*finished with scan line; end of field? end of DCB?
**********************************************
uibVideoLastIOFetch:
***** IOSTROBE done early; next task is last for this line
IOSTROBE, uibIOCBscanlines←(uibIOCBscanlines)-1,GOTO[uibDCBDONE, R<0];
uibDCBnotDone:
SKIP[R<0], LU←uibWordsPerLine;* zero width IOCB flag
IOFETCH16[uibBitmapBase,uibDATABUFaddr];*last fetch16, this path
uibScanLineCount ← (uibScanLineCount)-1,GOTO[uibDCBcontinue,R>=0];
GOTO[uibENDFIELD, R <0], t←uibInterruptLine;*more scanlines?
uibInterruptLine←(zero) -1;*set to no more scanlines
LOADPAGE[NotifyInterruptPage], uibScanLineCount←t;*set count for remainder
CALL[NotifyInterrupt], t←uibScanLineNotifyMask;
uibDCBcontinue:
t←(uibWordsPerLine) AND NOT (17c);*stay on 16 word boundary
GOTO[uibNormalVideoExit], uibVideoBitmapPtr←(uibVideoBitmapPtr)+t;

uibDCBdone:
uibTempReg1←t;*save t for last iofetch16; get next dcb first
t←(uibIOCBlink);
GOTO[uibFinishLastDCB, ALU=0], uibVideoUnloadPtr ← uibBufferSize;
ODDPFETCH4[uibZeroBase,uibIOCBlink]; *Fetch IOCB
t←uibTempReg1;
SKIP[R<0], LU←uibWordsPerLine;* zero width IOCB flag
IOFETCH16[uibBitmapBase,uibDATABUFaddr]; *last fetch16, this path
uibScanLineCount ← (uibScanLineCount)-1,GOTO[uibNextDCB,R>=0];
SKIP[R >=0], uibInterruptLine←(uibInterruptLine)-1;*test waitscanline
GOTO[uibENDFIELD];
GOTO[uibNextDCB];*cannot do scanline notify and nextDCB


**********************************************
*Next DCBset pointers - bitmap, load, unload
**********************************************
uibNextDCB:
*covered by last IOFETCH16
t←RHMASK[uibIOCBparms];
LU←LDF[uibStatusReg1,14,1];*check field
SKIP[ALU#0], uibVideoUnloadPtr←(uibVideoUnloadPtr)-t;*buffer size - words/line
uibVideoBitmapPtr←(uibVideoBitmapPtr) + t;*interlace
LU←LDF[uibVideoBitmapPtr,14,4];*hex or octal align?
SKIP[ALU=0],uibVideoBitmapPtr←(uibVideoBitmapPtr) AND NOT (17c);*force hex
uibVideoPtrs←(uibVideoPtrs)-(4000c);*sub 8 from loadPtr
t←LSH[uibVideoUnloadPtr,10];*compute loadPtr
uibVideoPtrs←(uibVideoUnloadPtr) + t;
OUTPUT[uibVideoPtrs,uibBPREG];
CALL[uibCheckCursor], uibIOCBscanlines←(uibIOCBscanlines)-(2c);

* the following code is executed the first part of the next scanline
uibHTAB←277c;*set for white background and 32 bit cursor
t ← LDF[uibIOCBparms,2,6]; *calculate HTAB
LU←LDF[uibIOCBparms,1,1]; *black background bit
uibHTAB ← (uibHTAB) - (T),GOTO[.+2,ALU#0];
uibHTAB ← (uibHTAB) AND NOT (200C);
OUTPUT[uibHTAB,uibHTABaddr];
t←RHMASK[uibIOCBparms];
SKIP[ALU#0], uibWordsPerLine←t; *uibWordsPerLine and uibIOCBparms are the same reg !!!!!
uibWordsPerLine ← (zero) - 1;*flag for zero width IOCB
goto[uibVideoData];


**********************************************
*
no more DCBs
**********************************************
uibFinishLastDCB:
OUTPUT[uibVideoUnloadPtr,uibBPREG];
t←uibTempReg1;*restore t for IOFETCH
SKIP[R<0], LU←uibWordsPerLine;* zero width IOCB flag
IOFETCH16[uibBitmapBase,uibDATABUFaddr]; *last fetch16, this path;
uibNoMoreDCBscanlineCheck:
uibScanLineCount ← (uibScanLineCount)-1,GOTO[uibNoMoreDCBtask,R>=0];
SKIP[R >=0], t←uibInterruptLine;*test waitscanline
GOTO[uibENDFIELD];
uibInterruptLine←(zero) -1;*set to no more scanlines
LOADPAGE[NotifyInterruptPage], uibScanLineCount←t;*set count for remainder
CALL[NotifyInterrupt], t←uibScanLineNotifyMask;
uibNoMoreDCBtask:
nop; *placement
call[uibCheckCursor];
uibNoMoreDCBs:
GOTO[uibNoMoreDCBscanlineCheck], IOSTROBE;


**********************************************
*FIFO
COMMANDS AND DATA
**********************************************
uibFifoCommands:
uibFetchKeyQuad:
AT[uibFifoCommandsDispLoc,0],
t←uibKeyBitsQuad1Offset;
GOTO[uibEntryLoopEnd], PFETCH4[uibCSBbase,uibQuadWord0];

uibStoreKeyQuad:
AT[uibFifoCommandsDispLoc,1],
uibUIstatus←(uibUIstatus) OR (uibUIstatusKeyMask);
t←uibKeyBitsQuad1Offset;
GOTO[uibEntryLoopEnd], PSTORE4[uibCSBbase,uibQuadWord0];

uibUpdateMouse:
AT[uibFifoCommandsDispLoc,2],
t←uibMouseDelXY;
uibTempReg1←t;* save since fetch will clobber uibMouseDelXY
PFETCH4[uibCSBbase,uibMouseXcoord,uibMouseXcoordOffset];
uibUIstatus←(uibUIstatus) OR (uibUIstatusMouseXYMask);
t←RHMASK[uibTempReg1];
SKIP[NOH2BIT8], uibMouseXcoord←(uibMouseXcoord)+t;
uibMouseXcoord←(uibMouseXcoord) + (177400c);*extend sign bit
t←LDF[uibTempReg1,0,10];
SKIP[NOH2BIT8],uibMouseYcoord←(uibMouseYcoord)+t;
uibMouseYcoord←(uibMouseYcoord) + (177400c);*extend sign bit
nop;*allow write of uibMouseYcoord before store
GOTO[uibEntryLoopEnd], PSTORE4[uibCSBbase,uibMouseXcoord,uibMouseXcoordOffset];

uibUpdateMouseButtons:
AT[uibFifoCommandsDispLoc,3],
uibUIstatus←(uibUIstatus) OR (uibUIstatusButtonMask);
uibMouseButtonWord←t;
t←uibMouseButtonWordOffset;
GOTO[uibEntryLoopEnd], PSTORE1[uibCSBbase, uibMouseButtonWord];

uibFetchSCBcsbQuad0:
AT[uibFifoCommandsDispLoc,4],
t←uibSCBcsbQuad0offset;
GOTO[uibEntryLoopEnd], PFETCH4[uibCSBbase,uibQuadWord0];

uibStoreSCBcsbQuad0:
AT[uibFifoCommandsDispLoc,5],
t←uibSCBcsbQuad0offset;
GOTO[uibEntryLoopEnd], PSTORE4[uibCSBbase,uibQuadWord0];

uibFetchSCBcsbQuad1:
AT[uibFifoCommandsDispLoc,6],
t←uibSCBcsbQuad1offset;
GOTO[uibEntryLoopEnd], PFETCH4[uibCSBbase,uibQuadWord0];

uibStoreSCBcsbQuad1:
AT[uibFifoCommandsDispLoc,7],
t←uibSCBcsbQuad1offset;
GOTO[uibEntryLoopEnd], PSTORE4[uibCSBbase,uibQuadWord0];

uibInputChanTransfer:
AT[uibFifoCommandsDispLoc,10],
uibChannelTransferFlags←(uibChannelTransferFlags) OR (uibInputChannelFlag);
uibOutputChanTransfer:
AT[uibFifoCommandsDispLoc,11],
uibChannelTransferFlags←(uibChannelTransferFlags) OR (uibExecuteChannelTransfer);
t←(LDF[uibUIBdata,14,4]);*get block count specifying amount of data
uibChannelBlockCnt←t;
uibUIBdata←(LDF[uibUIBdata,10,2]);*n th additional transfer of a multi-buffer transfer
t←LSH[uibUIBdata,10];*multiply by buffer size (256d)
GOTO[uibEntryLoopEnd], uibChannelBuffPtr←(uibChannelBuffPtr)+t; * (start+n*256)

uibStoreTouch:
AT[uibFifoCommandsDispLoc,12],
uibUIstatus←(uibUIstatus) OR (uibUIstatusTouchMask);
GOTO[uibEntryLoopEnd], PSTORE2[uibCSBbase,uibTouchX,uibTouchOffset];


uibNotifyMesaSCBdriver:
AT[uibFifoCommandsDispLoc,13],
t←uibSCBinterruptMaskOffset;
PFETCH1[uibCSBbase,uibSCBinterruptMask];
LOADPAGE[NotifyInterruptPage];
CALL[NotifyInterrupt], t←uibSCBinterruptMask;
GOTO[uibEntryLoopEnd];

uibFetchChannelIOCB:
AT[uibFifoCommandsDispLoc,14],
t←uibChannelIOCBbaseOffset;
PFETCH2[uibCSBbase,uibChannelIOCBbase];*fetch pointer to IOCB table
t←LDF[uibUIBdata,12,6];*select IOCB
LU←uibChannelIOCBbase;
GOTO[uibEntryLoopEnd], PFETCH4[uibChannelIOCBbase,uibChannelBuffBase];*fetch IOCB

:IF[ESSMode]; *********************************
uibFetchKeyQuad2:
AT[uibFifoCommandsDispLoc,15],
t←uibKeyBitsQuad2Offset;
GOTO[uibEntryLoopEnd], PFETCH4[uibCSBbase,uibQuadWord0];

uibStoreKeyQuad2:
AT[uibFifoCommandsDispLoc,16],
t←uibKeyBitsQuad2Offset;
GOTO[uibEntryLoopEnd], PSTORE4[uibCSBbase,uibQuadWord0];
:ENDIF; ***************************************

uibFifoDataTypes:
uibReplaceQuadByte0:AT[uibFifoDataTypesDispLoc,0],
GOTO[uibEntryLoopEnd], uibQuadWord0←(LHMASK[uibQuadWord0]) OR t;
uibReplaceQuadByte1:
AT[uibFifoDataTypesDispLoc,1],
t←LSH[uibUIBdata,10];
GOTO[uibEntryLoopEnd], uibQuadWord0←(RHMASK[uibQuadWord0]) OR t;
uibReplaceQuadByte2:
AT[uibFifoDataTypesDispLoc,2],
GOTO[uibEntryLoopEnd], uibQuadWord1←(LHMASK[uibQuadWord1]) OR t;
uibReplaceQuadByte3:
AT[uibFifoDataTypesDispLoc,3],
t←LSH[uibUIBdata,10];
GOTO[uibEntryLoopEnd], uibQuadWord1←(RHMASK[uibQuadWord1]) OR t;

uibReplaceQuadByte4:
AT[uibFifoDataTypesDispLoc,4],
GOTO[uibEntryLoopEnd], uibQuadWord2←(LHMASK[uibQuadWord2]) OR t;
uibReplaceQuadByte5:
AT[uibFifoDataTypesDispLoc,5],
t←LSH[uibUIBdata,10];
GOTO[uibEntryLoopEnd], uibQuadWord2←(RHMASK[uibQuadWord2]) OR t;
uibReplaceQuadByte6:
AT[uibFifoDataTypesDispLoc,6],
GOTO[uibEntryLoopEnd], uibQuadWord3←(LHMASK[uibQuadWord3]) OR t;
uibReplaceQuadByte7:
AT[uibFifoDataTypesDispLoc,7],
t←LSH[uibUIBdata,10];
GOTO[uibEntryLoopEnd], uibQuadWord3←(RHMASK[uibQuadWord3]) OR t;
uibMouseDeltaX:
AT[uibFifoDataTypesDispLoc,10],
GOTO[uibEntryLoopEnd], uibMouseDelXY←(LHMASK[uibMouseDelXY]) OR t;
uibMouseDeltaY:
AT[uibFifoDataTypesDispLoc,11],
t←LSH[uibUIBdata,10];
GOTO[uibEntryLoopEnd], uibMouseDelXY←(RHMASK[uibMouseDelXY]) OR t;


**********************************************
*
CHANNEL TRANSFER
**********************************************
uibChannelTransfer:
GOTO[uibChannelTransferDone,R<0], uibChannelBlockCnt←(uibChannelBlockCnt)-1;
t←uibChannelBuffPtr;
SKIP[R EVEN], LU←uibChannelTransferFlags;
SKIP, IOSTORE16[uibChannelBuffBase,uibInChannelBuffAddr];
IOFETCH16[uibChannelBuffBase,uibOutChannelBuffAddr];
GOTO[uibEntryLoopEnd], uibChannelBuffPtr←(uibChannelBuffPtr)+(20c);
uibChannelTransferDone:
GOTO[uibFifoScanLineLoop], uibChannelTransferFlags←zero;
**********************************************
*
CALL IT QUITS FOR THIS SCAN LINE
**********************************************
uibSleep:
IOSTROBE, uibScanLineCount←(uibScanLineCount)-1;
uibTaskOut:
RETURN;

**********************************************
*
CHECK CURSOR
**********************************************
*CursX is written once to start the cursor and once to turn it off

uibCheckCursor:
GOTO[uibCursRet, r>=0], uibCursY←(uibCursY)-(2c);*start cursor ?
LU←(uibCursY)+(4c);
GOTO[.+2,ALU<0];
GOTO[uibSendCursX];*first line of cursor; send CursX
LU←(uibCursY)+(uibCursLinesPerFrame);
GOTO[.+2, ALU<0], uibCursX←LDF[uibCursX,16,2];*maintain XC8 and XC9
GOTO[uibCursRet];
uibCursX←(uibCursX) OR (uibTurnOffCursor);*finished w cursor; turn it off
uibCursY←uibLargePositiveNumber;
uibSendCursX:
OUTPUT[uibCursX, uibCursorPointerAddr];
nop;*output gotcha
uibCursRet:
nop;*output gotcha
nop;*output gotcha
GOTO[ uibTaskOut];

END[DUIB];

:ELSE; ****************************************************

TITLE[No.DUIB.unless.WithUIB.eq.1];

:ENDIF; ***************************************************