#8949 - mtg101 - Thu Jul 24, 2003 7:14 pm
I'm trying to make a text engine for tile backgrounds. The idea is to have tiles in positions 32-126 which map to their respective ASCII chars. Thus tile 57 is a '9' tile and tile 85 is 'U'.
This is setup as follows:
Code: |
void BgTextInit(TileBg* aTileBg)
{
for(int loop = 0; loop < bgFont_NUM_PIXELS / 2; loop++) //load tile image data
aTileBg->tileData[loop+((32*64)/2)] = nologo_bgFont_gfx[loop];
}
|
Now ignoring cases of starting at odd tile positions or writing an odd number of characters, to write text to the background I have:
Code: |
void BgTextWrite(TileBg* aTileBg, int aX, int aY, char* aText)
{
memcpy(&aTileBg->mapData[(aX + (aY * width))/2], aText, strlen(aText));
}
|
I thought using memcpy() rather than using a loop and assigning each pair of map entries one at a time would be much more efficient.
However, things don't work as planned. If I call:
Code: |
BgTextWrite(bg2, 0, 0, "1234")
|
The output is "2244". My guess is that memcpy() is copying single bytes at a time, and when it tries to write just a byte both bytes of the 16bit entry are being set to the byte, hence the duplication in the output. Is this the case?
So am I stuck having to loop over and over to copy my map data, or is there a way to use memcpy() to do it? Or is there another function that copies 2 bytes at a time?
(FYI - I'm using DevKitAdv)
Thanks in advance for any help.
Cheers
Russell
_________________
---
Speaker for the Dead
#8951 - niltsair - Thu Jul 24, 2003 7:58 pm
-Video Memory can only be read/written 2 bytes at a time.
-1 Map entry takes 16bits.
You thus can't write your 8bits string directly.
Example, string of 3 values:
0x30, 0x31, 0x56
you need to write to the map data
0x0030, 0x0031, 0x0056
#8952 - mtg101 - Thu Jul 24, 2003 8:30 pm
niltsair wrote: |
-Video Memory can only be read/written 2 bytes at a time.
-1 Map entry takes 16bits.
|
Really? I thought map data was 8bits? If it were 16bit my code to draw the string "12" on the screen would index tile number 0x3132 (or maybe 0x3231 if I've got endians mixed up). However tile 0x32 it printed twice, which leads me to believe that map data is 8bit.
I realise that map data can only be written 2 bytes at a time, which is why I specified the case of an even number of chars to write, and an even starting point to avoid any complications (I've got other code that works to deal with the odd cases).
Cheers
Russell
_________________
---
Speaker for the Dead
#8953 - niltsair - Thu Jul 24, 2003 8:43 pm
Map data are 16bits.
The reason your data get displayed twice is because you're trying to write 8bits at a time. aText is of type char, so memcpy try to write in 8bits chunks.
Check the Pern project for more info about Map and Tiles.
http://www.thepernproject.com/index2.htm
A quick fix to your problem, do a loop that write your data to the map, one by one, casting each char to a (u16). Then try to find a way to optimize it afterward. One thing is for sure, each char need to take 16bits at the end, not 8bits.
#8954 - mtg101 - Thu Jul 24, 2003 8:56 pm
My apologies - I've just realised a rather important fact. I'm doing this for rotation backgrounds. I've only just realised that in text backgrounds you use 16bits for each tile.
So given I'm using a rotation background, each tile is 8bits; I checked this in The Pern Project tutorials, and it's the way that works for me in other rotation backgrounds I've tried.
_________________
---
Speaker for the Dead
#8956 - niltsair - Thu Jul 24, 2003 10:12 pm
In this case, cast aText as a u16 pointer instead when in rotation maps and then copy only half of the string lenght (since you're copying 2 chars at a time). Then, you need to take care of the odd number of chars.
memcpy(&aTileBg->mapData[(aX + (aY * width))/2], (u16*)aText, strlen(aText)/2);
If the number of chars to write is great, use dma instead. I'm not certain at what lenght it start being faster.
#8957 - mtg101 - Thu Jul 24, 2003 10:27 pm
I've just tried that and it didn't work - same output. I also tried cating all 3 arguments to (u16*) and that didn't work either.
In otherinvestigations,I've comeacross 2 others things.
1 - When using mode 4 I can use memcpy() to copy a bitmap to the screen with something like:
Code: |
memmove(BackBuffer, test_gfx, 240*160);
|
This works fine. Why can I write to VRAM in mode 4 using memcpy(), but in mode 1 it writes the same byte in both bytes of the 16bit addrress? Do they work differently, or am I doing something wrong?
2 - There seems to be a wmemcpy() function (for moving around 16bit at a time) in the header files, but I can't get it to compile. Anyone got any experience of using this?
Cheers
Russell
_________________
---
Speaker for the Dead
#8958 - mtg101 - Thu Jul 24, 2003 10:33 pm
Arg - more mistakes from me. I don't get quite the same output... I forogot to devide the length by 2...
When I do that, and try to print "12", I get "11" instead of the previous "22". Which I think backs up my theory that memcpy() deals in bytes only.
Where should I be including memcpy() from? I'm using DevKitAdv and using #include <string.h> to get memcpy() - is that right?
_________________
---
Speaker for the Dead
#9398 - mtg101 - Sun Aug 03, 2003 8:12 pm
So... eventually I decided that memcpy deals in single bytes and wasn't any use to me in this case; so I just used a loop.
Then I found out about DMA- which can copy either 16 or 32 bit chunks. So I've used that where I can - there are cases where the text input isn't 16bit aligned so I can't copy from it (eg drawing to an odd offest tile position). Useful experience... but leaves me with a bgText system that is faster or slower depending on where and how long your text is.
_________________
---
Speaker for the Dead
#9408 - niltsair - Mon Aug 04, 2003 5:53 am
There is a bios command to copy a bunch of data too, beside DMA. Someone did some interesting speed tests compare between the two. You can try to find the post, it was around friday.
#9413 - mtg101 - Mon Aug 04, 2003 9:38 am
Yeah I noticed that thread too - IIRC it found that the speed depended on the memory type being copied to / from. I'll look at that when I get round to optimizing my memory type usage I think, otherwise I'll just have to go back and change loads of stuff.
_________________
---
Speaker for the Dead