/* * Media System Initialisation * * Start up multimedia devices and input */ #include #include #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>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); }