unit GlobalUtils;

interface
	uses
		SMS, Palettes, Globals;

	procedure SetPage (secondPage: Boolean);
	procedure SpinBall;
	procedure GenericAlert (whatGives: Integer);
	procedure DoTheSound (whichOne: Integer);
	procedure DoTheBass (whichOne: Integer);
	procedure DoTheMusic (whichOne: Integer);
	function Randomize (range: Integer): Integer;
	procedure CalcRoomScore;
	procedure DoErrorSound (soundNumber: Integer);
	procedure DissBlocks;
	procedure DrawHiScores;
	procedure HideMenuBar;
	procedure ShowMenuBar;
	procedure FatalError;
	procedure RedrawWindowFrame;

implementation

{=================================}

	procedure SetPage (secondPage: Boolean);
	EXTERNAL;

{=================================}

	procedure SpinBall;
		var
			tempByte: SignedByte;

	begin
		if (ballList = nil) then
			Exit(SpinBall);
		tempByte := HGetState(Handle(ballList));
		HLock(Handle(ballList));
		with ballList^^ do
		begin
			if (whichBall = -1) then
				Exit(SpinBall);
			if (whichBall >= kCursCount) then
				whichBall := 1
			else
				whichBall := whichBall + 1;
			if (useColorCursor) then
				SetCCursor(ballC[whichBall])
			else
				SetCursor(ball[whichBall]^^);
		end;
		HSetState(Handle(ballList), tempByte);
	end;

{=================================}

	procedure GenericAlert;
		var
			dummyInt: Integer;
			line1, line2: Str255;
			alertHandle: AlertTHndl;
			alertRect: Rect;

	begin
		if ((areFlipping) and (mainScreenHidden)) then
		begin
			mainScreenHidden := FALSE;
			SetPage(mainScreenHidden);
		end;

		UseResFile(gliderResNum);
		InitCursor;
		if (whatGives > 0) then
		begin
			GetIndString(line1, rAlertStrIDs, whatGives);
			line2 := '';
		end
		else
		begin
			GetIndString(line1, rAlertStrIDs, 1);
			NumToString(whatGives, line2);
			line2 := CONCAT('Error = ', line2);
		end;

		ParamText(line1, line2, '', '');
		alertHandle := AlertTHndl(Get1Resource('ALRT', rAlertID));
		if (alertHandle <> nil) then
		begin
			HNoPurge(Handle(alertHandle));
			alertRect := alertHandle^^.boundsRect;
			OffsetRect(alertRect, -alertRect.left, -alertRect.top);
			dummyInt := (screenBits.bounds.right - alertRect.right) div 2;
			OffsetRect(alertRect, dummyInt, 0);
			dummyInt := (screenBits.bounds.bottom - alertRect.bottom) div 3;
			OffsetRect(alertRect, 0, dummyInt);
			alertHandle^^.boundsRect := alertRect;
			HPurge(Handle(alertHandle));
		end;
		dummyInt := Alert(rAlertID, nil);
	end;

{=================================}

	procedure DoTheMusic;
	begin
		if (musicOn and soundOn) then
			SMSStartChan(whichOne, 1);
	end;

{=================================}

	procedure DoTheBass;
	begin
		if (musicOn) then
			SMSStart(whichOne);
	end;

{=================================}

	procedure DoTheSound;
	begin
		if (soundOn) then
			SMSStart(whichOne);
	end;

{=================================}

	function Randomize;
		var
			rawResult: LongInt;
	begin
		rawResult := ABS(Random);
		Randomize := (rawResult * range) div 32768;
	end;

{=================================}

	procedure CalcRoomScore;
		var
			index: Integer;

	begin
		roomScore := 0;
		for index := 1 to 40 do
			if (roomVisits[index]) then
				roomScore := roomScore + (500 * (index div 10 + 1)) + (roomsPassed div 41) * 2000;
	end;

{=================================}

	procedure DoErrorSound;
		var
			dummyLong: LongInt;
			tempVolume, i: Integer;
	begin
		GetSoundVol(tempVolume);
		if (tempVolume <> 0) then
			for i := 0 to soundNumber do
			begin
				FlashMenuBar(0);
				Delay(8, dummyLong);
				FlashMenuBar(0);
			end;
	end;

{=================================}

	procedure DissBlocks;
		var
			h, v: Integer;
			value: LongInt;
			maskR: Rect;
	begin
		value := 1;
		repeat
			if (BTST(value, 0)) then
			begin
				value := BSR(value, 1);
				value := BitXor(value, $240);
			end
			else
			begin
				value := BSR(value, 1);
			end;
			h := (value mod 32) * 16;
			v := (value div 32) * 16;
			SetRect(maskR, h, v, h + 16, v + 16);
			if (inColor) then
				CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, maskR, maskR, srcCopy, wholeRgn)
			else
				CopyBits(offVirginMap, mainWndo^.portBits, maskR, maskR, srcCopy, wholeRgn);
		until (value = 1);
		if (inColor) then
			CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, wholeArea, wholeArea, srcCopy, wholeRgn)
		else
			CopyBits(offVirginMap, mainWndo^.portBits, wholeArea, wholeArea, srcCopy, wholeRgn);
		if (inColor) then
			CopyBits(BitMapPtr(virginCPtr^.portPixMap^)^, BitMapPtr(loadCPtr^.portPixMap^)^, wholeArea, wholeArea, srcCopy, wholeRgn)
		else
			CopyBits(offVirginMap, offLoadMap, wholeArea, wholeArea, srcCopy, wholeRgn);
	end;

{=================================}

	procedure DrawHiScores;
		var
			i, ranking: Integer;
			leftRect, rightRect, hole, tempRect: Rect;
			tempStr: Str255;
			wasPort: GrafPtr;
	begin
		if (playing) then
		begin
			demoMode := Randomize(lastDemo) + 1;
			Exit(DrawHiScores);
		end;

		GetPort(wasPort);
		if (inColor) then
			SetPort(GrafPtr(loadCPtr))
		else
			SetPort(offLoadPort);
		PenNormal;

		ranking := scoreList.rank;

		SetRect(leftRect, 10, 30, 251, 332);
		FillRect(leftRect, white);
		FrameRect(leftRect);
		PenPat(gray);
		if (inColor) then
			RGBForeColor(rgbLtBlue);
		for i := 0 to 20 do
		begin
			MoveTo(leftRect.left + 1, leftRect.top + 35 + (i * 13));
			LineTo(leftRect.right - 2, leftRect.top + 35 + (i * 13));
		end;
		if (inColor) then
			RGBForeColor(rgbBlack);
		if ((ranking < 20) and (inColor)) then
		begin
			RGBForeColor(rgbYellow);
			i := (ranking * 13) + leftRect.top + 36;
			SetRect(tempRect, leftRect.left + 32, i, leftRect.right - 2, i + 12);
			PaintRect(tempRect);
			RGBForeColor(rgbBlack);
		end;

		TextFont(16);
		TextSize(12);
		if (inColor) then
			RGBForeColor(rgbRed);
		MoveTo(leftRect.left + 33, leftRect.top + 30);
		DrawString('Rank');
		MoveTo(leftRect.left + 108, leftRect.top + 30);
		DrawString('Name');
		MoveTo(leftRect.left + 186, leftRect.top + 30);
		DrawString('Room #');
		if (inColor) then
			RGBForeColor(rgbBlack);
		for i := 0 to 19 do
		begin
			MoveTo(leftRect.left + 38, leftRect.top + 47 + (i * 13));
			NumToString(i + 1, tempStr);
			DrawString(tempStr);
			MoveTo(leftRect.left + 58, leftRect.top + 47 + (i * 13));
			DrawString(thisHouse.hiName[i]);
			MoveTo(leftRect.left + 206, leftRect.top + 47 + (i * 13));
			if (thisHouse.hiLevel[i] = 0) then
				tempStr := '+'
			else
				NumToString(thisHouse.hiLevel[i], tempStr);
			DrawString(tempStr);
		end;
		if ((ranking < 20) and (not inColor)) then
		begin
			i := (ranking * 13) + leftRect.top + 36;
			SetRect(tempRect, leftRect.left + 32, i, leftRect.right - 2, i + 12);
			InvertRect(tempRect);
		end;
		if (inColor) then
			RGBForeColor(rgbViolet);
		MoveTo(leftRect.left + 30, leftRect.top + 1);
		LineTo(leftRect.left + 30, leftRect.bottom);
		if (inColor) then
			RGBForeColor(rgbBlack);
		SetRect(hole, 0, 0, 12, 12);
		OffsetRect(hole, leftRect.left + 10, leftRect.top + 30);
		FillOval(hole, black);
		OffsetRect(hole, 0, 30);
		FillOval(hole, black);
		OffsetRect(hole, 0, 85);
		FillOval(hole, black);
		OffsetRect(hole, 0, 85);
		FillOval(hole, black);
		OffsetRect(hole, 0, 30);
		FillOval(hole, black);

		PenNormal;
		SetRect(rightRect, 261, 30, 502, 332);
		FillRect(rightRect, white);
		FrameRect(rightRect);
		PenPat(gray);
		if (inColor) then
			RGBForeColor(rgbLtBlue);
		for i := 0 to 20 do
		begin
			MoveTo(rightRect.left + 1, rightRect.top + 35 + (i * 13));
			LineTo(rightRect.right - 2, rightRect.top + 35 + (i * 13));
		end;

		if (inColor) then
			RGBForeColor(rgbBlack);

		if ((ranking < 20) and (inColor)) then
		begin
			RGBForeColor(rgbYellow);
			i := (ranking * 13) + rightRect.top + 36;
			SetRect(tempRect, rightRect.left + 32, i, rightRect.right - 2, i + 12);
			PaintRect(tempRect);
			RGBForeColor(rgbBlack);
		end;

		TextFont(16);
		TextSize(12);
		if (inColor) then
			RGBForeColor(rgbRed);
		MoveTo(rightRect.left + 33, rightRect.top + 30);
		DrawString('Score');
		MoveTo(rightRect.left + 98, rightRect.top + 30);
		DrawString('Room Name');
		if (inColor) then
			RGBForeColor(rgbBlack);
		for i := 0 to 19 do
		begin
			MoveTo(rightRect.left + 33, rightRect.top + 47 + (i * 13));
			NumToString(thisHouse.hiScores[i], tempStr);
			DrawString(tempStr);
			MoveTo(rightRect.left + 81, rightRect.top + 47 + (i * 13));
			DrawString(thisHouse.hiRoom[i]);
		end;
		if ((ranking < 20) and (not inColor)) then
		begin
			i := (ranking * 13) + rightRect.top + 36;
			SetRect(tempRect, rightRect.left + 32, i, rightRect.right - 2, i + 12);
			InvertRect(tempRect);
		end;

		if (inColor) then
			RGBForeColor(rgbViolet);
		MoveTo(rightRect.left + 30, rightRect.top + 1);
		LineTo(rightRect.left + 30, rightRect.bottom);
		if (inColor) then
			RGBForeColor(rgbBlack);
		SetRect(hole, 0, 0, 12, 12);
		OffsetRect(hole, rightRect.left + 10, rightRect.top + 30);
		FillOval(hole, black);
		OffsetRect(hole, 0, 30);
		FillOval(hole, black);
		OffsetRect(hole, 0, 85);
		FillOval(hole, black);
		OffsetRect(hole, 0, 85);
		FillOval(hole, black);
		OffsetRect(hole, 0, 30);
		FillOval(hole, black);

		if (inColor) then
		begin
			CopyBits(BitMapPtr(loadCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, leftRect, leftRect, srcCopy, wholeRgn);
			CopyBits(BitMapPtr(loadCPtr^.portPixMap^)^, GrafPtr(mainWndo)^.portBits, rightRect, rightRect, srcCopy, wholeRgn);
		end
		else
		begin
			CopyBits(offLoadMap, MainWndo^.portBits, leftRect, leftRect, srcCopy, wholeRgn);
			CopyBits(offLoadMap, MainWndo^.portBits, rightRect, rightRect, srcCopy, wholeRgn);
		end;
		SetPort(wasPort);
		demoMode := highScoreMode;
	end;

{=================================}

	function GetGrayRgn: RgnHandle;
	inline
		$2EB8, $09EE;

{=================================}

	function GetMBarHeight: Integer;
	inline
		$3EB8, $0BAA;

{=================================}

	procedure SetMBarHeight (newHeight: Integer);
	inline
		$31DF, $0BAA;

{=================================}

	function GetWindowList: WindowPtr;
	inline
		$2EB8, $9D6;

{=================================}

	function GetMBarRgn: RgnHandle;
		var
			theRect: Rect;
			worldRgn, mBarRgn: RgnHandle;
	begin
		theRect := GetGrayRgn^^.rgnBBox;
		UnionRect(theRect, screenBits.bounds, theRect);
		worldRgn := NewRgn;
		OpenRgn;
		FrameRoundRect(theRect, 16, 16);
		CloseRgn(worldRgn);

		theRect := screenBits.bounds;
		theRect.bottom := theRect.top + wasMBarHeight;
		mBarRgn := NewRgn;
		RectRgn(mBarRgn, theRect);
		SectRgn(worldRgn, mBarRgn, mBarRgn);

		DisposeRgn(worldRgn);
		GetMBarRgn := mBarRgn;
	end;

{=================================}

	procedure HideMenuBar;
		var
			theRect: Rect;
			mBarHeight: Integer;
			grayRgn, menuBarRgn: RgnHandle;
			startWindow: WindowPeek;
	begin
		mBarHeight := GetMBarHeight;
		if (mBarHeight <> 0) then
		begin
			grayRgn := GetGrayRgn;
			wasMBarHeight := mBarHeight;
			menuBarRgn := GetMBarRgn;
			SetMBarHeight(0);
			UnionRgn(grayRgn, menuBarRgn, grayRgn);

			startWindow := WindowPeek(GetWindowList);
			PaintBehind(startWindow, menuBarRgn);
			CalcVisBehind(startWindow, menuBarRgn);
			DisposeRgn(menuBarRgn);
		end;
	end;

{=================================}

	procedure ShowMenuBar;
		var
			grayRgn, menuBarRgn: RgnHandle;
	begin
		if (GetMBarHeight = 0) then
		begin
			grayRgn := GetGrayRgn;
			menuBarRgn := GetMBarRgn;
			SetMBarHeight(wasMBarHeight);

			DiffRgn(grayRgn, menuBarRgn, grayRgn);
			CalcVisBehind(WindowPeek(GetWindowList), menuBarRgn);
			DisposeRgn(menuBarRgn);
			DrawMenuBar;
		end;
	end;

{=================================}

	procedure FatalError;
	begin
		InitCursor;
		ShowMenuBar;
		ExitToShell;
	end;

{=================================}

	procedure RedrawWindowFrame;
		var
			tempRect: Rect;
			tempByte: SignedByte;
			thePict: PicHandle;
	begin
		SetPort(GrafPtr(mainWndo));
		PenNormal;
		if (inColor) then
			RGBForeColor(rgbBlack);

		ClipRect(fullArea);
		SetRect(tempRect, -rightOffset, -downOffset, 512 + (2 * rightOffset), 0);
		FillRect(tempRect, black);
		SetRect(tempRect, -rightOffset, 342, 512 + (2 * rightOffset), 342 + downOffset);
		FillRect(tempRect, black);
		SetRect(tempRect, -rightOffset, 0, 0, 342);
		FillRect(tempRect, black);
		SetRect(tempRect, 512, 0, 512 + rightOffset, 342);
		FillRect(tempRect, black);
		UseResFile(gliderResNum);
		if (inColor) then
		begin
			SetRect(tempRect, -64, 0, 0, 342);
			thePict := GetPicture(rSidePict1);
			if (thePict <> nil) then
			begin
				tempByte := HGetState(Handle(thePict));
				MoveHHi(Handle(thePict));
				HLock(Handle(thePict));
				DrawPicture(thePict, tempRect);
				HSetState(Handle(thePict), tempByte);
			end
			else
				GenericAlert(kErrNotEnoughMem);
			ReleaseResource(Handle(thePict));
		end;
		if (inColor) then
		begin
			SetRect(tempRect, 512, 0, 512 + 64, 342);
			thePict := GetPicture(rSidePict2);
			if (thePict <> nil) then
			begin
				tempByte := HGetState(Handle(thePict));
				MoveHHi(Handle(thePict));
				HLock(Handle(thePict));
				DrawPicture(thePict, tempRect);
				HSetState(Handle(thePict), tempByte);
			end
			else
				GenericAlert(kErrNotEnoughMem);
			ReleaseResource(Handle(thePict));
		end;
		ClipRect(wholeArea);
	end;

{=================================}

end.