Blitter and packed pixel mode

GFA, ASM, STOS, ...
Post Reply
User avatar
Idek Tramielski
Captain Atari
Captain Atari
Posts: 212
Joined: Thu Oct 25, 2007 6:25 pm

Blitter and packed pixel mode

Post by Idek Tramielski »

I have zero experience with programming the MegaST Blitter. All examples I found are somewhat confusing to me, probably because of the planar layout of the ST modes. I am looking for some code to use the Blitter in packed pixel mode (if possible at all). Does anybody have some example code?
Thanks.
User avatar
metalages
Captain Atari
Captain Atari
Posts: 482
Joined: Thu Jun 06, 2013 5:14 pm
Location: France
Contact:

Re: Blitter and packed pixel mode

Post by metalages »

http://files.dhs.nu/files_coding/blitfaq.zip

A lot of interesting considerations there
User avatar
Cyprian
10 GOTO 10
10 GOTO 10
Posts: 3331
Joined: Fri Oct 04, 2002 11:23 am
Location: Warsaw, Poland

Re: Blitter and packed pixel mode

Post by Cyprian »

Idek Tramielski wrote: Sun May 05, 2024 1:08 pm I have zero experience with programming the MegaST Blitter. All examples I found are somewhat confusing to me, probably because of the planar layout of the ST modes. I am looking for some code to use the Blitter in packed pixel mode (if possible at all). Does anybody have some example code?
Thanks.
what blitter function (e.g. copy block area) do you need and in what mode 8/16/32bit?
Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
Hatari / Steem SSE / Aranym / Saint
http://260ste.atari.org
User avatar
Idek Tramielski
Captain Atari
Captain Atari
Posts: 212
Joined: Thu Oct 25, 2007 6:25 pm

Re: Blitter and packed pixel mode

Post by Idek Tramielski »

Cyprian wrote: Sun May 05, 2024 8:37 pm
Idek Tramielski wrote: Sun May 05, 2024 1:08 pm I have zero experience with programming the MegaST Blitter. All examples I found are somewhat confusing to me, probably because of the planar layout of the ST modes. I am looking for some code to use the Blitter in packed pixel mode (if possible at all). Does anybody have some example code?
Thanks.
what blitter function (e.g. copy block area) do you need and in what mode 8/16/32bit?
Well, I guess copy block area in 8bit would be a good start to learn from. :D
User avatar
metalages
Captain Atari
Captain Atari
Posts: 482
Joined: Thu Jun 06, 2013 5:14 pm
Location: France
Contact:

Re: Blitter and packed pixel mode

Post by metalages »

Blitter operates on 16 bits words. But then you can use endmasks and shift to access bytes in particular.
User avatar
Orion_
Atari Super Hero
Atari Super Hero
Posts: 572
Joined: Sat Jan 10, 2004 12:20 pm
Location: France
Contact:

Re: Blitter and packed pixel mode

Post by Orion_ »

Code: Select all

; FGDL / Atari Blitter functions by Orion_ [2022 - 2023]

	machine	68030

	xdef	_SetupBlitter

	xdef	_BlitterCopy16
	xdef	_BitmapBlitterCopy8
	xdef	_BlitterClear8

	section	text

;***********************

B_HALF_RAM	equ	$FFFF8A00
B_SRC_XINC	equ	$FFFF8A20
B_SRC_YINC	equ	$FFFF8A22
B_SRC_ADRS	equ	$FFFF8A24
B_ENDMASK1	equ	$FFFF8A28
B_ENDMASK2	equ	$FFFF8A2A
B_ENDMASK3	equ	$FFFF8A2C
B_DST_XINC	equ	$FFFF8A2E
B_DST_YINC	equ	$FFFF8A30
B_DST_ADRS	equ	$FFFF8A32
B_XCOUNT	equ	$FFFF8A36
B_YCOUNT	equ	$FFFF8A38
B_HALF_OP	equ	$FFFF8A3A
B_OP		equ	$FFFF8A3B
B_CTRL		equ	$FFFF8A3C
B_SKEW		equ	$FFFF8A3D

B_H_DIRECT	equ	0
B_HALFTONE	equ	1
B_H_SRC		equ	2
B_H_SRCANDHALF	equ	3

B_ZERO		equ	0
B_SRC_AND_DST	equ	1
B_SRC_AND_NDST	equ	2
B_SRC		equ	3
B_NSRC_AND_DST	equ	4
B_DST		equ	5
B_SRC_XOR_DST	equ	6
B_SRC_OR_DST	equ	7
B_NSRC_AND_NDST	equ	8
B_NSRC_XOR_DST	equ	9
B_NDST		equ	10
B_SRC_OR_NDST	equ	11
B_NSRC		equ	12
B_NSRC_OR_DST	equ	13
B_NSRC_OR_NDST	equ	14
B_ONE		equ	15

B_EXTRA_SRC	equ	%10000000
B_NOFINAL_SRC	equ	%01000000

B_START		equ	%10000000
B_HOG		equ	%01000000
B_SMUDGE	equ	%00100000

;<=------------------=>
;   Blitter Routines
;<=------------------=>

_SetupBlitter:
	moveq	#-1,d0
	move.w	d0,B_ENDMASK2.w		; Setup blitter endmask one time
	rts

;-------
; Copy data using Blitter (16bytes size aligned)

_BlitterCopy16:	; a0 = src, a1 = dst
		; d0 = size must be multiple of 16 !

	lea	B_SRC_XINC.w,a2

	move.l	#((16/8)<<16)|(16/8),d1

	move.l	d1,(a2)+	; B_SRC_XINC / B_SRC_YINC
	move.l	a0,(a2)+	; B_SRC_ADRS

	addq.l	#B_DST_XINC-B_ENDMASK1,a2

	move.l	d1,(a2)+	; B_DST_XINC / B_DST_YINC
	move.l	a1,(a2)+	; B_DST_ADRS

	lsr.l	#4,d0		; size / 16
	swap	d0
	move.w	#8,d0		; 8 word = 16 bytes
	swap	d0
	move.l	d0,(a2)+	; B_XCOUNT / B_YCOUNT

	move.w	#(B_H_SRC<<8)|B_SRC,(a2)+	; B_HALF_OP Source direct copy
	move.b	#B_START|B_HOG,(a2)		; B_CTRL Start Blitter

;	tst.b	(a2)	; Wait Blitter
;	bmi.s	*-6

	rts

;-------
; Copy bitmap using Blitter on 8bpp plannar screen

_BitmapBlitterCopy8:	; a0 = src, a1 = dst
			; d0 = width, d1 = height	width must be multiple of 16 !
			; d2 = src x, d3 = src y	x must be multiple of 16 !
			; d4 = dst x, d5 = dst y	x must be multiple of 16 !
			; d6 = src width, d7 = dst width

	lea	B_SRC_XINC.w,a2

	movem.l	d6-d7,-(a7)
	mulu.w	d3,d6		; y * width
	mulu.w	d5,d7
	add.l	d6,a0
	add.l	d7,a1
	add.w	d2,a0
	add.w	d4,a1
	movem.l	(a7)+,d6-d7

	sub.w	d0,d6
	sub.w	d0,d7
	addq.w	#16/8,d6	; last word is not added by blitter !
	addq.w	#16/8,d7
	swap	d6
	swap	d7
	move.w	#(16/8),d6
	move.w	d6,d7
	swap	d6
	swap	d7

	move.l	d6,(a2)+	; B_SRC_XINC / B_SRC_YINC
	move.l	a0,(a2)+	; B_SRC_ADRS

	addq.l	#B_DST_XINC-B_ENDMASK1,a2

	move.l	d7,(a2)+	; B_DST_XINC / B_DST_YINC
	move.l	a1,(a2)+	; B_DST_ADRS

	lsr.w	#1,d0		; size is in word (not byte)
	swap	d0
	move.w	d1,d0
	move.l	d0,(a2)+	; B_XCOUNT / B_YCOUNT

	move.w	#(B_H_SRC<<8)|B_SRC,(a2)+	; B_HALF_OP Source direct copy
	move.b	#B_START|B_HOG,(a2)		; B_CTRL Start Blitter

;	tst.b	(a2)	; Wait Blitter
;	bmi.s	*-6

	rts

;***********************

;-------
; Clear a zone using Blitter on 8bpp plannar screen

_BlitterClear8:	; a1 = dst
		; d0 = width, d1 = height	width must be multiple of 16 !
		; d4 = dst x, d5 = dst y	x must be multiple of 16 !
		; d7 = dst width

	lea	B_DST_XINC.w,a2

	move.l	d7,d6
	mulu.w	d5,d7
	add.l	d7,a1
	add.w	d4,a1
	move.l	d6,d7

	sub.w	d0,d7
	addq.w	#16/8,d7	; last word is not added by blitter !
	swap	d7
	move.w	#(16/8),d7
	swap	d7

	move.l	d7,(a2)+	; B_DST_XINC / B_DST_YINC
	move.l	a1,(a2)+	; B_DST_ADRS

	lsr.w	#1,d0		; size is in word (not byte)
	swap	d0
	move.w	d1,d0
	move.l	d0,(a2)+	; B_XCOUNT / B_YCOUNT

	move.w	#(B_H_SRC<<8)|B_ZERO,(a2)+
	move.b	#B_START|B_HOG,(a2)		; B_CTRL Start Blitter

;	tst.b	(a2)	; Wait Blitter
;	bmi.s	*-6

	rts

;***********************
User avatar
Idek Tramielski
Captain Atari
Captain Atari
Posts: 212
Joined: Thu Oct 25, 2007 6:25 pm

Re: Blitter and packed pixel mode

Post by Idek Tramielski »

Thanks! :thumbs:
I will try to understand how it ticks.
User avatar
Jinroh
Atari maniac
Atari maniac
Posts: 89
Joined: Sat Mar 18, 2017 4:30 pm
Contact:

Re: Blitter and packed pixel mode

Post by Jinroh »

If you fancy C, I had this example of a blit continuous scrolling background I made some years ago.

Just in case you're wondering. -> If you have a blitter, vro_cpyfm uses the blitter. If not, it's a slooooooooooooow software blit.

Code: Select all

//Easy Blit Continuous Scroll Background by Jinroh
// needed by VBCC cross compiler...
// may need to change if a different compiler is used
#include <tos.h>
#include <gem.h>
#include <stdio.h>

#define FALSE       0
#define TRUE        1

#define COPY_SOURCE_ONLY 3

#define DEGAS_RES_LEN 2 //2 bytes
#define DEGAS_PAL_LEN 32 //32 bytes
#define DEGAS_IMG_LEN 32000 //32,000 bytes

void loadDegasImg(char *path, long* img);
void backupDesktopPalette();
void restoreDesktop();
void blitSection(void* data, int mode, int dx, int dy, int width, int height);
void open_vwork(void);
void debugMsg(char *message);
void blitSection(void* data, int mode, int blitX, int blitY, int blitWidth, int blitHeight, int sx, int sy, int srcPitch);
void flip();
//Global variables
char msgBuffer[80];

int scrollX;

//Screen stuff.
long *blitImg;
long *screen, *logical;
long *page1, *buffer, *active, *hidden, *temp;

//Palette stuff.
int bgPalette[16];
int deskPalette[16];

//AES (windows and messages) related variables
int gl_hchar;       //height of system font (pixels)
int gl_wchar;       //width of system font (pixels)
int gl_wbox;        //width of box able to hold system font
int gl_hbox;        //height of box able to hold system font

int phys_handle;    //physical workstation handle
int handle;         //virtual workstation handle

int game;

//GEM Arrays
int work_in[11];    //Input to GSX parameter array
int work_out[57];   //Output from GSX parameter array

int timer;
int main(void)
{
    appl_init();
	game = TRUE;
    phys_handle=graf_handle(&gl_wchar, &gl_hchar, &gl_wbox, &gl_hbox);
    open_vwork();

	//Make sure that we are in low res mode.
	//And check if we have a blitter.
	if(Getrez() != ST_LOW)
	{
		form_alert( 1, "[3][This demo must be run in low resolution.][OK]" );
		game = FALSE;
	}else{
		screen = Physbase(); //Store a pointer to the screen.
		buffer = Malloc((32768 & 0xffffff00) + 0x100);
		active = screen;
		hidden = buffer;
		scrollX = 0;
		timer = 0;

		//Allocate the background.
		blitImg = Malloc(32000); //Allocate 32K for the blit background.
		if(blitImg == NULL)
			form_alert( 1, "[3][Could Not Allocate blitImg][OK]" );

		//Setup the image and junk.
		backupDesktopPalette(); //Store the TOS desktop palette, so we can restore it later.	
		loadDegasImg("YourImage.PI1", blitImg);
	}
	
	while(game)
	{
		if(Cconis())
		{
			game = FALSE;
		}

		//Call Vsync so the draw functions don't cause artifacts.
		Vsync();
		if(scrollX > 0)
		{
			blitSection(blitImg, 3, scrollX, 0, 320-scrollX, 200, 0, 0, 320);
			blitSection(blitImg, 3, 0, 0, scrollX, 200, 320 - scrollX, 0, 320);
		}else{
			blitSection(blitImg, 3, 0, 0, 320, 200, 0, 0, 320);
		}

		timer++;

		//if(timer == 8)
		{
			scrollX+=2;
			if(scrollX > 319)
				scrollX = 0;
			//timer = 0;
		}
		flip();
	}	

	//Destroy the images, and set back to normal.
	restoreDesktop();
	Mfree(blitImg);
	Mfree(buffer);
	v_clsvwk(handle);
    appl_exit();
    return 0;
}

//Open the virtual workstation.
void open_vwork()
{
    int i;

    for (i = 0; i < 10;) { work_in[i++] = 1; }
    work_in[10] = 2;
    handle = phys_handle;
    v_opnvwk(work_in, &handle, work_out);
}

void backupDesktopPalette()
{
	for(int x = 0; x < 16; x++)
	{
		deskPalette[x] = Setcolor(x, -1);
	}
}

void restoreDesktop()
{
	//Restore the desktop.
	Setscreen(screen, screen, -1);

	//Restore the Desktop Palette.
	Setpalette(deskPalette);
}

void loadDegasImg(char *path, long* img)
{
	int file; //File handle
	int bleh; //Temporary Buffer for Unused Bytes
	file = Fopen(path, FO_READ);
	if(file != -1)
	{
		//Read the first two bytes, which is the type of image.
		//1 word, so it is 2 bytes.
		Fread(file, 2, &bleh);

		//The desktop palette is 16 words, so 32 bytes.
		Fread(file, DEGAS_PAL_LEN, bgPalette);

		//Read the entire image, after the palette it is 32,000 bytes.
		Fread(file, DEGAS_IMG_LEN, img);

		Fclose(file);
	}

	//If it's successful set the palette.
	Setpalette(bgPalette);
}

void debugMsg(char *message)
{
	form_alert(1, message);
}

void flip()
{
	temp = active;
	active = hidden;
	hidden = temp;
	Setscreen(active, active, -1);
}

//Draws a Sprite From an area in memory.
void blitSection(void* data, int mode, int blitX, int blitY, int blitWidth, int blitHeight, int sx, int sy, int srcPitch)
{
	MFDB s_m, scr_m;
	int pxy[8];

	s_m.fd_addr = data; //Sprite data Address.
	s_m.fd_w = blitWidth; //Sprite Width
	s_m.fd_h = blitHeight; //Sprite Height
	s_m.fd_wdwidth = srcPitch / 16; //The pitch in words, which is the base image width / 16, not the blitted width.
	s_m.fd_stand = ST_LOW; //Interleaved Bit Planes Screen.
	s_m.fd_nplanes = 4; //Low Res Screen, so 4 bitplanes.

	scr_m.fd_addr = hidden; //Screen memory address
	scr_m.fd_w = 320;           //Screen X Resolution
	scr_m.fd_h = 200;           //Screen Y Resolution
	scr_m.fd_wdwidth = 20;      //Width in words
	scr_m.fd_stand = ST_LOW;    //Interleaved Bit Planes Screen.
	scr_m.fd_nplanes = 4;       //Low Res Screen, so 4 bitplanes.

	//Setup the Area we want to blit to and from.

	//The first two are the upper left point, x and y of the rectangle area we want to copy from.
	pxy[0] = blitX;
	pxy[1] = blitY;

	//The next two are the bottom right of the rectangle area we wanna copy from.
	pxy[2] = blitX + blitWidth;
	pxy[3] = blitY + blitHeight;

	//The first two are the upper left point, x and y of the rectangle area we want to copy to the screen.
	pxy[4] = sx;
	pxy[5] = sy;

	//The next two are the bottom right of the rectangle area we wanna copy to the screen.
	pxy[6] = sx + blitWidth;
	pxy[7] = sy + blitHeight;

	//Actually copy the data.
	vro_cpyfm(handle, mode, pxy, &s_m, &scr_m);
}
Free to download--> Carrot Kingdom™- Atari 2600 - Released 5/11/2021
User avatar
Idek Tramielski
Captain Atari
Captain Atari
Posts: 212
Joined: Thu Oct 25, 2007 6:25 pm

Re: Blitter and packed pixel mode

Post by Idek Tramielski »

Jinroh wrote: Mon May 06, 2024 6:29 pm If you fancy C, I had this example of a blit continuous scrolling background I made some years ago.

Just in case you're wondering. -> If you have a blitter, vro_cpyfm uses the blitter. If not, it's a slooooooooooooow software blit.
Thanks for the nice demo. Yes, vro_cpyfm uses the blitter if it is a standard ST screen. If you use a graphic card and a different VDI, it is done by software or, in some cases the blitter of the graphic card, depending on the VDI used.
User avatar
Jinroh
Atari maniac
Atari maniac
Posts: 89
Joined: Sat Mar 18, 2017 4:30 pm
Contact:

Re: Blitter and packed pixel mode

Post by Jinroh »

Idek Tramielski wrote: Mon May 06, 2024 9:12 pm Thanks for the nice demo.
I hope you or someone finds it useful. :D I used it in a track and field game years ago, but it wasn't on the ST. So I was curious how smooth it'd be on the ST.
Idek Tramielski wrote: Mon May 06, 2024 9:12 pm Yes, vro_cpyfm uses the blitter if it is a standard ST screen. If you use a graphic card and a different VDI, it is done by software or, in some cases the blitter of the graphic card, depending on the VDI used.
Interesting. I'd be curious to check out how it works with other cards, but don't have one in my MegaSTe. :D I just always coded for the typical ST screen modes.
Free to download--> Carrot Kingdom™- Atari 2600 - Released 5/11/2021
elliot
Captain Atari
Captain Atari
Posts: 396
Joined: Tue Mar 17, 2009 2:00 pm

Re: Blitter and packed pixel mode

Post by elliot »

I understand that the TT used software to Blitter stuff (I think Atari did not have a BLITTER fast enough for the TT BUS). I assume it was compatible on a VDI level too but not hardware.
Falcon with CT60 in rack mountable case. Two STFMs, one upgraded lots. My original STE from when I was a teen with Switchable TOS, 1.44Mb drive, 4MB RAM, Supra Hard Drive and very very yellow case. Mega STE with (currently none working) Crazy Dots 2. Atari 2600 and a Jag. And a mountain of commercial software and lots of hardware addons.
User avatar
Cyprian
10 GOTO 10
10 GOTO 10
Posts: 3331
Joined: Fri Oct 04, 2002 11:23 am
Location: Warsaw, Poland

Re: Blitter and packed pixel mode

Post by Cyprian »

elliot wrote: Mon May 13, 2024 7:35 am I understand that the TT used software to Blitter stuff (I think Atari did not have a BLITTER fast enough for the TT BUS). I assume it was compatible on a VDI level too but not hardware.
who knows why Atari didn't add the BLiTTER to the TT, but I see three reasons:
1) the TT bus is 64bit, the BLiTTER - 16bit;
2) 32MHz CPU was faster than it;
3) lack of money for developing a new better blitter.

E.g. Amiga 1200/4000 blitter was exactly the same as in A500 in terms of performance: slow one and 16bit.
Falcon's the BLiTTER was the same as in the ST/STE - 16bit but with much better performance.
Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
Hatari / Steem SSE / Aranym / Saint
http://260ste.atari.org
Post Reply

Return to “Coding”