⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.cpp

📁 VIGASOCO (VIdeo GAmes SOurce COde) Windows port (v0.01)
💻 CPP
字号:
// Video.cpp
//
/////////////////////////////////////////////////////////////////////////////

#include "Game.h"
#include <memory.h>
#include "Video.h"

int Video::pillOffsets[] = {
	0x62, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x0c, 0x01, 0x01, 0x04, 0x01, 0x01,
	0x01, 0x04, 0x04, 0x03, 0x0c, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x0c, 0x03,
	0x01, 0x01, 0x01, 0x03, 0x04, 0x04, 0x03, 0x0c, 0x06, 0x03, 0x04, 0x04, 0x03,
	0x0c, 0x06, 0x03, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x03, 0x04, 0x04, 0x0f, 0x03, 0x06, 0x04, 0x04, 0x0f, 0x03,
	0x06, 0x04, 0x04, 0x01, 0x01, 0x01, 0x0c, 0x03, 0x01, 0x01, 0x01, 0x03, 0x04,
	0x04, 0x03, 0x0c, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x0c, 0x03, 0x03, 0x03, 
	0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x0c, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01,
	0x01, 0x08, 0x18, 0x08, 0x18, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x0c, 0x01, 
	0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x04, 0x04, 0x03, 0x0c, 0x03, 0x03, 0x03,
	0x04, 0x04, 0x03, 0x0c, 0x03, 0x03, 0x03, 0x04, 0x04, 0x01, 0x01, 0x01, 0x0c,
	0x03, 0x01, 0x01, 0x01, 0x03, 0x04, 0x04, 0x0f, 0x03, 0x06, 0x04, 0x04, 0x0f,
	0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x03, 0x04, 0x04, 0x03, 0x0c, 0x06, 0x03, 0x04, 0x04, 0x03, 0x0c,
	0x06, 0x03, 0x04, 0x04, 0x03, 0x0c, 0x03, 0x01, 0x01, 0x01, 0x03, 0x04, 0x04,
	0x03, 0x0c, 0x03, 0x03, 0x03, 0x04, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x0c,
	0x01, 0x01, 0x04, 0x01, 0x01, 0x01
};

/////////////////////////////////////////////////////////////////////////////
// conversion methods
/////////////////////////////////////////////////////////////////////////////

// converts a position to a tile position
void Video::pos2TilePos(int posX, int posY, int &tilePosX, int &tilePosY)
{
	// each tile is 8x8
	tilePosX = posX/8;
	tilePosY = posY/8;

	// adjust to tile ranges
	tilePosX += 0x1e;
	tilePosY += 0x20;
}

// converts a tile position to screen coordinates
int Video::tilePos2ScreenCoord(int tilePosX, int tilePosY)
{
	tilePosX -= 0x20;
	tilePosY -= 0x20;

	return ((tilePosX & 0xff)*32 + (tilePosY & 0xff) + 0x40) & 0x3ff;
}

/////////////////////////////////////////////////////////////////////////////
// CRAM/VRAM initialization
/////////////////////////////////////////////////////////////////////////////

// clears Video RAM
void Video::clearVRAM(bool gamePlayAreaOnly)
{
	int init = (gamePlayAreaOnly) ? 0x040 : 0x000;
	int size = (gamePlayAreaOnly) ? 0x380 : 0x400;

	memset(&theGame->VRAM[init], 0x40, size);
}

// clears Color RAM
void Video::clearCRAM()
{
	memset(theGame->CRAM, 0x00, 0x400);
}

// inits CRAM data
void Video::initCRAM(int mode)
{
	// inits gameplay CRAM
	memset(&theGame->CRAM[0x040], (mode == 2) ? 0x1f : 0x10, 0x380);

	// inits top UI CRAM
	memset(&theGame->CRAM[0x3c0], 0x0f, 0x040);

	// mark "special" tiles if necessary
	if (mode == 1){
		// special color entry for pacman and ghosts initial map positions
		for (int i = 0; i < 6; i++){
			theGame->CRAM[0x1a0 + i*0x20 + 0x0c] = 0x1a;
			theGame->CRAM[0x1a0 + i*0x20 + 0x18] = 0x1a;
		}

		// special color entry for tunnel areas
		for (int i = 0; i < 5; i++){
			theGame->CRAM[0x040 + i*0x20 + 0x0e] = 0x1b;
			theGame->CRAM[0x040 + i*0x20 + 0x0f] = 0x1b;
			theGame->CRAM[0x040 + i*0x20 + 0x10] = 0x1b;

			theGame->CRAM[0x320 + i*0x20 + 0x0e] = 0x1b;
			theGame->CRAM[0x320 + i*0x20 + 0x0f] = 0x1b;
			theGame->CRAM[0x320 + i*0x20 + 0x10] = 0x1b;
		}

		// special color entry for ghost door
		theGame->CRAM[0x1ed] = 0x18;
		theGame->CRAM[0x20d] = 0x18;
	}
}

// init CRAM area where lives are displayed
void Video::initLivesCRAM()
{
	for (int j = 0; j < 2; j++){
		for (int i = 0; i < 10; i++){
			theGame->CRAM[0x012 + 0x20*j + i] = 0x09;
		}
	}
}

// restores special CRAM entries overwriten by player one or player two strings
void Video::restorePlayerTextCRAM()
{
	for (int i = 0; i < 6; i++){
		theGame->CRAM[0x1a0 + i*0x20 + 0x0c] = 0x1a;
	}
}

/////////////////////////////////////////////////////////////////////////////
// drawing
/////////////////////////////////////////////////////////////////////////////

// draw a ghost in the VRAM
void Video::drawTileGhost(int offset, int color)
{
	// draw first half
	theGame->VRAM[offset + 0x00] = 0xb1;
	theGame->VRAM[offset + 0x01] = 0xb3;
	theGame->VRAM[offset + 0x02] = 0xb5;

	// draw second half
	theGame->VRAM[offset + 0x20] = 0xb0;
	theGame->VRAM[offset + 0x21] = 0xb2;
	theGame->VRAM[offset + 0x22] = 0xb4;

	// set the color
	theGame->CRAM[offset + 0x00] = theGame->CRAM[offset + 0x01] = theGame->CRAM[offset + 0x02] = color;
	theGame->CRAM[offset + 0x20] = theGame->CRAM[offset + 0x21] = theGame->CRAM[offset + 0x22] = color;
}


// draw the fruits corresponding to the level (up to 7)
void Video::drawLevelFruits()
{
	if (theGame->state != DEMO){
		int currentLevel = theGame->levelState[0].currentLevel;

		static int levelFruit[20][2] = 
		{
			{ 0x90, 0x14 },	// cherry
			{ 0x94, 0x0f },	// strawberry
			{ 0x98, 0x15 }, // 1st orange
			{ 0x98, 0x15 }, // 2nd orange
			{ 0xa0, 0x14 }, // 1st apple
			{ 0xa0, 0x14 }, // 2nd apple
			{ 0xa4, 0x17 },	// 1st pineapple
			{ 0xa4, 0x17 }, // 2nd pineapple
			{ 0xa8, 0x09 },	// 1st galaxian
			{ 0xa8, 0x09 }, // 2nd galaxian
			{ 0x9c, 0x16 }, // 1st bell
			{ 0x9c, 0x16 },	// 2nd bell
			{ 0xac, 0x16 },	// 1st key
			
			{ 0xac, 0x16 },	// 1st key
			{ 0xac, 0x16 },	// 2nd key
			{ 0xac, 0x16 },	// 3rd key
			{ 0xac, 0x16 },	// 4th key
			{ 0xac, 0x16 },	// 5th key
			{ 0xac, 0x16 },	// 6th key
			{ 0xac, 0x16 }	// 7th key
		};

		int startingIndex = currentLevel - 6;

		// check bounds
		if (startingIndex < 0) startingIndex = 0;
		if (startingIndex > 12) startingIndex = 12;
		
		// show the fruits
		for (int i = 0; i < 7; i++){
			// should this fruit be visible?
			if (i <= currentLevel){
				// draw fruit
				Video::draw2x2Tile(0x004 + i*2, levelFruit[startingIndex + i][0]);
				Video::set2x2TileColor(0x004 + i*2, levelFruit[startingIndex + i][1]);
			} else {
				// draw emplty space
				Video::draw2x2Tile(0x004 + i*2, 0x40);
				Video::set2x2TileColor(0x004 + i*2, 0x00);
			}
		}
	}
}

// draw the lives
void Video::drawLives(int lives)
{
	// maxium of 5 lives
	for (int i = 0; i < 5; i++){
		if ((lives >= 6) || (lives == 0)){
			// empty that area
			Video::clear2x2Tile(0x01a - 2*i, 0x40);
		} else {
			// draw a pacman
			Video::draw2x2Tile(0x01a - 2*i, 0x20);
			lives--;
		}
	}
}

// draw 2 invisible lines to create a mini level
void Video::drawInvisibleMiniLevel()
{
	// for each column
	for (int i = 0; i < 28; i++){
		// mark two tiles as not accesible
		theGame->VRAM[0x40 + i*0x20 + 0x11] = 0xfc;
		theGame->VRAM[0x40 + i*0x20 + 0x13] = 0xfc;
	}
}

// draws the game level
void Video::drawGameLevel()
{
	static int levelTileData[] = {
		0x40, 0xfc, 0xd0, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd4, 0xfc,
		0xfc, 0xfc, 0xda, 0x02, 0xdc, 0xfc, 0xfc, 0xfc, 0xd0, 0xd2, 0xd2, 0xd2, 0xd2, 
		0xd6, 0xd8, 0xd2, 0xd2, 0xd2, 0xd2, 0xd4, 0xfc, 0xda, 0x09, 0xdc, 0xfc, 0xfc,
		0xfc, 0xda, 0x02, 0xdc, 0xfc, 0xfc, 0xfc, 0xda, 0x05, 0xde, 0xe4, 0x05, 0xdc,
		0xfc, 0xda, 0x02, 0xe6, 0xe8, 0xea, 0x02, 0xe6, 0xea, 0x02, 0xdc, 0xfc, 0xfc,
		0xfc, 0xda, 0x02, 0xdc, 0xfc, 0xfc, 0xfc, 0xda, 0x02, 0xe6, 0xea, 0x02, 0xe7,
		0xeb, 0x02, 0xe6, 0xea, 0x02, 0xdc, 0xfc, 0xda, 0x02, 0xde, 0xfc, 0xe4, 0x02,
		0xde, 0xe4, 0x02, 0xdc, 0xfc, 0xfc, 0xfc, 0xda, 0x02, 0xdc, 0xfc, 0xfc, 0xfc, 
		0xda, 0x02, 0xde, 0xe4, 0x05, 0xde, 0xe4, 0x02, 0xdc, 0xfc, 0xda, 0x02, 0xde, 
		0xfc, 0xe4, 0x02, 0xde, 0xe4, 0x02, 0xdc, 0xfc, 0xfc, 0xfc, 0xda, 0x02, 0xdc, 
		0xfc, 0xfc, 0xfc, 0xda, 0x02, 0xde, 0xf2, 0xe8, 0xe8, 0xea, 0x02, 0xde, 0xe4, 
		0x02, 0xdc, 0xfc, 0xda, 0x02, 0xe7, 0xe9, 0xeb, 0x02, 0xe7, 0xeb, 0x02, 0xe7,
		0xd2, 0xd2, 0xd2, 0xeb, 0x02, 0xe7, 0xd2, 0xd2, 0xd2, 0xeb, 0x02, 0xe7, 0xe9,
		0xe9, 0xe9, 0xeb, 0x02, 0xde, 0xe4, 0x02, 0xdc, 0xfc, 0xda, 0x1b, 0xde, 0xe4,
		0x02, 0xdc, 0xfc, 0xda, 0x02, 0xe6, 0xe8, 0xf8, 0x02, 0xf6, 0xe8, 0xe8, 0xe8,
		0xe8, 0xe8, 0xe8, 0xf8, 0x02, 0xf6, 0xe8, 0xe8, 0xe8, 0xea, 0x02, 0xe6, 0xf8,
		0x02, 0xf6, 0xe8, 0xe8, 0xf4, 0xe4, 0x02, 0xdc, 0xfc, 0xda, 0x02, 0xde, 0xfc,
		0xe4, 0x02, 0xf7, 0xe9, 0xe9, 0xf5, 0xf3, 0xe9, 0xe9, 0xf9, 0x02, 0xf7, 0xe9,
		0xe9, 0xe9, 0xeb, 0x02, 0xde, 0xe4, 0x02, 0xf7, 0xe9, 0xe9, 0xf5, 0xe4, 0x02,
		0xdc, 0xfc, 0xda, 0x02, 0xde, 0xfc, 0xe4, 0x05, 0xde, 0xe4, 0x0b, 0xde, 0xe4,
		0x05, 0xde, 0xe4, 0x02, 0xdc, 0xfc, 0xda, 0x02, 0xde, 0xfc, 0xe4, 0x02, 0xe6, 
		0xea, 0x02, 0xde, 0xe4, 0x02, 0xec, 0xd3, 0xd3, 0xd3, 0xee, 0x02, 0xe6, 0xea,
		0x02, 0xde, 0xe4, 0x02, 0xe6, 0xea, 0x02, 0xde, 0xe4, 0x02, 0xdc, 0xfc, 0xda,
		0x02, 0xe7, 0xe9, 0xeb, 0x02, 0xde, 0xe4, 0x02, 0xe7, 0xeb, 0x02, 0xdc, 0xfc, 
		0xfc, 0xfc, 0xda, 0x02, 0xde, 0xe4, 0x02, 0xe7, 0xeb, 0x02, 0xde, 0xe4, 0x02,
		0xe7, 0xeb, 0x02, 0xdc, 0xfc, 0xda, 0x06, 0xde, 0xe4, 0x05, 0xf0, 0xfc, 0xfc,
		0xfc, 0xda, 0x02, 0xde, 0xe4, 0x05, 0xde, 0xe4, 0x05, 0xdc, 0xfc, 0xfa, 0xe8,
		0xe8, 0xe8, 0xea, 0x02, 0xde, 0xf2, 0xe8, 0xe8, 0xea, 0x02, 0xce, 0xfc, 0xfc,
		0xfc, 0xda, 0x02, 0xde, 0xf2, 0xe8, 0xe8, 0xea, 0x02, 0xde, 0xf2, 0xe8, 0xe8,
		0xea, 0x02, 0xdc, 0x00
	};

	int tile;
	int i = 0;
	int offset = 0;

	while (true){
		// get data (0 = end of level data)
		tile = levelTileData[i];

		if (tile == 0) break;

		// if it's < 0x80, it's an offset
		if (tile < 0x80){
			offset += tile - 1;
			i++;
			tile = levelTileData[i];
		}

		offset++;

		// store tile
		theGame->VRAM[offset] = tile;

		// calculate mirror position
		int mirrorOffset = (0x3e0 + (offset & 0x1f)*2) - offset;

		// store mirror tile
		theGame->VRAM[mirrorOffset] = tile ^ 1;

		i++;
	}
}

// draw active player pills
void Video::drawPlayerPills()
{
	int offset = 0;

	// iterate through normal pills
	for (int i = 0; i < 240; i++){
		offset += pillOffsets[i];

		// if the player hasn't eaten it, draw it
		if (theGame->levelState[0].normalPills[i]){
			theGame->VRAM[offset] = 0x10;
		}
	}

	// draw big pills
	theGame->VRAM[0x064] = theGame->levelState[0].superPills[0];
	theGame->VRAM[0x078] = theGame->levelState[0].superPills[1];
	theGame->VRAM[0x384] = theGame->levelState[0].superPills[2];
	theGame->VRAM[0x398] = theGame->levelState[0].superPills[3];
}

// clear remainig level pills (used if rack test is set)
void Video::clearLevelPills()
{
	int pos = 0x040;

	while (pos != 0x3c0){
		int tile = theGame->VRAM[pos];

		// if it has found a tile, clear it
		if ((tile == 0x10) || (tile == 0x12) || (tile == 0x14)){
			theGame->VRAM[pos] = 0x40;
		}

		pos++;
	}
}

/////////////////////////////////////////////////////////////////////////////
// helper methods
/////////////////////////////////////////////////////////////////////////////

// draws a 2x2 tile graphic
void Video::draw2x2Tile(int offset, int tile)
{
	theGame->VRAM[offset + 0x00] = tile + 0;
	theGame->VRAM[offset + 0x01] = tile + 1;
	theGame->VRAM[offset + 0x20] = tile + 2;
	theGame->VRAM[offset + 0x21] = tile + 3;
}

// clear a 2x2 tile graphic
void Video::clear2x2Tile(int offset, int tile)
{
	theGame->VRAM[offset + 0x00] = tile;
	theGame->VRAM[offset + 0x01] = tile;
	theGame->VRAM[offset + 0x20] = tile;
	theGame->VRAM[offset + 0x21] = tile;
}

// sets the color for a 2x2 tile graphic
void Video::set2x2TileColor(int offset, int color)
{
	theGame->CRAM[offset + 0x00] = color;
	theGame->CRAM[offset + 0x01] = color;
	theGame->CRAM[offset + 0x20] = color;
	theGame->CRAM[offset + 0x21] = color;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -