Hello.c

Let's get coding!

Moderator: a31chris

Post Reply
User avatar
a31chris
Jaguar MOD
Posts: 826
Joined: Mon Apr 01, 2013 7:09 am

Hello.c

Post by a31chris » Fri Feb 21, 2014 7:58 am

A discussion of the Hello.c program included with the Hillsoftware Atari Jaguar SDKs and how it works.

Code: Select all

#include"font.h"
    
    extern void *vidmem;
    unsigned char *jagscreen;
    
    void DrawCharLine (int charloc, int screenloc)
    {
      static unsigned char shift[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
      int xcnt;
    
      for (xcnt = 0; xcnt < F_WIDTH; xcnt++) 
      {
        if (((textfont[charloc] >> shift[xcnt]) & 0x1)) 
          jagscreen[screenloc++] = 1;
        else
          jagscreen[screenloc++] = 0;
      }
    }
    
    void DrawChar (int x, int y, char ch)
    {
      int ycnt, charloc, screenloc;
    
      charloc = ch * F_CHARSIZE;
    
      screenloc = (y * T_XREZ) + x;
    
      for (ycnt = 0; ycnt < F_HEIGHT; ycnt++) 
      {
        DrawCharLine (charloc, screenloc);
        screenloc += T_XREZ;
        charloc++;
      }
    }
    
    void DrawString (int x, int y, char *str)
    {
      int cnt;
    
      for (cnt = 0; str[cnt] != 0; cnt++) 
      {
        DrawChar (x, y, str[cnt]);
        x += F_WIDTH;
      }
    }
    
    void __main(void) 
    {
      int w;
    
      jagscreen = (unsigned char *)&vidmem;
    
      *(unsigned short int *) 0xf00400 = 0x0000; /* Color reg 0 = black */
      *(unsigned short int *) 0xf00402 = 0xffff; /* Color reg 1 = white */
    
      for(w=0;w<64000;w++) jagscreen[w]=0;
    
      DrawString(5,5,"Hello Jag Users");
    
      for(;;);  /* Infinite Loop.  Alpine users can delete this.  */
    }



Here is the font.h source:



Code: Select all

#define F_WIDTH          0x08
    #define F_HEIGHT         0x08
    #define F_CHARSIZE       0x08
    
    #define T_XREZ           320
    #define T_YREZ           200
    
    
    
    unsigned char textfont[] =
      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81,
        0xBD, 0x99, 0x81, 0x7E, 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
        0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7C, 0xFE,
        0x7C, 0x38, 0x10, 0x00, 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C,
        0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, 0x00, 0x00, 0x18, 0x3C,
        0x3C, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
        0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0xFF, 0xC3, 0x99, 0xBD,
        0xBD, 0x99, 0xC3, 0xFF, 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
        0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x3F, 0x33, 0x3F, 0x30,
        0x30, 0x70, 0xF0, 0xE0, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0,
        0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, 0x80, 0xE0, 0xF8, 0xFE,
        0xF8, 0xE0, 0x80, 0x00, 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
        0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x66, 0x66, 0x66, 0x66,
        0x66, 0x00, 0x66, 0x00, 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00,
        0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
        0x7E, 0x7E, 0x7E, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF,
        0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18,
        0x7E, 0x3C, 0x18, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
        0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
        0xC0, 0xFE, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00,
        0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7E,
        0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x30, 0x78, 0x78, 0x78, 0x30, 0x00, 0x30, 0x00, 0x6C, 0x6C, 0x6C, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
        0x30, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x30, 0x00, 0x00, 0xC6, 0xCC, 0x18,
        0x30, 0x66, 0xC6, 0x00, 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
        0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60,
        0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
        0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xFC,
        0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
        0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x30, 0x30, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
        0x7C, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0x7C, 0x00, 0x30, 0x70, 0x30, 0x30,
        0x30, 0x30, 0xFC, 0x00, 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
        0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, 0x1C, 0x3C, 0x6C, 0xCC,
        0xFE, 0x0C, 0x1E, 0x00, 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
        0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, 0xFC, 0xCC, 0x0C, 0x18,
        0x30, 0x30, 0x30, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
        0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, 0x00, 0x30, 0x30, 0x00,
        0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
        0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0xFC, 0x00,
        0x00, 0xFC, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
        0x78, 0xCC, 0x0C, 0x18, 0x30, 0x00, 0x30, 0x00, 0x7C, 0xC6, 0xDE, 0xDE,
        0xDE, 0xC0, 0x78, 0x00, 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
        0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x3C, 0x66, 0xC0, 0xC0,
        0xC0, 0x66, 0x3C, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
        0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7E, 0x00, 0x7E, 0x60, 0x60, 0x78,
        0x60, 0x60, 0x60, 0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00,
        0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, 0x78, 0x30, 0x30, 0x30,
        0x30, 0x30, 0x78, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
        0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x60, 0x60, 0x60, 0x60,
        0x60, 0x60, 0x7E, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
        0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
        0xC6, 0x6C, 0x38, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
        0x78, 0xCC, 0xCC, 0xCC, 0xDC, 0x78, 0x1C, 0x00, 0xFC, 0x66, 0x66, 0x7C,
        0x6C, 0x66, 0xE6, 0x00, 0x78, 0xCC, 0xE0, 0x70, 0x1C, 0xCC, 0x78, 0x00,
        0xFC, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0xCC, 0xCC, 0xCC, 0xCC,
        0xCC, 0xCC, 0xFC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
        0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00, 0xC6, 0xC6, 0x6C, 0x38,
        0x38, 0x6C, 0xC6, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
        0xFE, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFE, 0x00, 0x78, 0x60, 0x60, 0x60,
        0x60, 0x60, 0x78, 0x00, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
        0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6C, 0xC6,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
        0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C,
        0x7C, 0xCC, 0x76, 0x00, 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
        0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, 0x1C, 0x0C, 0x0C, 0x7C,
        0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
        0x38, 0x6C, 0x60, 0xF0, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x76, 0xCC,
        0xCC, 0x7C, 0x0C, 0xF8, 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
        0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x0C, 0x00, 0x0C, 0x0C,
        0x0C, 0xCC, 0xCC, 0x78, 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
        0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xCC, 0xFE,
        0xFE, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
        0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0xDC, 0x66,
        0x66, 0x7C, 0x60, 0xF0, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
        0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x7C, 0xC0,
        0x78, 0x0C, 0xF8, 0x00, 0x10, 0x30, 0x7C, 0x30, 0x30, 0x34, 0x18, 0x00,
        0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0xCC, 0xCC,
        0xCC, 0x78, 0x30, 0x00, 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00,
        0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0xCC, 0xCC,
        0xCC, 0x7C, 0x0C, 0xF8, 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
        0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, 0x18, 0x18, 0x18, 0x00,
        0x18, 0x18, 0x18, 0x00, 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
        0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C,
        0xC6, 0xC6, 0xFE, 0x00, 0xE9
    };
What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

User avatar
a31chris
Jaguar MOD
Posts: 826
Joined: Mon Apr 01, 2013 7:09 am

Re: Hello.c

Post by a31chris » Fri Feb 21, 2014 8:00 am

Tursi wrote:One thing that might help - the Jag doesn't really do fonts. What happens there is it's just drawing a bunch of 2d rectangles that happen to look like letters - the DrawCharLine function takes one horizontal line from that rectangle, and converts the monochrome 1-bit picture into 8 pixels in the frame buffer.
im going to have to take the drawcharline function and font.h and pull the ol' paper computer trick.
What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

User avatar
a31chris
Jaguar MOD
Posts: 826
Joined: Mon Apr 01, 2013 7:09 am

Re: Hello.c

Post by a31chris » Fri Feb 21, 2014 8:01 am

Wozencl wrote:It's really great that Belboz has posted these examples and even better that someone is putting them to use.

A simple breakdown would be:

DrawCharLine - check to see if the pixel in the font is greater than one, if so, set the corresponding screen pixel to 1 as well. In effect making it display a colour as opposed to remaining black. Creates a line of a character pixel by pixel.
DrawChar - calls the above x number of times depending on the value held in F_HEIGHT. Creates a character on the screen line by line.
DrawString - calls DrawChar for each char passed to it and increments x by F_WIDTH so you don't end up writing over the same area of the screen. Uses the above to display a string, an array of chars, character by character.
What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

User avatar
a31chris
Jaguar MOD
Posts: 826
Joined: Mon Apr 01, 2013 7:09 am

Re: Hello.c

Post by a31chris » Fri Feb 21, 2014 8:07 am

Tursi wrote:
'JagChris wrote:My first specific question from the above code. In the first pass it passes the character 'H' from 'Hello Jag users! '

So the line :

Code: Select all

charloc = ch * F_CHARSIZE;
translates to 'charloc = 'H' * 0x08;

Is this multiplying the character H by 0x08 hexadecimal? I'm not following this line all that clearly.
That's correct. It helps to remember that there is no such thing as a character or a string in C, rather there are bytes, and arrays of bytes that end with a 0.

So 'H' is equivalent to it's ASCII value, which is 72 (http://asciitable.com/).

Each character is drawn as 8 pixels by 8 pixels. The pixels are stored in monochrome binary, so 8 bits is one line of one character, and a character takes 8 bytes. Multiplying by 8 thus gives an index into the "font" where the letter's pattern actually starts.

A common variation on this theme is to start the patterns with space, which is ASCII 32, rather than starting at 0 which has no fixed pattern. This saves room in the ROM if you don't use the extra characters. In cases like that you'll see something like (ch-32)*F_CHARSIZE, which just removes the offset. I have to admit I expect to see that in this program, and I'm not sure why I am missing it.
What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

User avatar
a31chris
Jaguar MOD
Posts: 826
Joined: Mon Apr 01, 2013 7:09 am

Re: Hello.c

Post by a31chris » Fri Feb 21, 2014 8:10 am

Tursi wrote:
JagChris wrote:So the frame buffer is set up in the extern void *vidmem pointer right? Thats a function already pre-configured and included with the Jag C setup I guess?
No, not exactly. It's just a reserved block of memory. It's reserved in STARTUP.S near the bottom of the file:

Code: Select all

_vidmem:
                .ds.b   64000
The '_' is needed to make it line up with C, as C names get the _ added when they are compiled to assembly. "DS" is an assembler statement that means "define space", and the 'b' tells it you are counting in bytes. 64,000 bytes is enough for a 320x200 screen with 8-bit color (one byte per pixel).
ok so textfont is an 1025 character array.
Yes... but to avoid confusion in this context, I would say it is 1025 /bytes/ (or 1025 unsigned chars, as that's its type. Byte and unsigned char are usually the same type anyway). Since we are talking about a font, when you say 'character' we don't know if you are talking about the C "char" type or a character from the font.
So this is coming out to 72 * 8 = 576. Its hopping over to the 576th index in the array which is turning out to be... 0x00. And this represents what? the upper left most bit of the first 8 bit line of the character H?
This represents the entire first line of the character pattern - one bit per pixel.

I think you may have miscounted by 1 - remember the first byte in the array is index 0. The 8 bytes that I see at 576 are:

0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00

If you convert these bytes to binary, you should see the letter appear:

Code: Select all

CC = 11001100
CC = 11001100
CC = 11001100
FC = 11111100
CC = 11001100
CC = 11001100
CC = 11001100
00 = 00000000
Or if we instead space that out with '#' for 1 and '.' for 0:

Code: Select all

CC = ##..##..
CC = ##..##..
CC = ##..##..
FC = ######..
CC = ##..##..
CC = ##..##..
CC = ##..##..
00 = ........
What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

User avatar
a31chris
Jaguar MOD
Posts: 826
Joined: Mon Apr 01, 2013 7:09 am

Re: Hello.c

Post by a31chris » Fri Feb 21, 2014 8:14 am

Tursi wrote:
JagChris wrote:Thats fantastic Tursi. Thanks!

Code: Select all

 *(unsigned short int *) 0xf00400 = 0x0000; /* Color reg 0 = black */
      *(unsigned short int *) 0xf00402 = 0xffff; /* Color reg 1 = white */
A pointer without a variable assigned to it. Is this sort of like a poke statement in basic? Poke x0000 into 0xf00400 and make sure the value poked is a short integer? And this memory location I'm assuming is in the same memory range that *vidmem is pointing to?
Yeah, you've sussed it out pretty well.

Putting a type into parantheses means "whatever follows, treat it as this type of variable". In this case, an integer follows, so that integer is treated as an unsigned short int * (these days most people just write "unsigned short", but technically that's still right). In this case it's important to note the asterisk BEFORE the parentheses, too, which tells it to write to that address. A short on the Jaguar is 16-bits, so this makes sure that the compiler uses 16-bit access (and not 8-bit or 32-bit, which may not work right on the registers). Then it writes the 16-bit value that follows to that address, and yep, just like POKE.

However, this is not the range of vidmem... you can access that directly. If you search your Jaguar reference manual for "f00400", you'll see that it's an address inside Tom. Like the comments say, these lines are poking colors into the 256-color palette space. The color format is either RGB or CRY, depending on the graphics mode selected (usually CRY).
What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman

Post Reply