mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-09 12:22:51 +00:00
15602e77c7
Refactor the existing CGA rendering code to make it compatible with HGA rendering. The main changes include the introduction of engine variables and a move away from macros.
330 lines
7.1 KiB
C++
330 lines
7.1 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/system.h"
|
|
|
|
#include "chamber/chamber.h"
|
|
|
|
#include "chamber/common.h"
|
|
#include "chamber/resdata.h"
|
|
#include "chamber/cga.h"
|
|
#include "chamber/room.h"
|
|
#include "chamber/sound.h"
|
|
|
|
namespace Chamber {
|
|
|
|
|
|
byte *anima_end_ofs;
|
|
|
|
byte last_anim_y = 0;
|
|
byte last_anim_x = 0;
|
|
byte anim_shift_y = 0;
|
|
byte anim_shift_x = 0;
|
|
byte last_anim_height;
|
|
byte last_anim_width;
|
|
byte anim_cycle;
|
|
byte anim_flags;
|
|
byte anim_use_dot_effect;
|
|
uint16 anim_draw_delay;
|
|
byte dot_effect_step;
|
|
uint16 dot_effect_delay;
|
|
|
|
extern uint16 cpu_speed_delay;
|
|
|
|
extern void loadLutinSprite(uint16 lutidx);
|
|
|
|
void getScratchBuffer(byte mode) {
|
|
byte *buffer = scratch_mem2;
|
|
uint16 offs = 0;
|
|
if (mode & 0x80)
|
|
offs += 3200;
|
|
if (mode & 0x40)
|
|
offs += 1600;
|
|
lutin_mem = buffer + offs;
|
|
}
|
|
|
|
void animLoadSprite(byte **panim) {
|
|
byte mode;
|
|
byte index;
|
|
mode = *((*panim)++);
|
|
index = *((*panim)++);
|
|
getScratchBuffer(mode);
|
|
loadLutinSprite(index);
|
|
}
|
|
|
|
void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx, int8 dy) {
|
|
if (anim_flags == 7)
|
|
return;
|
|
if (anim_flags & 4) {
|
|
if (anim_cycle == 0)
|
|
return;
|
|
if (anim_flags & 2) {
|
|
*sprh = anim_cycle;
|
|
if (anim_cycle >= dy)
|
|
anim_cycle -= dy;
|
|
else
|
|
anim_cycle = 0;
|
|
} else if (anim_flags & 1) {
|
|
*sprw = anim_cycle;
|
|
anim_cycle--;
|
|
} else {
|
|
*x -= dx;
|
|
*sprite += (*sprw - anim_cycle) * 2;
|
|
*sprw = anim_cycle;
|
|
anim_cycle--;
|
|
}
|
|
} else if (anim_flags & 2) {
|
|
if (*sprw == anim_cycle) {
|
|
anim_cycle = 0;
|
|
} else if (anim_flags & 1) {
|
|
*sprw = anim_cycle;
|
|
anim_cycle++;
|
|
} else {
|
|
*x -= dx;
|
|
*sprite += (*sprw - anim_cycle) * 2;
|
|
*sprw = anim_cycle;
|
|
anim_cycle++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte height, byte *target) {
|
|
uint16 offs;
|
|
uint16 xx = x * 4;
|
|
uint16 ww = width * 4;
|
|
uint16 cur_image_end = ww * height;
|
|
|
|
for (offs = 0; offs != cur_image_end;) {
|
|
byte mask = 0xC0 >> (((xx + offs % ww) % 4) * 2);
|
|
uint16 ofs = cga_CalcXY(xx + offs % ww, y + offs / ww);
|
|
|
|
target[ofs] = (target[ofs] & ~mask) | (source[ofs] & mask);
|
|
|
|
if (dot_effect_delay / 4 != 0) {
|
|
uint16 i;
|
|
for (i = 0; i < dot_effect_delay / 4; i++) ; /*TODO: weak delay*/
|
|
}
|
|
|
|
offs += dot_effect_step;
|
|
if (offs > cur_image_end)
|
|
offs -= cur_image_end;
|
|
}
|
|
}
|
|
|
|
void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 pitch) {
|
|
uint16 delay;
|
|
byte ex, ey, updx, updy, updw, updh;
|
|
uint16 ofs = CalcXY_p(x, y);
|
|
cga_BackupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
|
|
cga_BlitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
|
|
ex = x + sprw;
|
|
ey = y + sprh;
|
|
if (last_anim_height != 0) {
|
|
if (last_anim_x + last_anim_width > ex)
|
|
ex = last_anim_x + last_anim_width;
|
|
|
|
if (last_anim_y + last_anim_height > ey)
|
|
ey = last_anim_y + last_anim_height;
|
|
|
|
updx = (x > last_anim_x) ? last_anim_x : x;
|
|
updy = (y > last_anim_y) ? last_anim_y : y;
|
|
} else {
|
|
updx = x;
|
|
updy = y;
|
|
}
|
|
updw = ex - updx;
|
|
updh = ey - updy;
|
|
ofs = CalcXY_p(updx, updy);
|
|
/*TODO looks like here was some code before*/
|
|
for (delay = 0; delay < anim_draw_delay; delay++) {
|
|
g_system->delayMillis(1000 / 16 / 25);
|
|
}
|
|
waitVBlank();
|
|
|
|
if (anim_use_dot_effect)
|
|
copyScreenBlockWithDotEffect(backbuffer, updx, updy, updw, updh, frontbuffer);
|
|
else {
|
|
cga_CopyScreenBlock(backbuffer, updw, updh, frontbuffer, ofs);
|
|
}
|
|
cga_RestoreImage(sprit_load_buffer, backbuffer);
|
|
|
|
last_anim_x = x;
|
|
last_anim_y = y;
|
|
last_anim_width = sprw;
|
|
last_anim_height = sprh;
|
|
|
|
anim_shift_x = anim_shift_y = 0;
|
|
}
|
|
|
|
void animUndrawSprite(void) {
|
|
cga_CopyScreenBlock(backbuffer, last_anim_width, last_anim_height, CGA_SCREENBUFFER, CalcXY_p(last_anim_x, last_anim_y));
|
|
last_anim_height = 0;
|
|
}
|
|
|
|
void playAnimCore(byte **panim) {
|
|
byte mode;
|
|
uint16 count, count2;
|
|
byte *pframe;
|
|
mode = *((*panim)++);
|
|
anim_flags = mode & 7;
|
|
count = mode >> 3;
|
|
|
|
while (count--) {
|
|
pframe = *panim;
|
|
mode = *pframe++;
|
|
anim_draw_delay = ((mode & ~7) >> 3) << 1;
|
|
dot_effect_step = (mode & ~7) >> 3;
|
|
dot_effect_delay = 500;
|
|
count2 = mode & 7;
|
|
while (count2--) {
|
|
byte *sprite;
|
|
byte sprw, sprh;
|
|
byte x, y;
|
|
int8 dx, dy;
|
|
uint16 pitch;
|
|
mode = *pframe++;
|
|
getScratchBuffer(mode);
|
|
dy = mode & 7;
|
|
dx = (mode >> 3) & 7;
|
|
|
|
dx = (dx & 1) ? -(dx & ~1) : dx;
|
|
dx /= 2;
|
|
dy = (dy & 1) ? -(dy & ~1) : dy;
|
|
|
|
x = last_anim_x + dx + anim_shift_x;
|
|
y = last_anim_y + dy + anim_shift_y;
|
|
|
|
sprite = lutin_mem;
|
|
sprw = *sprite++;
|
|
sprh = *sprite++;
|
|
|
|
pitch = sprw * 2;
|
|
clipSprite(&x, &y, &sprw, &sprh, &sprite, dx, dy);
|
|
animDrawSprite(x, y, sprw, sprh, sprite, pitch);
|
|
|
|
if (anim_flags & 4) {
|
|
if (anim_cycle == 0) {
|
|
animUndrawSprite();
|
|
goto end;
|
|
}
|
|
} else if (anim_flags & 2) {
|
|
if (anim_cycle == 0) {
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
end:
|
|
;
|
|
mode = *((*panim)++);
|
|
*panim += mode & 7;
|
|
}
|
|
|
|
void anim1(byte **panim) {
|
|
anim_cycle = 0xFF;
|
|
anim_use_dot_effect = 0;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
void anim2(byte **panim) {
|
|
anim_cycle = 1;
|
|
anim_use_dot_effect = 0;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
void anim3(byte **panim) {
|
|
anim_cycle = 1;
|
|
anim_use_dot_effect = 0;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
void anim4(byte **panim) {
|
|
anim_cycle = last_anim_width - 1;
|
|
anim_use_dot_effect = 0;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
void anim5(byte **panim) {
|
|
anim_cycle = last_anim_width - 1;
|
|
anim_use_dot_effect = 0;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
void anim6(byte **panim) {
|
|
anim_cycle = last_anim_height;
|
|
anim_use_dot_effect = 0;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
void anim7(byte **panim) {
|
|
anim_cycle = 0xFF;
|
|
anim_use_dot_effect = 1;
|
|
playAnimCore(panim);
|
|
}
|
|
|
|
typedef void (*animhandler_t)(byte **panim);
|
|
|
|
animhandler_t anim_handlers[] = {
|
|
animLoadSprite,
|
|
anim1,
|
|
anim2,
|
|
anim3,
|
|
anim4,
|
|
anim5,
|
|
anim6,
|
|
anim7
|
|
};
|
|
|
|
void playAnim(byte index, byte x, byte y) {
|
|
byte sound;
|
|
byte *panim;
|
|
|
|
last_anim_width = 0;
|
|
last_anim_height = 0;
|
|
last_anim_x = x;
|
|
last_anim_y = y;
|
|
|
|
panim = seekToEntry(anima_data, index - 1, &anima_end_ofs);
|
|
while (panim != anima_end_ofs) {
|
|
byte mode = *panim;
|
|
switch (mode) {
|
|
case 0xFE: /*set shift*/
|
|
panim++;
|
|
anim_shift_x = *panim++;
|
|
anim_shift_y = *panim++;
|
|
break;
|
|
case 0xFD: /*play sfx*/
|
|
panim++;
|
|
sound = *panim++;
|
|
panim++; /*unused*/
|
|
playSound(sound);
|
|
break;
|
|
case 0xFC: /*nothing*/
|
|
panim++;
|
|
break;
|
|
default:
|
|
anim_handlers[mode & 7](&panim);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End of namespace Chamber
|