Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F627623
RlePack.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
RlePack.cpp
View Options
/***************************************************************************
This file is part of MortalEditor, the OpenMortal character editor.
This is an internal tool, no warranty or support. Use at your own risk.
Copyright 2004 UPi upi@sourceforge
***************************************************************************/
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<qimage.h>
#include
"RlePack.h"
typedef
unsigned
char
Uint8
;
typedef
struct
{
Uint8
r
;
Uint8
g
;
Uint8
b
;
Uint8
unused
;
}
SDL_Color
;
typedef
struct
RLE_SPRITE
/* a RLE compressed sprite */
{
int
w
,
h
;
/* width and height in pixels */
int
color_depth
;
/* color depth of the image */
int
size
;
/* size of sprite data in bytes */
signed
char
dat
[
0
];
}
RLE_SPRITE
;
struct
RlePack_P
{
SDL_Color
palette
[
256
];
int
count
,
arraysize
;
RLE_SPRITE
**
sprites
;
};
RlePack
::
RlePack
(
const
char
*
filename
)
{
p
=
new
RlePack_P
;
p
->
count
=
p
->
arraysize
=
0
;
p
->
sprites
=
NULL
;
//@ Load file and stuff
FILE
*
f
;
f
=
fopen
(
filename
,
"rb"
);
if
(
f
==
NULL
)
{
debug
(
"Can't open file '%s'.
\n
"
,
filename
);
return
;
}
int
datacount
;
#define READDW(I) { \
unsigned char data[4]; \
fread( data, 4, 1, f ); \
(I) = (data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]; }
#define READW(I) { \
unsigned char data[2]; \
fread( data, 2, 1, f ); \
(I) = (data[0]<<8) + data[1]; }
#define READCH(S,C) { \
fread( S, C, 1, f ); S[C] = 0; }
fseek
(
f
,
8
,
SEEK_SET
);
// Skip header
READDW
(
datacount
);
debug
(
"File '%s' contains %d entries.
\n
"
,
filename
,
datacount
);
if
(
datacount
>
500
)
datacount
=
500
;
// Sanity
p
->
arraysize
=
datacount
;
p
->
sprites
=
new
RLE_SPRITE
*
[
datacount
];
while
(
(
!
feof
(
f
))
&&
(
!
ferror
(
f
))
&&
(
datacount
>
0
)
)
{
char
s
[
10
];
READCH
(
s
,
4
);
if
(
!
strcmp
(
s
,
"prop"
))
// Found a property
{
fseek
(
f
,
4
,
SEEK_CUR
);
unsigned
int
propsize
;
READDW
(
propsize
);
fseek
(
f
,
propsize
,
SEEK_CUR
);
}
else
if
(
!
strcmp
(
s
,
"RLE "
))
// Found an RLE_SPRITE
{
datacount
--
;
unsigned
int
length
,
bpp
,
width
,
height
,
size
;
READDW
(
length
);
READDW
(
length
);
READW
(
bpp
);
READW
(
width
);
READW
(
height
);
READDW
(
size
);
RLE_SPRITE
*
sprite
=
(
RLE_SPRITE
*
)
malloc
(
sizeof
(
RLE_SPRITE
)
+
size
);
p
->
sprites
[
p
->
count
]
=
sprite
;
(
p
->
count
)
++
;
sprite
->
w
=
width
;
sprite
->
h
=
height
;
sprite
->
color_depth
=
bpp
;
sprite
->
size
=
size
;
fread
(
sprite
->
dat
,
1
,
size
,
f
);
}
else
if
(
!
strcmp
(
s
,
"PAL "
))
// Found a palette
{
datacount
--
;
unsigned
int
length
,
pallength
;
READDW
(
length
);
READDW
(
length
);
pallength
=
length
>
1024
?
1024
:
length
;
pallength
/=
4
;
for
(
uint
i
=
0
;
i
<
pallength
;
i
++
)
{
char
c
[
4
];
fread
(
c
,
4
,
1
,
f
);
p
->
palette
[
i
].
r
=
c
[
0
]
*
4
;
p
->
palette
[
i
].
g
=
c
[
1
]
*
4
;
p
->
palette
[
i
].
b
=
c
[
2
]
*
4
;
p
->
palette
[
i
].
unused
=
0
;
}
fseek
(
f
,
length
-
pallength
*
4
,
SEEK_CUR
);
}
else
// Found something else
{
debug
(
"Unknown: %s."
,
s
);
datacount
--
;
unsigned
int
length
;
READDW
(
length
);
READDW
(
length
);
fseek
(
f
,
length
,
SEEK_CUR
);
}
}
fclose
(
f
);
}
RlePack
::~
RlePack
()
{
if
(
!
p
)
return
;
if
(
p
->
sprites
)
{
for
(
int
i
=
0
;
i
<
p
->
count
;
++
i
)
{
delete
p
->
sprites
[
i
];
p
->
sprites
[
i
]
=
NULL
;
}
delete
[]
p
->
sprites
;
p
->
sprites
=
NULL
;
}
delete
(
p
);
p
=
NULL
;
}
/*
void OffsetRLESprite( RLE_SPRITE* spr, int offset )
{
if (!spr || !offset) return;
signed char *s = spr->dat;
signed char c;
int y;
for (y=0; y<spr->h; y++)
{
c = *s++;
while (c)
{
// For positive c: solid pixels.
for ( ; c>0; c-- )
{
*s = (*s) + offset;
s++;
}
c = *s++;
}
}
}
void RlePack::offsetSprites( int offset )
{
if ( (offset<=0) || (offset>255) )
return;
int i;
// Offset every RLE_SPRITE
for ( i=0; i<p->count; ++i )
{
OffsetRLESprite( p->sprites[i], offset );
}
}
*/
/*
SDL_Color* RlePack::getPalette()
{
return p->palette;
}
*/
void
draw_rle_sprite
(
QImage
&
target
,
RLE_SPRITE
*
src
,
int
dx
,
int
dy
)
{
#define RLE_PTR signed char*
#define RLE_IS_EOL(c) ((c) == 0)
#define PIXEL_PTR unsigned char*
#define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x))
#define INC_PIXEL_PTR(p) ((p)++)
#define DEC_PIXEL_PTR(p) ((p)--)
#define PUT_PIXEL(p,c) (*((unsigned char *)(p)) = (c))
int
x
,
y
,
w
,
h
;
// width and height of visible area
int
dxbeg
,
dybeg
;
// beginning in destination
int
sxbeg
,
sybeg
;
// beginning in source
RLE_PTR
s
;
// Clip to dst->clip_rect
int
dst_cl
=
0
;
int
dst_cr
=
target
.
width
();
int
dst_ct
=
0
;
int
dst_cb
=
target
.
height
();
// if (dst->clip)
if
(
1
)
{
int
tmp
;
tmp
=
dst_cl
-
dx
;
sxbeg
=
((
tmp
<
0
)
?
0
:
tmp
);
dxbeg
=
sxbeg
+
dx
;
tmp
=
dst_cr
-
dx
;
w
=
((
tmp
>
src
->
w
)
?
src
->
w
:
tmp
)
-
sxbeg
;
if
(
w
<=
0
)
return
;
tmp
=
dst_ct
-
dy
;
sybeg
=
((
tmp
<
0
)
?
0
:
tmp
);
dybeg
=
sybeg
+
dy
;
tmp
=
dst_cb
-
dy
;
h
=
((
tmp
>
src
->
h
)
?
src
->
h
:
tmp
)
-
sybeg
;
if
(
h
<=
0
)
return
;
}
else
{
w
=
src
->
w
;
h
=
src
->
h
;
sxbeg
=
0
;
sybeg
=
0
;
dxbeg
=
dx
;
dybeg
=
dy
;
}
s
=
(
RLE_PTR
)
(
src
->
dat
);
/* Clip top. */
for
(
y
=
sybeg
-
1
;
y
>=
0
;
y
--
)
{
long
c
=
*
s
++
;
while
(
!
RLE_IS_EOL
(
c
))
{
if
(
c
>
0
)
s
+=
c
;
c
=
*
s
++
;
}
}
// Visible part.
for
(
y
=
0
;
y
<
h
;
y
++
)
{
//@@@ PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
PIXEL_PTR
d
=
target
.
scanLine
(
dybeg
+
y
)
+
dxbeg
;
if
(
!
d
)
break
;
//PIXEL_PTR d = (PIXEL_PTR) dst->pixels;
//d += (dybeg+y)*dst->pitch;
//d = OFFSET_PIXEL_PTR( d, dxbeg );
long
c
=
*
s
++
;
// Clip left.
for
(
x
=
sxbeg
;
x
>
0
;
)
{
if
(
RLE_IS_EOL
(
c
))
goto
next_line
;
else
if
(
c
>
0
)
{
/* Run of solid pixels. */
if
((
x
-
c
)
>=
0
)
{
/* Fully clipped. */
x
-=
c
;
s
+=
c
;
}
else
{
/* Visible on the right. */
c
-=
x
;
s
+=
x
;
break
;
}
}
else
{
/* Run of transparent pixels. */
if
((
x
+
c
)
>=
0
)
{
/* Fully clipped. */
x
+=
c
;
}
else
{
/* Visible on the right. */
c
+=
x
;
break
;
}
}
c
=
*
s
++
;
}
/* Visible part. */
for
(
x
=
w
;
x
>
0
;
)
{
if
(
RLE_IS_EOL
(
c
))
goto
next_line
;
else
if
(
c
>
0
)
{
/* Run of solid pixels. */
if
((
x
-
c
)
>=
0
)
{
/* Fully visible. */
x
-=
c
;
for
(
c
--
;
c
>=
0
;
s
++
,
INC_PIXEL_PTR
(
d
),
c
--
)
{
unsigned
long
col
=
*
s
;
PUT_PIXEL
(
d
,
col
);
}
}
else
{
/* Clipped on the right. */
c
-=
x
;
for
(
x
--
;
x
>=
0
;
s
++
,
INC_PIXEL_PTR
(
d
),
x
--
)
{
unsigned
long
col
=
*
s
;
PUT_PIXEL
(
d
,
col
);
}
break
;
}
}
else
{
/* Run of transparent pixels. */
x
+=
c
;
d
=
OFFSET_PIXEL_PTR
(
d
,
-
c
);
}
c
=
*
s
++
;
}
/* Clip right. */
while
(
!
RLE_IS_EOL
(
c
))
{
if
(
c
>
0
)
s
+=
c
;
c
=
*
s
++
;
}
next_line
:
;
}
}
int
RlePack
::
count
()
{
return
p
->
count
;
}
void
RlePack
::
draw
(
QImage
&
target
,
int
index
,
int
x
,
int
y
)
{
if
(
(
index
<
0
)
||
(
index
>=
p
->
count
)
)
return
;
RLE_SPRITE
*
sprite
=
p
->
sprites
[
index
];
if
(
!
sprite
)
return
;
draw_rle_sprite
(
target
,
sprite
,
x
,
y
);
}
QSize
RlePack
::
getSize
(
int
index
)
{
if
(
(
index
<
0
)
||
(
index
>=
p
->
count
)
)
return
QSize
();
RLE_SPRITE
*
sprite
=
p
->
sprites
[
index
];
return
QSize
(
sprite
->
w
,
sprite
->
h
);
}
void
RlePack
::
transferPalette
(
QImage
&
target
)
{
for
(
int
i
=
0
;
i
<
256
;
++
i
)
{
target
.
setColor
(
i
,
qRgb
(
p
->
palette
[
i
].
r
,
p
->
palette
[
i
].
g
,
p
->
palette
[
i
].
b
)
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sun, Nov 15, 2:25 AM (1 d, 23 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
116142
Default Alt Text
RlePack.cpp (7 KB)
Attached To
Mode
R76 OpenMortal
Attached
Detach File
Event Timeline