summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Robertshaw <simon@hardwired.org.uk>2012-08-11 19:24:48 (GMT)
committer Simon Robertshaw <simon@hardwired.org.uk>2012-08-11 19:24:48 (GMT)
commit08b4e5553aa10df74c4fdb0ba519fb700fa8100b (patch)
tree68cda233dcd82978c377978bb19b1fd61bbe0c70 /src
parentecbb1e910352aec1cda4e2d4c36cf3599bc43963 (diff)
downloadpowder-08b4e5553aa10df74c4fdb0ba519fb700fa8100b.zip
powder-08b4e5553aa10df74c4fdb0ba519fb700fa8100b.tar.gz
Implement some missing lua functions, PNG format creation (requires zlib)
Diffstat (limited to 'src')
-rw-r--r--src/Format.cpp263
-rw-r--r--src/Format.h4
-rw-r--r--src/cat/LuaScriptInterface.cpp103
-rw-r--r--src/graphics/Graphics.cpp9
-rw-r--r--src/graphics/Graphics.h3
-rw-r--r--src/graphics/Renderer.cpp17
-rw-r--r--src/graphics/Renderer.h2
7 files changed, 332 insertions, 69 deletions
diff --git a/src/Format.cpp b/src/Format.cpp
index 71a0e9e..ef0050d 100644
--- a/src/Format.cpp
+++ b/src/Format.cpp
@@ -1,7 +1,10 @@
-#include <time.h>
+#include <ctime>
#include <string>
+#include <stdexcept>
+#include <zlib.h>
#include "Format.h"
+#include "graphics/Graphics.h"
std::string format::UnixtimeToDate(time_t unixtime, std::string dateFormat)
{
@@ -33,3 +36,261 @@ std::string format::UnixtimeToDateMini(time_t unixtime)
return UnixtimeToDate(unixtime, "%H:%M:%S");
}
}
+
+struct PNGChunk
+{
+ int Length;
+ char Name[4];
+ char * Data;
+
+ //char[4] CRC();
+
+ PNGChunk(int length, std::string name)
+ {
+ if(name.length()!=4)
+ throw std::runtime_error("Invalid chunk name");
+ std::copy(name.begin(), name.begin()+4, Name);
+ Length = length;
+ if(length)
+ {
+ Data = new char[length];
+ std::fill(Data, Data+length, 0);
+ }
+ else
+ {
+ Data = NULL;
+ }
+ }
+ unsigned long CRC()
+ {
+ if(!Data)
+ {
+ return format::CalculateCRC((unsigned char*)Name, 4);
+ }
+ else
+ {
+ unsigned char * temp = new unsigned char[4+Length];
+ std::copy(Name, Name+4, temp);
+ std::copy(Data, Data+Length, temp+4);
+ unsigned long tempRet = format::CalculateCRC(temp, 4+Length);
+ delete[] temp;
+ return tempRet;
+ }
+ }
+ ~PNGChunk()
+ {
+ if(Data)
+ delete[] Data;
+ }
+};
+
+std::vector<char> format::VideoBufferToPNG(const VideoBuffer & vidBuf)
+{
+ std::vector<PNGChunk*> chunks;
+
+ //Begin IHDR (Image header) chunk (Image size and depth)
+ PNGChunk IHDRChunk = PNGChunk(13, "IHDR");
+
+ //Image Width
+ IHDRChunk.Data[0] = (vidBuf.Width>>24)&0xFF;
+ IHDRChunk.Data[1] = (vidBuf.Width>>16)&0xFF;
+ IHDRChunk.Data[2] = (vidBuf.Width>>8)&0xFF;
+ IHDRChunk.Data[3] = (vidBuf.Width)&0xFF;
+
+ //Image Height
+ IHDRChunk.Data[4] = (vidBuf.Height>>24)&0xFF;
+ IHDRChunk.Data[5] = (vidBuf.Height>>16)&0xFF;
+ IHDRChunk.Data[6] = (vidBuf.Height>>8)&0xFF;
+ IHDRChunk.Data[7] = (vidBuf.Height)&0xFF;
+
+ //Bit depth
+ IHDRChunk.Data[8] = 8; //8bits per channel or 24bpp
+
+ //Colour type
+ IHDRChunk.Data[9] = 2; //RGB triple
+
+ //Everything else is default
+ chunks.push_back(&IHDRChunk);
+
+ //Begin image data, format is 8bit RGB (24bit pixel)
+ int dataPos = 0;
+ unsigned char * uncompressedData = new unsigned char[(vidBuf.Width*vidBuf.Height*3)+vidBuf.Height];
+
+ //Byte ordering and filtering
+ unsigned char * previousRow = new unsigned char[vidBuf.Width*3];
+ std::fill(previousRow, previousRow+(vidBuf.Width*3), 0);
+ unsigned char * currentRow = new unsigned char[vidBuf.Width*3];
+ for(int y = 0; y < vidBuf.Height; y++)
+ {
+ int rowPos = 0;
+ for(int x = 0; x < vidBuf.Width; x++)
+ {
+ currentRow[rowPos++] = PIXR(vidBuf.Buffer[(y*vidBuf.Width)+x]);
+ currentRow[rowPos++] = PIXG(vidBuf.Buffer[(y*vidBuf.Width)+x]);
+ currentRow[rowPos++] = PIXB(vidBuf.Buffer[(y*vidBuf.Width)+x]);
+ }
+
+ uncompressedData[dataPos++] = 2; //Up Sub(x) filter
+ for(int b = 0; b < rowPos; b++)
+ {
+ int filteredByte = (currentRow[b]-previousRow[b])&0xFF;
+ uncompressedData[dataPos++] = filteredByte;
+ }
+
+ unsigned char * tempRow = previousRow;
+ previousRow = currentRow;
+ currentRow = tempRow;
+ }
+ delete[] currentRow;
+ delete[] previousRow;
+
+ //Compression
+ int compressedBufferSize = (vidBuf.Width*vidBuf.Height*3)*2;
+ unsigned char * compressedData = new unsigned char[compressedBufferSize];
+
+ int result;
+ z_stream zipStream;
+ zipStream.zalloc = Z_NULL;
+ zipStream.zfree = Z_NULL;
+ zipStream.opaque = Z_NULL;
+
+ result = deflateInit2(&zipStream,
+ 9, // level
+ Z_DEFLATED, // method
+ 10, // windowBits
+ 1, // memLevel
+ Z_DEFAULT_STRATEGY // strategy
+ );
+
+ if (result != Z_OK) exit(result);
+
+ zipStream.next_in = uncompressedData;
+ zipStream.avail_in = dataPos;
+
+ zipStream.next_out = compressedData;
+ zipStream.avail_out = compressedBufferSize;
+
+
+ result = deflate(&zipStream, Z_FINISH);
+ if (result != Z_STREAM_END) exit(result);
+
+ int compressedSize = compressedBufferSize-zipStream.avail_out;
+ PNGChunk IDATChunk = PNGChunk(compressedSize, "IDAT");
+ std::copy(compressedData, compressedData+compressedSize, IDATChunk.Data);
+ chunks.push_back(&IDATChunk);
+
+ deflateEnd(&zipStream);
+
+ delete[] compressedData;
+ delete[] uncompressedData;
+
+ PNGChunk IENDChunk = PNGChunk(0, "IEND");
+ chunks.push_back(&IENDChunk);
+
+ //Write chunks to output buffer
+ int finalDataSize = 8;
+ for(std::vector<PNGChunk*>::iterator iter = chunks.begin(), end = chunks.end(); iter != end; ++iter)
+ {
+ PNGChunk * cChunk = *iter;
+ finalDataSize += 4 + 4 + 4;
+ finalDataSize += cChunk->Length;
+ }
+ unsigned char * finalData = new unsigned char[finalDataSize];
+ int finalDataPos = 0;
+
+ //PNG File header
+ finalData[finalDataPos++] = 0x89;
+ finalData[finalDataPos++] = 0x50;
+ finalData[finalDataPos++] = 0x4E;
+ finalData[finalDataPos++] = 0x47;
+ finalData[finalDataPos++] = 0x0D;
+ finalData[finalDataPos++] = 0x0A;
+ finalData[finalDataPos++] = 0x1A;
+ finalData[finalDataPos++] = 0x0A;
+
+ for(std::vector<PNGChunk*>::iterator iter = chunks.begin(), end = chunks.end(); iter != end; ++iter)
+ {
+ PNGChunk * cChunk = *iter;
+
+ //Chunk length
+ finalData[finalDataPos++] = (cChunk->Length>>24)&0xFF;
+ finalData[finalDataPos++] = (cChunk->Length>>16)&0xFF;
+ finalData[finalDataPos++] = (cChunk->Length>>8)&0xFF;
+ finalData[finalDataPos++] = (cChunk->Length)&0xFF;
+
+ //Chunk name
+ std::copy(cChunk->Name, cChunk->Name+4, finalData+finalDataPos);
+ finalDataPos += 4;
+
+ //Chunk data
+ if(cChunk->Data)
+ {
+ std::copy(cChunk->Data, cChunk->Data+cChunk->Length, finalData+finalDataPos);
+ finalDataPos += cChunk->Length;
+ }
+
+ //Chunk CRC
+ unsigned long tempCRC = cChunk->CRC();
+ finalData[finalDataPos++] = (tempCRC>>24)&0xFF;
+ finalData[finalDataPos++] = (tempCRC>>16)&0xFF;
+ finalData[finalDataPos++] = (tempCRC>>8)&0xFF;
+ finalData[finalDataPos++] = (tempCRC)&0xFF;
+ }
+
+ std::vector<char> outputData(finalData, finalData+finalDataPos);
+
+ delete[] finalData;
+
+ return outputData;
+}
+
+//CRC functions, copypasta from W3 PNG spec.
+
+/* Table of CRCs of all 8-bit messages. */
+unsigned long crc_table[256];
+
+/* Flag: has the table been computed? Initially false. */
+int crc_table_computed = 0;
+
+/* Make the table for a fast CRC. */
+void make_crc_table(void)
+{
+ unsigned long c;
+ int n, k;
+
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long) n;
+ for (k = 0; k < 8; k++) {
+ if (c & 1)
+ c = 0xedb88320L ^ (c >> 1);
+ else
+ c = c >> 1;
+ }
+ crc_table[n] = c;
+ }
+ crc_table_computed = 1;
+}
+
+/* Update a running CRC with the bytes buf[0..len-1]--the CRC
+ should be initialized to all 1's, and the transmitted value
+ is the 1's complement of the final running CRC (see the
+ crc() routine below)). */
+
+unsigned long update_crc(unsigned long crc, unsigned char *buf, int len)
+{
+ unsigned long c = crc;
+ int n;
+
+ if (!crc_table_computed)
+ make_crc_table();
+ for (n = 0; n < len; n++)
+ {
+ c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
+ }
+ return c;
+}
+
+unsigned long format::CalculateCRC(unsigned char * data, int len)
+{
+ return update_crc(0xffffffffL, data, len) ^ 0xffffffffL;
+} \ No newline at end of file
diff --git a/src/Format.h b/src/Format.h
index 1df883f..fc55f8f 100644
--- a/src/Format.h
+++ b/src/Format.h
@@ -1,7 +1,9 @@
#pragma once
#include <sstream>
+#include <vector>
+class VideoBuffer;
namespace format
{
template <typename T> std::string NumberToString(T number)
@@ -20,4 +22,6 @@ namespace format
std::string UnixtimeToDate(time_t unixtime, std::string dateFomat = "%d %b %Y");
std::string UnixtimeToDateMini(time_t unixtime);
+ std::vector<char> VideoBufferToPNG(const VideoBuffer & vidBuf);
+ unsigned long CalculateCRC(unsigned char * data, int length);
} \ No newline at end of file
diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp
index 97c323c..b37633d 100644
--- a/src/cat/LuaScriptInterface.cpp
+++ b/src/cat/LuaScriptInterface.cpp
@@ -7,8 +7,11 @@
#include <string>
#include "Config.h"
+#include "Format.h"
#include "LuaScriptInterface.h"
#include "TPTScriptInterface.h"
+#include "dialogues/ErrorMessage.h"
+#include "dialogues/InformationMessage.h"
#include "simulation/Simulation.h"
#include "game/GameModel.h"
#include "LuaScriptHelper.h"
@@ -258,7 +261,7 @@ bool LuaScriptInterface::OnMouseWheel(int x, int y, int d)
bool LuaScriptInterface::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
- int modifiers;
+ int modifiers = 0;
if(shift)
modifiers |= 0x001;
if(ctrl)
@@ -270,7 +273,7 @@ bool LuaScriptInterface::OnKeyPress(int key, Uint16 character, bool shift, bool
bool LuaScriptInterface::OnKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
- int modifiers;
+ int modifiers = 0;
if(shift)
modifiers |= 0x001;
if(ctrl)
@@ -994,16 +997,8 @@ int luatpt_graphics_func(lua_State *l)
int luatpt_error(lua_State* l)
{
- /*char *error = "";
- error = mystrdup((char*)luaL_optstring(l, 1, "Error text"));
- if(vid_buf!=NULL){
- error_ui(vid_buf, 0, error);
- free(error);
- return 0;
- }
- free(error);
- return luaL_error(l, "Screen buffer does not exist");*/
- //TODO IMPLEMENT
+ std::string errorMessage = std::string(luaL_optstring(l, 1, "Error text"));
+ new ErrorMessage("Error", errorMessage);
return 0;
}
int luatpt_drawtext(lua_State* l)
@@ -1539,7 +1534,7 @@ int luatpt_get_property(lua_State* l)
int luatpt_drawpixel(lua_State* l)
{
- /*int x, y, r, g, b, a;
+ int x, y, r, g, b, a;
x = luaL_optint(l, 1, 0);
y = luaL_optint(l, 2, 0);
r = luaL_optint(l, 3, 255);
@@ -1557,12 +1552,8 @@ int luatpt_drawpixel(lua_State* l)
if (b>255) b = 255;
if (a<0) a = 0;
if (a>255) a = 255;
- if (luacon_g->vid!=NULL)
- {
- luacon_g->drawpixel(x, y, r, g, b, a);
- return 0;
- }*/
- return luaL_error(l, "Deprecated");
+ luacon_g->blendpixel(x, y, r, g, b, a);
+ return 0;
}
int luatpt_drawrect(lua_State* l)
@@ -1672,10 +1663,6 @@ int luatpt_get_name(lua_State* l)
int luatpt_set_shortcuts(lua_State* l)
{
- /*int state;
- state = luaL_optint(l, 1, 0);
- sys_shortcuts = (state==0?0:1);
- return 0;*/
return luaL_error(l, "set_shortcuts: deprecated");
}
@@ -1879,20 +1866,9 @@ int luatpt_input(lua_State* l)
}
int luatpt_message_box(lua_State* l)
{
- /*char *title, *text;
- title = mystrdup(luaL_optstring(l, 1, "Title"));
- text = mystrdup(luaL_optstring(l, 2, "Message"));
- if (vid_buf!=NULL)
- {
- info_ui(vid_buf, title, text);
- free(title);
- free(text);
- return 0;
- }
- free(title);
- free(text);
- return luaL_error(l, "Screen buffer does not exist");;*/
- //TODO IMPLEMENT
+ std::string title = std::string(luaL_optstring(l, 1, "Title"));
+ std::string message = std::string(luaL_optstring(l, 2, "Message"));
+ new InformationMessage(title, message);
return 0;
}
int luatpt_get_numOfParts(lua_State* l)
@@ -1945,15 +1921,12 @@ int luatpt_hud(lua_State* l)
}
int luatpt_gravity(lua_State* l)
{
- //luacon_sim->
- /*int gravstate;
+ int gravstate;
gravstate = luaL_optint(l, 1, 0);
if(gravstate)
- start_grav_async();
+ luacon_sim->grav->start_grav_async();
else
- stop_grav_async();
- ngrav_enable = (gravstate==0?0:1);*/
- //TODO IMPLEMENT
+ luacon_sim->grav->stop_grav_async();
return 0;
}
int luatpt_airheat(lua_State* l)
@@ -1991,7 +1964,7 @@ int luatpt_heat(lua_State* l)
int luatpt_cmode_set(lua_State* l)
{
//TODO IMPLEMENT
- return luaL_error(l, "Not implemented");
+ return luaL_error(l, "cmode_set: Deprecated");
}
int luatpt_setfire(lua_State* l)
{
@@ -2002,11 +1975,7 @@ int luatpt_setfire(lua_State* l)
}
int luatpt_setdebug(lua_State* l)
{
- /*int debug = luaL_optint(l, 1, 0);
- debug_flags = debug;
- return 0;*/
- //TODO IMPLEMENT
- return luaL_error(l, "Not implemented");
+ return luaL_error(l, "setdebug: Deprecated");
}
int luatpt_setfpscap(lua_State* l)
{
@@ -2108,32 +2077,30 @@ fin:
int luatpt_setwindowsize(lua_State* l)
{
- /*int result, scale = luaL_optint(l,1,1), kiosk = luaL_optint(l,2,0);
+ int scale = luaL_optint(l,1,1), kiosk = luaL_optint(l,2,0);
if (scale!=2) scale = 1;
if (kiosk!=1) kiosk = 0;
- result = set_scale(scale, kiosk);
- lua_pushnumber(l, result);
- return 1;*/
- //TODO Implement
- return luaL_error(l, "Not implemented");
+ ui::Engine::Ref().SetScale(scale);
+ ui::Engine::Ref().SetFullscreen(kiosk);
+ return 0;
}
int luatpt_screenshot(lua_State* l)
{
//TODO Implement
- /*int captureUI = luaL_optint(l, 1, 0);
- if(vid_buf)
+ int captureUI = luaL_optint(l, 1, 0);
+ std::vector<char> data;
+ if(captureUI)
{
- if(captureUI)
- {
- dump_frame(vid_buf, XRES+BARSIZE, YRES+MENUSIZE, XRES+BARSIZE);
- }
- else
- {
- dump_frame(vid_buf, XRES, YRES, XRES+BARSIZE);
- }
- return 0;
- }*/
- return luaL_error(l, "Not implemented");
+ VideoBuffer screenshot(ui::Engine::Ref().g->DumpFrame());
+ data = format::VideoBufferToPNG(screenshot);
+ }
+ else
+ {
+ VideoBuffer screenshot(luacon_ren->DumpFrame());
+ data = format::VideoBufferToPNG(screenshot);
+ }
+ Client::Ref().WriteFile(data, "screenshot.png");
+ return 0;
}
diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp
index eb92435..e7cce03 100644
--- a/src/graphics/Graphics.cpp
+++ b/src/graphics/Graphics.cpp
@@ -909,3 +909,12 @@ void Graphics::draw_image(VideoBuffer * vidBuf, int x, int y, int a)
draw_image(vidBuf->Buffer, x, y, vidBuf->Width, vidBuf->Height, a);
}
+VideoBuffer Graphics::DumpFrame()
+{
+#ifdef OGLI
+#else
+ VideoBuffer newBuffer(XRES+BARSIZE, YRES+MENUSIZE);
+ std::copy(vid, vid+((XRES+BARSIZE)*(YRES+MENUSIZE)), newBuffer.Buffer);
+ return newBuffer;
+#endif
+} \ No newline at end of file
diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h
index e74239e..46d28b4 100644
--- a/src/graphics/Graphics.h
+++ b/src/graphics/Graphics.h
@@ -4,6 +4,7 @@
#include <string>
#include <cstdlib>
#include <cstring>
+#include <vector>
#if defined(OGLI)
#include "OpenGLHeaders.h"
#endif
@@ -135,6 +136,8 @@ public:
static int textwidth(const char *s);
static void textsize(const char * s, int & width, int & height);
+ VideoBuffer DumpFrame();
+
void Acquire();
void Release();
diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp
index 11cf9c3..6c1a31b 100644
--- a/src/graphics/Renderer.cpp
+++ b/src/graphics/Renderer.cpp
@@ -2475,6 +2475,23 @@ unsigned int Renderer::GetColourMode()
return colour_mode;
}
+VideoBuffer Renderer::DumpFrame()
+{
+#ifdef OGLR
+#elif defined(OGLI)
+ VideoBuffer newBuffer(XRES, YRES);
+ std::copy(vid, vid+(XRES*YRES), newBuffer.Buffer);
+ return newBuffer;
+#else
+ VideoBuffer newBuffer(XRES, YRES);
+ for(int y = 0; y < YRES; y++)
+ {
+ std::copy(vid+(y*(XRES+BARSIZE)), vid+(y*(XRES+BARSIZE))+XRES, newBuffer.Buffer+(y*XRES));
+ }
+ return newBuffer;
+#endif
+}
+
Renderer::~Renderer()
{
#if !defined(OGLR)
diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h
index 6691ef1..cc7debe 100644
--- a/src/graphics/Renderer.h
+++ b/src/graphics/Renderer.h
@@ -113,6 +113,8 @@ public:
void draw_image(pixel *img, int x, int y, int w, int h, int a);
#endif
+ VideoBuffer DumpFrame();
+
void drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb);
//...
//Display mode modifiers