Preface.
In this article you will learn how to add Russian font to SGDK. I will say right away, the method is crutch,as with the array of collisions in SGDK. Creating a platformer for Sega Genesis. however, it is simple, and most importantly working! First of all, let’s dig into the function of VDP_drawText from the first lesson on SGDK.
Download the finished project with MEGA.
A little bit about symbols.
The symbol (char), like any other type is a set of bits, i.e. the number. So, you can add a number to the symbol, and get another symbol. For example, if you add 1to ‘c‘ , you get ‘d‘. That is, with the symbol you can perform the same operations as with the numbers.
Digging into SGDK libraries.
Open C:SGDKsrcvdp_bg.c and find the VDP_drawText
void VDP_drawText(const char *str, u16 x, u16 y)
{
VDP_drawTextBG(text_plan, str, x, y);
}
As you can see, VDP_drawText this is a shell for VDP_drawTextBG,go there.
void VDP_drawTextBG(VDPPlane plane, const char *str, u16 x, u16 y)
{
u16 data [128] ;
const u8 *s;
u16 *d;
u16 i, pw, ph, len;
get the horizontal plane size (in cell)
pw = (plane == WINDOW)?windowWidth:planeWidth;
ph = (plane == WINDOW)?32:planeHeight;
string outside plane --> exit
if ((x >= pw) || (y >= ph))
return;
get string len
len = strlen(str);
if string don't fit in plane, we cut it
if (len > (pw - x))
len = pw - x;
s = (const u8*) str;
d = data;
i = len;
while(i--)
*d++ = TILE_FONTINDEX + (*s++ - 32);
VDP_setTileMapDataRowEx(plane, data, text_basetile, y, x, len, CPU);
}
Here, we see that the function simply draws tiles on the plein (layer) using the VDP_setTileMapDataRowExfunction. I will notdisassemble this code, because I wrote my own, simpler. I wrote it based on this function.
We analyze resources.
The res folder contains font, background image and resources.res
in resources.res the font is loaded as a tileset
TILESET font_rus "font.png" BEST NONE
Note,I removed the optimization (NONE). If you don’t, the font may break. Imagine that in your font there are 2 identical tiles,for example:
: and ;
Or:
0 and O
Then, if optimization is enabled, SGDK will remove duplicate tiles from the tileset. As a result, the tiles will shift and the order will be broken. I myself had problemswith this, how much free time it killed,which can not be returned.
In general, this tileset,then driven into VRAM,from which we will take the tiles of our symbols,and draw on the plain.
We study the code.
Find the VDP_drawTextOffset function in main.c
void VDP_drawTextOffset(VDPPlane plane, const u16 *vram_offsets, u16 len, u16 first_tile, u16 x, u16 y)
{
u16 i, pw, ph, curX;
get the horizontal plane size (in cell)
pw = (plane == WINDOW)?windowWidth:planeWidth;
ph = (plane == WINDOW)?32:planeHeight;
string outside plane --> exit
if ((x >= pw) || (y >= ph))
return;
len = array_u16len(vram_offsets); sometimes works sometimes no, scored on this function now enter the length of the handles.
if string don't fit in plane, we cut it
if (len > (pw - x))
len = pw - x;
i = 0;
curX = 1;
u16 curTileInd = 0;
VDP_setPaletteColor(16+1,RGB24_TO_VDPCOLOR(0xffffff));
while(i < len) {
curTileInd = first_tile-1 + vram_offsets [i] ;
KLog_S1("curTile: ", curTileInd);
VDP_setTileMapXY(plane, TILE_ATTR_FULL(PAL1,0,FALSE,FALSE,curTileInd), curX, y);
i++;
curX++;
}
}
This function takes an array of values insteadof the string ,
const u16 *vram_offsets
According to them, we will determine the index_of_the_tile, which, we will draw on the screen.
- len – string length.
- first_tile is the tileindex in which the tailset of our font is loaded. The values inside the array vram_offsetsare set relative to the first_tile.
The function is 60% copy-paste VDP_drawTextBG,part of the code to:
i = 0;
Simply, limits the text within the screen.
i = 0;
curX = 1;
u16 curTileInd = 0;
VDP_setPaletteColor(16+1,RGB24_TO_VDPCOLOR(0xffffff));
Announced the necessary variables
VDP_setPaletteColor(16+1,RGB24_TO_VDPCOLOR(0xffffff));
And set the 2nd color in the 2nd palette(VDP_setPaletteColor). Read more about palettes in SGDK. Fade-in and Fade-out transitions.
The 2nd color, in the 2nd palette, is the color of our text.
Specify the tile indexthat you want to draw.
curTileInd = first_tile-1 + vram_offsets [i] ;
Perhaps an explanation of -1is needed here. After all, in theory, the formula should look like this.
Idex_tile = first_tile + offset_character
The number -1,this is a way to fix the bug. Because if vram_offsets [i] == 0, then the loop stops and the string is trimmed. In any case, in vram_offsets displacements, and so, are overestimated by 1,so everything is compensated.
Next, set the tiles on the screen
VDP_setTileMapXY(plane, TILE_ATTR_FULL(PAL1,0,FALSE,FALSE,curTileInd), curX, y);
By the following syntax
VDP_setTileMapXY(plain, tile, x, y);
- plain – a layer on which the tile will be located(BG_A or BG_B).
- tile – information about the tile, set through the macro TILE_ATTR_FULL,more here.
- x, y is the coordinates of the tile.
Tiles (symbols) are drawn, one after another(curX++).
VDP_setTileMapXY(plane, TILE_ATTR_FULL(PAL1,0,FALSE,FALSE,curTileInd), curX, y);
i++;
curX++;
Now, let’s look at the main function
VDP_drawImage(BG_A, &img, 0, 0);
u16 ind = 1300;
VDP_loadTileSet(&font_rus, ind, DMA);
Here, did the following:
- Drew a background image (a circle on a black background)
- Set the index of the initial tile (the tile from which our font begins)
- Loaded the tileset into VRAM.
Next, there are arrays of displacements (lines).
u16 textArr [15] = {49, 86, 79, 76, 88, 72, 74, 83, 103, 102, 1, 51, 37, 38, 44};
u16 textArr2 [28] = {52, 77, 87, 77, 88, 100, 13, 1, 90, 99, 1, 87, 86, 85, 80, 84, 72, 77, 96, 100, 1, 88, 91, 89, 89, 82, 80, 81};
And putting them on the screen.
VDP_drawTextOffset(BG_A, textArr, 15, ind, 1, 1);
VDP_drawTextOffset(BG_A, textArr2, 28, ind, 1, 2);
As a result, it turned out the following.
And now I will tell you how to make an array of displacements (line).
Create an array of offsets (string).
First, download the Python script from MEGA.
Then, create a text file,and write something there (in Russian language). Transfer this file to text_to_arr.exe
Now, in the text file, an array of offsets appeared and you can replace the text on the screen.
int main()
{
VDP_drawImage(BG_A, &img, 0, 0);
u16 ind = 1300;
VDP_loadTileSet(&font_rus, ind, DMA);
u16 textArr [15] = {49, 86, 79, 76, 88, 72, 74, 83, 103, 102, 1, 51, 37, 38, 44};
u16 textArr2 [28] = {52, 77, 87, 77, 88, 100, 13, 1, 90, 99, 1, 87, 86, 85, 80, 84, 72, 77, 96, 100, 1, 88, 91, 89, 89, 82, 80, 81};
SGDK, drink coffee.
u16 textArr3 [17] = {51, 37, 38, 44, 13, 1, 74, 99, 87, 77, 81, 1, 82, 86, 92, 77, 15};
VDP_drawTextOffset(BG_A, textArr, 15, ind, 1, 1);
VDP_drawTextOffset(BG_A, textArr2, 28, ind, 1, 2);
VDP_drawTextOffset(BG_A, textArr3, 17, ind, 1, 3);
while(1)
{
drawCharCode('a');
SYS_doVBlankProcess();
}
return (0);
}
VDP_drawTextOffset I moved from the main loop(while),so as not to load the system.
This font is a bit artifat,because *drum roll* it is generated automatically from ttf font.
Transfer TTF font to SGDK.
The #2 script I created in Python to not work, i put on MEGA.
Now transfer the ttf font to the ttf2Img4_SGDK.exe icon
Font created.
It remains to limit its palette to 16 colors, how to do this, I said here.
And transfer the font.png to the res folder of the project.
Conclusion.
If you have any questions, ask, the topic is complicated, and I could miss a lot. If there are suggestions for the release of the following articles, write, we will understand.