The relevant code is screen_char_draw() in src/screen.c
Currently, there is an 8x12 font that's sitting in src/font.h, this is for 640x400 displays.
There will ostensibly be other fonts, e.g.:
8x16 for 640x512 (PAL) displays
5x6 for 320x200 displays
5x8 for 320x256 displays
etc...
Each of these fonts is defined as a 1bpp bitmap.
I am thinking that using BltBitMapRastPort() is the right thing to do, but it doesn't natively allow you to specify which bitplanes to blit to, so, I was thinking:
Implement a routine given a color index #, to blit the 1bpp font data to the correct target bitplanes in the RastPort.
or if a better way can be done, then great.
I first saw a problem when I ran PLATOTerm in 1.3, because the swapped foreground/background default palettes, the output text became black under 1.3.
The original code for outputting text for PLATOTerm64 was thus:
/**
* screen_char_draw(Coord, ch, count) - Output buffer from ch* of length count as PLATO characters
*/
void screen_char_draw(padPt* Coord, unsigned char* ch, unsigned char count)
{
int16_t offset; /* due to negative offsets */
uint16_t x; /* Current X and Y coordinates */
uint16_t y;
uint16_t* px; /* Pointers to X and Y coordinates used for actual plotting */
uint16_t* py;
uint8_t i; /* current character counter */
uint8_t a; /* current character byte */
uint8_t j,k; /* loop counters */
int8_t b; /* current character row bit signed */
uint8_t width=FONT_SIZE_X;
uint8_t height=FONT_SIZE_Y;
uint16_t deltaX=1;
uint16_t deltaY=1;
uint8_t mainColor=1;
uint8_t altColor=0;
uint8_t *p;
uint8_t* curfont;
switch(CurMem)
{
case M0:
curfont=font;
offset=-32;
break;
case M1:
curfont=font;
offset=64;
break;
case M2:
curfont=fontm23;
offset=-32;
break;
case M3:
curfont=fontm23;
offset=32;
break;
}
if (CurMode==ModeRewrite)
{
altColor=0;
}
else if (CurMode==ModeInverse)
{
altColor=1;
}
if (CurMode==ModeErase || CurMode==ModeInverse)
mainColor=0;
else
mainColor=1;
tgi_setcolor(mainColor);
#ifdef __ATARI__
x=mul0625((Coord->x&0x1FF));
y=mul0375((Coord->y+15^0x1FF)&0x1FF);
#else
x=scalex[(Coord->x&0x1FF)];
y=scaley[(Coord->y)+15&0x1FF];
#endif
if (FastText==padF)
{
goto chardraw_with_fries;
}
/* the diet chardraw routine - fast text output. */
for (i=0;i<count;++i)
{
a=*ch;
++ch;
a+=offset;
p=&curfont[fontptr[a]];
for (j=0;j<FONT_SIZE_Y;++j)
{
b=*p;
for (k=0;k<FONT_SIZE_X;++k)
{
if (b<0) /* check sign bit. */
{
tgi_setcolor(mainColor);
tgi_setpixel(x,y);
#ifdef __C64_COLOR__
x_coord=x-4;
y_coord=y;
color_transform(); // take x_coord/y_coord, return offset into color ram in colorpt.
asm("sei"); // stop interrupts.
asm("lda $01"); // value of kernal banking address
asm("pha"); // push onto stack
asm("and #$FC"); // AND off last two bits (to page out kernal and basic roms)
asm("sta $01"); // and pop back into kernal banking address
POKE(0xD000+colorpt,(current_foreground << 4) | PEEK(0xD000+colorpt)); // Plop on new color ram value
asm("pla"); // Pop old kernal banking value off stack back into A
asm("sta $01"); // store
asm("cli"); // and turn back on interrupts, like nothing ever happened.
#endif
}
++x;
b<<=1;
}
++y;
x-=width;
++p;
}
x+=width;
y-=height;
}
return;
chardraw_with_fries:
if (Rotate)
{
deltaX=-abs(deltaX);
width=-abs(width);
px=&y;
py=&x;
}
else
{
px=&x;
py=&y;
}
if (ModeBold)
{
deltaX = deltaY = 2;
width<<=1;
height<<=1;
}
for (i=0;i<count;++i)
{
a=*ch;
++ch;
a+=offset;
p=&curfont[fontptr[a]];
for (j=0;j<FONT_SIZE_Y;++j)
{
b=*p;
if (Rotate)
{
px=&y;
py=&x;
}
else
{
px=&x;
py=&y;
}
for (k=0;k<FONT_SIZE_X;++k)
{
if (b<0) /* check sign bit. */
{
tgi_setcolor(mainColor);
if (ModeBold)
{
tgi_setpixel(*px+1,*py);
tgi_setpixel(*px,*py+1);
tgi_setpixel(*px+1,*py+1);
}
tgi_setpixel(*px,*py);
}
else
{
if (CurMode==ModeInverse || CurMode==ModeRewrite)
{
tgi_setcolor(altColor);
if (ModeBold)
{
tgi_setpixel(*px+1,*py);
tgi_setpixel(*px,*py+1);
tgi_setpixel(*px+1,*py+1);
}
tgi_setpixel(*px,*py);
}
}
x += deltaX;
b<<=1;
}
y+=deltaY;
x-=width;
++p;
}
Coord->x+=width;
x+=width;
y-=height;
}
return;
}
So as you can see, there are a few different text states:
Text writing modes
Write - any ON pixels get written in current foreground color
Erase - any ON pixels get written in current background color
Rewrite - any OFF pixels get the current background color, any ON pixels get the current foreground color
Inverse - any OFF pixels get the current foreground color, any ON pixels get the current background color
Bold mode
double pixels in both X and Y directions.
Reverse
Write text from right to left (without flipping glyph orientation)
Rotate
Flip text counterclockwise. (not really used, but I implemented anyway)
The glyphs can be pulled from one of four text memories:
M0 - The first 64 built in characters (pulled from font.h)
M1 - The second set of 64 built in characters (pulled from font.h)
M2 - The first 64 of the downloadable character set (fontm23)
M3 - The second 64 of the downloadable character set
The relevant code is screen_char_draw() in src/screen.c
Currently, there is an 8x12 font that's sitting in src/font.h, this is for 640x400 displays.
There will ostensibly be other fonts, e.g.:
Each of these fonts is defined as a 1bpp bitmap.
I am thinking that using BltBitMapRastPort() is the right thing to do, but it doesn't natively allow you to specify which bitplanes to blit to, so, I was thinking:
or if a better way can be done, then great.
I first saw a problem when I ran PLATOTerm in 1.3, because the swapped foreground/background default palettes, the output text became black under 1.3.
The original code for outputting text for PLATOTerm64 was thus:
So as you can see, there are a few different text states:
Text writing modes
Bold mode
Reverse
Rotate
The glyphs can be pulled from one of four text memories: