Homebrew Homebrew Development

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,565
Country
Chile
I'm not seeing much, is bitmap->pixels a (u8*) and not a (u32*)?

The only things I could see cause a crash is accessing a bad pointer or writing out of memory.
If Flipped is fine and bitmap is correct, then the loop it self is doing the deed. I think you just need print some debug messages and find exactly what line it crashes on.

ARM Cores do not really care if (u8*) or (u32*) because they're all rounded to 4 bytes long when static variable is assigned except the hardware is limited to u8/u16/u32 read/writes or if you want your access to be width-fixed. But you may be getting there ..


Yes, i've just done sanity checks and function doesn't report me any problem.
Anyway even if i use memcpy, result are the same, console still crashes.

Code:
Bitmap* bitmap = (Bitmap*)luaL_checkinteger(L, 1);
   if(!bitmap) return luaL_error(L, "Error loading image");
   u8* flipped = (u8*)malloc(bitmap->width*bitmap->height*4);
   for (int y = 0; y < bitmap->height; y++){
     memcpy(&flipped[y*bitmap->width*4], &bitmap->pixels[(bitmap->height - y - 1) * bitmap->width * 4], bitmap->width * 4);
   }
   free(bitmap->pixels);
   bitmap->pixels = flipped;

aside that, shouldnt :

Code:
for (int y = 0; y < bitmap->height; y++){
for (int x = 0; x < bitmap->width; x++){
*(u32*)(&(flipped[(x+y * bitmap->width)*4])) = *(u32*)&(bitmap->pixels[(x + (bitmap->height - y - 1) * bitmap->width)*4]);
}
}

be instead
Code:
for (int y = 0; y < bitmap->height/4; y++){
for (int x = 0; x < bitmap->width/4; x++){
*(u32*)(&(flipped[(x+y * bitmap->width)*4])) = *(u32*)&(bitmap->pixels[(x + (bitmap->height - y - 1) * bitmap->width)*4]);
}
}

Pretty sure you're allocating four times your currently drawn line, while your loop memory access should match the new boundary requirement that is already *4. So divided by four your get the required boundary step index access done by the loop
 

Jim_e

Well-Known Member
Newcomer
Joined
Nov 13, 2007
Messages
79
Trophies
0
XP
267
Country
United States
bitmap->pixels is a correct pointer (infact if i use it without flipping the image is works fine), i tried also with something like this and i got always the same problem:

Code:
u8* tmp = (u8*)malloc(bitmap->width * 4);
   for (int y = 0; y < bitmap->height / 2; y++){
     memcpy(tmp, &bitmap->pixels[y*bitmap->width*4], bitmap->width * 4);
     memcpy(&bitmap->pixels[y*bitmap->width*4], &bitmap->pixels[(bitmap->height - y - 1) * bitmap->width * 4], bitmap->width * 4);
     memcpy(&bitmap->pixels[(bitmap->height - y - 1) * bitmap->width * 4], tmp, bitmap->width * 4);
   }
   free(tmp);
All of the code you posted here looks fine. And I tested what I could. Nothing is wrong with it.

I looked at your github code for lpp, there is a bug there. In luaScreen.cpp line 232, you don't verify the bitPerPixels and allocate a 24bit pixel buffer.

Shouldn't flipBitmap allocate the buffer itself, instead of passing a buffer and then returning that buffer?


ARM Cores do not really care if (u8*) or (u32*) because they're all rounded to 4 bytes long when static variable is assigned except the hardware is limited to u8/u16/u32 read/writes or if you want your access to be width-fixed. But you may be getting there ..




aside that, shouldnt :

Code:
for (int y = 0; y < bitmap->height; y++){
for (int x = 0; x < bitmap->width; x++){
*(u32*)(&(flipped[(x+y * bitmap->width)*4])) = *(u32*)&(bitmap->pixels[(x + (bitmap->height - y - 1) * bitmap->width)*4]);
}
}

be instead
Code:
for (int y = 0; y < bitmap->height/4; y++){
for (int x = 0; x < bitmap->width/4; x++){
*(u32*)(&(flipped[(x+y * bitmap->width)*4])) = *(u32*)&(bitmap->pixels[(x + (bitmap->height - y - 1) * bitmap->width)*4]);
}
}

Pretty sure you're allocating four times your currently drawn line, while your loop memory access should match the new boundary requirement that is already *4. So divided by four your get the required boundary step index access done by the loop
This is C++ not ARM the underlying architecture has little barring, and width in height are defined in pixels, not bytes.
 
  • Like
Reactions: Rinnegatamante

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
All of the code you posted here looks fine. And I tested what I could. Nothing is wrong with it.

I looked at your github code for lpp, there is a bug there. In luaScreen.cpp line 232, you don't verify the bitPerPixels and allocate a 24bit pixel buffer.

Shouldn't flipBitmap allocate the buffer itself, instead of passing a buffer and then returning that buffer?



This is C++ not ARM the underlying architecture has little barring, and width in height are defined in pixels, not bytes.

You right, now it works fine ;)
 

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,565
Country
Chile
This is C++ not ARM the underlying architecture has little barring.

That's absolutely wrong (vague response I must say), since all pointer assignment are 4 bytes wide ... :

http://www.keil.com/support/man/docs/armccref/armccref_Babfcgfc.htm

This following basic data types are implemented in ARM C and C++:

Type Size in bits Natural alignment in bytes
char 8 1 (byte-aligned)
short 16 2 (halfword-aligned)
int 32 4 (word-aligned)
long 32 4 (word-aligned)
long long 64 8 (doubleword-aligned)
float 32 4 (word-aligned)
double 64 8 (doubleword-aligned)
long double 64 8 (doubleword-aligned)
All pointers 32 4 (word-aligned)
bool (C++ only) 8 1 (byte-aligned)
_Bool (C only[a]) 8 1 (byte-aligned)
wchar_t (C++ only) 16 2 (halfword-aligned)

This is a 32 bit processor

check here:
http://stackoverflow.com/questions/399003/is-the-sizeofsome-pointer-always-equal-to-four

If you're on a 16 bit system your pointer will be 2 bytes long, there is unexpected behaviour even if the u32 write is 4 bytes long.
Due to how you access the memory directly, breaking the whole pixel write to buffer.

Or if you set (u16*) or (u8*) on ARM Cores is always 4 byte, but every other platform will cause corruption, again, due to how you access the memory directly (16bit little endian, vs 16 bit big endian, memory fetch order) will assemble a malformed address , unaligned memory access.

https://www.kernel.org/doc/Documentation/unaligned-memory-access.txt

This is C++ for every platform right?

-

ARM Cores do not really care if (u8*) or (u32*) because they're all rounded to 4 bytes long when static variable is assigned except the hardware is limited to u8/u16/u32 read/writes or if you want your access to be width-fixed.

--

and width in height are defined in pixels, not bytes.
Yes, I read them as bytes , that's my mistake. It's a copy of pixels from different buffer formats
 
Last edited by Coto,

Jim_e

Well-Known Member
Newcomer
Joined
Nov 13, 2007
Messages
79
Trophies
0
XP
267
Country
United States
That's absolutely wrong (vague response I must say), since all pointer assignment are 4 bytes wide ... :

http://www.keil.com/support/man/docs/armccref/armccref_Babfcgfc.htm

This following basic data types are implemented in ARM C and C++:



This is a 32 bit processor

check here:
http://stackoverflow.com/questions/399003/is-the-sizeofsome-pointer-always-equal-to-four

If you're on a 16 bit system your pointer will be 2 bytes long, there is unexpected behaviour even if the u32 write is 4 bytes long.
Due to how you access the memory directly, breaking the whole pixel write to buffer.

Or if you set (u16*) or (u8*) on ARM Cores is always 4 byte, but every other platform will cause corruption, again, due to how you access the memory directly (16bit little endian, vs 16 bit big endian, memory fetch order) will assemble a malformed address , unaligned memory access.

https://www.kernel.org/doc/Documentation/unaligned-memory-access.txt

This is C++ for every platform right?

-



--


Yes, I read them as bytes , that's my mistake. It's a copy of pixels from different buffer formats
Still has little barring. You're referring to portability, that's not an issue here. I was referring to the possibility that the pixel buffer pointer was a u32* as opposed to the expected u8*. Given that width was in pixels, Rinnegatamante may have been attempting to index into a u32 array as if it were a u8. The index would have been 4 times larger than it should have been thus addressing into un-allocated memory causing a crash. That wasn't the issue, but it was worth verifying.

ARM Cores do not really care if (u8*) or (u32*) because they're all rounded to 4 bytes long
I was being vague because i didn't really understand what you were trying to say here and I still don't. But since we're having this conversation...

(u8*) is very different than (u32*) particularly in how it's index. The fact that it's on an arm core doesn't affect anything(other than size, alignment, and endianness of the pointer itself, but that's irrelevant for this case).
So what I'm getting at is what do you mean the Arm core doesn't care between a (u8*) and (u32*)?
 

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,565
Country
Chile
Still has little barring. You're referring to portability, that's not an issue here.
Wrong, see the below comment.

I was being vague because i didn't really understand what you were trying to say here and I still don't. But since we're having this conversation...

(u8*) is very different than (u32*) particularly in how it's index. The fact that it's on an arm core doesn't affect anything(other than size, alignment, and endianness of the pointer itself, but that's irrelevant for this case).
So what I'm getting at is what do you mean the Arm core doesn't care between a (u8*) and (u32*)?

The arm core prefetch must be aligned, and the alignment is always 4 bytes little endian. The ARM standard defines pointer sizes of 4 bytes for all u8,u16,u32 (yes, it's treated as unsigned by the spec). And that you can't really use that drawing function if the CPU core does not treat the pointer static assignment as 4 bytes, (see the linked ARM site), because some platforms (as said previously on the stackoverflow site linked) will make the pointer static assignment of 2 bytes instead, which causes a malformed address.
 

Jim_e

Well-Known Member
Newcomer
Joined
Nov 13, 2007
Messages
79
Trophies
0
XP
267
Country
United States
The arm core prefetch must be aligned, and the alignment is always 4 bytes little endian.
That's reasonable. A lot of architecture have penalties and limitations for un-aligned data. The pointers in the code came from malloc so we're good there.

The ARM standard defines pointer sizes of 4 bytes for all u8,u16,u32 (yes, it's treated as unsigned by the spec).
That's true for almost all 32bit processors.

And that you can't really use that drawing function if the CPU core does not treat the pointer static assignment as 4 bytes, (see the linked ARM site), because some platforms (as said previously on the stackoverflow site linked) will make the pointer static assignment of 2 bytes instead, which causes a malformed address.
Now here's where you lose me. I've been here since the GBA and NDS days. I'm well aware of the issues we had accessing VRAM that had 16 bit writes only. But what does that have to do with (u8*) and (u32*) pointers and how does that affect Rinnegatamante code?

I'm curious, are you confusing sizeof(u8*) with sizeof(*(u8*)). Even if the pointer is 4 bytes and is aligned, that does not affect the array it's pointing to. On the 3ds we can read and write a byte at a time without fear of alignment or word size. Otherwise, I'm really not seeing what you're trying to say in relation to Rinnegatamante code and the 3ds.
 

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,565
Country
Chile
Now here's where you lose me. I've been here since the GBA and NDS days. I'm well aware of the issues we had accessing VRAM that had 16 bit writes only. But what does that have to do with (u8*) and (u32*) pointers and how does that affect Rinnegatamante code?

I'm curious, are you confusing sizeof(u8*) with sizeof(*(u8*)). Even if the pointer is 4 bytes and is aligned, that does not affect the array it's pointing to. On the 3ds we can read and write a byte at a time without fear of alignment or word size. Otherwise, I'm really not seeing what you're trying to say in relation to Rinnegatamante code and the 3ds.

It's all in the addressing bus scheme.

ARM (little endian):
Aligned 4 byte block is shifted (through Inmediate offsets) using the barrel shifter then the opcode for fetch a byte is done.
(if the compiler is smart enough to use these platform specific abilities).

16 bit Core (little endian):
two 16 bit (2 bytes) long pointer static assignment as an address, converted to 32bit address will cause endianness issues even if aligned (2)


Because the compiler can't really translate those custom made (u32*) unaligned accesses, it will fall back to the limited hardware unaligned access ability.

https://www.kernel.org/doc/Documentation/unaligned-memory-access.txt (again yep)

Please read the below message from www.kernel.org

Code that causes unaligned access
=================================

With the above in mind, let's move onto a real life example of a function
that can cause an unaligned memory access. The following function taken
from include/linux/etherdevice.h is an optimized routine to compare two
ethernet MAC addresses for equality.

bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
{
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));

return fold == 0;
#else
const u16 *a = (const u16 *)addr1;
const u16 *b = (const u16 *)addr2;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
#endif
}

In the above function, when the hardware has efficient unaligned access
capability, there is no issue with this code. But when the hardware isn't
able to access memory on arbitrary boundaries, the reference to a[0] causes
2 bytes (16 bits) to be read from memory starting at address addr1.

Think about what would happen if addr1 was an odd address such as 0x10003.
(Hint: it'd be an unaligned access.)

Despite the potential unaligned access problems with the above function, it
is included in the kernel anyway but is understood to only work normally on
16-bit-aligned addresses. It is up to the caller to ensure this alignment or
not use this function at all. This alignment-unsafe function is still useful
as it is a decent optimization for the cases when you can ensure alignment
,
which is true almost all of the time in ethernet networking context.

Alignment that the ARM Core does, but most platforms don't.
 

onepiecefreak

Kuriimu 2 Developer
Member
Joined
Aug 12, 2015
Messages
526
Trophies
0
XP
1,758
Country
Germany
Moah, the pixels are very strange. I was testing it the last 4hours with various combinations of functions, variables and whatever, but now I have an elementary important question:
Are there only Tiles for blue and yellow colors? No matter what I tried there isn't any red or green. I can only combine yellow and blue colorvalues. Pls, can anyone tell me whats wrong there?
 

Jim_e

Well-Known Member
Newcomer
Joined
Nov 13, 2007
Messages
79
Trophies
0
XP
267
Country
United States
custom made (u32*) unaligned accesses
What unaligned access? The pointers came from malloc, the pixels are all 32bit. There's nothing unaligned, this is a perfectly safe code.

You keep posting references dealing with porting, but there's no porting going on here, and I'm not sure what question you were trying to answer. I asked what you meant about (u8*) and (u32*) in relation to the code that was posted. I explained the issue creating indices 4 times greater than intended. I don't see what unaligned access has to do with ANYTHING here at all.
 

Coto

-
Member
Joined
Jun 4, 2010
Messages
2,979
Trophies
2
XP
2,565
Country
Chile
I asked what you meant about (u8*) and (u32*) in relation to the code that was posted. I explained the issue creating indices 4 times greater than intended. I don't see what unaligned access has to do with ANYTHING here at all.

it's not safe code, that's it. You port over that and you'll run into addressing issues (wrong pixel references, memory freezes). In fact it works but compiler will have trouble dealing with

custom made (u32*) unaligned accesses

if CPU does not alignment (or compiler for you), or lacks a hardware alignment method, or if pointer depth size is different from 8,16, or 32 bit you will get undefined behaviour.

ARM Cores (from disassembling realview compiled code), I found they perform sanity checks, or insert stubs so all data is at least a multiple of four (bytes).

The past examples came from kernel.org, of course it has to do if you're calling memory without any kind of addressing validation.
 

DiscostewSM

Well-Known Member
Member
Joined
Feb 10, 2009
Messages
5,484
Trophies
2
Location
Sacramento, California
Website
lazerlight.x10.mx
XP
5,506
Country
United States
Does anyone have any examples of rendering to a texture buffer? I'm looking to to render a pre-defined command list to a separate buffer (instead of the main display buffers) so that I may use that buffer as a texture to use on other polygons for the main display buffers.

I thought I knew how to do it, but everything I've tried resulted in a freeze with a black screen.
 

Tjessx

Well-Known Member
Member
Joined
Dec 3, 2014
Messages
1,160
Trophies
0
Age
27
XP
952
Country
Belgium
Does anyone have any examples of rendering to a texture buffer? I'm looking to to render a pre-defined command list to a separate buffer (instead of the main display buffers) so that I may use that buffer as a texture to use on other polygons for the main display buffers.

I thought I knew how to do it, but everything I've tried resulted in a freeze with a black screen.
You could just use an u8* to store your textures in just lije the display biffers. (If i get what you're trying to do).

I worked on a port of terraria for the 3ds, and i stored all the images in u8* and used these to render everything.
2 days later terraria announces that a 3ds port will arrive in early 2016 --'
 

filfat

CTO @ Nordcom Group Inc.
Member
Joined
Nov 24, 2012
Messages
1,261
Trophies
1
Location
Gothenburg, Sweden
Website
www.sweetsideofsweden.com
XP
1,749
Country
Sweden
Would just like to notify anyone whom might be interested in taking over DownloadMii.
There's a lot of work, for example you will need to re-develop most of the backend (personally I would move to Node.js) you would most likely ditch the badly written 3DS application for the DownloadMii-Core which of course is nowhere near completed.

If anyone feels like this is something you would like to do, just send me an email to [email protected]

Cheers! :)
 

onepiecefreak

Kuriimu 2 Developer
Member
Joined
Aug 12, 2015
Messages
526
Trophies
0
XP
1,758
Country
Germany
Ok, I nearly give up. Can anyone give me a working drawPixel function?
The function from AlbertoSONIC doesnt draw the pixels correct. If it does, pls tell me how, because if I give a value of 200 to x and y its not draw the pixel to 200,200. It draws to 300,180.
Pls help me.
 
Last edited by onepiecefreak,

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy

onepiecefreak

Kuriimu 2 Developer
Member
Joined
Aug 12, 2015
Messages
526
Trophies
0
XP
1,758
Country
Germany
Ok, thx. I will try it.

Ok, I implemented it. But if I give the value 200 to x and y, its the same result. The Pixel appears at 300,180. Maybe I implemented it wrong but I dont know where I can do this :D
 
Last edited by onepiecefreak,

KingOfHell

Well-Known Member
Newcomer
Joined
Mar 15, 2015
Messages
74
Trophies
0
Age
36
XP
83
Country
United States
Ok, thx. I will try it.

Ok, I implemented it. But if I give the value 200 to x and y, its the same result. The Pixel appears at 300,180. Maybe I implemented it wrong but I dont know where I can do this :D

Post the snippet of code from your project in code tags, that way we can actually SEE what's wrong with it
EDIT:
Would just like to notify anyone whom might be interested in taking over DownloadMii.
There's a lot of work, for example you will need to re-develop most of the backend (personally I would move to Node.js) you would most likely ditch the badly written 3DS application for the DownloadMii-Core which of course is nowhere near completed.

If anyone feels like this is something you would like to do, just send me an email to [email protected]

Cheers! :)
It's a shame that you're unable to continue the project. If I had the time, I would take it on.
 

Tjessx

Well-Known Member
Member
Joined
Dec 3, 2014
Messages
1,160
Trophies
0
Age
27
XP
952
Country
Belgium
Would just like to notify anyone whom might be interested in taking over DownloadMii.
There's a lot of work, for example you will need to re-develop most of the backend (personally I would move to Node.js) you would most likely ditch the badly written 3DS application for the DownloadMii-Core which of course is nowhere near completed.

If anyone feels like this is something you would like to do, just send me an email to [email protected]

Cheers! :)
I was planning on getting started with something similar in the future.
I used the function downloadFile() from your project, but after using it a few times it always returns error -7 ((result != 0) || statuscode != 200 || statuscode == 403).

Have you had the same problem with this?
 

Rinnegatamante

Well-Known Member
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
I was planning on getting started with something similar in the future.
I used the function downloadFile() from your project, but after using it a few times it always returns error -7 ((result != 0) || statuscode != 200 || statuscode == 403).

Have you had the same problem with this?

It's a common issue of httpc service, filfat reported this also on ctrulib repo if i'm not wrong.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    K3Nv2 @ K3Nv2: Thought I saw my ex on that new kingdom of the Apes poster