/* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ /* * This code is based on original Mortville Manor DOS source code * Copyright (c) 1988-1989 Lankhor */ #include "common/endian.h" #include "common/rect.h" #include "mortevielle/mouse.h" #include "mortevielle/mortevielle.h" #include "mortevielle/var_mor.h" namespace Mortevielle { const int m_arrow = 0; const int m_point_hand = 1; bool int_m, clic; int m_show, x_s, y_s, p_o_s, mouse_shwn; int s_s[12][6]; /** * Initialize the mouse * @remarks Originally called 'init_mouse' */ void initMouse() { registres reg; mouse_shwn = 0; x_s = 0; y_s = 0; p_o_s = 0; g_vm->setMouseClick(false); m_show = m_arrow; if ((READ_LE_UINT16(&mem[0xcc]) == 0) && (READ_LE_UINT16(&mem[0xce]) == 0)) int_m = false; if (int_m) { reg.ax = 0; intr(0x33, reg); int_m = (reg.ax == -1); if (int_m) { reg.ax = 4; reg.cx = 0; reg.dx = 0; intr(0x33, reg); } } } /** * Hide the mouse * @remarks Originally called 'hide_mouse' */ void hideMouse() { int i, j, k, ps;; bool imp; --mouse_shwn; if (mouse_shwn == 0) { imp = odd(y_s); j = p_o_s; switch (_currGraphicalDevice) { case MODE_CGA: k = 0; j = ((uint)y_s >> 1) * 80 + ((uint)x_s >> 2); do { WRITE_LE_UINT16(&mem[0xb000 * 16 + j], s_s[0][k]); WRITE_LE_UINT16(&mem[0xb800 * 16 + j + 2], s_s[1][k]); WRITE_LE_UINT16(&mem[0xba00 * 16 + j], s_s[2][k]); WRITE_LE_UINT16(&mem[0xba00 * 16 + j + 2], s_s[3][k]); j += 80; ++k; } while (!(k >= 5)); break; case MODE_AMSTRAD1512: for (i = 0; i <= 3; ++i) { port[0x3dd] = 1 << i; k = 0; j = p_o_s; do { if (imp) { WRITE_LE_UINT16(&mem[0xb800 * 16 + j], s_s[i][k]); j += 80 - 0x2000; } else { WRITE_LE_UINT16(&mem[0xb800 * 16 + j], s_s[i][k]); j += 0x2000; } imp = !imp; ++k; } while (!(k >= 8)); } break; case MODE_EGA: port[0x3c4] = 2; port[0x3ce] = 8; port[0x3cf] = 255; i = 0; do { port[0x3c5] = 1 << i; k = 0; j = p_o_s; do { ps = mem[0xa000 * 16 + j]; mem[0xa000 * 16 + j] = lo(s_s[i][k]); ps = mem[0xa000 * 16 + j + 1]; mem[0xa000 * 16 + j + 1] = hi(s_s[i][k]); j += 80; ++k; } while (!(k >= 8)); ++i; } while (!(i == 4)); break; case MODE_HERCULES: j = ((uint)y_s >> 1) * 80 + ((uint)x_s >> 3); for (i = 0; i <= 5; ++i) { for (k = 0; k <= 3; ++k) WRITE_LE_UINT16(&mem[0xb000 * 16 + k * 0x200 + j], s_s[i][k]); j += 80; } break; case MODE_TANDY: j = ((uint)y_s >> 2) * 160 + ((uint)x_s >> 1); k = 0; do { for (i = 0; i <= 3; ++i) { WRITE_LE_UINT16(&mem[0xb800 * 16 + 0x200 * i + j], s_s[k][i + (k << 2)]); WRITE_LE_UINT16(&mem[0xb800 * 16 + 0x200 * i + j + 2], s_s[k + 3][i + (k << 2)]); } j += 160; ++k; } while (!(k == 3)); break; default: break; } // case Gd } } /** * Show mouse * @remarks Originally called 'show_mouse' */ void showMouse() { int i, j, k, l; bool imp; mouse_shwn = mouse_shwn + 1; if (mouse_shwn != 1) return; j = p_o_s; imp = odd(y_s); i = x_s & 7; switch (_currGraphicalDevice) { case MODE_CGA: k = 0; j = ((uint)y_s >> 1) * 80 + ((uint)x_s >> 2); do { s_s[0][k] = READ_LE_UINT16(&mem[0xb800 * 16 + j]); s_s[1][k] = READ_LE_UINT16(&mem[0xb800 * 16 + j + 2]); s_s[2][k] = READ_LE_UINT16(&mem[0xba00 * 16 + j]); s_s[3][k] = READ_LE_UINT16(&mem[0xba00 * 16 + j + 2]); j += 80; ++k; } while (!(k >= 5)); break; case MODE_AMSTRAD1512: for (i = 0; i <= 3; ++i) { j = p_o_s; imp = odd(y_s); port[0x3de] = i; k = 0; do { if (imp) { s_s[i][k] = READ_LE_UINT16(&mem[0xb800 * 16 + j]); j += 80 - 0x2000; } else { s_s[i][k] = READ_LE_UINT16(&mem[0xb800 * 16 + j]); j += 0x2000; } imp = !imp; ++k; } while (!(k >= 8)); } break; case MODE_EGA: port[0x3ce] = 4; l = 0; do { port[0x3cf] = l; k = 0; j = p_o_s; do { s_s[l][k] = mem[0xa000 * 16 + j] + (mem[(0xa000 * 16) + j + 1] << 8); j += 80; ++k; } while (!(k >= 8)); ++l; } while (!(l == 4)); break; case MODE_HERCULES: j = ((uint)y_s >> 1) * 80 + ((uint)x_s >> 3); for (i = 0; i <= 5; ++i) { for (k = 0; k <= 3; ++k) s_s[i][k] = READ_LE_UINT16(&mem[0xb000 * 16 + k * 0x200 + j]); j += 80; } break; case MODE_TANDY: j = ((uint)y_s >> 2) * 160 + ((uint)x_s >> 1); k = 0; do { for (i = 0; i <= 3; ++i) { s_s[k][i + (k << 2)] = READ_LE_UINT16(&mem[0xb800 * 16 + 0x200 * i + j]); s_s[k + 3][i + (k << 2)] = READ_LE_UINT16(&mem[0xb800 * 16 + 0x200 * i + j + 2]); } j += 160; ++k; } while (!(k == 3)); break; default: break; } // case Gd } /** * Set mouse position * @remarks Originally called 'pos_mouse' */ void setMousePos(int x, int y) { if (x > 314 * res) x = 314 * res; else if (x < 0) x = 0; if (y > 199) y = 199; else if (y < 0) y = 0; if ((x == x_s) && (y == y_s)) return; // Set the new position g_vm->setMousePos(Common::Point(x, y)); } /** * Get mouse poisition * @remarks Originally called 'read_pos_mouse' */ void getMousePos(int &x, int &y, int &c) { x = g_vm->getMousePos().x; y = g_vm->getMousePos().y; c = g_vm->getMouseClick() ? 1 : 0; } /** * Move mouse * @remarks Originally called 'mov_mouse' */ void moveMouse(bool &funct, char &key) { bool p_key; char in1, in2; int cx, cy, cd; // Set defaults and check pending events funct = false; key = '\377'; p_key = keypressed(); // If mouse button clicked, return it if (g_vm->getMouseClick()) return; // Handle any pending keypresses while (p_key) { CHECK_QUIT; in1 = get_ch(); getMousePos(cx, cy, cd); switch (toupper(in1)) { case '4': cx = cx - 8; break; case '2': cy = cy + 8; break; case '6': cx = cx + 8; break; case '8': cy = cy - 8; break; case '7': cy = 1; cx = 1; break; case '1': cx = 1; cy = 190; break; case '9': cx = 315 * res; cy = 1; break; case '3': cy = 190; cx = 315 * res; break; case '5': cy = 100; cx = 155 * res; break; case ' ': case '\15': g_vm->setMouseClick(true); return; break; case '\33': p_key = keypressed(); if (p_key) { in2 = get_ch(); if ((in2 >= ';') && (in2 <= 'D')) { funct = true; key = in2; return; } else { switch (in2) { case 'K': --cx; break; case 'P': ++cy; break; case 'M': cx += 2; break; case 'H': --cy; break; case 'G': --cx; --cy; break; case 'I': ++cx; --cy; break; case 'O': --cx; ++cy; break; case 'Q': ++cx; ++cy; break; default: break; } // case } } break; case 'I': cx = res * 32; cy = 8; break; case 'D': cx = 80 * res; cy = 8; break; case 'A': cx = 126 * res; cy = 8; break; case 'S': cx = 174 * res; cy = 8; break; case 'P': cx = 222 * res; cy = 8; break; case 'F': cx = res * 270; cy = 8; break; case '\23': _soundOff = !_soundOff; return; break; case '\26': zuul = true; return; break; case '\24': // ^T => mode tandy funct = true; key = '\11'; break; case '\10': // ^H => mode Hercule funct = true; key = '\7'; break; case '\1': case '\3': case '\5': funct = true; key = in1; break; default: break; } setMousePos(cx, cy); p_key = keypressed(); } } } // End of namespace Mortevielle