/*
 * Kangaroo Punch MultiPlayer Game Server Mark II
 * Copyright (C) 2020-2021  Scott Duensing
 *
 * 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 <https://www.gnu.org/licenses/>.
 *
 */


#include "mouse.h"
#include "vesa.h"


// Based on http://www.brackeen.com/vga/source/djgpp20/mouse.c.html


#define MOUSE_INT             0x33

#define MOUSE_RESET           0x00
#define MOUSE_STATUS          0x03
#define MOUSE_GETMOTION       0x0B

#define MOUSE_LEFT_BUTTON     0x01
#define MOUSE_RIGHT_BUTTON    0x02
#define MOUSE_MIDDLE_BUTTON   0x04


static MouseT _mouse;


MouseT *mouseRead(void) {
	int32_t    x;
	int32_t    y;
	int16_t    dx;
	int16_t    dy;
	union REGS regs;

	regs.x.ax = MOUSE_GETMOTION;
	int86(MOUSE_INT, &regs, &regs);
	dx = regs.x.cx;  // Temporary assignment changes values to signed.
	dy = regs.x.dx;  // Don't skip this step.  :-)
	x = _mouse.x + dx;
	y = _mouse.y + dy;
	if (x < 0)            x = 0;
	if (x > _mouse.w - 1) x = _mouse.w - 1;
	if (y < 0)            y = 0;
	if (y > _mouse.h - 1) y = _mouse.h - 1;
	_mouse.x = (uint16_t)x;
	_mouse.y = (uint16_t)y;

	_mouse.buttonLeftWasDown   = _mouse.buttonLeft;
	_mouse.buttonRightWasDown  = _mouse.buttonRight;
	_mouse.buttonMiddleWasDown = _mouse.buttonMiddle;

	regs.x.ax = MOUSE_STATUS;
	int86(MOUSE_INT, &regs, &regs);
	_mouse.buttonLeft   = ((regs.x.bx & MOUSE_LEFT_BUTTON) > 0);
	_mouse.buttonRight  = ((regs.x.bx & MOUSE_RIGHT_BUTTON) > 0);
	_mouse.buttonMiddle = ((regs.x.bx & MOUSE_MIDDLE_BUTTON) > 0);

	return &_mouse;
}


void mouseShutdown(void) {
	// Nothing to do in DOS
}


int16_t mouseStartup(void) {
	union REGS regs;

	regs.x.ax = MOUSE_RESET;
	int86(MOUSE_INT, &regs, &regs);
	_mouse.active              = regs.x.ax;
	_mouse.buttonCount         = regs.x.bx == 0x0002 ? 2 : 3;
	_mouse.buttonLeft          = 0;
	_mouse.buttonRight         = 0;
	_mouse.buttonMiddle        = 0;
	_mouse.buttonLeftWasDown   = 0;
	_mouse.buttonRightWasDown  = 0;
	_mouse.buttonMiddleWasDown = 0;
	_mouse.x                   = 0;
	_mouse.y                   = 0;
	_mouse.w                   = vbeDisplayWidthGet();
	_mouse.h                   = vbeDisplayHeightGet();

	mouseRead();

	return _mouse.active;
}
