/* Screen handling utility functions V1.22 4/9/04
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM 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.
   WOUM 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 WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _SCREEN_H
#define _SCREEN_H

/* Screen BPP settings for mode specifiers */
#define SCRN_1B 0
#define SCRN_2B 1
#define SCRN_4B 2
#define SCRN_8B 3
#define SCRN_16B 4
#define SCRN_24B 5
/* Screen BPP settings as stored in screen_struct's */
#define MODE_1B 1
#define MODE_2B 3
#define MODE_4B 15
#define MODE_8B 63
#define MODE_8BP 255
#define MODE_16B 65535
#define MODE_24B -1

#ifndef SCREEN_C_ONLY
/* ARM code CLS function*/
#ifdef __cplusplus
extern "C" {
#endif
void screen_qcls(int,int);
#ifdef __cplusplus
}
#endif

#define screen_cls() screen_qcls((int) screen.vdu,screen.length)
#else
#define screen_cls() ({fputc(12,stdout);fflush(stdout);})
#endif
/* screen_cls()
   If the fast ARM code version from armscreen.s is in use, then the screen information must be up-to-date. The current VDU bank will be cleared to colour 0 (i.e. black), and the cursor relocated to the top-left corner.
   If the slow version is in use, then VDU code 12 will be sent to stdout (which will also be flushed). This means that only the current text window will be cleared, and to the current text background colour. Of course it will only work properly if output hasn't been redirected.
*/

typedef struct {
	void *vdu; /* VDU and display screen buffers */
	void *display;
	int length; /* Length of a single screen */
	int width; /* number of pixels-1 */
	int height; /* number of rows-1 */
	int colours; /* Maximum logical colour; i.e. one of the MODE_ values */
	int xeig; /* X and Y eigen factors. ScreenX = OsX >> XEig, etc. */
	int yeig;
	int size; /* Memory allocated to screen buffer */ 
	int osx; /* Screen size in OS units */
	int osy;
	int vdunum,displaynum; /* Bank numbers of the VDU and hardware banks. screen_getdata will not write to these */
	int num_banks; /* Number of screen banks available (from 1 to num_banks inclusive) */
} screen_struct;

extern screen_struct screen;

typedef struct {
	/* Real format is 0x00BBGGRR */
	char r,g,b,x;
} trucol;

/* Screen coordinates are measured in pixels:
   0,0 is the top-left of the screen
   screen.width,screen.height is the bottom-right of the screen
*/

extern void screen_getdata(void);
/* Fills 'screen' with information about the current screen mode
*/ 

extern void screen_write8(int x,int y,int c);
/* Changes the colour of the pixel at x,y in the current VDU bank to the value 'c' (which must be in internal format)
   The current screen mode must be 8BPP, and the coordinates given must be within range
*/

extern int screen_read8(int x,int y);
/* Returns the internal colour of the pixel at x,y in the current VDU bank.
   x and y must be within range, and the current mode must be 8BPP
*/

extern trucol screen_reados(int x,int y);
/* Reads a pixel from the current VDU bank, using coordinates specified in OS units.
   It translates the colour to a trucol (i.e. 24bit) value
   Note that the value of trucol.x will always be 0
   Old-style 8BPP modes (i.e. screen.colours == MODE_8B) are assumed to be using the default palette
*/

extern void screen_swap();
/* Swaps the current VDU and hardware banks
   This function goes by the values of screen.vdunum and screen.displaynum, so make sure these are correct (via screen_getbanks) if you're unsure what banks are currently being displayed.
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern void screen_setbank(int b);
/* Switches both VDU and hardware banks to bank number 'b'
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern void screen_setvdu(int b);
/* Switches the VDU bank to bank number 'b'
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern void screen_setdisplay(int b);
/* Switches the hardware bank to bank number 'b'
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern void screen_getbanks();
/* Reads the current vdu and display bank numbers into the screen.vdunum and screen.displaynum variables
*/

extern void screen_vsync(void);
/* Waits for a VSync signal
*/

extern void screen_setmode(int mode);
/* Calls OS_ScreenMode to change the current mode
   Thus is only available on RISC OS 3.5+, and 'mode' can either be a mode number or a pointer to a mode specifier block
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern void screen_oldmode(int mode);
/* Sets the screen mode using VDU calls, i.e. works on any version of RISC OS
   However 'mode' can only be a mode number, and not a mode specifier block
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern void screen_rpcmode(int x,int y,int col);
/* Creates a mode specifier block and uses that to set the screen mode
   Only available on RISC OS 3.5+
   x and y should be the width and height in pixels (e.g. 320,256)
   col should be one of the SCRN_ values defined at the top of this file
   screen_getdata() should be called afterwards to re-read the screen information
*/

extern trucol screen_s8_2_24(int col);
/* Converts an 8bpp BGGRBRTT (i.e. screen internal format) colour to a trucol
*/

extern int screen_24_2_s8(trucol col);
/* Converts a trucol into the screens internal 8bpp format
*/

extern int screen_24_2_s16(trucol col);
/* Converts a trucol into 16bpp format
*/

extern int screen_createbanks(int nb);
/* Attempts to enlarge/shrink screen memory so that 'nb' screen banks are available
   Returns 1 on success, 0 on failure
*/

extern int screen_readmode();
/* Read current screen mode, and return either the mode number or a pointer to a
   mode specifier block (Which you can keep/free() as you wish). This call is
   only avaiable in RISC OS 3.5+.
*/

extern int *screen_enumeratemodes(int *l);
/* Return a list of all the screen modes available, as per OS_ScreenMode 2.
   l will be updated to contain the number of modes in the block. This call is
   only available in RISC OS 3.5+.
*/

#endif
