diff options
author | Robert Göffringmann | 2003-05-27 16:42:20 +0000 |
---|---|---|
committer | Robert Göffringmann | 2003-05-27 16:42:20 +0000 |
commit | bc290162bd01acfad205d91175a727d21e032fbe (patch) | |
tree | 6dc6021e97cf585cbbb2646e0951dcd08ebde1bc | |
parent | af2574c02d23e220010bc727b3488a1aeaed78d1 (diff) | |
download | scummvm-rg350-bc290162bd01acfad205d91175a727d21e032fbe.tar.gz scummvm-rg350-bc290162bd01acfad205d91175a727d21e032fbe.tar.bz2 scummvm-rg350-bc290162bd01acfad205d91175a727d21e032fbe.zip |
implemented screen.asm and sprites.asm (not yet working)
svn-id: r8036
-rw-r--r-- | sky/logic.cpp | 25 | ||||
-rw-r--r-- | sky/logic.h | 15 | ||||
-rw-r--r-- | sky/screen.cpp | 434 | ||||
-rw-r--r-- | sky/screen.h | 52 | ||||
-rw-r--r-- | sky/sky.cpp | 56 | ||||
-rw-r--r-- | sky/sky.h | 3 | ||||
-rw-r--r-- | sky/skydefs.h | 13 |
7 files changed, 567 insertions, 31 deletions
diff --git a/sky/logic.cpp b/sky/logic.cpp index cf5c88f9a3..3b17128dc7 100644 --- a/sky/logic.cpp +++ b/sky/logic.cpp @@ -48,7 +48,8 @@ static const LogicTable logicTable[] = { &SkyLogic::simpleAnim, // 16 Module anim without x,y's }; -SkyLogic::SkyLogic(SkyDisk *skyDisk, SkyGrid *skyGrid, SkyText *skyText, SkyMusicBase *skyMusic, SkyMouse *skyMouse, SkySound *skySound, uint32 gameVersion) { +SkyLogic::SkyLogic(SkyScreen *skyScreen, SkyDisk *skyDisk, SkyGrid *skyGrid, SkyText *skyText, SkyMusicBase *skyMusic, SkyMouse *skyMouse, SkySound *skySound, uint32 gameVersion) { + _skyScreen = skyScreen; _skyDisk = skyDisk; _skyGrid = skyGrid; _skyText = skyText; @@ -1113,7 +1114,8 @@ bool SkyLogic::fnCacheFast(uint32 a, uint32 b, uint32 c) { } bool SkyLogic::fnDrawScreen(uint32 a, uint32 b, uint32 c) { - warning("Stub: fnDrawScreen"); + printf("Call: fnDrawScreen(%X, %X)\n",a,b); + _skyScreen->fnDrawScreen(a, b); return true; } @@ -1995,20 +1997,30 @@ bool SkyLogic::fnStopFx(uint32 a, uint32 b, uint32 c) { } bool SkyLogic::fnStartMusic(uint32 a, uint32 b, uint32 c) { - error("Stub: fnStartMusic"); + _skyMusic->startMusic((uint16)a); + return true; + //error("Stub: fnStartMusic"); } bool SkyLogic::fnStopMusic(uint32 a, uint32 b, uint32 c) { - error("Stub: fnStopMusic"); + _skyMusic->startMusic(0); + return true; + //error("Stub: fnStopMusic"); } bool SkyLogic::fnFadeDown(uint32 a, uint32 b, uint32 c) { + printf("fnFadeDown(scroll = %d);\n",a); + _skyScreen->fnFadeDown(a); + return true; // this is actually already implemented in SkyScreen - error("Stub: fnFadeDown"); + //error("Stub: fnFadeDown"); } bool SkyLogic::fnFadeUp(uint32 a, uint32 b, uint32 c) { - error("Stub: fnFadeUp"); + printf("fnFadeUp(scroll = %d, palette = %d);\n",a,b); + _skyScreen->fnFadeUp(a,b); + return true; + //error("Stub: fnFadeUp"); } bool SkyLogic::fnQuitToDos(uint32 a, uint32 b, uint32 c) { @@ -2027,4 +2039,3 @@ bool SkyLogic::fnPrintf(uint32 a, uint32 b, uint32 c) { printf("fnPrintf: %d\n", a); return true; } - diff --git a/sky/logic.h b/sky/logic.h index 4fae765399..e3fc3a6559 100644 --- a/sky/logic.h +++ b/sky/logic.h @@ -28,11 +28,13 @@ #include "sky/autoroute.h" #include "sky/musicbase.h" #include "sky/mouse.h" +#include "sky/screen.h" enum scriptVariableOffsets { RESULT = 0, SCREEN = 1, LOGIC_LIST_NO = 2, + DRAW_LIST_NO = 8, CUR_ID = 12, MOUSE_STATUS = 13, MOUSE_STOP = 14, @@ -42,6 +44,13 @@ enum scriptVariableOffsets { PLAYER_MOOD = 29, PLAYER_SCREEN = 30, HIT_ID = 37, + LAYER_0_ID = 41, + LAYER_1_ID = 42, + LAYER_2_ID = 43, + LAYER_3_ID = 44, + GRID_1_ID = 45, + GRID_2_ID = 46, + GRID_3_ID = 47, THE_CHOSEN_ONE = 51, TEXT1 = 53, MENU_LENGTH = 100, @@ -50,9 +59,12 @@ enum scriptVariableOffsets { CUR_SECTION = 143 }; +class SkyAutoRoute; +class SkyScreen; + class SkyLogic { public: - SkyLogic(SkyDisk *skyDisk, SkyGrid *skyGrid, SkyText *skyText, SkyMusicBase *skyMusic, SkyMouse *skyMouse, SkySound *skySound, uint32 gameVersion); + SkyLogic(SkyScreen *skyScreen, SkyDisk *skyDisk, SkyGrid *skyGrid, SkyText *skyText, SkyMusicBase *skyMusic, SkyMouse *skyMouse, SkySound *skySound, uint32 gameVersion); void engine(); void nop(); @@ -216,6 +228,7 @@ protected: uint32 _gameVersion; + SkyScreen *_skyScreen; SkyDisk *_skyDisk; SkyGrid *_skyGrid; SkyText *_skyText; diff --git a/sky/screen.cpp b/sky/screen.cpp index 6f0d721bae..1599e30b2c 100644 --- a/sky/screen.cpp +++ b/sky/screen.cpp @@ -50,8 +50,12 @@ SkyScreen::SkyScreen(OSystem *pSystem, SkyDisk *pDisk) { uint8 tmpPal[1024]; _system->init_size(FULL_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); - _gameGrid = (uint8 *)malloc(GRID_X * GRID_Y * 2); + _gameGrid = (uint8*)malloc(GRID_X * GRID_Y * 2); + _backScreen = (uint8*)malloc(GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT); + forceRefresh(); + _currentScreen = NULL; + _scrollScreen = NULL; //blank the first 240 colors of the palette memset(tmpPal, 0, GAME_COLOURS * 4); @@ -66,6 +70,7 @@ SkyScreen::SkyScreen(OSystem *pSystem, SkyDisk *pDisk) { //set the palette _system->set_palette(tmpPal, 0, VGA_COLOURS); + _currentPalette = 0; _seqInfo.framesLeft = 0; _seqInfo.seqData = _seqInfo.seqDataPos = NULL; @@ -76,6 +81,7 @@ SkyScreen::~SkyScreen(void) { free(_gameGrid); if (_currentScreen) free(_currentScreen); + if (_backScreen) free(_backScreen); } //set a new palette, pal is a pointer to dos vga rgb components 0..63 @@ -86,6 +92,18 @@ void SkyScreen::setPalette(uint8 *pal) { _system->update_screen(); } +void SkyScreen::halvePalette(void) { + + uint8 halfPalette[1024]; + for (uint8 cnt = 0; cnt < GAME_COLOURS; cnt++) { + halfPalette[(cnt << 2) | 0] = _palette[(cnt << 2) | 0] >> 1; + halfPalette[(cnt << 2) | 1] = _palette[(cnt << 2) | 1] >> 1; + halfPalette[(cnt << 2) | 2] = _palette[(cnt << 2) | 2] >> 1; + halfPalette[(cnt << 2) | 3] = 0; + } + _system->set_palette(halfPalette, 0, GAME_COLOURS); +} + void SkyScreen::setPalette(uint16 fileNum) { uint8 *tmpPal = _skyDisk->loadFile(fileNum, NULL); @@ -122,22 +140,100 @@ void SkyScreen::convertPalette(uint8 *inPal, uint8* outPal) { //convert 3 byte 0 } } -//action = 0, simply fade out -//action = 1, scroll left -//action = 2, scroll right -void SkyScreen::fnFadeDown(uint8 action) { +void SkyScreen::recreate(void) { - if (action) { - - //do scroll - warning("SkyScreen::fnFadeDown: Scrolling not yet implemented!\n"); + // check the game grid for changed blocks + if (!SkyLogic::_scriptVariables[LAYER_0_ID]) return ; + uint8 *gridPos = _gameGrid; + uint8 *screenData = (uint8*)SkyState::fetchItem(SkyLogic::_scriptVariables[LAYER_0_ID]); + if (!screenData) { + error("SkyScreen::recreate():\nSkyState::fetchItem(SkyLogic::_scriptVariables[LAYER_0_ID](%X)) returned NULL",SkyLogic::_scriptVariables[LAYER_0_ID]); + } + uint8 *screenPos = _backScreen; + + for (uint8 cnty = 0; cnty < GRID_Y; cnty++) { + for (uint8 cntx = 0; cntx < GRID_X; cntx++) { + if (gridPos[0] & 0x80) { + gridPos[0] &= 0x7F; // reset recreate flag + gridPos[0] |= 1; // set bit for flip routine + uint8 *savedScreenY = screenPos; + for (uint8 gridCntY = 0; gridCntY < GRID_H; gridCntY++) { + memcpy(screenPos, screenData, GRID_W); + screenPos += GAME_SCREEN_WIDTH; + screenData += GRID_W; + } + screenPos = savedScreenY + GRID_W; + } else { + screenPos += GRID_W; + screenData += GRID_W * GRID_H; + } + gridPos++; + } + screenPos += (GRID_H - 1) * GAME_SCREEN_WIDTH; + } + showScreen(_backScreen); +} + +void SkyScreen::flip(void) { + + // mouse_flag |= MF_NO_UPDATE; + // drawMouseToBackScreen(); + uint8 *screenPos = _currentScreen; + uint8 *backPos = _backScreen; + for (uint8 cnty = 0; cnty < GRID_Y; cnty++) { + for (uint8 cntx = 0; cntx < GRID_X; cntx++) { + if (_gameGrid[cnty * GRID_X +cntx] & 1) { + _gameGrid[cnty * GRID_X +cntx] &= ~1; + uint8 *saveBackY = backPos; + uint8 *saveScreenY = screenPos; + for (uint8 gridLineCnt = 0; gridLineCnt < GRID_H; gridLineCnt++) { + memcpy(screenPos, backPos, GRID_W); + screenPos += GAME_SCREEN_WIDTH; + backPos += GAME_SCREEN_WIDTH; + } + backPos = saveBackY + GRID_W; + screenPos = saveBackY + GRID_W; + } else { + backPos += GRID_W; + screenPos += GRID_W; + } + } + screenPos += (GRID_H - 1) * GAME_SCREEN_WIDTH; + backPos += (GRID_H - 1) * GAME_SCREEN_WIDTH; + } + // mouse_flag &= ~MF_NO_UPDATE; + // _skyMouse->restoreDataToBackScreen(); + showScreen(_backScreen); +} + +void SkyScreen::fnDrawScreen(uint32 palette, uint32 scroll) { + + // set up the new screen + fnFadeDown(scroll); + forceRefresh(); + recreate(); + spriteEngine(); + flip(); + fnFadeUp(palette, scroll); + showScreen(_backScreen); +} + +void SkyScreen::fnFadeDown(uint32 scroll) { + if (scroll) { + printf("warning: SkyScreen::fnFadeDown doesn't check (SYSTEM_FLAGS & SF_NO_SCROLL)\n"); + // scrolling is performed by fnFadeUp. It's just prepared here + _scrollScreen = _currentScreen; + _currentScreen = (uint8*)malloc(FULL_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); + // the game will draw the new room into _currentScreen which + // will be scrolled into the visible screen by fnFadeUp + // fnFadeUp also frees the _scrollScreen } else { for (uint8 cnt = 0; cnt < 32; cnt++) { palette_fadedown_helper((uint32 *)_palette, GAME_COLOURS); _system->set_palette(_palette, 0, GAME_COLOURS); _system->update_screen(); - waitForTimer(); + waitForTimer(); } } } @@ -189,6 +285,65 @@ void SkyScreen::paletteFadeUp(uint8 *pal) { } } +void SkyScreen::fnFadeUp(uint32 palNum, uint32 scroll) { + + //_currentScreen points to new screen, + //_scrollScreen points to graphic showing old room + //if (!(systemFlags & SF_NO_SCROLL) && (!scroll)) { + if (scroll) printf("warning: fnFadeUp doesn't check (systemFlags & SF_NO_SCROLL)"); + if (scroll == 123) { + // scroll left (going right) + if (!_currentScreen) error("SkyScreen::fnFadeUp[Scroll L]: _currentScreen is NULL!\n"); + if (!_scrollScreen) error("SkyScreen::fnFadeUp[Scroll L]: _scrollScreen is NULL!\n"); + uint8 *scrNewPtr, *scrOldPtr; + for (uint8 scrollCnt = 0; scrollCnt < (GAME_SCREEN_WIDTH / SCROLL_JUMP) - 1; scrollCnt++) { + scrNewPtr = _currentScreen + scrollCnt * SCROLL_JUMP; + scrOldPtr = _scrollScreen; + for (uint8 lineCnt = 0; lineCnt < GAME_SCREEN_HEIGHT; lineCnt++) { + memmove(scrOldPtr, scrOldPtr + SCROLL_JUMP, GAME_SCREEN_WIDTH - SCROLL_JUMP); + memcpy(scrOldPtr + GAME_SCREEN_WIDTH - SCROLL_JUMP, scrNewPtr, SCROLL_JUMP); + scrNewPtr += GAME_SCREEN_WIDTH; + scrOldPtr += GAME_SCREEN_WIDTH; + } + showScreen(_scrollScreen); + waitForTimer(); + } + showScreen(_currentScreen); + free(_scrollScreen); + } else if (scroll == 321) { + // scroll right (going left) + if (!_currentScreen) error("SkyScreen::fnFadeUp[Scroll R]: _currentScreen is NULL!\n"); + if (!_scrollScreen) error("SkyScreen::fnFadeUp[Scroll R]: _scrollScreen is NULL!\n"); + uint8 *scrNewPtr, *scrOldPtr; + for (uint8 scrollCnt = 0; scrollCnt < (GAME_SCREEN_WIDTH / SCROLL_JUMP) - 1; scrollCnt++) { + scrNewPtr = _currentScreen + GAME_SCREEN_WIDTH - (scrollCnt + 1) * SCROLL_JUMP; + scrOldPtr = _scrollScreen; + for (uint8 lineCnt = 0; lineCnt < GAME_SCREEN_HEIGHT; lineCnt++) { + memmove(scrOldPtr + SCROLL_JUMP, scrOldPtr, GAME_SCREEN_WIDTH - SCROLL_JUMP); + memcpy(scrOldPtr, scrNewPtr, SCROLL_JUMP); + scrNewPtr += GAME_SCREEN_WIDTH; + scrOldPtr += GAME_SCREEN_WIDTH; + } + showScreen(_scrollScreen); + waitForTimer(); + } + showScreen(_currentScreen); + free(_scrollScreen); + } else { + uint8 *palette = (uint8*)SkyState::fetchCompact(palNum); + if (palette == NULL) + error("SkyScreen::fnFadeUp: can't fetch compact %X.\n", palNum); +#ifdef SCUMM_BIG_ENDIAN + byte tmpPal[256 * 3]; + for (uint16 cnt = 0; cnt < 256*3; cnt++) + tmpPal[cnt] = palette[cnt ^ 1]; + paletteFadeUp(tmpPal); +#else + paletteFadeUp(palette); +#endif + } +} + void SkyScreen::waitForTimer(void) { _gotTick = false; @@ -260,3 +415,262 @@ bool SkyScreen::sequenceRunning(void) { return _seqInfo.running; } + +//- sprites.asm routines + +void SkyScreen::spriteEngine(void) { + + doSprites(BACK); + sortSprites(); + doSprites(FORE); +} + +void SkyScreen::sortSprites(void) { + + StSortList sortList[30]; + uint32 currDrawList = DRAW_LIST_NO; + bool nextDrawList = false; + while (SkyLogic::_scriptVariables[currDrawList]) { + // big_sort_loop + uint32 spriteCnt = 0; + do { // a_new_draw_list: + uint16 *drawListData = (uint16*)SkyState::fetchCompact(SkyLogic::_scriptVariables[currDrawList]); + nextDrawList = false; + while ((!nextDrawList) && (drawListData[0])) { + if (drawListData[0] == 0xFFFF) { + currDrawList = drawListData[1]; + nextDrawList = true; + } else { + // process_this_id: + Compact *spriteComp = SkyState::fetchCompact(drawListData[0]); + if ((spriteComp->status & 4) && // is it sortable playfield?(!?!) + (spriteComp->screen == SkyLogic::_scriptVariables[SCREEN])) { // on current screen + dataFileHeader *spriteData = + (dataFileHeader*)SkyState::fetchItem(spriteComp->frame >> 6); + if (!spriteData) { + printf("Missing file %d!\n",spriteComp->frame >> 6); + spriteComp->status = 0; + } else { + sortList[spriteCnt].yCood = spriteComp->ycood + spriteData->s_offset_y + spriteData->s_height; + sortList[spriteCnt].compact = spriteComp; + sortList[spriteCnt].sprite = spriteData; + spriteCnt++; + } + } + drawListData++; + } + } + } while (nextDrawList); + // made_list: + if (spriteCnt > 1) { // bubble sort + for (uint32 cnt1 = 0; cnt1 < spriteCnt; cnt1++) + for (uint32 cnt2 = cnt1 + 1; cnt2 < spriteCnt; cnt2++) + if (sortList[cnt1].yCood <= sortList[cnt2].yCood) { + StSortList tmp; + tmp.yCood = sortList[cnt1].yCood; + tmp.sprite = sortList[cnt1].sprite; + tmp.compact = sortList[cnt1].compact; + sortList[cnt1].yCood = sortList[cnt2].yCood; + sortList[cnt1].sprite = sortList[cnt2].sprite; + sortList[cnt1].compact = sortList[cnt2].compact; + sortList[cnt2].yCood = tmp.yCood; + sortList[cnt2].sprite = tmp.sprite; + sortList[cnt2].compact = tmp.compact; + } + } + for (uint32 cnt = 0; cnt < spriteCnt; cnt++) { + drawSprite((uint8*)sortList[cnt].sprite, sortList[cnt].compact); + if (sortList[cnt].compact->status & 8) vectorToGame(0x81); + else vectorToGame(1); + if (sortList[cnt].compact->status & 0x200) verticalMask(); + } + } +} + +void SkyScreen::doSprites(uint8 layer) { + + uint16 drawListNum = DRAW_LIST_NO; + uint32 idNum; + bool getNextDrawList; + uint16* drawList; + while (SkyLogic::_scriptVariables[drawListNum]) { // std sp loop + idNum = SkyLogic::_scriptVariables[drawListNum]; + drawListNum++; + + drawList = (uint16*)SkyState::fetchCompact(idNum); + getNextDrawList = false; + while(drawList[0]) { + // new_draw_list: + while ((!getNextDrawList) && (drawList[0])) { + // back_loop: + if (drawList[0]) { + if (drawList[0] == 0xFFFF) { + // new_draw_list + idNum = drawList[1]; + getNextDrawList = true; + } else { + // not_new_list + Compact *spriteData = SkyState::fetchCompact(drawList[0]); + drawList++; + if ((spriteData->status & (1 << layer)) && + (spriteData->screen == SkyLogic::_scriptVariables[SCREEN])) { + uint8 *toBeDrawn = (uint8*)SkyState::fetchItem(spriteData->frame >> 6); + drawSprite(toBeDrawn, spriteData); + if (layer == FORE) verticalMask(); + + if (spriteData->status & 8) vectorToGame(0x81); + else vectorToGame(1); + } + } + } + } + if (drawList[0]) { + drawList = (uint16*)SkyState::fetchCompact(idNum); + getNextDrawList = false; + } + } + } +} + +void SkyScreen::drawSprite(uint8 *spriteInfo, Compact *sprCompact) { + + if (spriteInfo == NULL) { + warning("SkyScreen::drawSprite Can't draw sprite. Data %d was not loaded.\n", sprCompact->frame >> 6); + sprCompact->status = 0; + return ; + } + dataFileHeader *sprDataFile = (dataFileHeader *)spriteInfo; + _sprWidth = sprDataFile->s_width; + _sprHeight = sprDataFile->s_height; + _maskX1 = _maskX2 = 0; + uint8 *spriteData = spriteInfo + (sprCompact->frame & 0x3F) * sprDataFile->s_sp_size; + spriteData += sizeof(dataFileHeader); + + int32 spriteY = sprCompact->ycood + sprDataFile->s_offset_y - TOP_LEFT_Y; + if (spriteY < 0) { + spriteY = ~spriteY; + if (_sprHeight <= (uint32)spriteY) { + _sprWidth = 0; + return ; + } + _sprHeight -= spriteY; + spriteData += sprDataFile->s_width * spriteY; + spriteY = 0; + } else { + int32 botClip = GAME_SCREEN_HEIGHT - sprDataFile->s_height - spriteY; + if (botClip < 0) { + if (botClip + _sprHeight <= 0) { + _sprWidth = 0; + return ; + } + _sprHeight += botClip; + } + } + _sprY = (uint32)spriteY; + int32 spriteX = sprCompact->xcood + sprDataFile->s_offset_x - TOP_LEFT_X; + if (spriteX < 0) { + spriteX = ~spriteX; + if (_sprWidth <= (uint32)spriteX) { + _sprWidth = 0; + return ; + } + _sprWidth -= spriteX; + _maskX1 = spriteX; + spriteX = 0; + } else { + int32 rightClip = GAME_SCREEN_WIDTH - sprDataFile->s_width - spriteX; + if (rightClip < 0) { + rightClip = ~rightClip; + if (_sprWidth <= (uint32)rightClip) { + _sprWidth = 0; + return ; + } + _sprWidth -= rightClip; + _maskX2 = rightClip; + } + } + _sprX = (uint32)spriteX; + uint8 *screenPtr = _backScreen + _sprY * GAME_SCREEN_WIDTH + _sprX; + if ((_sprX + _sprWidth >= 320) || (_sprY + _sprHeight >= 192)) { + warning("SkyScreen::drawSprite fatal error: got x = %d, y = %d, w = %d, h = %d\n",_sprX, _sprY, _sprWidth, _sprHeight); + _sprWidth = 0; + return ; + } + for (uint8 cnty = 0; cnty < _sprHeight; cnty++) { + spriteData += _maskX1; + for (uint8 cntx = 0; cntx < _sprWidth; cntx++) + if (spriteData[cntx]) screenPtr[cntx] = spriteData[cntx]; + spriteData += _maskX2; + screenPtr += GAME_SCREEN_WIDTH; + } + // Convert the sprite coordinate/size values to blocks for vertical mask and/or vector to game + _sprWidth += _sprX + GRID_W-1; + _sprHeight += _sprY + GRID_H-1; + + _sprX >>= GRID_W_SHIFT; + _sprWidth >>= GRID_W_SHIFT; + _sprY >>= GRID_H_SHIFT; + _sprHeight >>= GRID_H_SHIFT; + + _sprWidth -= _sprX; + _sprHeight -= _sprY; +} + +void SkyScreen::vectorToGame(uint8 gridVal) { + + uint8 *trgGrid = _gameGrid + _sprY * GRID_X +_sprX; // why?!?! + for (uint32 cnty = 0; cnty < _sprHeight; cnty++) { + for (uint32 cntx = 0; cntx < _sprWidth; cntx++) + trgGrid[cntx] |= gridVal; + trgGrid += GRID_X; + } +} + +void SkyScreen::vertMaskSub(uint16 *grid, uint32 gridOfs, uint8 *screenPtr, uint32 layerId) { + + for (uint32 cntx = 0; cntx < _sprHeight; cntx++) { // start_x | block_loop + if (grid[gridOfs]) { + if (!(grid[gridOfs] & 0x8000)) { + uint32 gridVal = grid[gridOfs]-1; + gridVal *= GRID_W * GRID_H; + uint8 *dataSrc = (uint8*)SkyState::fetchItem(SkyLogic::_scriptVariables[layerId]) + gridVal; + uint8 *dataTrg = screenPtr; + for (uint32 grdCntY = 0; grdCntY < GRID_H; grdCntY++) { + for (uint32 grdCntX = 0; grdCntX < GRID_W; grdCntX++) + if (dataSrc[grdCntX]) dataTrg[grdCntX] = dataSrc[grdCntX]; + dataSrc += GRID_W; + dataTrg += GAME_SCREEN_WIDTH; + } + } // dummy_end: + screenPtr -= GRID_H * GAME_SCREEN_WIDTH; + gridOfs -= GRID_X; + } else return; + } // next_x +} + +void SkyScreen::verticalMask(void) { + + if (_sprWidth == 0) return ; + uint32 startGridOfs = (_sprY + _sprHeight - 1) * GRID_X + _sprX; + uint8 *startScreenPtr = (_sprY + _sprHeight - 1) * GRID_H * GAME_SCREEN_WIDTH + _sprX * GRID_W + _backScreen; + + for (uint32 layerCnt = LAYER_1_ID; layerCnt <= LAYER_3_ID; layerCnt++) { + uint32 gridOfs = startGridOfs; + uint8 *screenPtr = startScreenPtr; + for (uint32 widCnt = 0; widCnt < _sprWidth; widCnt++) { // x_loop + uint32 nLayerCnt = layerCnt; + while (SkyLogic::_scriptVariables[nLayerCnt + 3]) { + uint16 *scrGrid; + scrGrid = (uint16*)SkyState::fetchItem(SkyLogic::_scriptVariables[layerCnt + 3]); + if (scrGrid[gridOfs]) { + vertMaskSub(scrGrid, gridOfs, screenPtr, layerCnt); + break; + } else nLayerCnt++; + } + // next_x: + screenPtr += GRID_W; + gridOfs++; + } + } +} + diff --git a/sky/screen.h b/sky/screen.h index f88be28555..ac315b94a4 100644 --- a/sky/screen.h +++ b/sky/screen.h @@ -29,20 +29,31 @@ #include "sky/disk.h" #include "sky/skydefs.h" #include "sky/sky.h" +#include "sky/logic.h" #define SCROLL_JUMP 16 #define VGA_COLOURS 256 #define GAME_COLOURS 240 #define SEQ_DELAY 3 +#define FORE 1 +#define BACK 0 + +typedef struct { + uint16 yCood; + Compact *compact; + dataFileHeader *sprite; +} StSortList; + +class SkyState; + class SkyScreen { public: SkyScreen(OSystem *pSystem, SkyDisk *pDisk); ~SkyScreen(void); +// void takeScriptVars(uint32 *pScriptVars) { _scriptVariables = pScriptVars; }; void setPalette(uint8 *pal); void setPalette(uint16 fileNum); - - void fnFadeDown(uint8 action); void paletteFadeUp(uint8 *pal); void paletteFadeUp(uint16 fileNr); @@ -55,16 +66,31 @@ public: bool sequenceRunning(void); uint32 seqFramesLeft(void) { return _seqInfo.framesLeft; }; uint8 *giveCurrent(void) { return _currentScreen; }; + void halvePalette(void); + + //- regular screen.asm routines + void forceRefresh(void) { memset(_gameGrid, 0x80, GRID_X * GRID_Y); }; + void fnFadeUp(uint32 palNum, uint32 scroll); + void fnFadeDown(uint32 scroll); + void fnDrawScreen(uint32 palette, uint32 scroll); + void clearScreen(void) { memset(_currentScreen, 0, FULL_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); }; + private: OSystem *_system; SkyDisk *_skyDisk; static uint8 _top16Colours[16*3]; uint8 _palette[1024]; + uint32 _currentPalette; bool volatile _gotTick; - void waitForTimer(void); + void processSequence(void); + uint8 *_gameGrid; + uint8 *_currentScreen; + uint8 *_scrollScreen; + uint8 *_backScreen; + //uint32 *_scriptVariables; struct { uint32 framesLeft; uint32 delay; @@ -72,21 +98,29 @@ private: uint8 *seqDataPos; bool running; } _seqInfo; - void processSequence(void); - - uint8 *_currentScreen; - //byte *_workScreen; - //byte *_backScreen; //byte *_tempPal; //byte *_workPalette; //byte *_halfPalette; //byte *_scrollAddr; //byte *_lScreenBuf, *_lPaletteBuf; - byte *_gameGrid; + //- more regular screen.asm + layer.asm routines void convertPalette(uint8 *inPal, uint8* outPal); void palette_fadedown_helper(uint32 *pal, uint num); + void recreate(void); + void flip(void); + + //- sprite.asm routines + // fixme: get rid of these globals + uint32 _sprWidth, _sprHeight, _sprX, _sprY, _maskX1, _maskX2; + void spriteEngine(void); + void doSprites(uint8 layer); + void sortSprites(void); + void drawSprite(uint8 *spriteData, Compact *sprCompact); + void verticalMask(void); + void vertMaskSub(uint16 *grid, uint32 gridOfs, uint8 *screenPtr, uint32 layerId); + void vectorToGame(uint8 gridVal); }; #endif //SKYSCREEN_H diff --git a/sky/sky.cpp b/sky/sky.cpp index 46f6042d30..13a3b7409e 100644 --- a/sky/sky.cpp +++ b/sky/sky.cpp @@ -73,8 +73,51 @@ SkyState::SkyState(GameDetector *detector, OSystem *syst) _introTextSave = 0; } +void SkyState::showQuitMsg(void) { + + uint8 *textBuf1 = (uint8*)calloc(GAME_SCREEN_WIDTH * 14 + sizeof(struct dataFileHeader),1); + uint8 *textBuf2 = (uint8*)calloc(GAME_SCREEN_WIDTH * 14 + sizeof(struct dataFileHeader),1); + char *vText1, *vText2; + uint8 *screenData = _skyScreen->giveCurrent(); + switch (_language) { + case DE_DEU: vText1 = VIG_DE1; vText2 = VIG_DE2; break; + case FR_FRA: vText1 = VIG_FR1; vText2 = VIG_FR2; break; + case IT_ITA: vText1 = VIG_IT1; vText2 = VIG_IT2; break; + case PT_BRA: vText1 = VIG_PT1; vText2 = VIG_PT2; break; + default: vText1 = VIG_EN1; vText2 = VIG_EN2; break; + } + _skyText->displayText(vText1, textBuf1, true, 320, 255); + _skyText->displayText(vText2, textBuf2, true, 320, 255); + uint8 *curLine1 = textBuf1 + sizeof(struct dataFileHeader); + uint8 *curLine2 = textBuf2 + sizeof(struct dataFileHeader); + uint8 *targetLine = screenData + GAME_SCREEN_WIDTH * 80; + for (uint8 cnty = 0; cnty < 14; cnty++) { + for (uint16 cntx = 0; cntx < GAME_SCREEN_WIDTH; cntx++) { + if (curLine1[cntx]) + targetLine[cntx] = curLine1[cntx]; + if (curLine2[cntx]) + (targetLine + 24 * GAME_SCREEN_WIDTH)[cntx] = curLine2[cntx]; + } + curLine1 += GAME_SCREEN_WIDTH; + curLine2 += GAME_SCREEN_WIDTH; + targetLine += GAME_SCREEN_WIDTH; + } + _skyScreen->halvePalette(); + _skyScreen->showScreen(screenData); + free(textBuf1); free(textBuf2); +} + SkyState::~SkyState() { - + + delete _skyLogic; + delete _skyGrid; + delete _skySound; + delete _skyMusic; + showQuitMsg(); + delete _skyText; + delete _skyMouse; + delete _skyScreen; + delay(1500); } void SkyState::errorString(const char *buf1, char *buf2) { @@ -98,7 +141,7 @@ void SkyState::go() { intro(); loadBase0(); - + while (1) { delay(100); _skyLogic->engine(); @@ -121,8 +164,8 @@ void SkyState::initialise(void) { _gameVersion = _skyDisk->determineGameVersion(); _skyText = new SkyText(_skyDisk, _gameVersion, _language); _skyMouse = new SkyMouse(_skyDisk); - _skyScreen = new SkyScreen(_system, _skyDisk); + initVirgin(); //initMouse(); initItemList(); @@ -130,7 +173,7 @@ void SkyState::initialise(void) { //initialiseRouter(); loadFixedItems(); _skyGrid = new SkyGrid(_skyDisk); - _skyLogic = new SkyLogic(_skyDisk, _skyGrid, _skyText, _skyMusic, _skyMouse, _skySound, _gameVersion); + _skyLogic = new SkyLogic(_skyScreen, _skyDisk, _skyGrid, _skyText, _skyMusic, _skyMouse, _skySound, _gameVersion); _timer = Engine::_timer; // initialize timer *after* _skyScreen has been initialized. _timer->installProcedure(&timerHandler, 1000000 / 50); //call 50 times per second @@ -190,6 +233,11 @@ void SkyState::loadFixedItems(void) { } +void **SkyState::fetchItem(uint32 num) { + + return _itemList[num]; +} + void SkyState::timerHandler(void *ptr) { ((SkyState*)ptr)->gotTimerTick(); @@ -94,6 +94,7 @@ public: static bool isCDVersion(uint32 version); static Compact *fetchCompact(uint32 a); + static void **fetchItem(uint32 num); static void **_itemList[300]; @@ -132,6 +133,8 @@ protected: void shutdown(); + void showQuitMsg(void); + RandomSource _rnd; }; diff --git a/sky/skydefs.h b/sky/skydefs.h index b3a916538a..382f208de3 100644 --- a/sky/skydefs.h +++ b/sky/skydefs.h @@ -26,6 +26,19 @@ //This file is incomplete, several flags still missing. +#define VIG_EN1 "Game over player one" +#define VIG_EN2 "BE VIGILANT" +#define VIG_DE1 "Das Spiel ist aus." +#define VIG_DE2 "SEI WACHSAM" +#define VIG_FR1 "Game over joueur 1" +#define VIG_FR2 "SOYEZ VIGILANTS" +#define VIG_SE1 "Spelet r slut, Agent 1." +#define VIG_SE2 "VAR VAKSAM" +#define VIG_IT1 "Game over giocatore 1" +#define VIG_IT2 "SIATE VIGILANTI" +#define VIG_PT1 "Fim de jogo para o jogador um" +#define VIG_PT2 "BE VIGILANT" + #define ST_COLLISION_BIT 5 #define S_COUNT 0 |