1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Use graphics backend in GLideNHQ

This commit is contained in:
Logan McNaughton 2018-03-26 14:00:25 -06:00 committed by Sergey Lipskiy
parent afc41907d5
commit 50998f2f33
10 changed files with 91 additions and 160 deletions

View File

@ -27,12 +27,6 @@ else(MINGW OR PANDORA OR BCMHOST)
endif(MINGW OR PANDORA OR BCMHOST)
LINK_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/lib )
if(GLES2)
add_definitions(
-DGLES2
)
endif(GLES2)
if(UNIX)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_definitions(
@ -161,11 +155,11 @@ else( NOT GHQCHK )
)
if( CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_libraries(ghqchk ${OPENGL_LIBRARIES} png z )
target_link_libraries(ghqchk png z )
endif( CMAKE_BUILD_TYPE STREQUAL "Debug")
if( CMAKE_BUILD_TYPE STREQUAL "Release")
target_link_libraries(ghqchk ${OPENGL_LIBRARIES} png z )
target_link_libraries(ghqchk png z )
endif( CMAKE_BUILD_TYPE STREQUAL "Release")
endif( NOT GHQCHK )

View File

@ -161,8 +161,8 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint
{
uint8 *texture = src;
uint8 *tmptex = _tex1;
if (srcformat == GL_RGBA)
srcformat = GL_RGBA8;
if (srcformat == u32(graphics::colorFormat::RGBA))
srcformat = u32(graphics::internalcolorFormat::RGBA8);
uint16 destformat = srcformat;
/* We need to be initialized first! */
@ -192,19 +192,18 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint
*/
if ((srcwidth >= 4 && srcheight >= 4) &&
((_options & (FILTER_MASK|ENHANCEMENT_MASK)) ||
(srcformat == GL_RGBA8 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)))) {
(srcformat == u32(graphics::internalcolorFormat::RGBA8) && (_maxbpp < 32 || _options & FORCE16BPP_TEX)))) {
if (srcformat != GL_RGBA8) {
if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, srcformat, GL_RGBA8)) {
if (srcformat != u32(graphics::internalcolorFormat::RGBA8)) {
if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, srcformat, u32(graphics::internalcolorFormat::RGBA8))) {
DBG_INFO(80, wst("Error: unsupported format! gfmt:%x\n"), srcformat);
return 0;
}
texture = tmptex;
destformat = GL_RGBA8;
destformat = u32(graphics::internalcolorFormat::RGBA8);
}
switch (destformat) {
case GL_RGBA8:
if (destformat == u32(graphics::internalcolorFormat::RGBA8)) {
/*
* prepare texture enhancements (x2, x4 scalers)
@ -356,12 +355,12 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint
/*
* texture (re)conversions
*/
if (destformat == GL_RGBA8 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)) {
if (srcformat == GL_RGBA8)
srcformat = GL_RGBA4;
if (srcformat != GL_RGBA8) {
if (destformat == u32(graphics::internalcolorFormat::RGBA8) && (_maxbpp < 32 || _options & FORCE16BPP_TEX)) {
if (srcformat == u32(graphics::internalcolorFormat::RGBA8))
srcformat = u32(graphics::internalcolorFormat::RGBA4);
if (srcformat != u32(graphics::internalcolorFormat::RGBA8)) {
tmptex = (texture == _tex1) ? _tex2 : _tex1;
if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, GL_RGBA8, srcformat)) {
if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, u32(graphics::internalcolorFormat::RGBA8), srcformat)) {
DBG_INFO(80, wst("Error: unsupported format! gfmt:%x\n"), srcformat);
return 0;
}
@ -369,10 +368,9 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint
destformat = srcformat;
}
}
break;
}
#if !_16BPP_HACK
case GL_RGBA4:
else if (destformat == u32(graphics::internalcolorFormat::RGBA4)) {
int scale = 1;
tmptex = (texture == _tex1) ? _tex2 : _tex1;
@ -438,14 +436,8 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint
SharpFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SHARP_FILTER_MASK));
texture = tmptex;
}
break;
case GL_RGB5_A1:
break;
case GL_RGB:
break;
#endif /* _16BPP_HACK */
}
#endif /* _16BPP_HACK */
}
/* fill in the texture info. */
@ -524,8 +516,8 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i
* A comp comes before RGB comp.
*/
// TODO: deal with palette textures
if (palette && info->format == GL_COLOR_INDEX8_EXT) {
DBG_INFO(80, wst("found GL_COLOR_INDEX8_EXT format. Need conversion!!\n"));
if (palette && info->format == u32(graphics::internalcolorFormat::COLOR_INDEX8)) {
DBG_INFO(80, wst("found COLOR_INDEX8 format. Need conversion!!\n"));
int width = info->width;
int height = info->height;
@ -537,7 +529,7 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i
/* use palette and convert to 16bit format */
_txQuantize->P8_16BPP((uint32*)texture, (uint32*)tmptex, info->width, info->height, (uint32*)palette);
texture = tmptex;
format = GL_RGB5_A1;
format = u32(graphics::internalcolorFormat::RGB5_A1);
/* fill in the required info to return */
info->data = texture;
@ -549,7 +541,7 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i
/* XXX: add to hires texture cache!!! */
_txHiResCache->add(r_crc64, info);
DBG_INFO(80, wst("GL_COLOR_INDEX8_EXT loaded as gfmt:%x!\n"), format);
DBG_INFO(80, wst("COLOR_INDEX8 loaded as gfmt:%x!\n"), format);
}
return 1;
@ -592,8 +584,8 @@ TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gf
DBG_INFO(80, wst("hirestex: r_crc64:%08X %08X\n"),
(uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff));
if (gfmt != GL_RGBA && gfmt != GL_RGBA8) {
if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, gfmt, GL_RGBA8))
if (gfmt != u32(graphics::colorFormat::RGBA) && gfmt != u32(graphics::internalcolorFormat::RGBA8)) {
if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, gfmt, u32(graphics::internalcolorFormat::RGBA8)))
return 0;
src = _tex1;
}

View File

@ -375,7 +375,7 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
if (tmptex) {
/* check if _rgb.* and _a.* have matching size and format. */
if (!tex || width != tmpwidth || height != tmpheight ||
format != GL_RGBA8 || tmpformat != GL_RGBA8) {
format != u32(graphics::internalcolorFormat::RGBA8) || tmpformat != u32(graphics::internalcolorFormat::RGBA8)) {
#if !DEBUG
INFO(80, wst("-----\n"));
INFO(80, wst("path: %ls\n"), dir_path.string().c_str());
@ -385,7 +385,7 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
INFO(80, wst("Error: missing _rgb.*!\n"));
} else if (width != tmpwidth || height != tmpheight) {
INFO(80, wst("Error: _rgb.* and _a.* have mismatched width or height!\n"));
} else if (format != GL_RGBA8 || tmpformat != GL_RGBA8) {
} else if (format != u32(graphics::internalcolorFormat::RGBA8) || tmpformat != u32(graphics::internalcolorFormat::RGBA8)) {
INFO(80, wst("Error: _rgb.* or _a.* not in 32bit color!\n"));
}
if (tex) free(tex);
@ -480,7 +480,7 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
DBG_INFO(80, wst("read in as %d x %d gfmt:%x\n"), tmpwidth, tmpheight, tmpformat);
/* check if size and format are OK */
if (!(format == GL_RGBA8 || format == GL_COLOR_INDEX8_EXT ) ||
if (!(format == u32(graphics::internalcolorFormat::RGBA8) || format == u32(graphics::internalcolorFormat::COLOR_INDEX8) ) ||
(width * height) < 4) { /* TxQuantize requirement: width * height must be 4 or larger. */
free(tex);
tex = nullptr;
@ -494,7 +494,7 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
}
/* analyze and determine best format to quantize */
if (format == GL_RGBA8) {
if (format == u32(graphics::internalcolorFormat::RGBA8)) {
int i;
int alphabits = 0;
int fullalpha = 0;
@ -597,14 +597,14 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
/* preparations based on above analysis */
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX) {
if (alphabits == 0) destformat = GL_RGB;
else if (alphabits == 1) destformat = GL_RGB5_A1;
else destformat = GL_RGBA8;
if (alphabits == 0) destformat = u32(graphics::internalcolorFormat::RGB8);
else if (alphabits == 1) destformat = u32(graphics::internalcolorFormat::RGB5_A1);
else destformat = u32(graphics::internalcolorFormat::RGBA8);
} else {
destformat = GL_RGBA8;
destformat = u32(graphics::internalcolorFormat::RGBA8);
}
if (fmt == 4 && alphabits == 0) {
destformat = GL_RGBA8;
destformat = u32(graphics::internalcolorFormat::RGBA8);
/* Rice I format; I = (R + G + B) / 3 */
for (i = 0; i < height * width; i++) {
uint32 texel = ((uint32*)tex)[i];
@ -622,7 +622,7 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
/* XXX: only RGBA8888 for now. comeback to this later... */
if (format == GL_RGBA8) {
if (format == u32(graphics::internalcolorFormat::RGBA8)) {
/* minification */
if (width > _maxwidth || height > _maxheight) {
@ -664,22 +664,18 @@ TxHiResCache::loadHiResTextures(const wchar_t * dir_path, boolean replace)
result = resError;
break;
}
switch (destformat) {
case GL_RGBA8:
case GL_RGBA4:
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
destformat = GL_RGBA4;
break;
case GL_RGB5_A1:
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
destformat = GL_RGB5_A1;
break;
case GL_RGB:
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
destformat = GL_RGB;
break;
if (destformat == u32(graphics::internalcolorFormat::RGBA8) ||
destformat == u32(graphics::internalcolorFormat::RGBA4)) {
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
destformat = u32(graphics::internalcolorFormat::RGBA4);
} else if (destformat == u32(graphics::internalcolorFormat::RGB5_A1)) {
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
destformat = u32(graphics::internalcolorFormat::RGB5_A1);
} else if (destformat == u32(graphics::internalcolorFormat::RGB8)) {
if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
destformat = u32(graphics::internalcolorFormat::RGB8);
}
if (_txQuantize->quantize(tex, tmptex, width, height, GL_RGBA8, destformat, 0)) {
if (_txQuantize->quantize(tex, tmptex, width, height, u32(graphics::internalcolorFormat::RGBA8), destformat, 0)) {
format = destformat;
free(tex);
tex = tmptex;

View File

@ -203,7 +203,7 @@ TxImage::readPNG(FILE* fp, int* width, int* height, uint16* format)
*width = (row_bytes >> 2);
*height = o_height;
*format = GL_RGBA8;
*format = u32(graphics::internalcolorFormat::RGBA8);
#if POW2_TEXTURES
/* next power of 2 size conversions */
@ -490,8 +490,8 @@ uint8*
TxImage::readBMP(FILE* fp, int* width, int* height, uint16* format)
{
/* NOTE: returned image format;
* 4, 8bit palette bmp -> GL_COLOR_INDEX8_EXT
* 24, 32bit bmp -> GL_RGBA8
* 4, 8bit palette bmp -> COLOR_INDEX8
* 24, 32bit bmp -> RGBA8
*/
uint8 *image = nullptr;
@ -611,11 +611,11 @@ TxImage::readBMP(FILE* fp, int* width, int* height, uint16* format)
switch (bmp_ihdr.biBitCount) {
case 8:
case 4:
*format = GL_COLOR_INDEX8_EXT;
*format = u32(graphics::internalcolorFormat::COLOR_INDEX8);
break;
case 32:
case 24:
*format = GL_RGBA8;
*format = u32(graphics::internalcolorFormat::RGBA8);
}
#if POW2_TEXTURES

View File

@ -27,6 +27,7 @@
#include "Ext_TxFilter.h"
#include "txWidestringWrapper.h"
#include <Graphics/Parameters.h>
#ifdef WIN32
#define KBHIT(key) ((GetAsyncKeyState(key) & 0x8001) == 0x8001)
@ -34,38 +35,6 @@
#define KBHIT(key) (0)
#endif
#ifdef OS_WINDOWS
#include <GL/gl.h>
#include <GL/glext.h>
#elif defined(GLES2)
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#ifndef GL_RGBA8
#define GL_RGBA8 0x8058
#endif
#define GL_COLOR_INDEX8_EXT 0x80E5
#elif defined(GLES3)
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#define GL_COLOR_INDEX8_EXT 0x80E5
#elif defined(GLES3_1)
#include <GLES3/gl31.h>
#include <GLES3/gl3ext.h>
#define GL_COLOR_INDEX8_EXT 0x80E5
#elif defined(OS_MAC_OS_X)
#include <OpenGL/gl3.h>
#include <OpenGL/glext.h>
#ifndef GL_COLOR_INDEX8_EXT
#define GL_COLOR_INDEX8_EXT 0x80E5
#endif
#elif defined(OS_LINUX)
#include <GL/gl.h>
#include <GL/glext.h>
#elif defined(OS_ANDROID)
#include <GL/gl.h>
#include <GL/glext.h>
#endif // OS_WINDOWS
/* in-memory zlib texture compression */
#define GL_TEXFMT_GZ 0x80000000

View File

@ -837,23 +837,18 @@ TxQuantize::quantize(uint8* src, uint8* dest, int width, int height, uint16 srcf
quantizerFunc quantizer;
int bpp_shift = 0;
if (destformat == GL_RGBA8 || destformat == GL_RGBA) {
switch (srcformat) {
case GL_RGB5_A1:
if (destformat == u32(graphics::internalcolorFormat::RGBA8) || destformat == u32(graphics::colorFormat::RGBA)) {
if (srcformat == u32(graphics::internalcolorFormat::RGB5_A1)) {
quantizer = &TxQuantize::ARGB1555_ARGB8888;
bpp_shift = 1;
break;
case GL_RGBA4:
} else if (srcformat == u32(graphics::internalcolorFormat::RGBA4)) {
quantizer = &TxQuantize::ARGB4444_ARGB8888;
bpp_shift = 1;
break;
case GL_RGB:
} else if (srcformat == u32(graphics::internalcolorFormat::RGB8)) {
quantizer = &TxQuantize::RGB565_ARGB8888;
bpp_shift = 1;
break;
default:
return 0;
}
} else
return 0;
unsigned int numcore = _numcore;
unsigned int blkrow = 0;
@ -891,23 +886,18 @@ TxQuantize::quantize(uint8* src, uint8* dest, int width, int height, uint16 srcf
(*this.*quantizer)((uint32*)src, (uint32*)dest, width, height);
}
} else if (srcformat == GL_RGBA8 || srcformat == GL_RGBA) {
switch (destformat) {
case GL_RGB5_A1:
} else if (srcformat == u32(graphics::internalcolorFormat::RGBA8) || srcformat == u32(graphics::colorFormat::RGBA)) {
if (destformat == u32(graphics::internalcolorFormat::RGB5_A1)) {
quantizer = fastQuantizer ? &TxQuantize::ARGB8888_ARGB1555 : &TxQuantize::ARGB8888_ARGB1555_ErrD;
bpp_shift = 1;
break;
case GL_RGBA4:
} else if (destformat == u32(graphics::internalcolorFormat::RGBA4)) {
quantizer = fastQuantizer ? &TxQuantize::ARGB8888_ARGB4444 : &TxQuantize::ARGB8888_ARGB4444_ErrD;
bpp_shift = 1;
break;
case GL_RGB:
} else if (destformat == u32(graphics::internalcolorFormat::RGB8)) {
quantizer = fastQuantizer ? &TxQuantize::ARGB8888_RGB565 : &TxQuantize::ARGB8888_RGB565_ErrD;
bpp_shift = 1;
break;
default:
return 0;
}
} else
return 0;
unsigned int numcore = _numcore;
unsigned int blkrow = 0;

View File

@ -61,22 +61,17 @@ TxUtil::sizeofTx(int width, int height, uint16 format)
int dataSize = 0;
/* a lookup table for the shifts would be better */
switch (format) {
case GL_COLOR_INDEX8_EXT:
if (format == u32(graphics::internalcolorFormat::COLOR_INDEX8)) {
dataSize = width * height;
break;
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB:
} else if (format == u32(graphics::internalcolorFormat::RGBA4) ||
format == u32(graphics::internalcolorFormat::RGB5_A1) ||
format == u32(graphics::internalcolorFormat::RGB8)) {
dataSize = (width * height) << 1;
break;
case GL_RGBA8:
} else if (format == u32(graphics::internalcolorFormat::RGBA8)) {
dataSize = (width * height) << 2;
break;
default:
} else {
/* unsupported format */
DBG_INFO(80, wst("Error: cannot get size. unsupported gfmt:%x\n"), format);
;
}
return dataSize;
@ -592,26 +587,20 @@ TxMemBuf::getThreadBuf(uint32 threadIdx, uint32 num, uint32 size)
void setTextureFormat(uint16 internalFormat, GHQTexInfo * info)
{
info->format = internalFormat;
switch (internalFormat) {
case GL_RGBA8:
info->texture_format = GL_RGBA;
info->pixel_type = GL_UNSIGNED_BYTE;
break;
case GL_RGB:
info->texture_format = GL_RGB;
info->pixel_type = GL_UNSIGNED_SHORT_5_6_5;
break;
case GL_RGBA4:
info->texture_format = GL_RGBA;
info->pixel_type = GL_UNSIGNED_SHORT_4_4_4_4;
break;
case GL_RGB5_A1:
info->texture_format = GL_RGBA;
info->pixel_type = GL_UNSIGNED_SHORT_5_5_5_1;
break;
default:
info->texture_format = GL_RGBA;
info->pixel_type = GL_UNSIGNED_BYTE;
break;
if (internalFormat == u32(graphics::internalcolorFormat::RGBA8)) {
info->texture_format = u32(graphics::colorFormat::RGBA);
info->pixel_type = u32(graphics::datatype::UNSIGNED_BYTE);
} else if (internalFormat == u32(graphics::internalcolorFormat::RGB8)) {
info->texture_format = u32(graphics::colorFormat::RED_GREEN_BLUE);
info->pixel_type = u32(graphics::datatype::UNSIGNED_SHORT_5_6_5);
} else if (internalFormat == u32(graphics::internalcolorFormat::RGBA4)) {
info->texture_format = u32(graphics::colorFormat::RGBA);
info->pixel_type = u32(graphics::datatype::UNSIGNED_SHORT_4_4_4_4);
} else if (internalFormat == u32(graphics::internalcolorFormat::RGB5_A1)) {
info->texture_format = u32(graphics::colorFormat::RGBA);
info->pixel_type = u32(graphics::datatype::UNSIGNED_SHORT_5_5_5_1);
} else {
info->texture_format = u32(graphics::colorFormat::RGBA);
info->pixel_type = u32(graphics::datatype::UNSIGNED_BYTE);
}
}

View File

@ -4,6 +4,7 @@
namespace graphics {
namespace colorFormat {
ColorFormatParam RED_GREEN_BLUE(GL_RGB);
ColorFormatParam RGBA(GL_RGBA);
ColorFormatParam RG(GL_RG);
ColorFormatParam RED(GL_RED);
@ -12,7 +13,7 @@ namespace graphics {
}
namespace internalcolorFormat {
InternalColorFormatParam RGB8(GL_RGB);
InternalColorFormatParam RGB8(GL_RGB8);
InternalColorFormatParam RGBA8(GL_RGBA8);
InternalColorFormatParam RGBA4(GL_RGBA4);
InternalColorFormatParam RGB5_A1(GL_RGB5_A1);
@ -21,6 +22,7 @@ namespace graphics {
InternalColorFormatParam DEPTH(GL_DEPTH_COMPONENT24);
InternalColorFormatParam RG32F(GL_RG32F);
InternalColorFormatParam LUMINANCE(0x1909);
InternalColorFormatParam COLOR_INDEX8(0x80E5);
}
namespace datatype {
@ -28,6 +30,7 @@ namespace graphics {
DatatypeParam UNSIGNED_SHORT(GL_UNSIGNED_SHORT);
DatatypeParam UNSIGNED_INT(GL_UNSIGNED_INT);
DatatypeParam FLOAT(GL_FLOAT);
DatatypeParam UNSIGNED_SHORT_5_6_5(GL_UNSIGNED_SHORT_5_6_5);
DatatypeParam UNSIGNED_SHORT_5_5_5_1(GL_UNSIGNED_SHORT_5_5_5_1);
DatatypeParam UNSIGNED_SHORT_4_4_4_4(GL_UNSIGNED_SHORT_4_4_4_4);
}

View File

@ -4,6 +4,7 @@
namespace graphics {
namespace colorFormat {
extern ColorFormatParam RED_GREEN_BLUE; //Windows has a macro called RGB
extern ColorFormatParam RGBA;
extern ColorFormatParam RG;
extern ColorFormatParam RED;
@ -21,6 +22,7 @@ namespace graphics {
extern InternalColorFormatParam DEPTH;
extern InternalColorFormatParam RG32F;
extern InternalColorFormatParam LUMINANCE;
extern InternalColorFormatParam COLOR_INDEX8;
}
namespace datatype {
@ -28,6 +30,7 @@ namespace graphics {
extern DatatypeParam UNSIGNED_SHORT;
extern DatatypeParam UNSIGNED_INT;
extern DatatypeParam FLOAT;
extern DatatypeParam UNSIGNED_SHORT_5_6_5;
extern DatatypeParam UNSIGNED_SHORT_5_5_5_1;
extern DatatypeParam UNSIGNED_SHORT_4_4_4_4;
}

View File

@ -10,13 +10,8 @@
#include "winlnxdefs.h"
#endif
#ifdef __LIBRETRO__
#include <glsm/glsmsym.h>
#include <GLideN64_libretro.h>
#endif
#ifdef PANDORA
typedef char GLchar;
#endif
#endif // PLATFORM_H
#endif // PLATFORM_H