/*#include	<stdio.h>
#include	<allegro.h>

#include	"zone.h"
#include	"structs.h"
#include	"common.h"
#include	"draw.h"
#include	"text.h"
*/
#include	<stdio.h>
#include	<math.h>
#include	<allegro.h>

#include	"draw.h"
#include	"text.h"
#include	"error.h"



int InitDraw(ZONE *z)
{
	int i;
	
	screen_scale_x = (num_of_frames > 2);
	screen_scale_y = (num_of_frames > 1);
	
	screen_buffer_x = (screen_resolution_x + 32);
	screen_buffer_y = screen_resolution_y;
	
	composite = z->Act[act].Stage[stage].AboveWaterFilterL;	
	bmap = z->Act[act].Stage[stage].BlockMap;
	block = z->Act[act].Stage[stage].BlockArt;
	tmap = z->Act[act].Stage[stage].TileMap;
	wmap = z->Act[act].Stage[stage].WaterMap;
	palette_val = z->Act[act].Stage[stage].Palette;
	
	composite_ptr = z->FILTERCOMPOSITE_AddressTable[composite];
	bmap_ptr = z->BMAP_AddressTable[bmap] + 1;
	block_ptr = z->BLOCK_AddressTable[block] + 2;
	tmap_ptr = z->TMAP_AddressTable[tmap] + 2;
	wmap_ptr = z->WMAP_AddressTable[wmap];
	palette_ptr = z->PAL_AddressTable[palette_val];
	
	tilesize = z->BMAP[bmap_ptr-1];
	tiles_x_short = z->TMAP[tmap_ptr-2] + 1;		// e.g. 128 per row
	tiles_x_long = (z->TMAP[tmap_ptr-2] << 1) + 2;	// e.g. 256 per row
	blocks_x = (z->TMAP[tmap_ptr-2]+1) * (2<<tilesize);
	blocks_y = (z->TMAP[tmap_ptr-1]+1) * (2<<tilesize);
	
	for(i=0; i<4; i++){
		if(LayerB[i]){ destroy_bitmap(LayerB[i]); LayerB[i] = 0; }
		if(LayerL[i]){ destroy_bitmap(LayerL[i]); LayerL[i] = 0; }
		if(LayerH[i]){ destroy_bitmap(LayerH[i]); LayerH[i] = 0; }
		if(LayerSH[i]){ destroy_bitmap(LayerSH[i]); LayerSH[i] = 0; }
	}
	if(LayerM){ destroy_bitmap(LayerM); LayerM = 0; }
	
	if(num_of_frames == 2){
		for(i=0; i<2; i++){
			LayerB[i] = create_bitmap(screen_buffer_x, screen_buffer_y >> 1 << screen_double_y);
			LayerL[i] = create_bitmap(screen_buffer_x, screen_buffer_y >> 1 << screen_double_y);
			LayerH[i] = create_bitmap(screen_buffer_x, screen_buffer_y >> 1 << screen_double_y);
			LayerSH[i] = create_bitmap(screen_buffer_x, screen_buffer_y >> 1 << screen_double_y);
		}
		LayerM = create_bitmap((screen_resolution_x+32)+screen_padding_x, (screen_resolution_y+screen_padding_y) << screen_double_y);
	}
	else if(num_of_frames > 2){
		for(i=0; i<3; i++){
			LayerB[i] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
			LayerL[i] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
			LayerH[i] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
			LayerSH[i] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
		}
		if(num_of_frames > 3){
			LayerB[3] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
			LayerL[3] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
			LayerH[3] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
			LayerSH[3] = create_bitmap(screen_buffer_x >> 1 << screen_double_x, screen_buffer_y >> 1 << screen_double_y);
		}
		LayerM = create_bitmap(((screen_resolution_x+32)+screen_padding_x) << screen_double_x, (screen_resolution_y+screen_padding_y) << screen_double_y);
	}
	else{
		LayerB[0] = create_bitmap(screen_buffer_x, screen_buffer_y);
		LayerL[0] = create_bitmap(screen_buffer_x, screen_buffer_y);
		LayerH[0] = create_bitmap(screen_buffer_x, screen_buffer_y);
		LayerSH[0] = create_bitmap(screen_buffer_x, screen_buffer_y);
	}
	
	clear(LayerB[0]);
	clear(LayerL[0]);
	clear(LayerH[0]);
	clear(LayerSH[0]);
	
	#ifdef ENABLE_MOUSE
		position_mouse(screen_resolution_x >> 1 << screen_double_x, screen_resolution_y >> 1 << screen_double_y);
		show_mouse(screen);
		// the line below 'appears' to prevent a crash while in solidity editing mode
		position_mouse(screen_resolution_x >> 1 << screen_double_x, screen_resolution_y >> 1 << screen_double_y);
	#endif
	
	return 0;
}



void SetGfxMode(short res_x, short res_y, short pad_x, short pad_y, short dbl_x, short dbl_y, char full){	
	screen_resolution_x = res_x;
	screen_resolution_y = res_y;
	screen_padding_x = pad_x;
	screen_padding_y = pad_y;
	screen_double_x = dbl_x;
	screen_double_y = dbl_y;
	screen_offset_x = screen_padding_x >> 1;
	screen_offset_y = screen_padding_y >> 1;
	full_screen = full;
	
	if(full_screen)
		SetGfxModeFull();
	else
		SetGfxModeWindow();
	InitDraw(&z);
}



inline void SetGfxModeWindow(){
	int i = 1;
	
	#ifdef ALLEGRO_DOS
	request_refresh_rate(60);
	i = set_gfx_mode(GFX_AUTODETECT, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0)
		quit(ERROR_INIT_SCREEN);
	#endif
	
	#ifdef ALLEGRO_WINDOWS
	if(desktop_color_depth() == 16)
		i = set_gfx_mode(GFX_DIRECTX_OVL, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0){
		i = set_gfx_mode(GFX_DIRECTX_WIN, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
		if(i != 0){
			i = set_gfx_mode(GFX_GDI, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
			if(i != 0){
				quit(ERROR_INIT_SCREEN);
			}
		}
	}
	#endif
	
	#ifdef ALLEGRO_LINUX
	i = set_gfx_mode(GFX_AUTODETECT_WINDOWED, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0)
		quit(ERROR_INIT_SCREEN);
	#endif
	
	#ifdef ALLEGRO_MACOSX
	i = set_gfx_mode(GFX_QUARTZ_WINDOW, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0)
		quit(ERROR_INIT_SCREEN);
	#endif
	
	full_screen = 0;
	// The following line is used to run the engine in the background...
	#ifndef ALLEGRO_DOS
	set_display_switch_mode(SWITCH_BACKGROUND);
	#endif
}



inline void SetGfxModeFull(){
	int i = 1;
	
	#ifdef ALLEGRO_DOS
	request_refresh_rate(60);
	i = set_gfx_mode(GFX_AUTODETECT, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0)
		quit(ERROR_INIT_SCREEN);
	#endif
	
	#ifdef ALLEGRO_WINDOWS
	i = set_gfx_mode(GFX_DIRECTX_ACCEL, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0){
		i = set_gfx_mode(GFX_DIRECTX_SOFT, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
		if(i != 0){
			i = set_gfx_mode(GFX_DIRECTX_SAFE, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
			if(i != 0){
				SetGfxModeWindow();
			}
		}
	}
	#endif
	
	#ifdef ALLEGRO_LINUX
	i = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0)
		quit(ERROR_INIT_SCREEN);
	#endif
	
	#ifdef ALLEGRO_MACOSX
	i = set_gfx_mode(GFX_QUARTZ_FULLSCREEN, (screen_resolution_x + screen_padding_x) << screen_double_x, (screen_resolution_y + screen_padding_y) << screen_double_y, 0, 0);
	if(i != 0)
		SetGfxModeWindow();
	#endif
	
	full_screen = 1;
}



inline void DrawPlayArea(BITMAP *l, BITMAP *h){
	// I make all the variables integers for a slight performance boost
	unsigned short *block_art;
	unsigned int block_data;
	unsigned int blk_x;		// short
	unsigned int blk_y;		// short
	signed int screen_x;		// short
	signed int screen_y;		// short
	int x;
	int y;
	unsigned int draw_x;		// must be unsigned!
	unsigned int draw_y;		// must be unsigned!
	unsigned int color;			// short
	unsigned int start_x;		// char
	short screen_scale_x_saved = screen_scale_x;
	short screen_scale_y_saved = screen_scale_y;
	const signed short blocks_x_count = blocks_x;	// redundant, but improves performance
	const signed short blocks_y_count = blocks_y;	// redundant, but improves performance
	
	if(screen_double_x) screen_scale_x = 0;
	if(screen_double_y) screen_scale_y = 0;
	
	if(screen_scale_x){
		start_x = p->Camera_X_pos & 1;
		if(screen_scale_y){
			for(y = 0; y < screen_buffer_y+16; y += 16){
				screen_y = p->Camera_Y_pos + y;
				if(y==1) screen_y &= 0xFFF0;
				
				for(x = 0; x < screen_buffer_x+16; x += 16){
					screen_x = p->Camera_X_pos-16 + x;
					if(x==1) screen_x &= 0xFFF0;
					
					if(screen_x < 0 || screen_y < 0)
						block_data = 0;
					else
						block_data = COMPILED_MAP[
									((screen_x>>4) % blocks_x_count)
									+ (((screen_y>>4) % blocks_y_count) * blocks_x_count)];
					
					block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
					
					if(block_data & 0x100000){
						for(blk_y=0; blk_y < 16; blk_y += 2){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x += 2){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = (((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x;
								draw_y = (screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1;
								
								if(draw_y < (screen_buffer_y >> 1)
								 && draw_x < ((screen_buffer_x<<1) >> 1)){
									if(color != MASK_COLOR_16){
										*(short *)(&h->line[draw_y][draw_x]) = color;
									}
									*(short *)(&l->line[draw_y][draw_x]) = MASK_COLOR_16;
								}
							}
						}
					}
					else{
						for(blk_y=0; blk_y < 16; blk_y += 2){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x += 2){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = (((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x;
								draw_y = (screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1;
								
								if(draw_y < (screen_buffer_y >> 1)
								 && draw_x < ((screen_buffer_x<<1) >> 1)){
									//*(short *)(&h->line[(screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1][(((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x]) = MASK_COLOR_16;
									*(short *)(&l->line[draw_y][draw_x]) = color;
								}
							}
						}
					}
				}
			}
		}
		else{
			for(y = 0; y < screen_buffer_y+16; y += 16){
				screen_y = p->Camera_Y_pos + y;
				if(y==1) screen_y &= 0xFFF0;
				
				for(x = 0; x < screen_buffer_x+16; x += 16){
					screen_x = p->Camera_X_pos-16 + x;
					if(x==1) screen_x &= 0xFFF0;
					
					if(screen_x < 0 || screen_y < 0)
						block_data = 0;
					else
						block_data = COMPILED_MAP[
									((screen_x>>4) % blocks_x_count)
									+ (((screen_y>>4) % blocks_y_count) * blocks_x_count)];
					
					block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
					
					if(block_data & 0x100000){
						for(blk_y=0; blk_y < 16; blk_y++){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x += 2){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = (((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x;
								draw_y = screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF);
								
								if(draw_y < screen_buffer_y
								 && draw_x < ((screen_buffer_x<<1) >> 1)){
									if(color != MASK_COLOR_16){
										*(short *)(&h->line[draw_y][draw_x]) = color;
									}
									*(short *)(&l->line[draw_y][draw_x]) = MASK_COLOR_16;
								}
							}
						}
					}
					else{
						for(blk_y=0; blk_y < 16; blk_y++){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x += 2){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = (((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x;
								draw_y = screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF);
								
								if(draw_y < screen_buffer_y
								 && draw_x < ((screen_buffer_x<<1) >> 1)){
									//*(short *)(&h->line[screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF)][(((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x]) = MASK_COLOR_16;
									*(short *)(&l->line[draw_y][draw_x]) = color;
								}
							}
						}
					}
				}
			}
		}
	}
	else{
		start_x = 0;
		if(screen_scale_y){
			for(y = 0; y < screen_buffer_y+16; y += 16){
				screen_y = p->Camera_Y_pos + y;
				if(y==1) screen_y &= 0xFFF0;
				
				for(x = 0; x < screen_buffer_x+16; x += 16){
					screen_x = p->Camera_X_pos-16 + x;
					if(x==1) screen_x &= 0xFFF0;
					
					if(screen_x < 0 || screen_y < 0)
						block_data = 0;
					else
						block_data = COMPILED_MAP[
									((screen_x>>4) % blocks_x_count)
									+ (((screen_y>>4) % blocks_y_count) * blocks_x_count)];
					
					block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
					
					if(block_data & 0x100000){
						for(blk_y=0; blk_y < 16; blk_y += 2){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x++){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = ((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x;
								draw_y = (screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1;
								
								if(draw_y < (screen_buffer_y >> 1)
								 && draw_x < (screen_buffer_x<<1)){
									if(color != MASK_COLOR_16){
										*(short *)(&h->line[draw_y][draw_x]) = color;
									}
									*(short *)(&l->line[draw_y][draw_x]) = MASK_COLOR_16;
								}
							}
						}
					}
					else{
						for(blk_y=0; blk_y < 16; blk_y += 2){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x++){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = ((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x;
								draw_y = (screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1;
								
								if(draw_y < (screen_buffer_y >> 1)
								 && draw_x < (screen_buffer_x<<1)){
									//*(short *)(&h->line[(screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1][((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x]) = MASK_COLOR_16;
									*(short *)(&l->line[draw_y][draw_x]) = color;
								}
							}
						}
					}
				}
			}
		}
		else{
			for(y = 0; y < screen_buffer_y+16; y += 16){
				screen_y = p->Camera_Y_pos + y;
				if(y==1) screen_y &= 0xFFF0;
				
				for(x = 0; x < screen_buffer_x+16; x += 16){
					screen_x = p->Camera_X_pos-16 + x;
					if(x==1) screen_x &= 0xFFF0;
					
					if(screen_x < 0 || screen_y < 0)
						block_data = 0;
					else
						block_data = COMPILED_MAP[
									((screen_x>>4) % blocks_x_count)
									+ (((screen_y>>4) % blocks_y_count) * blocks_x_count)];
					
					block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
					
					if(block_data & 0x100000){
						for(blk_y=0; blk_y < 16; blk_y++){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x++){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = ((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x;
								draw_y = screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF);
								
								if(draw_y < screen_buffer_y
								 && draw_x < (screen_buffer_x<<1)){
									if(color != MASK_COLOR_16){
										*(short *)(&h->line[draw_y][draw_x]) = color;
									}
									*(short *)(&l->line[draw_y][draw_x]) = MASK_COLOR_16;
								}
							}
						}
					}
					else{
						for(blk_y=0; blk_y < 16; blk_y++){
							if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
							for(blk_x=0; blk_x < 16; blk_x++){
								if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
								
								switch((block_data >> 14) & 3){
									case 0:
										color = block_art[blk_x + (blk_y<<4)];
										break;
									case 1:
										color = block_art[(0xF-blk_x) + (blk_y<<4)];
										break;
									case 2:
										color = block_art[blk_x + ((0xF-blk_y)<<4)];
										break;
									case 3:
										color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
										//break;
								}
								
								draw_x = ((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x;
								draw_y = screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF);
								
								if(draw_y < screen_buffer_y
								 && draw_x < (screen_buffer_x<<1)){
									//*(short *)(&h->line[screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF)][((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x]) = MASK_COLOR_16;
									*(short *)(&l->line[draw_y][draw_x]) = color;
								}
							}
						}
					}
				}
			}
		}
	}
	
	screen_scale_x = screen_scale_x_saved;
	screen_scale_y = screen_scale_y_saved;
}



inline void DrawBackArea(BITMAP *b){
	// I make all the variables integers for a slight performance boost
	unsigned short *block_art;
	unsigned int block_data;
	unsigned int blk_x;		// short
	unsigned int blk_y;		// short
	signed int screen_x;		// short
	signed int screen_y;		// short
	int x;
	int y;
	unsigned int draw_x;		// must be unsigned!
	unsigned int draw_y;		// must be unsigned!
	int cell;
	unsigned int color;			// short
	unsigned int start_x;		// char
	short screen_scale_x_saved = screen_scale_x;
	short screen_scale_y_saved = screen_scale_y;
	short Camera_X_pos_saved = p->Camera_X_pos;
	short Camera_Y_pos_saved = p->Camera_Y_pos;
	// The following were commented out due to a performance "loss"
	//const signed short blocks_x_count = blocks_x;	// redundant, but improves performance
	//const signed short blocks_y_count = blocks_y;	// redundant, but improves performance
	
	if(screen_double_x) screen_scale_x = 0;
	if(screen_double_y) screen_scale_y = 0;
	
	if(screen_scale_x){
		if(screen_scale_y){
			for(cell=0; cell < num_of_cells; cell++){
				if(p->Camera_X_pos >= cell_data[cell].show_if_x_higher
				 && p->Camera_X_pos <= cell_data[cell].show_if_x_lower
				 && p->Camera_Y_pos >= cell_data[cell].show_if_y_higher
				 && p->Camera_Y_pos <= cell_data[cell].show_if_y_lower){
					// Scroll speed
					p->Camera_X_pos *= ((float)cell_data[cell].scroll_speed_x / 4096);
					p->Camera_Y_pos *= ((float)cell_data[cell].scroll_speed_y / 4096);
					
					// Autoscroll speed
					if(cell_data[cell].auto_speed_x)
						p->Camera_X_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_x);
					if(cell_data[cell].auto_speed_y)
						p->Camera_Y_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_y);
					
					// Scroll wrap
					p->Camera_X_pos %= cell_data[cell].scroll_wrap_x;
					p->Camera_Y_pos %= cell_data[cell].scroll_wrap_y;
					
					// Source (top/left)
					p->Camera_X_pos += cell_data[cell].src_x_left;
					p->Camera_Y_pos += cell_data[cell].src_y_top;
					
					// Destination
					//x_offset = cell_data[cell].dest_x;
					//y_offset = cell_data[cell].dest_y;
					
					
					
					start_x = p->Camera_X_pos & 1;
					
					for(y = 0; y < screen_buffer_y+16; y += 16){
						screen_y = p->Camera_Y_pos + y;
						if(y==1) screen_y &= 0xFFF0;
						
						for(x = 0; x < screen_buffer_x+16; x += 16){
							screen_x = p->Camera_X_pos-16 + x;
							if(x==1) screen_x &= 0xFFF0;
							
							if(screen_x < 0 || screen_y < 0)
								block_data = 0;
							else
								block_data = COMPILED_BACKMAP[
											((screen_x>>4) % blocks_x)
											+ (((screen_y>>4) % blocks_y) * blocks_x)];
							
							block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
							
							if(block_data & 0x3FFF || !cell_data[cell].transparent){
								for(blk_y=0; blk_y < 16; blk_y += 2){
									if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
									for(blk_x=0; blk_x < 16; blk_x += 2){
										if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
										
										switch((block_data >> 14) & 3){
											case 0:
												color = block_art[blk_x + (blk_y<<4)];
												break;
											case 1:
												color = block_art[(0xF-blk_x) + (blk_y<<4)];
												break;
											case 2:
												color = block_art[blk_x + ((0xF-blk_y)<<4)];
												break;
											case 3:
												color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
												//break;
										}
										
										draw_x = (((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x;
										draw_y = (screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1;
										
										if(draw_y < (screen_buffer_y >> 1)
										 && draw_x < ((screen_buffer_x<<1) >> 1)){
											*(short *)(&b->line[draw_y][draw_x]) = color;
										}
									}
								}
							}
						}
					}
					p->Camera_X_pos = Camera_X_pos_saved;
					p->Camera_Y_pos = Camera_Y_pos_saved;
				}
			}
		}
		else{
			for(cell=0; cell < num_of_cells; cell++){
				if(p->Camera_X_pos >= cell_data[cell].show_if_x_higher
				 && p->Camera_X_pos <= cell_data[cell].show_if_x_lower
				 && p->Camera_Y_pos >= cell_data[cell].show_if_y_higher
				 && p->Camera_Y_pos <= cell_data[cell].show_if_y_lower){
					// Scroll speed
					p->Camera_X_pos *= ((float)cell_data[cell].scroll_speed_x / 4096);
					p->Camera_Y_pos *= ((float)cell_data[cell].scroll_speed_y / 4096);
					
					// Autoscroll speed
					if(cell_data[cell].auto_speed_x)
						p->Camera_X_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_x);
					if(cell_data[cell].auto_speed_y)
						p->Camera_Y_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_y);
					
					// Scroll wrap
					p->Camera_X_pos %= cell_data[cell].scroll_wrap_x;
					p->Camera_Y_pos %= cell_data[cell].scroll_wrap_y;
					
					// Source (top/left)
					p->Camera_X_pos += cell_data[cell].src_x_left;
					p->Camera_Y_pos += cell_data[cell].src_y_top;
					
					// Destination
					//x_offset = cell_data[cell].dest_x;
					//y_offset = cell_data[cell].dest_y;
					
					
					
					start_x = p->Camera_X_pos & 1;
					
					for(y = 0; y < screen_buffer_y+16; y += 16){
						screen_y = p->Camera_Y_pos + y;
						if(y==1) screen_y &= 0xFFF0;
						
						for(x = 0; x < screen_buffer_x+16; x += 16){
							screen_x = p->Camera_X_pos-16 + x;
							if(x==1) screen_x &= 0xFFF0;
							
							if(screen_x < 0 || screen_y < 0)
								block_data = 0;
							else
								block_data = COMPILED_BACKMAP[
											((screen_x>>4) % blocks_x)
											+ (((screen_y>>4) % blocks_y) * blocks_x)];
							
							block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
							
							if(block_data & 0x3FFF || !cell_data[cell].transparent){
								for(blk_y=0; blk_y < 16; blk_y++){
									if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
									for(blk_x=0; blk_x < 16; blk_x += 2){
										if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
										
										switch((block_data >> 14) & 3){
											case 0:
												color = block_art[blk_x + (blk_y<<4)];
												break;
											case 1:
												color = block_art[(0xF-blk_x) + (blk_y<<4)];
												break;
											case 2:
												color = block_art[blk_x + ((0xF-blk_y)<<4)];
												break;
											case 3:
												color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
												//break;
										}
										
										draw_x = (((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)>> 1)-start_x;
										draw_y = screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF);
										
										if(draw_y < screen_buffer_y
										 && draw_x < ((screen_buffer_x<<1) >> 1)){
											*(short *)(&b->line[draw_y][draw_x]) = color;
										}
									}
								}
							}
						}
					}
					p->Camera_X_pos = Camera_X_pos_saved;
					p->Camera_Y_pos = Camera_Y_pos_saved;
				}
			}
		}
	}
	else{
		if(screen_scale_y){
			for(cell=0; cell < num_of_cells; cell++){
				if(p->Camera_X_pos >= cell_data[cell].show_if_x_higher
				 && p->Camera_X_pos <= cell_data[cell].show_if_x_lower
				 && p->Camera_Y_pos >= cell_data[cell].show_if_y_higher
				 && p->Camera_Y_pos <= cell_data[cell].show_if_y_lower){
					// Scroll speed
					p->Camera_X_pos *= ((float)cell_data[cell].scroll_speed_x / 4096);
					p->Camera_Y_pos *= ((float)cell_data[cell].scroll_speed_y / 4096);
					
					// Autoscroll speed
					if(cell_data[cell].auto_speed_x)
						p->Camera_X_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_x);
					if(cell_data[cell].auto_speed_y)
						p->Camera_Y_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_y);
					
					// Scroll wrap
					p->Camera_X_pos %= cell_data[cell].scroll_wrap_x;
					p->Camera_Y_pos %= cell_data[cell].scroll_wrap_y;
					
					// Source (top/left)
					p->Camera_X_pos += cell_data[cell].src_x_left;
					p->Camera_Y_pos += cell_data[cell].src_y_top;
					
					// Destination
					//x_offset = cell_data[cell].dest_x;
					//y_offset = cell_data[cell].dest_y;
					
					
					
					start_x = 0;
					
					for(y = 0; y < screen_buffer_y+16; y += 16){
						screen_y = p->Camera_Y_pos + y;
						if(y==1) screen_y &= 0xFFF0;
						
						for(x = 0; x < screen_buffer_x+16; x += 16){
							screen_x = p->Camera_X_pos-16 + x;
							if(x==1) screen_x &= 0xFFF0;
							
							if(screen_x < 0 || screen_y < 0)
								block_data = 0;
							else
								block_data = COMPILED_BACKMAP[
											((screen_x>>4) % blocks_x)
											+ (((screen_y>>4) % blocks_y) * blocks_x)];
							
							block_art =(unsigned short *) &z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
							
							if(block_data & 0x3FFF || !cell_data[cell].transparent){
								for(blk_y=0; blk_y < 16; blk_y += 2){
									if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
									for(blk_x=0; blk_x < 16; blk_x++){
										if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
										
										switch((block_data >> 14) & 3){
											case 0:
												color = block_art[blk_x + (blk_y<<4)];
												break;
											case 1:
												color = block_art[(0xF-blk_x) + (blk_y<<4)];
												break;
											case 2:
												color = block_art[blk_x + ((0xF-blk_y)<<4)];
												break;
											case 3:
												color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
												//break;
										}
										
										draw_x = ((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x;
										draw_y = (screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF))>> 1;
										
										if(draw_y < (screen_buffer_y >> 1)
										 && draw_x < (screen_buffer_x<<1)){
											*(short *)(&b->line[draw_y][draw_x]) = color;
										}
									}
								}
							}
						}
					}
					p->Camera_X_pos = Camera_X_pos_saved;
					p->Camera_Y_pos = Camera_Y_pos_saved;
				}
			}
		}
		else{
			for(cell=0; cell < num_of_cells; cell++){
				if(p->Camera_X_pos >= cell_data[cell].show_if_x_higher
				 && p->Camera_X_pos <= cell_data[cell].show_if_x_lower
				 && p->Camera_Y_pos >= cell_data[cell].show_if_y_higher
				 && p->Camera_Y_pos <= cell_data[cell].show_if_y_lower){
					// Scroll speed
					p->Camera_X_pos *= ((float)cell_data[cell].scroll_speed_x / 4096);
					p->Camera_Y_pos *= ((float)cell_data[cell].scroll_speed_y / 4096);
					
					// Autoscroll speed
					if(cell_data[cell].auto_speed_x)
						p->Camera_X_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_x);
					if(cell_data[cell].auto_speed_y)
						p->Camera_Y_pos += ticCounterL * (1 / (float)cell_data[cell].auto_speed_y);
					
					// Scroll wrap
					p->Camera_X_pos %= cell_data[cell].scroll_wrap_x;
					p->Camera_Y_pos %= cell_data[cell].scroll_wrap_y;
					
					// Source (top/left)
					p->Camera_X_pos += cell_data[cell].src_x_left;
					p->Camera_Y_pos += cell_data[cell].src_y_top;
					
					// Destination
					//x_offset = cell_data[cell].dest_x;
					//y_offset = cell_data[cell].dest_y;
					
					
					
					start_x = 0;
					
					for(y = 0; y < screen_buffer_y+16; y += 16){
						screen_y = p->Camera_Y_pos + y;
						if(y==1) screen_y &= 0xFFF0;
						
						for(x = 0; x < screen_buffer_x+16; x += 16){
							screen_x = p->Camera_X_pos-16 + x;
							if(x==1) screen_x &= 0xFFF0;
							
							if(screen_x < 0 || screen_y < 0)
								block_data = 0;
							else
								block_data = COMPILED_BACKMAP[
											((screen_x>>4) % blocks_x)
											+ (((screen_y>>4) % blocks_y) * blocks_x)];
							
							block_art = (unsigned short *)&z.BLOCK[((block_data & 0x3FFF) << 9) + block_ptr];
							
							if(block_data & 0x3FFF || !cell_data[cell].transparent){
								for(blk_y=0; blk_y < 16; blk_y++){
									if(y==0 && blk_y < (p->Camera_Y_pos & 0xF)) blk_y = (p->Camera_Y_pos & 0xF);
									for(blk_x=0; blk_x < 16; blk_x++){
										if(x==0 && blk_x < (p->Camera_X_pos & 0xF)) blk_x = (p->Camera_X_pos & 0xF);
										
										switch((block_data >> 14) & 3){
											case 0:
												color = block_art[blk_x + (blk_y<<4)];
												break;
											case 1:
												color = block_art[(0xF-blk_x) + (blk_y<<4)];
												break;
											case 2:
												color = block_art[blk_x + ((0xF-blk_y)<<4)];
												break;
											case 3:
												color = block_art[(0xF-blk_x) + ((0xF-blk_y)<<4)];
												//break;
										}
										
										draw_x = ((screen_x+16 - p->Camera_X_pos + blk_x - (p->Camera_X_pos & 0xF))<<1)-start_x;
										draw_y = screen_y - p->Camera_Y_pos + blk_y - (p->Camera_Y_pos & 0xF);
										
										if(draw_y < screen_buffer_y
										 && draw_x < (screen_buffer_x<<1)){
											*(short *)(&b->line[draw_y][draw_x]) = color;
										}
									}
								}
							}
						}
					}
					p->Camera_X_pos = Camera_X_pos_saved;
					p->Camera_Y_pos = Camera_Y_pos_saved;
				}
			}
		}
	}
	
	screen_scale_x = screen_scale_x_saved;
	screen_scale_y = screen_scale_y_saved;
}
