CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

DLLInterfaceEditor.cpp (21888B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 //#include <string>
     17 #include <stdio.h>
     18 
     19 #include	"function.h"
     20 #include "externs.h"
     21 #include "DLLInterface.h"
     22 #include "Gadget.h"
     23 #include "defines.h" // VOC_COUNT, VOX_COUNT
     24 #include "SidebarGlyphx.h"
     25 #include	"mixfile.h"
     26 #include "ccini.H"
     27 
     28 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Startup();
     29 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Cleanup();
     30 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map(char* cncdata_directory, char* house_name, int scenario_index, char* east_west, char* variant);
     31 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map_By_Scenario_Name(char* cncdata_directory, char* scenario_name);
     32 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Clear_Map();
     33 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Map_Stats(int& map_width, int& map_height, int& theater);
     34 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data_By_Index(int cell_index, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index);
     35 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data(int x, int y, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index);
     36 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Texture_Buffer(int x, int y, int& out_width, int& out_height, SAFEARRAY*& out_texture_array);
     37 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Scenario_Names(char* cncdata_directory);
     38 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Template_Data(int template_type_index, SAFEARRAY*& template_points);
     39 
     40 int LoadScenario();
     41 
     42 extern int DLL_Startup(const char * command_line);
     43 
     44 char EditorMapINIBuffer[SHAPE_BUFFER_SIZE];
     45 bool EditorMapInitialized = false;
     46 
     47 const static int EDITOR_COMMMAND_SUCCESS = 0;
     48 const static int EDITOR_COMMMAND_FAILURE = 1;
     49 
     50 const char* CD1Path = "\\RED_ALERT\\CD1\\";
     51 const char* CD2Path = "\\RED_ALERT\\COUNTERSTRIKE\\";
     52 const char* CD3Path = "\\RED_ALERT\\AFTERMATH\\";
     53 
     54 char RedAlertINI[_MAX_PATH];
     55 
     56 /**************************************************************************************************
     57 * CNC_Editor_Startup
     58 * Initializes the system to allow map loading for the editor
     59 **************************************************************************************************/
     60 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Startup()
     61 {
     62 	/*
     63 	BlackPalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];
     64 	GamePalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];
     65 	OriginalPalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];
     66 	WhitePalette = new(MEM_CLEAR | MEM_REAL) unsigned char[768];
     67 	memset(WhitePalette, 63, 768);
     68 
     69 
     70 	Set_Palette(GamePalette);
     71 
     72 	TheaterData = 0;
     73 	TheaterIcons = 0;
     74 	LowTheaterData = 0;
     75 	*/
     76 
     77 	RunningFromEditor = true;
     78 
     79 	return EDITOR_COMMMAND_FAILURE;
     80 }
     81 
     82 /**************************************************************************************************
     83 * CNC_Editor_Cleanup
     84 * Cleans up systems initialized by the editor
     85 **************************************************************************************************/
     86 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Cleanup()
     87 {
     88 	/*
     89 	if (BlackPalette)
     90 	{
     91 		delete[] BlackPalette;
     92 	}
     93 
     94 	if (GamePalette)
     95 	{
     96 		delete[] GamePalette;
     97 	}
     98 
     99 	if (OriginalPalette)
    100 	{
    101 		delete[] OriginalPalette;
    102 	}
    103 	if (WhitePalette)
    104 	{
    105 		delete[] WhitePalette;
    106 	}
    107 	*/
    108 
    109 	return EDITOR_COMMMAND_SUCCESS;
    110 }
    111 /**************************************************************************************************
    112 * CNC_Editor_Load_Mix_Files
    113 * Loads all the Mix files for Tiberian Dawn
    114 **************************************************************************************************/
    115 void CNC_Editor_Load_Mix_Files()
    116 {
    117 	const char* MixFileNames[] =
    118 	{
    119 		"MAIN.MIX",
    120 		"REDALERT.MIX",
    121 		"EXPAND2.MIX",
    122 		"EXPAND.MIX",
    123 		"HIRES1.MIX",
    124 		//"LORES1.MIX"
    125 		
    126 		"GENERAL.MIX",		
    127 		
    128 		"LOCAL.MIX",
    129 		"HIRES.MIX",
    130 		"NCHIRES.MIX",
    131 		"CONQUER.MIX",
    132 		
    133 		"RUSSIAN.MIX",
    134 		"ALLIES.MIX",
    135 
    136 		"SNOW.MIX",
    137 		"TEMPERAT.MIX",
    138 		"INTERIOR.MIX",
    139 	};
    140 
    141 	int count = sizeof(MixFileNames) / sizeof(MixFileNames[0]);
    142 
    143 	for (int i = count - 1; i >= 0; --i)
    144 	{
    145 		MFCD::Free(MixFileNames[i]);
    146 	}
    147 
    148 	for (int i = 0; i < count; ++i)
    149 	{
    150 		MFCD* file = new MFCD(MixFileNames[i], &FastKey);
    151 		file->Cache();
    152 		
    153 	}
    154 	
    155 }
    156 
    157 /**************************************************************************************************
    158 * CNC_Editor_Setup_Content_Directory
    159 * Sets up where the system should load map data from.
    160 *
    161 * cncdata_directory: path of the base CNC data directory
    162 * CD1: if true, consider this disc 1, otherwise consider this disc 2.
    163 **************************************************************************************************/
    164 void CNC_Editor_Setup_Content_Directory(char* cncdata_directory, int CD, char (&content_directory)[_MAX_PATH])
    165 {
    166 
    167 	switch (CD)
    168 	{
    169 	default:
    170 	case 1:
    171 		sprintf(content_directory, "%s%s", cncdata_directory, CD1Path);
    172 		break;
    173 	case 2:
    174 		sprintf(content_directory, "%s%s", cncdata_directory, CD2Path);
    175 		break;
    176 	case 3:
    177 		sprintf(content_directory, "%s%s", cncdata_directory, CD3Path);
    178 		break;
    179 	}
    180 
    181 	//Setup red alert path
    182 	sprintf(RedAlertINI, "%sREDALERT.INI",content_directory);
    183 
    184 	if (strlen(content_directory) != 0) {
    185 		CCFileClass::Clear_Search_Drives();
    186 		CCFileClass::Reset_Raw_Path();
    187 		char *dll_dir = strdup(content_directory);
    188 		CCFileClass::Set_Search_Drives(dll_dir);
    189 		free(dll_dir);
    190 	}
    191 }
    192 
    193 /**************************************************************************************************
    194 * CNC_Editor_Load_Map
    195 * Loads the map with the given parameters.
    196 *
    197 * cncdata_directory: path of the base CNC data directory
    198 * faction: the name of the faction we are loading the map for
    199 * scenario_index: int scenario index
    200 * east_west:
    201 * variant:
    202 *
    203 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    204 **************************************************************************************************/
    205 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map(
    206 	char* cncdata_directory,
    207 	char* house_name,
    208 	int scenario_index,
    209 	char* east_west,
    210 	char* variant)
    211 {
    212 
    213 	CNC_Editor_Clear_Map();
    214 
    215 	ScenarioPlayerType scen_player;
    216 	int CD = 1;
    217 	if (stricmp(house_name, "SPAIN") == 0) {
    218 		scen_player = SCEN_PLAYER_SPAIN;
    219 		Whom = HOUSE_GOOD;
    220 
    221 		if (scenario_index >= 40)
    222 		{
    223 			CD = 3;
    224 		}
    225 		else if (scenario_index >= 15)
    226 		{
    227 			CD = 2;
    228 		}
    229 	}
    230 
    231 	if (stricmp(house_name, "GREECE") == 0 || stricmp(house_name, "ALLY") == 0) {
    232 		scen_player = SCEN_PLAYER_GREECE;
    233 		Whom = HOUSE_GOOD;
    234 
    235 		if (scenario_index >= 40)
    236 		{
    237 			CD = 3;
    238 		}
    239 		else if (scenario_index >= 15)
    240 		{
    241 			CD = 2;
    242 		}
    243 	}
    244 
    245 	if (stricmp(house_name, "USSR") == 0) {
    246 		scen_player = SCEN_PLAYER_USSR;
    247 		Whom = HOUSE_BAD;
    248 
    249 		if (scenario_index >= 40)
    250 		{
    251 			CD = 3;
    252 		}
    253 		else if (scenario_index >= 15)
    254 		{
    255 			CD = 2;
    256 		}
    257 	}
    258 
    259 	if (stricmp(house_name, "MULTI") == 0)
    260 	{
    261 		scen_player = SCEN_PLAYER_MPLAYER;
    262 		Whom = HOUSE_MULTI1;
    263 
    264 		if (scenario_index >= 25)
    265 		{
    266 			CD = 3;
    267 		}
    268 
    269 	}
    270 
    271 	if (stricmp(house_name, "JAPAN") == 0)
    272 	{
    273 		scen_player = SCEN_PLAYER_JP;
    274 		Whom = HOUSE_JP;
    275 	}
    276 
    277 	char content_directory[_MAX_PATH];
    278 
    279 	CNC_Editor_Setup_Content_Directory(cncdata_directory, CD, content_directory);
    280 
    281 	char command_line[_MAX_PATH];
    282 	sprintf(command_line, "-CD%s", content_directory);
    283 
    284 	DLL_Startup(command_line);
    285 
    286 	Scen.Scenario = scenario_index;
    287 	ScenarioDirType scen_dir;
    288 	BuildLevel = 7;
    289 
    290 	if (stricmp(east_west, "w") == 0)
    291 	{
    292 		scen_dir = SCEN_DIR_WEST;
    293 	}
    294 	else
    295 	{
    296 		scen_dir = SCEN_DIR_EAST;
    297 	}
    298 
    299 	ScenarioVarType variant_enum;
    300 
    301 	if (stricmp(variant, "b") == 0)
    302 	{
    303 		variant_enum = SCEN_VAR_B;
    304 	}
    305 	else if (stricmp(variant, "c") == 0)
    306 	{
    307 		variant_enum = SCEN_VAR_C;
    308 	}
    309 	else if (stricmp(variant, "d") == 0)
    310 	{
    311 		variant_enum = SCEN_VAR_D;
    312 	}
    313 	else
    314 	{
    315 		variant_enum = SCEN_VAR_A;
    316 	}
    317 
    318 	Scen.Set_Scenario_Name(Scen.Scenario, scen_player, scen_dir, (ScenarioVarType)variant_enum);
    319 
    320 	return LoadScenario();
    321 }
    322 
    323 /**************************************************************************************************
    324 * CNC_Editor_Load_Map_By_Scenario_Name
    325 * Loads the map with the given parameters.
    326 *
    327 * cncdata_directory: path of the base CNC data directory
    328 * scenario_name: name of the scnario to load
    329 *
    330 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    331 **************************************************************************************************/
    332 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Load_Map_By_Scenario_Name(
    333 	char* cncdata_directory,
    334 	char* scenario_name)
    335 {
    336 	int CD = 3; // Always use the aftermath cd
    337 	if (strnlen(scenario_name, _MAX_PATH) >= 3 && (scenario_name[2] == 'a' || scenario_name[2] == 'A'))
    338 	{
    339 		// Ant missions are CD 2
    340 		CD = 2;
    341 	}
    342 
    343 	CNC_Editor_Clear_Map();
    344 
    345 	char content_directory[_MAX_PATH];
    346 
    347 	CNC_Editor_Setup_Content_Directory(cncdata_directory, CD, content_directory);
    348 
    349 	char command_line[_MAX_PATH];
    350 	sprintf(command_line, "-CD%s", content_directory);
    351 
    352 	DLL_Startup(command_line);
    353 
    354 	snprintf(Scen.ScenarioName, _MAX_FNAME + _MAX_EXT, "%s.ini", scenario_name);
    355 
    356 	return LoadScenario();
    357 }
    358 
    359 int LoadScenario()
    360 {
    361 	CCFileClass file(Scen.ScenarioName);
    362 	
    363 	if (!file.Is_Available())
    364 	{
    365 		return(EDITOR_COMMMAND_FAILURE);
    366 	}
    367 
    368 
    369 	CCINIClass ini;
    370 	int result = ini.Load(file,true);
    371 	if (result == 0)
    372 	{
    373 		return(EDITOR_COMMMAND_FAILURE);
    374 	}
    375 
    376 	if (result == 2) 
    377 	{
    378 		//		if (Session.Type == GAME_NORMAL || Session.ScenarioIsOfficial) {
    379 					/*
    380 					**	Make a special exception so that multiplayer maps from 1 through
    381 					**	24 will not care if the message digest is in error. All other
    382 					**	maps will abort the scenario load.
    383 					*/
    384 		if (Scen.ScenarioName[2] != 'M' || Scen.Scenario >= 25) 
    385 		{
    386 			return(EDITOR_COMMMAND_FAILURE);
    387 		}
    388 	}
    389 
    390 	const char * const BASIC = "Basic";
    391 	NewINIFormat = ini.Get_Int(BASIC, "NewINIFormat", 0);
    392 
    393 	Map.One_Time();
    394 	Map.Read_INI(ini);
    395 
    396 	EditorMapInitialized = true;
    397 	
    398 	return EDITOR_COMMMAND_SUCCESS;
    399 }
    400 
    401 /**************************************************************************************************
    402 *	CNC_Editor_Clear_Map
    403 *	Deletes the data for the currently loaded map.
    404 *
    405 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    406 **************************************************************************************************/
    407 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Clear_Map()
    408 {
    409 	if (EditorMapInitialized)
    410 	{
    411 		Map.Init_Clear();
    412 		EditorMapInitialized = false;
    413 
    414 		return EDITOR_COMMMAND_SUCCESS;
    415 	}
    416 	else
    417 	{
    418 		return EDITOR_COMMMAND_FAILURE;
    419 	}
    420 
    421 	return EDITOR_COMMMAND_FAILURE;
    422 }
    423 
    424 /**************************************************************************************************
    425 * CNC_Editor_Get_Map_Stats
    426 * Gets the stats for the currently loaded map
    427 *
    428 * map_width: out parameter storing the width of the map
    429 * map_height: out parameter storing the height of the map
    430 * theater: out paramter storing the theater of the map
    431 *
    432 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    433 **************************************************************************************************/
    434 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Map_Stats(int& map_width, int& map_height, int& theater)
    435 {
    436 	if (EditorMapInitialized)
    437 	{
    438 		map_width = Map.MapCellWidth + 1;
    439 		map_height = Map.MapCellHeight + 1;
    440 		theater = Scen.Theater;
    441 		return EDITOR_COMMMAND_SUCCESS;
    442 	}
    443 
    444 	map_width = -1;
    445 	map_height = -1;
    446 	theater = -1;
    447 	return EDITOR_COMMMAND_FAILURE;
    448 }
    449 
    450 /**************************************************************************************************
    451 * CNC_Editor_Get_Cell_Data_By_Index
    452 * Get the data from the given cell.
    453 *
    454 * cell_index: The index of the desired cell.
    455 * cell_name: out buffer to be filled with the name of the given cell.
    456 * cell_name_size: the size of the cell name buffer.
    457 *
    458 *
    459 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    460 **************************************************************************************************/
    461 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data_By_Index(int cell_index, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index)
    462 {
    463 	CELL index = (CELL)cell_index;
    464 
    465 	CellClass * cellptr = &Map[index];
    466 
    467 	cell_name[0] = 0;
    468 	int icon = 0;
    469 	void *image_data = 0;
    470 
    471 	char template_name[10];
    472 	if (cellptr->Get_Template_Info(template_name, icon, image_data))
    473 	{
    474 		snprintf(cell_name, cell_name_size, "%s-%04d", template_name, icon);
    475 
    476 		template_type = cellptr->TType;
    477 		template_icon_index = icon;
    478 
    479 		//TemplateTypeClass::As_Reference(ptr->TType).
    480 
    481 		return EDITOR_COMMMAND_SUCCESS;
    482 	}
    483 
    484 	return EDITOR_COMMMAND_FAILURE;
    485 }
    486 
    487 /**************************************************************************************************
    488 * CNC_Editor_Get_Cell_Data
    489 * Get the data from the given cell.
    490 *
    491 * x,y: The corrdinates of the desired cell.
    492 * cell_name: out buffer to be filled with the name of the given cell.
    493 * cell_name_size: the size of the cell name buffer.
    494 *
    495 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    496 **************************************************************************************************/
    497 
    498 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Data(int x, int y, char* cell_name, unsigned long cell_name_size, int& template_type, int& template_icon_index)
    499 {
    500 	if (!EditorMapInitialized)
    501 	{
    502 		return EDITOR_COMMMAND_FAILURE;
    503 	}
    504 
    505 
    506 	int map_cell_x = Map.MapCellX;
    507 	int map_cell_y = Map.MapCellY;
    508 	int map_cell_width = Map.MapCellWidth;
    509 	int map_cell_height = Map.MapCellHeight;
    510 
    511 	if (map_cell_x > 0) {
    512 		map_cell_x--;
    513 		map_cell_width++;
    514 	}
    515 
    516 	if (map_cell_width < MAP_MAX_CELL_WIDTH) {
    517 		map_cell_width++;
    518 	}
    519 
    520 	if (map_cell_y > 0) {
    521 		map_cell_y--;
    522 		map_cell_height++;
    523 	}
    524 
    525 	if (map_cell_height < MAP_MAX_CELL_HEIGHT) {
    526 		map_cell_height++;
    527 	}
    528 
    529 	CELL cell = XY_Cell(map_cell_x + x, map_cell_y + y);
    530 
    531 	return CNC_Editor_Get_Cell_Data_By_Index((int)cell, cell_name, cell_name_size, template_type, template_icon_index);
    532 }
    533 
    534 /**************************************************************************************************
    535 * CNC_Editor_Get_Cell_Texture_Buffer
    536 *
    537 * x,y:
    538 * out_width, out_height: dimensions of the outputed texture array
    539 * out_texture_array: output array of unsigned chars storing the color data for the requested object,
    540 *							every 3 chars is a set of RGB values
    541 **************************************************************************************************/
    542 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Cell_Texture_Buffer(int x, int y, int& out_width, int& out_height, SAFEARRAY*& out_texture_array)
    543 {
    544 
    545 	int map_cell_x = Map.MapCellX;
    546 	int map_cell_y = Map.MapCellY;
    547 	int map_cell_width = Map.MapCellWidth;
    548 	int map_cell_height = Map.MapCellHeight;
    549 
    550 	if (map_cell_x > 0) {
    551 		map_cell_x--;
    552 		map_cell_width++;
    553 	}
    554 
    555 	if (map_cell_width < MAP_MAX_CELL_WIDTH) {
    556 		map_cell_width++;
    557 	}
    558 
    559 	if (map_cell_y > 0) {
    560 		map_cell_y--;
    561 		map_cell_height++;
    562 	}
    563 
    564 	if (map_cell_height < MAP_MAX_CELL_HEIGHT) {
    565 		map_cell_height++;
    566 	}
    567 
    568 	CELL cell = XY_Cell(map_cell_x + x, map_cell_y + y);
    569 	CellClass * cellptr = &Map[cell];
    570 
    571 	char cell_name[_MAX_PATH];
    572 
    573 	int icon = 0;
    574 	void *image_data = 0;
    575 	if (cellptr->Get_Template_Info(cell_name, icon, image_data))
    576 	{
    577 		GraphicBufferClass temp_gbuffer(24, 24);
    578 		GraphicViewPortClass	temp_viewport(&temp_gbuffer, 0, 0, 24, 24);
    579 
    580 		WindowList[WINDOW_CUSTOM][WINDOWX] = 0;
    581 		WindowList[WINDOW_CUSTOM][WINDOWY] = 0;
    582 		WindowList[WINDOW_CUSTOM][WINDOWWIDTH] = 24;
    583 		WindowList[WINDOW_CUSTOM][WINDOWHEIGHT] = 24;
    584 
    585 		temp_viewport.Draw_Stamp(image_data, icon, 0, 0, NULL, WINDOW_CUSTOM);
    586 
    587 		out_width = temp_viewport.Get_Width();
    588 		out_height = temp_viewport.Get_Height();
    589 
    590 		const int COLOR_SIZE = 3;
    591 
    592 		SAFEARRAYBOUND  Bound;
    593 		Bound.lLbound = 0;
    594 		Bound.cElements = out_width * out_height * COLOR_SIZE;
    595 
    596 		out_texture_array = SafeArrayCreate(VT_UI1, 1, &Bound);
    597 
    598 		unsigned char* out_buffer;
    599 
    600 		HRESULT hr = SafeArrayAccessData(out_texture_array, (void **)&out_buffer);
    601 		if (SUCCEEDED(hr))
    602 		{
    603 			GraphicBufferClass* Graphic_Buffer = temp_viewport.Get_Graphic_Buffer();
    604 
    605 			int VP_Scan_Line = temp_viewport.Get_Width() + temp_viewport.Get_XAdd();
    606 
    607 			char * start_ptr;
    608 			start_ptr = (char *)Graphic_Buffer->Get_Buffer();
    609 			start_ptr += ((temp_viewport.Get_YPos() * VP_Scan_Line) + temp_viewport.Get_XPos());
    610 
    611 			for (int y = 0; y < out_height; ++y)
    612 			{
    613 				unsigned char* scanline_ptr = (unsigned char*)start_ptr + y * VP_Scan_Line;
    614 				unsigned char* out_buffer_y_ptr = out_buffer + (y * out_width * COLOR_SIZE);
    615 				for (int x = 0; x < out_width; ++x)
    616 				{
    617 					unsigned char* pallete_index_ptr = scanline_ptr + x;
    618 					unsigned char* out_buffer_ptr = out_buffer_y_ptr + (x * COLOR_SIZE);
    619 
    620 					int palette_index = (*pallete_index_ptr);
    621 					out_buffer_ptr[0] = ((unsigned char)GamePalette[palette_index].Red_Component());
    622 					out_buffer_ptr[1] = ((unsigned char)GamePalette[palette_index].Green_Component());
    623 					out_buffer_ptr[2] = ((unsigned char)GamePalette[palette_index].Blue_Component());
    624 				}
    625 			}
    626 
    627 			SafeArrayUnaccessData(out_texture_array);
    628 
    629 			return EDITOR_COMMMAND_SUCCESS;
    630 		}
    631 	}
    632 
    633 	return EDITOR_COMMMAND_FAILURE;
    634 }
    635 
    636 /**************************************************************************************************
    637 * CNC_Editor_Get_Template_Data
    638 * Get the data from the given tile template type.
    639 *
    640 * template_type_index: The index of the template type to use. should come from the Get_Cell_Data function.
    641 * template_positions: Out buffer to be filled with the list of positions of the tiles as offsets from the origin of the template.
    642 *							This data is store is an X, Y, X, Y, X, Y format.
    643 *
    644 * returns EDITOR_COMMMAND_SUCCESS on success, all other values are failure
    645 **************************************************************************************************/
    646 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Template_Data(int template_type_index, SAFEARRAY*& template_points)
    647 {
    648 	if (template_type_index >= TEMPLATE_COUNT || template_type_index == TEMPLATE_NONE)
    649 	{
    650 		return EDITOR_COMMMAND_FAILURE;
    651 	}
    652 
    653 	const TemplateTypeClass& template_type = TemplateTypeClass::As_Reference((TemplateType)template_type_index);
    654 	if (template_type.Get_Image_Data() == nullptr)
    655 	{
    656 		return EDITOR_COMMMAND_FAILURE;
    657 	}
    658 
    659 
    660 	short const * occupy_list = template_type.Occupy_List();
    661 
    662 	short const * counter = occupy_list;
    663 	while (counter && *counter != REFRESH_EOL)
    664 	{
    665 		counter++;
    666 	}
    667 
    668 	int occupy_list_size = counter - occupy_list;
    669 
    670 
    671 	SAFEARRAYBOUND  bounds;
    672 	bounds.lLbound = 0;
    673 	bounds.cElements = occupy_list_size * 2;
    674 	template_points = SafeArrayCreate(VT_I4, 1, &bounds);
    675 
    676 	int *pData;
    677 	HRESULT hr = SafeArrayAccessData(template_points, (void **)&pData);
    678 	if (SUCCEEDED(hr))
    679 	{
    680 		for (int i = 0; i < occupy_list_size; i++)
    681 		{
    682 			CELL cell = occupy_list[i];
    683 
    684 			int x = Cell_X(cell);
    685 			int y = Cell_Y(cell);
    686 
    687 			pData[i * 2] = x;
    688 			pData[i * 2 + 1] = y;
    689 		}
    690 
    691 		SafeArrayUnaccessData(template_points);
    692 
    693 		return EDITOR_COMMMAND_SUCCESS;
    694 	}
    695 
    696 	return EDITOR_COMMMAND_FAILURE;
    697 }
    698 
    699 extern "C" __declspec(dllexport) int __cdecl CNC_Editor_Get_Scenario_Names(char* cncdata_directory)
    700 {
    701 	char content_directory[_MAX_PATH];
    702 
    703 	CNC_Editor_Setup_Content_Directory(cncdata_directory,false, content_directory);
    704 
    705 	char command_line[_MAX_PATH];
    706 	sprintf(command_line, "-CD%s", content_directory);
    707 	DLL_Startup(command_line);
    708 
    709 	char team_ids[] =
    710 	{
    711 		'a',
    712 		'b',
    713 		'c',
    714 		'd',
    715 		'e',
    716 		'f',
    717 		'g',
    718 		'h',
    719 		'i',
    720 		'j',
    721 		'k',
    722 		'l',
    723 		'm',
    724 		'n',
    725 		'o',
    726 		'p',
    727 		'q',
    728 		'r',
    729 		's',
    730 		't',
    731 		'u',
    732 		'v',
    733 		'w',
    734 		'x',
    735 		'y',
    736 		'z',
    737 	};
    738 	/*
    739 	{
    740 		'g',
    741 		'a',
    742 		'u',
    743 		'm'
    744 	};
    745 	*/
    746 	const int team_count = sizeof(team_ids) / sizeof(char);
    747 
    748 	char direction_ids[] =
    749 	{
    750 		'e',
    751 		'w',
    752 	};
    753 	const int direction_count = sizeof(direction_ids) / sizeof(char);
    754 
    755 	char variant_ids[] =
    756 	{
    757 		'a',
    758 		'b',
    759 		'c',
    760 		'd',
    761 		'e',
    762 		'f',
    763 		'g',
    764 		'h',
    765 		'i',
    766 		'j',
    767 		'k',
    768 		'l',
    769 		'm',
    770 		'n',
    771 		'o',
    772 		'p',
    773 		'q',
    774 		'r',
    775 		's',
    776 		't',
    777 		'u',
    778 		'v',
    779 		'w',
    780 		'x',
    781 		'y',
    782 		'z',
    783 	};
    784 	/*
    785 	{
    786 		'a',
    787 		'b',
    788 		'c',
    789 		'd'
    790 	};
    791 	*/
    792 	const int variant_count = sizeof(variant_ids) / sizeof(char);
    793 
    794 	const int min_scenario_index = 1;
    795 	const int max_scenario_index = 99;
    796 
    797 	char scenario_name[_MAX_FNAME + _MAX_EXT];
    798 	char file_name[_MAX_FNAME + _MAX_EXT];
    799 
    800 	FILE * names_file = fopen("d:\\RA_Disk2.txt", "w+");
    801 
    802 	for (int team_index = 0; team_index < team_count; team_index++)
    803 	{
    804 		for (int scenario_index = min_scenario_index; scenario_index <= max_scenario_index; ++scenario_index)
    805 		{
    806 			for (int direction_index = 0; direction_index < direction_count; direction_index++)
    807 			{
    808 				for (int variant_index = 0; variant_index < variant_count; variant_index++)
    809 				{
    810 					sprintf(scenario_name, "sc%c%.2d%c%c",
    811 						team_ids[team_index],
    812 						scenario_index,
    813 						direction_ids[direction_index],
    814 						variant_ids[variant_index]);
    815 
    816 					sprintf(file_name, "%s.INI", scenario_name);
    817 					CCFileClass file(file_name);
    818 					if (file.Is_Available())
    819 					{
    820 						fprintf(names_file, "%s\n", scenario_name);
    821 					}
    822 				}
    823 			}
    824 		}
    825 	}
    826 
    827 	fclose(names_file);
    828 
    829 	return EDITOR_COMMMAND_SUCCESS;
    830 }