/
trilirium
/
Pacman
Обзор
Документация
Войти
/
trilirium
/
Pacman
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Video.cpp
368 строк
12 KB
Trilirium
first commit
19 июн 2026, 11:07
19 июн 2026, 11:07
d44591e
Код
Авторство
О чём код?
// Video.cpp // ///////////////////////////////////////////////////////////////////////////// #include "Game.h" #include <memory.h> #include "Video.h" using namespace Puckman; 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; }