/*
* Media System Initialisation
*
* Start up multimedia devices and input
*/
#include <allegro.h>
#include <string.h>
#include "ithelib.h"
#include "loadfile.h"
#include "console.h"
#include "oscli.h"
#include "media.h"
#include "mouse.h"
#include "sound.h"
// Defines
#define CURSOR_CHAR "_"
#define KBSIZE 2 // Size of keyboard buffer
#ifdef _WIN32
#define WINDOWS_IS_BROKEN
#endif
// Variables
#ifdef WINDOWS_IS_BROKEN
BITMAP *screen=NULL;
#endif
BITMAP *swapscreen;
int ire_transparent,ire_nontransparent,ire_bpp,ire_black,ire_bytespp;
unsigned char ire_transparent_r,ire_transparent_g,ire_transparent_b;
static BITMAP *pic;
static BITMAP *oldpic;
//static BITMAP *load_cel(char *filename, RGB *pal);
static char media_on=0,media_clock=0;
static RGB pal[256];
COLOR_MAP light_table;
static RGB_MAP rgb_table;
static int ikeybuf_rptr=0; // Key buffer code
static int ikeybuf_wptr=0;
static int ikeybuf[KBSIZE+1];
static int imousebuf_rptr=0; // Mouse button buffer code
static int imousebuf_wptr=0;
static int imousebuf[KBSIZE+1];
// Functions
extern int gfx_mode_select_ire(int *card, int *bpp);
extern void ire_alert_mode();
extern void RFS_getescape();
static void ChooseMode();
static int rkbuf();
static int rmbuf();
// Code
/*
* Timer code and it's volatile data
*/
static volatile int ready_for_tick=0; // Timer clock
static volatile unsigned int ire_uticks=0;
static volatile unsigned int ire_animticks=0;
static volatile unsigned int ire_divisor=0;
static void ire_animation_clock(void)
{
ire_uticks++;
ire_divisor++;
// Divide the animation clock by four
if(ire_divisor >= 4)
{
ire_animticks++;
ready_for_tick=1;
ire_divisor=0;
}
}
END_OF_STATIC_FUNCTION(ire_animation_clock)
/*
* UpdateAnim() - returns true if it's time to update the animations
*/
int UpdateAnim()
{
if(ready_for_tick)
{
ready_for_tick = 0;
return 1;
}
return 0;
}
END_OF_STATIC_FUNCTION(UpdateAnim)
unsigned int GetIREClock()
{
return ire_uticks;
}
void ResetIREClock()
{
ire_uticks=0;
if(in_editor)
return;
// Sync animation clock
ready_for_tick=0;
ire_divisor=0;
ire_animticks=0;
}
unsigned int GetAnimClock()
{
return ire_animticks;
}
//
// Core media initialisation
//
void init_media(int game)
{
int r;
if(media_on)
return;
media_on=1;
ilog_printf("Starting up:\n");
ilog_printf(" Keyboard: ");
if(!install_keyboard())
ilog_printf("OK\n");
else
{
ilog_printf("FAILED\n");
ilog_printf("%s\n",allegro_error);
exit(1);
}
if(game && !debug_nosound)
{
ilog_printf(" Sound: ");
if(S_Init())
ilog_printf("OK\n");
else
ilog_printf("FAILED\n");
}
// Set allegro panic button
if(allow_breakout)
three_finger_flag=1;
else
three_finger_flag=0;
ilog_printf(" Timer: ");
if(install_timer() != -1)
ilog_printf("OK\n");
else
{
ilog_printf("FAILED\n");
ilog_printf("%s\n",allegro_error);
exit(1);
}
ilog_printf(" Mouse: ");
if(install_mouse() != -1)
ilog_printf("OK\n");
else
{
ilog_printf("FAILED\n");
ilog_printf("%s\n",allegro_error);
exit(1);
}
ilog_printf(" Video:\n");
switch(VideoMode)
{
// Windowed mode
case -2:
// Get colour depth
ire_bpp = desktop_color_depth();
// Work out bytes per pixel
ire_bytespp=ire_bpp/8;
if(ire_bpp==15)
ire_bytespp=2; // hack for 15bpp
// Set it up..
set_color_depth(ire_bpp);
set_color_conversion(COLORCONV_TOTAL);
if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0))
ChooseMode();
break;
// Supported video depths (fullscreen)
case 8:
case 15:
case 16:
case 24:
case 32:
ire_bpp=VideoMode;
// Work out bytes per pixel
ire_bytespp=ire_bpp/8;
if(ire_bpp==15)
ire_bytespp=2; // hack for 15bpp
set_color_depth(ire_bpp);
set_color_conversion(COLORCONV_TOTAL);
if(set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0))
ChooseMode();
break;
// Anything we don't understand
default:
ChooseMode();
break;
}
#ifdef WINDOWS_IS_BROKEN
ilog_quiet(" Attempting to fix windows bug\n");
screen = create_video_bitmap(640,480);
#endif
ilog_quiet(" Palette\n");
if(ire_bpp == 8)
{
for(r=0;r<256;r++)
{
pal[r].r = r>>2;
pal[r].g = r>>2;
pal[r].b = r>>2;
// pal[r].r|=4; // stop it being 0
}
// Purple transparent
pal[0].r = 0;
pal[0].g = 0;
pal[0].b = 0;
}
else
generate_332_palette(pal);
set_palette(pal);
ilog_quiet("Primary media init succesful\n");
ilog_printf("\n");
}
//
// Secondary media initialisation
//
void init_enginemedia()
{
int r,g,b,sum;
char picpath[1024];
ilog_quiet(" Video:\n");
ilog_quiet(" RGBtab\n");
ilog_quiet(" RGBtab\n");
if(ire_bpp == 8)
{
// Make a greyscale translation table for 8bpp mode
for(r=0;r<32;r++)
for(g=0;g<32;g++)
for(b=0;b<32;b++)
{
sum=((r<<3)+(g<<3)+(b<<3))/3;
/*
if(sum == 0 && r+g+b>0)
sum = 1;
*/
rgb_table.data[r][g][b]=sum;
}
}
else
create_rgb_table(&rgb_table,pal,NULL); // proper translation table
// Use it, whichever it is
rgb_map=&rgb_table;
ilog_quiet(" Light tab\n");
create_light_table(&light_table,pal,0,0,0,NULL);
color_map=&light_table;
ilog_quiet(" Transparency\n");
if(ire_bpp == 8)
{
ire_transparent = 0;
ire_black = 1;
}
else
{
ire_transparent = makecol(255,0,255);
ire_black = makecol(0,0,0);
}
ire_transparent_r = getr(ire_transparent);
ire_transparent_g = getg(ire_transparent);
ire_transparent_b = getb(ire_transparent);
ilog_quiet(" Text mode\n");
clear_to_color(screen,ire_black);
swapscreen=MakeScreen(640,480);
if(!swapscreen)
{
allegro_exit();
ilog_quiet("Can't create swapscreen\n");
printf("Can't create swapscreen\n");
exit(1);
}
oldpic=MakeScreen(640,480);
if(!oldpic)
{
allegro_exit();
ilog_quiet("Can't create save/restore bitmap\n");
printf("Can't create save/restore bitmap\n");
exit(1);
}
if(loadingpic[0] == 0)
{
// None specified
clear_to_color(swapscreen,ire_black);
Show();
}
else
{
loadfile(loadingpic,picpath);
pic = iload_bitmap(picpath);
if(!pic)
{
ilog_quiet(" Oh dear\n");
allegro_exit();
ilog_quiet("Can't load backing picture '%s'\n",picpath);
printf("Can't load backing picture '%s'\n",picpath);
exit(1);
}
clear_to_color(swapscreen,ire_black);
masked_blit(pic,swapscreen,0,0,0,0,640,480);
Show();
destroy_bitmap(pic);
}
ilog_quiet(" Start console\n");
irecon_init(logx,logy,80,loglen);
set_trans_blender(0, 0, 0, 128);
ilog_quiet(" Locks\n");
// Ok, let's do the timer stuff now
// Lock these when in DOS to prevent a horrible crash
LOCK_FUNCTION(ire_animation_clock);
LOCK_FUNCTION(UpdateAnim); // Not strictly necessary
LOCK_VARIABLE(ready_for_tick);
LOCK_VARIABLE(ire_uticks);
media_clock=0;
// Ok, let's do it
ilog_quiet(" Clock: ");
if(!install_int_ex(ire_animation_clock,BPS_TO_TIMER(140))) // 35
ilog_quiet("Ok\n");
else
{
ilog_quiet("Failed: %s\n",allegro_error);
readkey();
exit(1);
}
media_clock=1;
ilog_quiet("Media INIT successful\n");
}
void term_media()
{
if(!media_on)
{
ilog_quiet("Media not active, can't shut down\n");
return;
}
media_on=0;
ilog_quiet("Shut down Media:\n");
ilog_quiet(" Clock:\n");
if(media_clock)
{
remove_int(ire_animation_clock);
media_clock=0;
}
ilog_quiet(" Gfx:\n");
KillGFX();
ilog_quiet(" Keyboard:\n");
remove_keyboard();
ilog_quiet(" Allegro:\n");
//allegro_exit();
S_Term();
ilog_quiet("Media shutdown completed\n");
}
int sizeof_sprite(BITMAP *bmp)
{
int cd=0;
switch(bitmap_color_depth(bmp))
{
case 8:
cd=1;
break;
case 15:
case 16:
cd=2;
break;
case 24:
cd=3;
break;
case 32:
cd=4;
break;
default:
ithe_panic("Unknown colour depth in object",NULL);
break;
};
return bmp->w*bmp->h*cd;
}
/*
* Get a key, if one is pending, else return 0
*/
int GetKey()
{
return rkbuf()>>8;
}
int GetMouseButton()
{
return rmbuf();
}
/*
* Wait for a key
*/
unsigned char WaitForKey()
{
int k;
do
{
k = rkbuf();
// S_PollMusic();
// look for a mouse click?
poll_mouse();
CheckMouseRanges();
if(MouseID != -1)
{
return KEY_MAX+1; // Not a valid key, a mouse click
}
} while(!k);
return k>>8;
}
unsigned char WaitForAscii()
{
int k;
do
{
k = rkbuf();
// S_PollMusic();
} while(!k);
return k&0xff;
}
void FlushKeys()
{
clear_keybuf();
ikeybuf_rptr=0;
ikeybuf_wptr=0;
memset(ikeybuf,0,sizeof(ikeybuf));
}
// This is a ring buffer, not a stack
int rkbuf()
{
int k;
// Take key from buffer if necessary
rest(0);
poll_keyboard();
if(!keypressed())
{
k = ikeybuf[ikeybuf_rptr];
if(!k)
{
return k; // Abort if nothing is there
}
ikeybuf[ikeybuf_rptr++]=0;
// Wrap the buffer around if we go too far
if(ikeybuf_rptr>=KBSIZE)
ikeybuf_rptr=0;
return k;
}
// Fill the buffer
while(keypressed())
{
poll_keyboard();
if(ikeybuf[ikeybuf_wptr]) // It's full.
{
clear_keybuf();
}
else
{
ikeybuf[ikeybuf_wptr]=readkey();
if(key_shifts & KEY_LSHIFT)
ikeybuf[ikeybuf_wptr] |= 0x8000; // High bit is for SHIFT
ikeybuf_wptr++;
if(ikeybuf_wptr>=KBSIZE)
{
ikeybuf_wptr=0;
}
}
};
k = ikeybuf[ikeybuf_rptr];
ikeybuf[ikeybuf_rptr++]=0;
if(ikeybuf_rptr>=KBSIZE)
{
ikeybuf_rptr=0;
}
return k;
}
// Buffered mouse button code..
int rmbuf()
{
int k;
// Take key from buffer if necessary
poll_mouse();
if(!mouse_b)
{
k = imousebuf[imousebuf_rptr];
if(!k)
{
return k; // Abort if nothing is there
}
imousebuf[imousebuf_rptr++]=0;
// Wrap the buffer around if we go too far
if(imousebuf_rptr>=KBSIZE)
{
imousebuf_rptr=0;
}
return k;
}
// Fill the buffer
while(mouse_b)
{
poll_mouse();
if(imousebuf[imousebuf_wptr]) // It's full.
{
mouse_b=0; // Smash The Man
}
else
{
imousebuf[imousebuf_wptr]=mouse_b;
imousebuf_wptr++;
if(imousebuf_wptr>=KBSIZE)
{
imousebuf_wptr=0;
}
}
};
k = imousebuf[imousebuf_rptr];
imousebuf[imousebuf_rptr++]=0;
if(imousebuf_rptr>=KBSIZE)
{
imousebuf_rptr=0;
}
return k;
}
/*
* Plot - draw the little row of dots
*
* Call Plot(number); to set the maximum length of the row
* Then call Plot(0); each cycle of the loop to draw a dot
*/
void Plot(int max)
{
static int mpos,ctr=0;
ctr++;
if(max)
{
mpos=max/40;
if(mpos<1)
mpos=1;
ctr=0;
}
if(ctr>mpos)
{
ilog_printf(".");
ctr=0;
}
}
/*
* BMPShot - Take a screenshot in .BMP format
*/
void BMPshot()
{
char name[256];
int ctr=0;
do
{
sprintf(name,"ire%05d.bmp",ctr++);
} while(!access(name,F_OK));
// Create file or bail out
save_bitmap(name,swapscreen,pal);
}
void ChooseMode()
{
int card,ok;
// Choose sensible default BPP
#ifdef __DJGPP__
ire_bpp = 16;
#else
ire_bpp = desktop_color_depth();
#endif
set_gfx_mode(GFX_SAFE, 320, 200, 0, 0);
generate_332_palette(pal);
set_palette(pal);
do {
ok=0;
if (!gfx_mode_select_ire(&card, &ire_bpp))
{
allegro_exit();
exit(1);
}
set_color_depth(ire_bpp);
set_color_conversion(COLORCONV_TOTAL);
if(!set_gfx_mode(card, 640, 480, 0, 0))
ok=1;
else
{
set_color_depth(8);
set_gfx_mode(GFX_SAFE, 320, 200, 0, 0);
generate_332_palette(pal);
set_palette(pal);
ire_alert_mode();
}
} while(!ok);
}
/*
* Get a string
*/
int GetStringInput(char *ptr,int len)
{
int input=0;
int bufpos=0;
char buf[128];
strcpy(buf,ptr);
bufpos=strlen(buf);
buf[bufpos]=0;
do {
irecon_clearline();
if(buf[0] != 0)
irecon_print(buf); // Printing an empty line makes a newline
irecon_print(CURSOR_CHAR);
irecon_update();
Show();
if(keypressed())
{
input = readkey();
if((input>>8) == KEY_F10)
BMPshot();
if((input&0xff) >= ' ' && (input&0xff) <= 'z')
{
if(bufpos<conwid && bufpos<len)
{
buf[bufpos++]=input&0xff;
buf[bufpos]=0;
}
}
if((input>>8) == KEY_DEL || (input>>8) == KEY_BACKSPACE)
if(bufpos>0)
{
bufpos--;
buf[bufpos]=0;
}
}
else
input=0;
} while((input>>8) != KEY_ESC && (input>>8) != KEY_ENTER);
irecon_clearline();
irecon_print(buf);
irecon_print("\n");
if((input>>8) == KEY_ESC)
return 0;
strcpy(ptr,buf);
return 1;
}
BITMAP *MakeScreen(int w, int h)
{
if(use_hw_video)
if(gfx_capabilities&GFX_HW_VRAM_BLIT_MASKED)
return create_video_bitmap(w, h);
return create_bitmap(w,h);
//return screen;
}
void SaveScreen()
{
blit(swapscreen,oldpic,0,0,0,0,640,480);
}
void RestoreScreen()
{
blit(oldpic,swapscreen,0,0,0,0,640,480);
}