diff options
Diffstat (limited to 'simon/icons.cpp')
-rw-r--r-- | simon/icons.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/simon/icons.cpp b/simon/icons.cpp new file mode 100644 index 0000000000..413195ec8e --- /dev/null +++ b/simon/icons.cpp @@ -0,0 +1,228 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001-2004 The ScummVM project + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" + +#include "common/file.h" + +#include "simon/simon.h" +#include "simon/intern.h" + +namespace Simon { + +void SimonEngine::loadIconFile() { + File in; + if (_game & GF_ACORN) + in.open("ICONDATA"); + else if (_game & GF_AMIGA) + in.open("icon.pkd"); + else + in.open("ICON.DAT"); + uint size; + + if (in.isOpen() == false) + error("Can't open icons file 'ICON.DAT'"); + + size = in.size(); + + _icon_file_ptr = (byte *)malloc(size); + if (_icon_file_ptr == NULL) + error("Out of icon memory"); + + in.read(_icon_file_ptr, size); + in.close(); +} + +// Thanks to Stuart Caie for providing the original +// C conversion upon which this function is based. +void decompress_icon_amiga (byte *dst, byte *src, byte base, uint pitch) { + byte icon_pln[288]; + byte *i, *o, x, y; + + // Decode RLE planar icon data + i = src; + o = icon_pln; + while (o < &icon_pln[288]) { + x = *i++; + if (x < 128) { + do { + *o++ = *i++; + *o++ = *i++; + *o++ = *i++; + } while (x-- > 0); + } else { + x = 256 - x; + do { + *o++ = i[0]; + *o++ = i[1]; + *o++ = i[2]; + } while (x-- > 0); + i += 3; + } + } + + // Translate planar data to chunky (very slow method) + for (y = 0; y < 24; y++) { + for (x = 0; x < 24; x++) { + byte pixel = + (icon_pln[(( y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 1 : 0) + | (icon_pln[((24 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 2 : 0) + | (icon_pln[((48 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 4 : 0) + | (icon_pln[((72 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 8 : 0); + if (pixel) + dst[x] = pixel | base; + } + dst += pitch; + } +} + +static void decompress_icon(byte *dst, byte *src, uint w, uint h_org, byte base, uint pitch) { + int8 reps; + byte color_1, color_2; + byte *dst_org = dst; + uint h = h_org; + + for (;;) { + reps = *src++; + if (reps < 0) { + reps--; + color_1 = *src >> 4; + if (color_1 != 0) + color_1 |= base; + color_2 = *src++ & 0xF; + if (color_2 != 0) + color_2 |= base; + + do { + if (color_1 != 0) + *dst = color_1; + dst += pitch; + if (color_2 != 0) + *dst = color_2; + dst += pitch; + + // reached bottom? + if (--h == 0) { + // reached right edge? + if (--w == 0) + return; + dst = ++dst_org; + h = h_org; + } + } while (++reps != 0); + } else { + do { + color_1 = *src >> 4; + if (color_1 != 0) + *dst = color_1 | base; + dst += pitch; + + color_2 = *src++ & 0xF; + if (color_2 != 0) + *dst = color_2 | base; + dst += pitch; + + // reached bottom? + if (--h == 0) { + // reached right edge? + if (--w == 0) + return; + dst = ++dst_org; + h = h_org; + } + } while (--reps >= 0); + } + } +} + + +void SimonEngine::draw_icon_c(FillOrCopyStruct *fcs, uint icon, uint x, uint y) { + byte *dst; + byte *src; + + _lock_word |= 0x8000; + dst = dx_lock_2(); + + if (!(_game & GF_SIMON2)) { + // Simon 1 + dst += (x + fcs->x) * 8; + dst += (y * 25 + fcs->y) * _dx_surface_pitch; + + if (_game & GF_AMIGA) { + src = _icon_file_ptr; + src += READ_BE_UINT32(&((uint32 *)src)[icon]); + decompress_icon_amiga (dst, src, 0xE0, _dx_surface_pitch); + } else { + src = _icon_file_ptr; + src += READ_LE_UINT16(&((uint16 *)src)[icon]); + decompress_icon(dst, src, 24, 12, 0xE0, _dx_surface_pitch); + } + } else { + // Simon 2 + dst += 110; + dst += x; + dst += (y + fcs->y) * _dx_surface_pitch; + + src = _icon_file_ptr; + src += READ_LE_UINT16(&((uint16 *)src)[icon * 2 + 0]); + decompress_icon(dst, src, 20, 10, 0xE0, _dx_surface_pitch); + + src = _icon_file_ptr; + src += READ_LE_UINT16(&((uint16 *)src)[icon * 2 + 1]); + decompress_icon(dst, src, 20, 10, 0xD0, _dx_surface_pitch); + } + + dx_unlock_2(); + _lock_word &= ~0x8000; +} + +uint SimonEngine::setup_icon_hit_area(FillOrCopyStruct *fcs, uint x, uint y, uint icon_number, + Item *item_ptr) { + HitArea *ha; + + ha = findEmptyHitArea(); + + if (!(_game & GF_SIMON2)) { + ha->x = (x + fcs->x) << 3; + ha->y = y * 25 + fcs->y; + ha->item_ptr = item_ptr; + ha->width = 24; + ha->height = 24; + ha->flags = 0xB0; + ha->id = 0x7FFD; + ha->layer = 100; + ha->unk3 = 0xD0; + } else { + ha->x = x + 110; + ha->y = fcs->y + y; + ha->item_ptr = item_ptr; + ha->width = 20; + ha->height = 20; + ha->flags = 0xB0; + ha->id = 0x7FFD; + ha->layer = 100; + ha->unk3 = 0xD0; + } + + return ha - _hit_areas; +} + +} // End of namespace Simon |