/* * PSX-Tools Bundle Pack * Copyright (C) 2002-2003 Nicolas "Pixel" Noble * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: luapsx.cpp,v 1.4 2004-05-24 23:18:59 pixel Exp $ */ #include #include "luapsx.h" #include "generic.h" void over(Byte * d, Byte R, Byte G, Byte B, Byte A) { d[0] = R; d[1] = G; d[2] = B; } void alpha(Byte * d, Byte R, Byte G, Byte B, Byte A) { A = MIN(A, (Byte) 128); d[0] = ((int)d[0] * (128 - A) + R * A) >> 7; d[1] = ((int)d[1] * (128 - A) + G * A) >> 7; d[2] = ((int)d[2] * (128 - A) + B * A) >> 7; } void lighten(Byte * d, Byte R, Byte G, Byte B, Byte A) { A = MIN(A, (Byte) 128); R = ((int)d[0] * (128 - A) + R * A) >> 7; G = ((int)d[1] * (128 - A) + G * A) >> 7; B = ((int)d[2] * (128 - A) + B * A) >> 7; d[0] = MAX(R, d[0]); d[1] = MAX(G, d[1]); d[2] = MAX(B, d[2]); } void darken(Byte * d, Byte R, Byte G, Byte B, Byte A) { A = MIN(A, (Byte) 128); R = ((int)d[0] * (128 - A) + R * A) >> 7; G = ((int)d[1] * (128 - A) + G * A) >> 7; B = ((int)d[2] * (128 - A) + B * A) >> 7; d[0] = MIN(R, d[0]); d[1] = MIN(G, d[1]); d[2] = MIN(B, d[2]); } enum { BLIT_OVER = 0, BLIT_OVER32, BLIT_ALPHA, BLIT_LIGHTEN, BLIT_LIGHTEN32, BLIT_DARKEN, BLIT_DARKEN32, }; typedef void psx; enum psx_functions_t { PSX_BSDECODE = 0, PSX_BSENCODE, PSX_BLIT, }; struct lua_functypes_t psx_functions[] = { { PSX_BSDECODE, "bsdecode", 3, 3, { LUA_OBJECT, LUA_NUMBER, LUA_NUMBER } }, { PSX_BSENCODE, "bsencode", 3, 5, { LUA_OBJECT, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER } }, { PSX_BLIT, "blit", 9, 9, { LUA_OBJECT, LUA_OBJECT, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER, LUA_NUMBER } }, { -1, 0, 0, 0, 0 } }; class sLua_psx : public Base { public: DECLARE_FUNCTION(psx, PSX_BSDECODE); DECLARE_FUNCTION(psx, PSX_BSENCODE); DECLARE_FUNCTION(psx, PSX_BLIT); private: static int psx_proceed_statics(Lua * L, int n, int caller); }; void Luapsx::pushstatics(Lua * L) throw (GeneralException ) { CHECK_FUNCTIONS(psx); PUSH_FUNCTION(psx, PSX_BSDECODE); PUSH_FUNCTION(psx, PSX_BSENCODE); PUSH_FUNCTION(psx, PSX_BLIT); L->push("BLIT_OVER"); L->push((lua_Number) BLIT_OVER); L->settable(LUA_GLOBALSINDEX); L->push("BLIT_OVER32"); L->push((lua_Number) BLIT_OVER32); L->settable(LUA_GLOBALSINDEX); L->push("BLIT_ALPHA"); L->push((lua_Number) BLIT_ALPHA); L->settable(LUA_GLOBALSINDEX); L->push("BLIT_LIGHTEN"); L->push((lua_Number) BLIT_LIGHTEN); L->settable(LUA_GLOBALSINDEX); L->push("BLIT_LIGHTEN32"); L->push((lua_Number) BLIT_LIGHTEN32); L->settable(LUA_GLOBALSINDEX); L->push("BLIT_DARKEN"); L->push((lua_Number) BLIT_DARKEN); L->settable(LUA_GLOBALSINDEX); L->push("BLIT_DARKEN32"); L->push((lua_Number) BLIT_DARKEN32); L->settable(LUA_GLOBALSINDEX); } int sLua_psx::psx_proceed_statics(Lua * L, int n, int caller) { int r = 0; switch (caller) { case PSX_BSDECODE: r = 1; { Buffer * b = new Buffer(true); Handle * f = (Handle *) LuaObject::getme(L, 1); int width = L->tonumber(2); int height = L->tonumber(3); Byte * in = (Byte *) malloc(f->GetSize() + 10); Byte * out = (Byte *) malloc(width * height * 3); LuaBuffer lb(b); lb.pushdestruct(L); f->read(in, f->GetSize()); bs_decode_rgb24(out, (bs_header_t *) in, width, height, 0); for (int i = 0; i < width * height * 3; i++) { b[i] = out[i]; } free(out); free(in); } case PSX_BSENCODE: r = 3; { unsigned short out[0x80000]; Buffer * b = new Buffer(true); LuaBuffer lb(b); lb.pushdestruct(L); Handle * f = (Handle *) LuaObject::getme(L, 1); bs_input_image_t img; img.width = L->tonumber(2); img.height = L->tonumber(3); int max_size = 14112, cur_size; int q_scale = 1; if (n >= 4) max_size = L->tonumber(4); if (n >= 5) q_scale = L->tonumber(5); img.lpbits = (Byte *) malloc(f->GetSize()); img.top = img.lpbits; img.nextline = img.width * 3; img.bit = 24; f->read(img.lpbits, f->GetSize()); bs_init(); cur_size = max_size + 1; for (cur_size = max_size + 1; max_size < cur_size; q_scale++) { cur_size = bs_encode((bs_header_t *) out, &img, 2, q_scale, 0); } for (int i = 0; i < cur_size; i++) { b[i] = out[i]; } L->push((lua_Number) cur_size); L->push((lua_Number) q_scale); } case PSX_BLIT: r = 0; { Handle * d = (Handle *) LuaObject::getme(L, 1); Handle * s = (Handle *) LuaObject::getme(L, 2); int dw = L->tonumber(3), dh = L->tonumber(4), sw = L->tonumber(5), sh = L->tonumber(6), sx = L->tonumber(7), sy = L->tonumber(8), bl = L->tonumber(9); int bytes, dstart = 0, dskip = 0, sstart = 0, sskip = 0, i, j; Byte RGB[3], R, G, B, A = 128; void (*op_func)(Byte *, Byte, Byte, Byte, Byte); switch(bl) { case BLIT_OVER: bytes = 3; op_func = over; break; case BLIT_OVER32: bytes = 4; op_func = over; break; case BLIT_ALPHA: bytes = 4; op_func = alpha; break; case BLIT_LIGHTEN: bytes = 3; op_func = lighten; break; case BLIT_LIGHTEN32: bytes = 4; op_func = lighten; break; case BLIT_DARKEN: bytes = 3; op_func = darken; break; case BLIT_DARKEN32: bytes = 4; op_func = darken; break; default: L->error("Blitting operation unknown."); return 0; } if ((sx + sw) < 0) return; if (sx >= dw) return; if ((sy + sh) < 0) return; if (sy >= dh) return; if (sy < 0) { sstart -= sw * bytes * sy; sh += sy; sy = 0; } else { dstart += dw * 3 * sy; } if ((sy + sh) > dh) { sh -= (sy + sh) - dh; } if (sx < 0) { sstart -= sx * bytes; sskip -= sx * bytes; sw += sx; sx = 0; } else { dstart += sx * 3; } if ((sx + sw) > dw) { sskip += (sx + sw) - dw; sw -= (sx + sw) - dw; } dskip = (dw - sw) * 3; d->seek(dstart); s->seek(sstart); for (i = 0; i < sh; i++, s->seek(sskip, SEEK_CUR), d->seek(dskip, SEEK_CUR)) { for (j = 0; j < sw; j++) { RGB[0] = d->readU8(); RGB[1] = d->readU8(); RGB[2] = d->readU8(); d->seek(-3, SEEK_CUR); R = s->readU8(); G = s->readU8(); B = s->readU8(); if (bytes == 4) A = s->readU8(); op_func(RGB, R, G, B, A); d->writeU8(R); d->writeU8(G); d->writeU8(B); } } } } return r; }