Blitter "Hello" demo

Let's get coding!

Moderator: a31chris

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

Blitter "Hello" demo

Post by a31chris » Sun Oct 05, 2014 8:36 pm

ToArnold on AA modified the demo "hello" program Belboz created so that it uses the Blitter.

I thought I'd post it here so those like me who know nothing about graphics can analyze, discuss and study it.
This is my modified source. I extracted the ATARI 8-Bit font, made a blue background, and printed a white READY on the screen

Next step is to display a white block beneath the READY

Code: Select all

#ifndef _TYPES_H
#define _TYPES_H

/* Attention: sizeof(int)==sizeof(long) */

#define uint8_t unsigned char
#define byte unsigned char
#define uint16_t unsigned short
#define uint32_t unsigned int

#define int8_t char
#define int16_t short
#define int32_t int

#endif

Code: Select all

#include <jaguar.h>
#include "types.h"
#include "atarifnt.h"

#define CLUT16 (uint16_t *)CLUT

extern void *vidmem;
byte *jagscreen=(byte *)&vidmem;

void loopUntilBitIsSet32(void *adr, uint32_t bitmask)
{
	uint32_t val;
	do
	{
		val = *(uint32_t *)(adr);
	} while (val & bitmask == 0);
}

void *memset(void *str, byte c, uint16_t n)
{
	loopUntilBitIsSet32(B_CMD, 1 << 0);
	*A1_BASE = (uint32_t)str;
	*A1_PIXEL = 0;
	*A1_FLAGS = PIXEL8 | XADDPIX | PITCH1;
	*B_PATD = c;
	*B_COUNT = 0x010000 | n;
	*B_CMD = PATDSEL;
	return str;
}

uint16_t toRgb16(byte r, byte g, byte b)
{
	r &= 0x1f;
	g &= 0x3f;
	b &= 0x1f;
	return (r << 11) | (b << 6) | g;
}

void DrawChar(uint16_t x, uint16_t y, byte ch)
{
	loopUntilBitIsSet32(B_CMD, 1 << 0);

	*A1_BASE = (uint32_t)jagscreen;
	*A1_FLAGS = PIXEL8 | XADDPIX | WID320 | PITCH1;
	*A1_PIXEL = (y << 16) | x;
	*A1_STEP = 0x010000 | (uint16_t)-8;

	*A2_BASE = (uint32_t)(textfont + (ch << 3));
	*A2_FLAGS = PIXEL1 | XADDPIX | WID8 | PITCH1;
	*A2_PIXEL = 1;
	*A2_STEP = 0x010000 | (uint16_t)-1;

	*B_COUNT = 0x080008;
	*B_PATD = 1;
	*B_DSTD = 0;
	*B_CMD = SRCENX | UPDA1 | UPDA2 | PATDSEL | BCOMPEN | BKGWREN | DSTEN;
}

void DrawString (int x, int y, char *str)
{
	while (*str)
	{
		DrawChar(x, y, *str++);
		x += F_WIDTH;
	}
}

void __main(void)
{
	*CLUT16 = toRgb16(0x00, 0x00, 0xff);
	*(CLUT16 + 1) = toRgb16(0xff, 0xff, 0xff);

	memset(jagscreen, 0, 64000);

	DrawString(8, 16, "READY");

	for (;;);  /* Infinite Loop.  Alpine users can delete this.  */
}
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: 832
Joined: Mon Apr 01, 2013 7:09 am

Re: Blitter "Hello" demo

Post by a31chris » Tue Oct 07, 2014 5:52 pm

For me all the resulting bin does is produce a blue screen without the ready under emulation. Using Jagulator and PT.
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: 832
Joined: Mon Apr 01, 2013 7:09 am

Re: Blitter "Hello" demo

Post by a31chris » Tue Oct 21, 2014 8:36 am

This is not a Jaguar specific Question/Solution. This is a general C question I had that got answered on the C programming forums regarding this I thought i would share here.

Here is a line I am confused about:

Code: Select all

*B_CMD = SRCENX | UPDA1 | UPDA2 | PATDSEL | BCOMPEN | BKGWREN | DSTEN;
I understand that the left side is a pointer assignment. I understand that the right side is some sort of bitwise OR operation. I do not understand what it is meant to assign to the pointer. This has me totally confused. To me it seems like its ORing every bits in multiple values and then assigning end result to the pointer.
Such code is usually used when you want to pack multiple values into a single integer type: char, short, int, etc. It's common, for example, in lower level code like drivers, where many hardware registers use a similar mechanism; and in microcontrollers with limited resources since you don't want to use an entire int for each option when just 1 bit will do.

It might make more sense if you looked at the definitions for SRCENX, UPDA1, UPDA2, PATDSEL, etc and wrote out their binary values. You'll probably notice that there are no overlapping bits in any of them. So for example, you might see

Code: Select all

#define SRCENX 0x01   // 0000 0001
#define UPDA1 0x02    // 0000 0010
#define UPDA2 0x04    // 0000 0100
#define FOO 0x08      // 0000 8000
#define PATDSEL 0x10  // 0001 0000
...
Often, these values represent individual options for something. They are not mutually exclusive, and you want to be able to set any combination of them. Thus, you bitwise-OR each option you want to set to 1. You can set a bit to 0 by bitwise-ANDing it with it's bitwise inverse:

Code: Select all

*B_CMD &= ~FOO;  // disable foo option by setting it's bit to 0
Or you can toggle it by using XOR.

Sometimes you'll also see something similar, except an option will have multiple bits set. For example, an option that uses 2 bits can support up to four values. You'll often see something like this

Code: Select all

#define BAR 0xC0       // 1100 0000
#define BAR_VAL0 0x00  // 0000 0000
#define BAR_VAL1 0x40  // 0100 0000
#define BAR_VAL2 0x80  // 1000 0000
#define BAR_VAL3 0xC0  // 1100 0000
In that case, you would clear the bits then OR in the value you want.

Code: Select all

cmd &= ~BAR;  // clear BAR bits
cmd |= BAR_VAL1;  // set BAR option to VAL1
Hope that's clear enough.
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