Jump to content

Compiling on ARM


Guest ShadowJack

Recommended Posts

Guest ShadowJack

I am building GemRB on Armel

(Droid2 running debian)

 

I am seeing the following compilation errors.

 

/root/gemrb-0.6.2/gemrb/core/Scriptable/Actor.cpp: In member function 'void Actor::SetupFist()':

/root/gemrb-0.6.2/gemrb/core/Scriptable/Actor.cpp:5855: error: cast from 'char (*)[9]' to 'int*' increases required alignment of target type

/root/gemrb-0.6.2/gemrb/core/Scriptable/Actor.cpp:5864: error: cast from 'char (*)[9]' to 'int*' increases required alignment of target type

make[2]: *** [gemrb/core/CMakeFiles/gemrb_core.dir/Scriptable/Actor.o] Error 1

make[1]: *** [gemrb/core/CMakeFiles/gemrb_core.dir/all] Error 2

make: *** [all] Error 2

 

I have turned off warnings as errors, so this is an issue I do not know how to fix easily. I assume the Android port will also have the same issues.

 

It appears that issues like these were fixed a few years ago. I would be glad to do the fixing if someone can point me in the right direction.

 

Thanks,

ShadlowJack

Link to comment
Guest ShadowJack

Thanks for the quick response. Actor builds fine now. I did use git, and yes I did find more issues. I have a small change to CMakeLists.txt for those whose are not using OGG. What workflow do you prefer? git push or something more elaborate?

 

-sj

Link to comment
What workflow do you prefer? git push or something more elaborate?

 

git push to a repository somewhere (e.g. github) and then prodding us is easiest, or just putting patches somewhere.

 

I notice also that I forgot to fix ReadChrHeader last time I tried this myself, meh..

Link to comment
Guest ShadowJack

I finally got it built. Several plugins required work for ARM. I am still testing the changes, but here's a patch I would like to promote:

 

 

From 9c0555fe1b1ba733cc68685dbb63cec46fb582fd Mon Sep 17 00:00:00 2001

From: root <root@localhost.(none)>

Date: Thu, 2 Dec 2010 19:01:11 +0000

Subject: [PATCH] Allowed compilation without OGG support.

 

---

CMakeLists.txt | 4 +++-

1 files changed, 3 insertions(+), 1 deletions(-)

 

diff --git a/CMakeLists.txt b/CMakeLists.txt

index 598fe9e..ad88c76 100644

--- a/CMakeLists.txt

+++ b/CMakeLists.txt

@@ -183,7 +183,9 @@ find_path(VORBIS_FILE vorbisfile.h PATH_SUFFIXES vorbis)

IF(VORBIS_LIBRARY AND VORBIS_FILE)

MESSAGE(STATUS "Looking for Ogg Vorbis support: found")

ELSE()

- unset(VORBIS_LIBRARY) # disable the build for this plugin

+ IF(VORBIS_LIBRARY)

+ unset(VORBIS_LIBRARY) # disable the build for this plugin

+ ENDIF()

MESSAGE(WARNING "Looking for Ogg Vorbis support: not found!")

MESSAGE(WARNING "While no original game data is in OGG format, some mod data is and will need conversion.")

ENDIF()

--

1.5.6.5

Link to comment
Guest ShadowJack
Something cleaner was committed, rendering that patch unneeded. But thanks for bringing it to our attention.

 

Thanks, I picked up that code.

 

I see something odd in SDLAudio::Play(...). If I apply the following patch I can compile for arm.

 

diff --git a/gemrb/plugins/SDLAudio/SDLAudio.cpp b/gemrb/plugins/SDLAudio/SDLAudio.cpp

index 9bdb3a9..ada1297 100644

--- a/gemrb/plugins/SDLAudio/SDLAudio.cpp

+++ b/gemrb/plugins/SDLAudio/SDLAudio.cpp

@@ -144,11 +144,10 @@ Holder<SoundHandle> SDLAudio::Play(const char* ResRef, int XPos, int YPos, unsig

int cnt = acm->get_length();

int riff_chans = acm->get_channels();

int samplerate = acm->get_samplerate();

- //multiply always by 2 because it is in 16 bits

- int rawsize = cnt * 2;

- unsigned char * memory = (unsigned char*) malloc(rawsize);

+ //Use 16-bit word for memory allocation because read_samples takes a 16 bit alignment

+ short * memory = (short *) malloc(cnt);

//multiply always with 2 because it is in 16 bits

- int cnt1 = acm->read_samples( ( short* ) memory, cnt ) * 2;

+ int cnt1 = acm->read_samples( memory, cnt ) * 2;

//Sound Length in milliseconds

unsigned int time_length = ((cnt / riff_chans) * 1000) / samplerate;

 

@@ -161,7 +160,7 @@ Holder<SoundHandle> SDLAudio::Play(const char* ResRef, int XPos, int YPos, unsig

SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, riff_chans, samplerate,

audio_format, audio_channels, audio_rate);

cvt.buf = (Uint8*)malloc(cnt1*cvt.len_mult);

- memcpy(cvt.buf, memory, cnt1);

+ memcpy(cvt.buf, (char*) memory, cnt1);

cvt.len = cnt1;

SDL_ConvertAudio(&cvt);

 

It looks like the code is creating an extra copy of the samples (memory) that is thrown away after it us copied to cvt.buf, but I did not look at the larger picture, so I may be wrong. In any case, please apply this patch or something better.

 

-ShadowJack

Link to comment
Guest ShadowJack

This set of changes supports ARM5 and runs Baldur's Gate. I tested with PST and it works except for the 16-bit MVE. Where possible I wrote generic code for all machines, but I have some ARM specific code for cases when I think the performance is important and the original code is cleaner/better.

 

I will work on MVE-16 next, but that looks like slow going.

 

-ShadowJack

 

 

 

From ad74e1496260c751c1c3d1245ee2c1e889a6bcff Mon Sep 17 00:00:00 2001

From: root <root@localhost.(none)>

Date: Mon, 6 Dec 2010 22:04:45 +0000

Subject: [PATCH] Fix unaligned accesses for ARM5 architectures

 

---

gemrb/plugins/BIKPlayer/BIKPlayer.cpp | 36 +++++++++--

gemrb/plugins/BIKPlayer/GetBitContext.cpp | 17 +++++

gemrb/plugins/CREImporter/CREImporter.cpp | 5 +-

gemrb/plugins/SDLAudio/SDLAudio.cpp | 9 +--

gemrb/plugins/SDLVideo/SDLVideo.cpp | 95 ++++++++++++++++++++++++++---

gemrb/plugins/WAVReader/WAVReader.cpp | 19 ++++--

6 files changed, 154 insertions(+), 27 deletions(-)

 

diff --git a/gemrb/plugins/BIKPlayer/BIKPlayer.cpp b/gemrb/plugins/BIKPlayer/BIKPlayer.cpp

index 65092ab..580dc15 100644

--- a/gemrb/plugins/BIKPlayer/BIKPlayer.cpp

+++ b/gemrb/plugins/BIKPlayer/BIKPlayer.cpp

@@ -1153,10 +1153,35 @@ int BIKPlayer::read_colors(Bundle *b)

/** number of bits used to store first DC value in bundle */

#define DC_START_BITS 11

 

+#if defined(__arm__)

+#define SET_INT_TYPE uint8_t

+#define SET_INT_VALUE(ptr, value)\

+ *(ptr) = (value) && 0xff; \

+ (ptr)++; \

+ *(ptr) = ((value) >> 8) && 0xff; \

+ (ptr)++;

+#else

+#define SET_INT_TYPE int16_t

+#define SET_INT_VALUE(ptr, value)\

+ *(ptr)++ = (value);

+#endif

+

+#if defined(__arm__)

+#define GET_INT_VALUE(value, ptr)\

+ (value) = *(ptr); \

+ (ptr)++; \

+ (value) |= (*(ptr)) << 8; \

+ (ptr)++;

+#else

+#define GET_INT_VALUE(value, ptr)\

+ (value) = *(int16_t*)(ptr); \

+ (ptr) += 2;

+#endif

+

int BIKPlayer::read_dcs(Bundle *b, int start_bits, int has_sign)

{

int i, j, len, len2, bsize, v, v2;

- int16_t *dst = (int16_t*)b->cur_dec;

+ SET_INT_TYPE *dst = (SET_INT_TYPE*)b->cur_dec;

 

CHECK_READ_VAL(v_gb, b, len);

if (has_sign) {

@@ -1166,7 +1191,7 @@ int BIKPlayer::read_dcs(Bundle *b, int start_bits, int has_sign)

} else {

v = v_gb.get_bits(start_bits);

}

- *dst++ = v;

+ SET_INT_VALUE(dst, v);

len--;

for (i = 0; i < len; i += 8) {

len2 = FFMIN(len - i, 8);

@@ -1178,14 +1203,14 @@ int BIKPlayer::read_dcs(Bundle *b, int start_bits, int has_sign)

v2 = -v2;

}

v += v2;

- *dst++ = v;

+ SET_INT_VALUE(dst, v);

if (v < -32768 || v > 32767) {

return -1;

}

}

} else {

for (j = 0; j < len2; j++) {

- *dst++ = v;

+ SET_INT_VALUE(dst, v);

}

}

}

@@ -1204,8 +1229,7 @@ inline int BIKPlayer::get_value(int bundle)

if (bundle == BINK_SRC_X_OFF || bundle == BINK_SRC_Y_OFF) {

return (int8_t)*c_bundle[bundle].cur_ptr++;

}

- ret = *(int16_t*)c_bundle[bundle].cur_ptr;

- c_bundle[bundle].cur_ptr += 2;

+ GET_INT_VALUE(ret, c_bundle[bundle].cur_ptr);

return ret;

}

 

diff --git a/gemrb/plugins/BIKPlayer/GetBitContext.cpp b/gemrb/plugins/BIKPlayer/GetBitContext.cpp

index eaaca2d..ace0cee 100644

--- a/gemrb/plugins/BIKPlayer/GetBitContext.cpp

+++ b/gemrb/plugins/BIKPlayer/GetBitContext.cpp

@@ -175,6 +175,22 @@ int VLC::alloc_table(int size)

return index;

}

 

+#if defined(__arm__)

+#define GET_DATA(v, table, i, wrap, size) \

+{\

+ const uint8_t *ptr = (const uint8_t *)table + i * wrap;\

+ v = 0;\

+ switch(size) {\

+ case 4:\

+ v |= *((const uint8_t *)ptr+3) << 24;\

+ v |= *((const uint8_t *)ptr+2) << 16;\

+ case 2:\

+ v |= *((const uint8_t *)ptr+1) << 8;\

+ case 1:\

+ v |= *(const uint8_t *)ptr;\

+ }\

+}

+#else

#define GET_DATA(v, table, i, wrap, size) \

{\

const uint8_t *ptr = (const uint8_t *)table + i * wrap;\

@@ -190,6 +206,7 @@ int VLC::alloc_table(int size)

break;\

}\

}

+#endif

 

int VLC::build_table(int table_nb_bits, int nb_codes,

const void *bits, int bits_wrap, int bits_size,

diff --git a/gemrb/plugins/CREImporter/CREImporter.cpp b/gemrb/plugins/CREImporter/CREImporter.cpp

index 84e471c..3f73424 100644

--- a/gemrb/plugins/CREImporter/CREImporter.cpp

+++ b/gemrb/plugins/CREImporter/CREImporter.cpp

@@ -553,7 +553,6 @@ void CREImporter::ReadChrHeader(Actor *act)

ieVariable name;

char Signature[8];

ieDword offset, size;

- ieDword tmpDword;

ieWord tmpWord;

ieByte tmpByte;

 

@@ -562,8 +561,8 @@ void CREImporter::ReadChrHeader(Actor *act)

str->Read (Signature, 8);

str->Read (name, 32);

name[32]=0;

- tmpDword = *(ieDword *) name;

- if (tmpDword != 0 && tmpDword !=1) {

+ tmpByte = *name;

+ if (tmpByte != 0 && tmpByte !=1) {

act->SetName( name, 0 ); //setting longname

}

str->ReadDword( &offset);

diff --git a/gemrb/plugins/SDLAudio/SDLAudio.cpp b/gemrb/plugins/SDLAudio/SDLAudio.cpp

index 9bdb3a9..ada1297 100644

--- a/gemrb/plugins/SDLAudio/SDLAudio.cpp

+++ b/gemrb/plugins/SDLAudio/SDLAudio.cpp

@@ -144,11 +144,10 @@ Holder<SoundHandle> SDLAudio::Play(const char* ResRef, int XPos, int YPos, unsig

int cnt = acm->get_length();

int riff_chans = acm->get_channels();

int samplerate = acm->get_samplerate();

- //multiply always by 2 because it is in 16 bits

- int rawsize = cnt * 2;

- unsigned char * memory = (unsigned char*) malloc(rawsize);

+ //Use 16-bit word for memory allocation because read_samples takes a 16 bit alignment

+ short * memory = (short *) malloc(cnt);

//multiply always with 2 because it is in 16 bits

- int cnt1 = acm->read_samples( ( short* ) memory, cnt ) * 2;

+ int cnt1 = acm->read_samples( memory, cnt ) * 2;

//Sound Length in milliseconds

unsigned int time_length = ((cnt / riff_chans) * 1000) / samplerate;

 

@@ -161,7 +160,7 @@ Holder<SoundHandle> SDLAudio::Play(const char* ResRef, int XPos, int YPos, unsig

SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, riff_chans, samplerate,

audio_format, audio_channels, audio_rate);

cvt.buf = (Uint8*)malloc(cnt1*cvt.len_mult);

- memcpy(cvt.buf, memory, cnt1);

+ memcpy(cvt.buf, (char*) memory, cnt1);

cvt.len = cnt1;

SDL_ConvertAudio(&cvt);

 

diff --git a/gemrb/plugins/SDLVideo/SDLVideo.cpp b/gemrb/plugins/SDLVideo/SDLVideo.cpp

index f5e0d1c..893a0b7 100644

--- a/gemrb/plugins/SDLVideo/SDLVideo.cpp

+++ b/gemrb/plugins/SDLVideo/SDLVideo.cpp

@@ -1710,6 +1710,35 @@ void SDLVideoDriver::DrawRectSprite(const Region& rgn, const Color& color, const

}

 

inline void ReadPixel(long &val, unsigned char *pixels, int BytesPerPixel) {

+#if defined(__arm__)

+#if SDL_BYTEORDER == SDL_LIL_ENDIAN

+ long pixel = 0;

+ switch (BytesPerPixel) {

+ case 4:

+ pixel |= *(pixels+3) << 24;

+ case 3:

+ pixel |= *(pixels+2) << 16;

+ case 2:

+ pixel |= *(pixels+1) << 8;

+ case 1:

+ pixel |= *(pixels);

+ }

+ val = pixel;

+#else

+ long pixel = 0;

+ switch (BytesPerPixel) {

+ case 4:

+ pixel |= *(pixels+3);

+ case 3:

+ pixel |= *(pixels+2) << 8;

+ case 2:

+ pixel |= *(pixels+1) << 16;

+ case 1:

+ pixel |= *(pixels) << 24;

+ }

+ val = pixel;

+#endif

+#else

if (BytesPerPixel == 1) {

val = *pixels;

} else if (BytesPerPixel == 2) {

@@ -1722,10 +1751,35 @@ inline void ReadPixel(long &val, unsigned char *pixels, int BytesPerPixel) {

#endif

} else if (BytesPerPixel == 4) {

val = *(Uint32 *)pixels;

- }

+#endif

}

 

inline void WritePixel(const long val, unsigned char *pixels, int BytesPerPixel) {

+#if defined(__arm__)

+#if SDL_BYTEORDER == SDL_LIL_ENDIAN

+ switch (BytesPerPixel) {

+ case 4:

+ *(pixels+3) = val >> 24 & 0xFF;

+ case 3:

+ *(pixels+2) = val >> 16 & 0xFF;

+ case 2:

+ *(pixels+1) = val >> 8 & 0xFF;

+ case 1:

+ *pixels = val & 0xFF;

+ }

+#else

+ switch (BytesPerPixel) {

+ case 4:

+ *(pixels+3) = val & 0xFF;

+ case 3:

+ *(pixels+2) = val >> 8 & 0xFF;

+ case 2:

+ *(pixels+1) = val >> 16 & 0xFF;

+ case 1:

+ *pixels = val >> 24 & 0xFF;

+ }

+#endif

+#else

if (BytesPerPixel == 1) {

*pixels = (unsigned char)val;

} else if (BytesPerPixel == 2) {

@@ -1742,7 +1796,7 @@ inline void WritePixel(const long val, unsigned char *pixels, int BytesPerPixel)

#endif

} else if (BytesPerPixel == 4) {

*(Uint32 *)pixels = val;

- }

+#endif

}

 

void SDLVideoDriver::SetPixel(short x, short y, const Color& color, bool clipped)

@@ -2195,16 +2249,40 @@ void SDLVideoDriver::DrawPolyline(Gem_Polygon* poly, const Color& color, bool fi

 

// Draw a 50% alpha line from (y,lt) to (y,rt)

 

- if (backBuf->format->BytesPerPixel == 2) {

+ if (backBuf->format->BytesPerPixel == 2) {

+#if defined(__arm__)

+ Uint8* pix = line + (lt + xCorr) * 2;

+ Uint8* end = pix + (rt - lt) * 2;

+ for (; pix < end; pix+=2) {

+ Uint16 pixel = *pix | *(pix+1) << 8;

+ pixel = ((pixel >> 1)&mask16) + alphacol16;

+ *pix = pixel & 0xFF;

+ *(pix+1) = (pixel >> 8) & 0xFF;

+ }

+#else

Uint16* pix = (Uint16*)line + lt + xCorr;

Uint16* end = pix + (rt - lt);

for (; pix < end; pix++)

*pix = ((*pix >> 1)&mask16) + alphacol16;

+#endif

} else if (backBuf->format->BytesPerPixel == 4) {

+#if defined(__arm__)

+ Uint8* pix = line + (lt + xCorr) * 4;

+ Uint8* end = pix + (rt - lt) * 4;

+ for (; pix < end; pix+=4) {

+ Uint32 pixel = *pix | *(pix+1) << 8 | *(pix+2) << 16 | *(pix+3) << 24;

+ pixel = ((pixel >> 1)&mask32) + alphacol32;

+ *pix = pixel & 0xFF;

+ *(pix+1) = (pixel >> 8) & 0xFF;

+ *(pix+2) = (pixel >> 16) & 0xFF;

+ *(pix+3) = (pixel >> 24) & 0xFF;

+ }

+#else

Uint32* pix = (Uint32*)line + lt + xCorr;

Uint32* end = pix + (rt - lt);

for (; pix < end; pix++)

*pix = ((*pix >> 1)&mask32) + alphacol32;

+#endif

} else {

assert(false);

}

@@ -2411,12 +2489,13 @@ void SDLVideoDriver::ClickMouse(unsigned int button)

 

void SDLVideoDriver::MouseClickEvent(Uint8 type, Uint8 button)

{

- SDL_MouseButtonEvent *event = new SDL_MouseButtonEvent();

+ SDL_Event *event = new SDL_Event();

event->type = type;

- event->button = button;

- event->state = (type==SDL_MOUSEBUTTONDOWN)?SDL_PRESSED:SDL_RELEASED;

- event->x = CursorPos.x;

- event->y = CursorPos.y;

+ event->button.type = type;

+ event->button.button = button;

+ event->button.state = (type==SDL_MOUSEBUTTONDOWN)?SDL_PRESSED:SDL_RELEASED;

+ event->button.x = CursorPos.x;

+ event->button.y = CursorPos.y;

SDL_PushEvent((SDL_Event *) event);

}

 

diff --git a/gemrb/plugins/WAVReader/WAVReader.cpp b/gemrb/plugins/WAVReader/WAVReader.cpp

index 5774423..06a7000 100644

--- a/gemrb/plugins/WAVReader/WAVReader.cpp

+++ b/gemrb/plugins/WAVReader/WAVReader.cpp

@@ -53,6 +53,15 @@ const unsigned char data_4cc[] = {

'd', 'a', 't', 'a'

};

 

+inline bool cmp4cc(char* first, const unsigned char* second)

+{

+ for (int index = 0; index < 4; index++) {

+ if (first[index] != second[index])

+ return false;

+ }

+ return true;

+}

+

bool RawPCMReader::Open(DataStream* stream)

{

str = stream;

@@ -128,8 +137,8 @@ bool WavPCMReader::Open(DataStream* stream)

str->ReadDword(&r_hdr.length);

//don't swap this

str->Read( &wave, 4 );

- if (r_hdr.fourcc != *( unsigned int * ) RIFF_4cc ||

- wave != *( unsigned int * ) WAVE_4cc) {

+ if ( ! cmp4cc((char*) &r_hdr.fourcc, RIFF_4cc) ||

+ ! cmp4cc((char*) &wave, WAVE_4cc)) {

return false;

}

 

@@ -137,7 +146,7 @@ bool WavPCMReader::Open(DataStream* stream)

//don't swap this

str->Read(&fmt_hdr.fourcc,4);

str->ReadDword(&fmt_hdr.length);

- if (fmt_hdr.fourcc != *( unsigned int * ) fmt_4cc ||

+ if ( ! cmp4cc((char*) &fmt_hdr.fourcc, fmt_4cc) ||

fmt_hdr.length > sizeof( cWAVEFORMATEX )) {

return false;

}

@@ -166,13 +175,13 @@ bool WavPCMReader::Open(DataStream* stream)

str->Read(&data_hdr.fourcc,4);

str->ReadDword(&data_hdr.length);

 

- if (data_hdr.fourcc == *( unsigned int * ) fact_4cc) {

+ if (cmp4cc((char*) &data_hdr.fourcc, fact_4cc)) {

str->Seek( data_hdr.length, GEM_CURRENT_POS );

//str->Read( &data_hdr, sizeof( data_hdr ) );

str->ReadDword(&data_hdr.fourcc);

str->ReadDword(&data_hdr.length);

}

- if (data_hdr.fourcc != *( unsigned int * ) data_4cc) {

+ if ( ! cmp4cc((char *) &data_hdr.fourcc, data_4cc)) {

return false;

}

 

--

1.5.6.5

Link to comment

- tmpDword = *(ieDword *) name;

- if (tmpDword != 0 && tmpDword !=1) {

+ tmpByte = *name;

+ if (tmpByte != 0 && tmpByte !=1) {

 

I think checking for the 1 is not needed anymore, it was due to some bug (misunderstanding in the file structure on my part). That's why i used a dword in the first place too.

So it could be a simple if (!name[0])

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...