You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
13 KiB
433 lines
13 KiB
/*****************************************************************************\
|
|
* Smart 64k Color Bank Manager
|
|
*
|
|
* Copyright (c) 1992 Microsoft Corporation
|
|
\*****************************************************************************/
|
|
|
|
#include "driver.h"
|
|
|
|
/*****************************************************************************\
|
|
* pcoBankStart - Start the bank enumeration using the clip object.
|
|
*
|
|
* Used when the destination is the screen and we can't do the clipping
|
|
* ourselves (as we can for blt's).
|
|
\*****************************************************************************/
|
|
|
|
CLIPOBJ* pcoBankStart(
|
|
PPDEV ppdev,
|
|
RECTL* prclScans,
|
|
SURFOBJ* pso,
|
|
CLIPOBJ* pco)
|
|
{
|
|
LONG iTopScan;
|
|
|
|
// Remember what the last scan is that we're going to, and
|
|
// make sure we only try to go as far as we need to. It could
|
|
// happen that when get a prclScans bigger than the screen:
|
|
|
|
ppdev->iLastScan = min(prclScans->bottom, (LONG) ppdev->cyScreen);
|
|
|
|
// Adjust for those weird cases where we're asked to start enumerating
|
|
// above or below the bottom of the screen:
|
|
|
|
iTopScan = max(0, prclScans->top);
|
|
iTopScan = min(iTopScan, (LONG) ppdev->cyScreen - 1);
|
|
|
|
if (pco->iDComplexity != DC_TRIVIAL)
|
|
{
|
|
iTopScan = max(pco->rclBounds.top, iTopScan);
|
|
ppdev->iLastScan = min(pco->rclBounds.bottom, ppdev->iLastScan);
|
|
}
|
|
|
|
// Map in the top bank:
|
|
|
|
if (iTopScan < ppdev->rcl1WindowClip.top ||
|
|
iTopScan >= ppdev->rcl1WindowClip.bottom)
|
|
{
|
|
ppdev->pfnBankControl(ppdev, iTopScan, JustifyTop);
|
|
}
|
|
|
|
pso->pvScan0 = ppdev->pvBitmapStart;
|
|
|
|
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
|
|
{
|
|
// The call may have come down to us as having no clipping, but
|
|
// we have to clip to the banks, so use our own clip object:
|
|
|
|
pco = ppdev->pcoNull;
|
|
pco->rclBounds = ppdev->rcl1WindowClip;
|
|
|
|
ASSERTVGA(pco->fjOptions & OC_BANK_CLIP, "Default BANK_CLIP not set");
|
|
ASSERTVGA(pco->iDComplexity == DC_RECT, "Default clip not DC_RECT");
|
|
}
|
|
else
|
|
{
|
|
// Save the engine's clip object data that we'll be tromping on:
|
|
|
|
ppdev->rclSaveBounds = pco->rclBounds;
|
|
ppdev->iSaveDComplexity = pco->iDComplexity;
|
|
ppdev->fjSaveOptions = pco->fjOptions;
|
|
|
|
// Let engine know it has to pay attention to the rclBounds of the
|
|
// clip object:
|
|
|
|
pco->fjOptions |= OC_BANK_CLIP;
|
|
|
|
// Use the bank bounds if they are tighter than the existing
|
|
// bounds.
|
|
|
|
if (pco->rclBounds.top <= ppdev->rcl1WindowClip.top)
|
|
pco->rclBounds.top = ppdev->rcl1WindowClip.top;
|
|
|
|
if (pco->rclBounds.bottom >= ppdev->rcl1WindowClip.bottom)
|
|
pco->rclBounds.bottom = ppdev->rcl1WindowClip.bottom;
|
|
|
|
if ((pco->rclBounds.top >= pco->rclBounds.bottom) ||
|
|
(pco->rclBounds.left >= pco->rclBounds.right))
|
|
{
|
|
// It's conceivable that we could get a situation where our
|
|
// draw rectangle is completely disjoint from the specified
|
|
// rectangle's rclBounds. Make sure we don't puke on our
|
|
// shoes:
|
|
|
|
pco->rclBounds.left = 0;
|
|
pco->rclBounds.top = 0;
|
|
pco->rclBounds.right = 0;
|
|
pco->rclBounds.bottom = 0;
|
|
ppdev->iLastScan = 0;
|
|
}
|
|
}
|
|
|
|
return(pco);
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* bBankEnum - Continue the bank enumeration.
|
|
\*****************************************************************************/
|
|
|
|
BOOL bBankEnum(PPDEV ppdev, SURFOBJ* pso, CLIPOBJ* pco)
|
|
{
|
|
LONG yNewTop = ppdev->rcl1WindowClip.bottom;
|
|
|
|
if (yNewTop >= ppdev->iLastScan)
|
|
{
|
|
// Okay, that was the last bank, so restore our structures:
|
|
|
|
if (pco != ppdev->pcoNull)
|
|
{
|
|
pco->rclBounds = ppdev->rclSaveBounds;
|
|
pco->iDComplexity = ppdev->iSaveDComplexity;
|
|
pco->fjOptions = ppdev->fjSaveOptions;
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
ppdev->pfnBankControl(ppdev, yNewTop, JustifyTop);
|
|
|
|
ASSERTVGA(yNewTop >= ppdev->rcl1WindowClip.top &&
|
|
yNewTop < ppdev->rcl1WindowClip.bottom, "Out of bounds");
|
|
|
|
// Adjust the pvScan0 because we've moved the window to view
|
|
// a different area:
|
|
|
|
pso->pvScan0 = ppdev->pvBitmapStart;
|
|
|
|
// Set the bounds to the new bank:
|
|
|
|
pco->rclBounds.top = yNewTop;
|
|
pco->rclBounds.left = ppdev->rcl1WindowClip.left;
|
|
pco->rclBounds.bottom = ppdev->rcl1WindowClip.bottom;
|
|
pco->rclBounds.right = ppdev->rcl1WindowClip.right;
|
|
|
|
if (pco != ppdev->pcoNull)
|
|
{
|
|
// If we were originally given a non-trivial clip object, we have
|
|
// to clip to the original bounds:
|
|
|
|
if (pco->rclBounds.left <= ppdev->rclSaveBounds.left)
|
|
pco->rclBounds.left = ppdev->rclSaveBounds.left;
|
|
|
|
if (pco->rclBounds.right >= ppdev->rclSaveBounds.right)
|
|
pco->rclBounds.right = ppdev->rclSaveBounds.right;
|
|
|
|
if (pco->rclBounds.bottom >= ppdev->rclSaveBounds.bottom)
|
|
pco->rclBounds.bottom = ppdev->rclSaveBounds.bottom;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* vBankStartBltSrc - Start the bank enumeration for when the screen is
|
|
* the source.
|
|
\***************************************************************************/
|
|
|
|
VOID vBankStartBltSrc(
|
|
PPDEV ppdev,
|
|
SURFOBJ* pso,
|
|
POINTL* pptlSrc,
|
|
RECTL* prclDest,
|
|
POINTL* pptlNewSrc,
|
|
RECTL* prclNewDest)
|
|
{
|
|
LONG xRightSrc;
|
|
LONG yBottomSrc;
|
|
LONG iTopScan = max(0, pptlSrc->y);
|
|
|
|
if (iTopScan >= (LONG) ppdev->cyScreen)
|
|
{
|
|
// In some instances we may be asked to start on a scan below the screen.
|
|
// Since we obviously won't be drawing anything, don't bother mapping in
|
|
// a bank:
|
|
|
|
return;
|
|
}
|
|
|
|
// Map in the bank:
|
|
|
|
if (iTopScan < ppdev->rcl1WindowClip.top ||
|
|
iTopScan >= ppdev->rcl1WindowClip.bottom)
|
|
{
|
|
ppdev->pfnBankControl(ppdev, iTopScan, JustifyTop);
|
|
}
|
|
|
|
if (ppdev->rcl1WindowClip.right <= pptlSrc->x)
|
|
{
|
|
// We have to watch out for those rare cases where we're starting
|
|
// on a broken raster and we won't be drawing on the first part:
|
|
|
|
ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird start bounds");
|
|
|
|
ppdev->pfnBankNext(ppdev);
|
|
}
|
|
|
|
pso->pvScan0 = ppdev->pvBitmapStart;
|
|
|
|
// Adjust the source:
|
|
|
|
pptlNewSrc->x = pptlSrc->x;
|
|
pptlNewSrc->y = pptlSrc->y;
|
|
|
|
// Adjust the destination:
|
|
|
|
prclNewDest->left = prclDest->left;
|
|
prclNewDest->top = prclDest->top;
|
|
|
|
yBottomSrc = pptlSrc->y + prclDest->bottom - prclDest->top;
|
|
prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, yBottomSrc);
|
|
prclNewDest->bottom += prclDest->top - pptlSrc->y;
|
|
|
|
xRightSrc = pptlSrc->x + prclDest->right - prclDest->left;
|
|
prclNewDest->right = min(ppdev->rcl1WindowClip.right, xRightSrc);
|
|
prclNewDest->right += prclDest->left - pptlSrc->x;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* bBankEnumBltSrc - Continue the bank enumeration for when the screen is
|
|
* the source.
|
|
\***************************************************************************/
|
|
|
|
BOOL bBankEnumBltSrc(
|
|
PPDEV ppdev,
|
|
SURFOBJ* pso,
|
|
POINTL* pptlSrc,
|
|
RECTL* prclDest,
|
|
POINTL* pptlNewSrc,
|
|
RECTL* prclNewDest)
|
|
{
|
|
LONG xLeftSrc;
|
|
LONG xRightSrc;
|
|
LONG yBottomSrc;
|
|
|
|
LONG cx = prclDest->right - prclDest->left;
|
|
LONG cy = prclDest->bottom - prclDest->top;
|
|
|
|
LONG dx;
|
|
LONG dy;
|
|
|
|
LONG yBottom = min(pptlSrc->y + cy, (LONG) ppdev->cyScreen);
|
|
LONG yNewTop = ppdev->rcl1WindowClip.bottom;
|
|
|
|
if (ppdev->flBank & BANK_BROKEN_RASTER1)
|
|
{
|
|
ppdev->pfnBankNext(ppdev);
|
|
if (ppdev->rcl1WindowClip.left >= pptlSrc->x + cx)
|
|
{
|
|
if (ppdev->rcl1WindowClip.bottom < yBottom)
|
|
ppdev->pfnBankNext(ppdev);
|
|
else
|
|
{
|
|
// We're done:
|
|
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
else if (yNewTop < yBottom)
|
|
{
|
|
ppdev->pfnBankControl(ppdev, yNewTop, JustifyTop);
|
|
if (ppdev->rcl1WindowClip.right <= pptlSrc->x)
|
|
{
|
|
ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird bounds");
|
|
ppdev->pfnBankNext(ppdev);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We're done:
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
// Adjust the source:
|
|
|
|
pso->pvScan0 = ppdev->pvBitmapStart;
|
|
|
|
pptlNewSrc->x = max(ppdev->rcl1WindowClip.left, pptlSrc->x);
|
|
pptlNewSrc->y = yNewTop;
|
|
|
|
// Adjust the destination:
|
|
|
|
dy = prclDest->top - pptlSrc->y; // y delta from source to dest
|
|
|
|
prclNewDest->top = yNewTop + dy;
|
|
|
|
yBottomSrc = pptlSrc->y + cy;
|
|
prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, yBottomSrc) + dy;
|
|
|
|
dx = prclDest->left - pptlSrc->x; // x delta from source to dest
|
|
|
|
xLeftSrc = pptlSrc->x;
|
|
prclNewDest->left = pptlNewSrc->x + dx;
|
|
|
|
xRightSrc = pptlSrc->x + cx;
|
|
prclNewDest->right = min(ppdev->rcl1WindowClip.right, xRightSrc) + dx;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* vBankStartBltDest - Start the bank enumeration for when the screen is
|
|
* the destination.
|
|
\***************************************************************************/
|
|
|
|
VOID vBankStartBltDest(
|
|
PPDEV ppdev,
|
|
SURFOBJ* pso,
|
|
POINTL* pptlSrc,
|
|
RECTL* prclDest,
|
|
POINTL* pptlNewSrc,
|
|
RECTL* prclNewDest)
|
|
{
|
|
LONG iTopScan = max(0, prclDest->top);
|
|
|
|
if (iTopScan >= (LONG) ppdev->cyScreen)
|
|
{
|
|
// In some instances we may be asked to start on a scan below the screen.
|
|
// Since we obviously won't be drawing anything, don't bother mapping in
|
|
// a bank:
|
|
|
|
return;
|
|
}
|
|
|
|
// Map in the bank:
|
|
|
|
if (iTopScan < ppdev->rcl1WindowClip.top ||
|
|
iTopScan >= ppdev->rcl1WindowClip.bottom)
|
|
{
|
|
ppdev->pfnBankControl(ppdev, iTopScan, JustifyTop);
|
|
}
|
|
|
|
if (ppdev->rcl1WindowClip.right <= prclDest->left)
|
|
{
|
|
// We have to watch out for those rare cases where we're starting
|
|
// on a broken raster and we won't be drawing on the first part:
|
|
|
|
ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird start bounds");
|
|
ppdev->pfnBankNext(ppdev);
|
|
}
|
|
|
|
pso->pvScan0 = ppdev->pvBitmapStart;
|
|
|
|
// Adjust the destination:
|
|
|
|
prclNewDest->left = prclDest->left;
|
|
prclNewDest->top = prclDest->top;
|
|
prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, prclDest->bottom);
|
|
prclNewDest->right = min(ppdev->rcl1WindowClip.right, prclDest->right);
|
|
|
|
// Adjust the source if there is one:
|
|
|
|
if (pptlSrc != NULL)
|
|
*pptlNewSrc = *pptlSrc;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* bBankEnumBltDest - Continue the bank enumeration for when the screen is
|
|
* the destination.
|
|
\***************************************************************************/
|
|
|
|
BOOL bBankEnumBltDest(
|
|
PPDEV ppdev,
|
|
SURFOBJ* pso,
|
|
POINTL* pptlSrc,
|
|
RECTL* prclDest,
|
|
POINTL* pptlNewSrc,
|
|
RECTL* prclNewDest)
|
|
{
|
|
LONG yBottom = min(prclDest->bottom, (LONG) ppdev->cyScreen);
|
|
LONG yNewTop = ppdev->rcl1WindowClip.bottom;
|
|
|
|
if (ppdev->flBank & BANK_BROKEN_RASTER1)
|
|
{
|
|
ppdev->pfnBankNext(ppdev);
|
|
if (ppdev->rcl1WindowClip.left >= prclDest->right)
|
|
{
|
|
if (ppdev->rcl1WindowClip.bottom < yBottom)
|
|
ppdev->pfnBankNext(ppdev);
|
|
else
|
|
{
|
|
// We're done:
|
|
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
else if (yNewTop < yBottom)
|
|
{
|
|
ppdev->pfnBankControl(ppdev, yNewTop, JustifyTop);
|
|
if (ppdev->rcl1WindowClip.right <= prclDest->left)
|
|
{
|
|
ASSERTVGA(ppdev->flBank & BANK_BROKEN_RASTER1, "Weird bounds");
|
|
ppdev->pfnBankNext(ppdev);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We're done:
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
pso->pvScan0 = ppdev->pvBitmapStart;
|
|
|
|
// Adjust the destination:
|
|
|
|
prclNewDest->top = yNewTop;
|
|
prclNewDest->left = max(ppdev->rcl1WindowClip.left, prclDest->left);
|
|
prclNewDest->bottom = min(ppdev->rcl1WindowClip.bottom, prclDest->bottom);
|
|
prclNewDest->right = min(ppdev->rcl1WindowClip.right, prclDest->right);
|
|
|
|
// Adjust the source if there is one:
|
|
|
|
if (pptlSrc != NULL)
|
|
{
|
|
pptlNewSrc->x = pptlSrc->x + (prclNewDest->left - prclDest->left);
|
|
pptlNewSrc->y = pptlSrc->y + (prclNewDest->top - prclDest->top);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|