Thread: An old game needs your help

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    6

    An old game needs your help

    Hi Guys.

    First post here so please go easy on me.

    First a bit of background. I'm part of a group of enthusiasts who have been given permission by Atari to work on an old Flight Sim, called European Air Wars, released in 1998.

    The game engine is very old, dating from 1996, with bits which go back to 1994, and earlier, but we have managed to add a lot to the game engine without to many problems, but where we are hitting a major block, is updating the front end screens.

    Recently, we remapped the screens 1024x768, which seems to have fixed the dreaded 7217 error, which was killing the game. All the screens are 8 bit colour, but linked to fixed programmed pallets, which suavely limit the colours we can use in new graphics.

    We changed the game engine to 24bit BMP, but because of the complications of the way the screens work with animated colours, and cursor/text colours which are hard coded into the EXE.

    Now, one of our team is trying to work out how these screens work.

    They posted today:

    "Discussion at GameRanger with Ralf yesterday afternoon, and some testing confirmed that the spots problem is not due to the colour cycle, and they are not transparencies so that you are seeing a colour underneath. I also confirmed that the entire palette is stored in the mpc file after the 8 byte header.
    What we did not find is any reason why the last 12 colours are not used correctly.
    If a 244 colour palette is used the screens I had problems with are OK. If I use a 256 colour palette I get spots, mainly yellow. "

    http://www.users.on.net/pam_biddell/pal21.jpg

    "None of the colours in the bottom three rows are yellow..."

    http://www.users.on.net/pam_biddell/pal22.jpg

    "....so where is the exe getting the data from? "


    "i found where the 1st 8 pallet colours for menues get "specialized" and i dont know why it it like that.

    Its in:

    size_t ReadPicHeader(int file_handle, PicHeader *hdr, PALETTEENTRY *palette)

    Inside this routine is this:

    Code:
    if (menu_pal_loaded)
    CopyPal2Pal(MenuColors, palette, 12);


    When i disable it, the colours get used like they should(tested with the F4F hangar screen Tony showed above).

    Wait.........................

    2min s later: The 1st colours get used for the mouse cursor and other on screen messages(right mouse click).

    When i disable the lines above, the cursor and the messages appear in different colours, depending to the pallet entry's.

    This is very interesting and bring me a good step forward.

    So the 1st 8 colour entry's get overwritten with the (probably) hard coded "menu colors". What we need to do is to increase the "MyPalet" size to 256 + 12 (menu colors).

    How?? I don't know, maybe later"

    "Don't seems to be easy to give the menu itself the "normal" white colour, while the screens use the full pallet.

    Disabling the lines above could have some advantages.

    1. 12 colours more for the screens.

    2. The possibility to adjust the menu colour specially fitting to each screen. In this way very bright screens can get used, where the default white cursor and text tend to disappear.

    The drawback is that many screens/pallets would need to get adjusted(1st 12 colours = white or so). "


    Now, we really need some help to understand what is going on, and if possible to drop the 8bit screens and go to 24bit BMP. I can post sections of code related to the screens if any of you would like to get in deeper.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    6
    Here is the chunk of code we are trying to get to grips with.

    The references to animations, and sounds are sonething we will probably drop. We would like to have a full 8bit free pallet, or 24bit, but is it possible without a total re write?

    Code:
    char pic_name[80];
    
    void SetupHangarMenu(int NationOrd, Menu ** menu, int Special, InputInfo *input)
    {
    	if (!Special)
    	{
    		get_hangar_picname(pic_name);
    		strcpy(menu_over_pic,pic_name);
    
    		sprintf(message,"hangar%s.mnu",pilot_pre[NationOrd]);
    		*menu = load_menu(message , pic_name);
    		readpictopal(Windows[DISPLAY_PAGE], pic_name, MyPal);
    
    		SetHangarAnimations();
    		SetAnimDrawPage((*menu)->Window);
    	}
    	else
    	{
    		get_special_hangar_picname(pic_name);
    		strcpy(menu_over_pic,pic_name);
    
    		if (is_campaign_mission())
    		{		
    			if (NationOrd==0)
    				sprintf(message,"outsidgr.mnu");
    			else 
    				sprintf(message,"outsiduk.mnu");
    		}
    		else
    		{
    			sprintf(message,"hangar%s.mnu",pilot_pre[NationOrd]);
    		}
    		*menu=load_menu(message, pic_name);
    		readpictopal(Windows[DISPLAY_PAGE],pic_name,MyPal);
    	}
    
    	InitInputInfo(input, menu_stuff, DoAnimationStuff, &screen_hot_spots[0], screen_hot_count, 0);
    	if (!Special)
    		DoAnimationStuff(input);
    
    	// turn off view plane
    	offit_screen_hot(5);
    
    	if( GameSetup.GameType != GS_SINGLE_MISSION )
    	{
    		// mission parameter option is only for single mission
    		offit_screen_hot(3);
    	}
    }
    
    int hangar_menu(void)
    {
    	Menu *menu;
    	InputInfo input;
    	int done, selection, quit;
    //	HotSpot *hs;
    	UWORD save_wf;
    	BOOL Special = use_special_hanger();
    
    	save_wf=window_flags;
    	window_flags&=~WF_IGNOREBACK_BUILD;
    
    	NationOrd = GetNationOrd(player_nation);
    //	if (NationOrd > 1) NationOrd = 1;
    	
    	FadeOutMusic();
    
    	quit = done = FALSE;
    
    	fade_flag = DO_NOTHING;
    
    	SetupHangarMenu(NationOrd, &menu, Special, &input);
    
    	state_screen_hots(TRUE,4);
    
    	sync_display_pages();
    	fade_in();
    
    	while (!done)
    	{
    		if (fade_flag == FADE_BACKPIC)
     		{
    			cursor.Status &= CURSOR_OFF;
    			
    			show_pic( pic_name, FADE_IN_ONLY );
    			fade_flag = DO_NOTHING;
     		}
    
    		selection = get_input( &input );
    
    		switch ( selection )
    		{
    			case 2:
    				remove_menu(menu);
    				if (!Special)
    					WipeAnimations();
    
    				hangar_chalkboard();
    				
    				if (!Special)
    					SetHangarAnimations();
    				ClearBuffer(NULL);
    				restore_menu(menu);
    				state_screen_hots(FALSE,4);
    				fade_flag = FADE_BACKPIC;
    				window_flags = save_wf;
    				break;
    
    			case 3:
    				if (GameSetup.GameType == GS_SINGLE_MISSION)
    				{
    //					remove_menu(menu);
    					delete_menu(menu);
    					screen_hot_count = 0;
    					clear_bytes(&screen_hot_spots[0], MAX_SCREEN_HOTSPOTS * sizeof(HotSpot));
    					if (!use_special_hanger())
    						WipeAnimations();
    
    					SingleSetup();
    					save_last_mission();
    					if (!use_special_hanger())
    						SetHangarAnimations();
    			//		ClearBuffer(NULL);
    					
    					NationOrd = GetNationOrd(player_nation);
    					SetupHangarMenu(NationOrd, &menu, use_special_hanger(), &input);
    					
    					menu->Status |= RENDER_MENU;
    //					state_screen_hots(FALSE,4);
    					fade_flag = FADE_BACKPIC;
     					window_flags = save_wf;
    				}
    				break;
    
    			case 6:
    			case 7:
    			case KBD_ALT_F:
    				done = TRUE;
    				break;
    
    			case 1:
    			case ABORT:
    				done = TRUE;
    				quit = TRUE;
    				break;
    		}
    	}
    
    	fade_out();
    
    	if (!Special)
    		WipeAnimations();
    
    	fade_flag = FADE_BACKPIC;
    	clear_screen_hot_spots();
    	delete_menu(menu);
    	ClearBuffer(NULL);
    	return(!quit);
    }
    
    
    void offit_screen_hot(UWORD ReturnCode)
    {
    	HotSpot *hs;
    
    	for ( hs = screen_hot_spots; hs < &screen_hot_spots[screen_hot_count]; hs++ )
    	{
    		if ( (hs->Status & HS_ACTIVE) && hs->ReturnCode==ReturnCode)
    		{
    			if (hs->Text)
    			{
    				GmFree(hs->Text);
    				hs->Text = NULL;
    			}
    
    			hs->Status &= ~HS_ACTIVE;
    			return;
    		}
    	}
    }
    
    
    Plane *get_hngr_plane_picname(char *pic_name) // cj this calls the profile view of the cockpit image....not used
    {
    	sprintf(pic_name, "plane%02d.mpc", player_plane_type);
    
    	return (current_plane);
    }
    
    
    void get_hangar_picname(char *pic_name)
    {
     	sprintf(pic_name, "hngr%02d.mpc", player_plane_type);
    }
    
    void get_special_hangar_picname(char *pic_name)
    {
     	sprintf(pic_name, "outsid%02d.mpc", player_plane_type);
    }
    Code:
    #include "xvars.h"
    
    static PALETTEENTRY MenuColors[12];
    static int menu_pal_loaded;
    
    void readpicnopal( Window *window, char *filename)
    {
    	readpictopal( window, filename, NULL);
    }
    
    
    void readpaltopal( char *filename, PALETTEENTRY *palette)
    {
    	PicHeader hdr;
    	int fd;
    
    	if ((fd = Copen(filename, O_RDONLY|O_BINARY)) == -1)
    		clean_exit(ERR_PIC_NOT_FOUND, "Pic not Found %s!\n", filename);
    
    	ReadPicHeader(fd, &hdr, palette);
    	close(fd);
    
    	return;
    }
    
    void readpictopal( Window *window, char *filename, PALETTEENTRY *palette )
    {
    	int fd;
    
    	if (!window)
    		clean_exit(757,"Error calling readpictopal %s\n", filename);
    
    
    	if ((fd = Copen(filename, O_RDONLY|O_BINARY)) == -1)
    		clean_exit(ERR_PIC_NOT_FOUND, "Pic not Found %s!\n", filename);
    
    	LZWUnCompress(fd, window, palette);
    
    	close(fd);
    
    	return;
    }
    
    void readpictopal16( Window *window, char *filename, PALETTEENTRY *palette )
    {
    	int fd;
    
    	if (!window)
    		clean_exit(757,"Error calling readpictopal16 %s\n", filename);
    
    
    	if ((fd = Copen(filename, O_RDONLY|O_BINARY)) == -1)
    		clean_exit(ERR_PIC_NOT_FOUND, "Pic not Found %s!\n", filename);
    
    	if ( window != NULL ) {
    		// alloc temporary storage
    		Window *win;
    		win = AllocWindow(window->Width,window->Height);
    		LZWUnCompress(fd, win, palette);
    		// make 16 bit palette here
    		Make16BitReferencedPalette(palette);
    
    		// copy bytes to original window, through 16bit index palette
    		Copy8BitTo16BitWithPalette(win->Buffer,(short*)window->Buffer,palette,window->Width,window->Height,window->Pitch);
    
    		// we're done (hopefully)
    		GmFree(win);
    	} 
    
    	close(fd);
    
    	return;
    }
    
    LPDIRECTDRAWSURFACE CreateDDSurfaceFromPict( char *filename, PALETTEENTRY *palette )
    {
    	Window *win;
    	PicHeader hdr;	    
    	void *ptr;
    	int fd;
    	int w,h;
    	LPDIRECTDRAWSURFACE ddsurf;
    	DDSURFACEDESC ddsd;
    
    	// open file
    	if ((fd = Copen(filename, O_RDONLY|O_BINARY)) == -1)
    		clean_exit(ERR_PIC_NOT_FOUND, "Pic not Found %s!\n", filename);
    
    	// read file header to get size
    	ReadPicHeader(fd, &hdr, palette);
    	w = hdr.Width;
    	h = hdr.Height;
    
    	// seek back to beginning of file
    	lseek(fd, 0L, SEEK_SET);
    
    	// create surface of the right size
    	ddsurf = ddAllocSurface(w,h);
    
    	// check to see if we're 8 bit or 16 bit
    	memset(&ddsd,0,sizeof(ddsd));
    	ddsd.dwSize = sizeof(ddsd);
    	ddsurf->lpVtbl->GetSurfaceDesc(ddsurf,&ddsd);
    
    	// alloc temporary storage
    	win = AllocWindow(w,h);
    	LZWUnCompress(fd, win, palette);
    	// lock surface
    	ptr = (void *)ddLock(ddsurf);
    	// load based on size
    	if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 ) {
    		// make 16 bit palette here
    		Make16BitReferencedPalette(palette);
    		// copy bytes to original window, through 16bit index palette
    		Copy8BitTo16BitWithPalette(win->Buffer,ptr,palette,w,h,ddsd.lPitch);
    	} else {
    		// copy bytes directly
    		memcpy(ptr,win->Buffer,w*h);
    	}
    	// unlock surface
    	ddUnlock(ddsurf,ptr);
    	// we're done (hopefully)
    	GmFree(win->Buffer);
    	GmFree(win);
    	// close the file
    	close(fd);
    
    	return ddsurf;
    }
    size_t readpicheader(char *filename, PicHeader *hdr, PALETTEENTRY *palette)
    {
    	int fd;
    	size_t amount_read;
    
    	if ( (fd = Copen(filename, O_RDONLY|O_BINARY)) == -1)
    		clean_exit(ERR_PIC_NOT_FOUND, "Pic not Found %s!\n", filename);
    
    	amount_read = ReadPicHeader(fd, hdr, palette);
    
    	close(fd);
    
    	return(amount_read);
    }
    
    
    
    size_t ReadPicHeader(int file_handle, PicHeader *hdr, PALETTEENTRY *palette)
    {
    	size_t read_size;
    	ColorTriplet rgb[256], *rgb_entry;
    	PALETTEENTRY *pal_entry;
    	int i;
    
    	if( (read_size = read(file_handle, hdr, sizeof(PicHeader))) == sizeof(PicHeader))
    	{
    		if (hdr->Status & PIC_PAL_DEFINED)
    		{
    			if (palette)
    			{
    				//
    				// The disk image palette is RGB (3 bytes), but our palette in memory is RGBx (dword)
    				//
    
    				read_size += read(file_handle, &rgb[0], 256*3);	// read disk image of palette.
    
    				if(!(hdr->Status & PIC_8_BIT_PAL))		// if this is a 6 bit pallette make it a 
    				{													// 8 bit pal for windows.
    					rgb_entry = &rgb[0];
    					pal_entry = palette;
    
    					for (i=0; i<256; i++, pal_entry++, rgb_entry++)
    					{
    						pal_entry->peRed   = rgb_entry->Red   << 2;
    						pal_entry->peGreen = rgb_entry->Green << 2;
    						pal_entry->peBlue  = rgb_entry->Blue  << 2;
    						pal_entry->peFlags = 0;  
    						// RJH debug
    //						dprintf("RPH : %d : in <%3d,%3d,%3d> out <%3d,%3d,%3d> \n",i,rgb_entry->Red,rgb_entry->Green,rgb_entry->Blue,pal_entry->peRed,pal_entry->peGreen,pal_entry->peBlue);
    					}
    				}
    				else
    				{
    					CopyTripletPal2Pal(&rgb[0], palette, 256);
    				}
    
    				if (menu_pal_loaded)
    					CopyPal2Pal(MenuColors, palette, 12);
    			}
    			else
    				lseek(file_handle, 256*3, SEEK_CUR);		// skip over the pallette
    		}
    	}
    
    	return (read_size);
    }
    
    
    
    void LoadMenuColors(void)
    {
    	PALETTEENTRY temp[256];
    
    	menu_pal_loaded = FALSE;
    
    	readpaltopal( "menu.pal", temp);
    
    	CopyPal2Pal(temp, MenuColors, 12);
    
    	menu_pal_loaded = TRUE;
    }
    
    void UnloadMenuColors( void )
    {
    	menu_pal_loaded = FALSE;
    }
    Last edited by Col. Gibbon; 05-24-2010 at 07:19 AM.

  3. #3
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    It is pretty standard when working with a palette to have a fixed number of them reserved for things like menus. I'm not sure why you think you need to change it, other than just because you want to.


    Quzah.
    Hope is the first step on the road to disappointment.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    6
    Hi Quzah.

    The limitations of the current system cause us real problems, when we try to use new graphics. We would like to use 24bit BMP's, instead of 8bit PCX, but our skill level is not good enough to do this code change.

    Most of us have worked in our own area of the EXE, so it's easy for us to understand the code, but the menu graphics side of things is out of our league, so I was hoping there might be a chance of some help here.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    So you're going to be rewriting all of the file handling routines as well? You'll want to visit some place like wotsit.org and read up on how to load and save BMP files. Then, you're going to need to rewrite the palette structure to take BMP info -- or at least to switch from 8 bit colors to 24 bit colors. You can still use the palette probably, unless you plan on changing number of available colors, in which case you'll probably need to get rid of the whole palette concept.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how do the game engine and the api interact?
    By Shadow12345 in forum Game Programming
    Replies: 9
    Last Post: 12-08-2010, 12:08 AM
  2. Replies: 15
    Last Post: 10-20-2009, 09:39 AM
  3. Open Source / Semi Open source game idea. Help needed
    By CaptainPatent in forum Projects and Job Recruitment
    Replies: 10
    Last Post: 05-16-2007, 10:44 AM
  4. game engine advice?
    By stien in forum Game Programming
    Replies: 0
    Last Post: 01-23-2007, 03:46 PM
  5. My Maze Game --- A Few Questions
    By TechWins in forum Game Programming
    Replies: 18
    Last Post: 04-24-2002, 11:00 PM