English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 18 October 2019, 18:47   #1
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Converting Photon's tuts to C

Hey everyone, I've decided it might be an idea to convert Photon's excellent assembly tutorials to C, so I'm not just copying and pasting.

I might even post them up on GitHub if there's any interest.

Anyway, I'm undecided on an aspect, I can't decide whether to do them 1 to 1 conversion, like this (tut4):

Code:
#include <exec/types.h>

#define VPOSR 0xdff004
#define VHPOSR 0xdff006
#define INTENAR 0xdff01c
#define INTENA 0xdff09a
#define COLOR00 0xdff180
#define CIAPRAA 0xbfe001

int main()
{
	volatile UBYTE *vhposr = (UBYTE *)VHPOSR;
	volatile UBYTE *vposr_lo = (UBYTE *)VPOSR + 1;	// point to low byte
	UWORD *color00 = (UWORD *)COLOR00;
	UWORD *intena = (UWORD *)INTENA;

	// line starting position
	UBYTE yPos = 0xac;

	// line direction
	BYTE yDir = 1;

	// save interrupts
	UWORD oldInt = *(UWORD *)INTENAR;

	// disable all interrupts
	*intena = 0x7fff;

	// do main loop until mouse pressed
	while(*(volatile UBYTE *)CIAPRAA & 64)
	{
		// wait for start of frame
		if((*vposr_lo & 1) == 0 && *vhposr == 0x2c)
		{
			*color00 = 0;	// bg black

			// update line y position
			yPos += yDir;

			// bounce line
			if(yPos > 0xf0 || yPos < 0x40)
			{
				yDir = -yDir;
			}

			// do literally nothing until we reach yPos
			while(*vhposr != yPos)
			{}
			*color00 = 0xfff;	// bg white

			// now do nothing until we're not on yPos
			while(*vhposr == yPos)
			{}
			*color00 = 0x116;	// bg blue
		}
	}

	// restore interrupts
	*intena = oldInt | 0xc000;	
	
    return 0;
}
Which produces practically the code in the tutorials.

Or, do it "properly" using headers like this:

Code:
#include <proto/exec.h>
#include <hardware/cia.h>
#include <hardware/custom.h>

#define HIBYTE(theword) (UBYTE)(theword >> 8)
#define LOBYTE(theword) (UBYTE)(theword & 0xff)

extern struct Custom custom;
extern struct CIA ciaa;

int main()
{
	// line starting position
	UBYTE yPos = 0xac;

	// line direction
	BYTE yDir = 1;

	// Save interrupts and DMA
	UWORD oldInt = custom.intenar;

	// disable all interrupts
	custom.intena = 0x7fff;

	// loop until mouse clicked
	while(ciaa.ciapra & CIAF_GAMEPORT0)
	{
		// wait for start of frame
		if((custom.vposr & 1) == 0 && HIBYTE(custom.vhposr) == 0x2c)
		{
			custom.color[0] = 0;	// bg black

			// update line y position
			yPos += yDir;

			// bounce line
			if(yPos > 0xf0 || yPos < 0x40)
			{
				yDir = -yDir;
			}

			// do literally nothing until we reach yPos
			while(HIBYTE(custom.vhposr) != yPos)
			{}
			custom.color[0] = 0xfff;	// bg white

			// now do nothing until we're not on yPos
			while(HIBYTE(custom.vhposr) == yPos)
			{}
			custom.color[0] = 0x116;	// bg blue
		}
	}

	// restore interrupts and DMA
	custom.intena = oldInt | 0x8000;

	return 0;
}
That leads me to a question, actually. That HIBYTE macro still produces:
Code:
move.w custom.vhposr,d1
lsr.w #8,d1
Is there a better way of doing this?

Ideally I'd want same code as
Code:
olatile UBYTE *vhposr = (UBYTE *)0xdff006;
which is just a move.b.

Last edited by Spec-Chum; 18 October 2019 at 19:27.
Spec-Chum is offline  
Old 18 October 2019, 19:13   #2
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
+1 for doing it "properly", using headers.
deimos is offline  
Old 18 October 2019, 21:29   #3
kamelito
Zone Friend
 
kamelito's Avatar
 
Join Date: May 2006
Location: France
Posts: 1,801
Nice keep them coming one guy on YouTube was showing how to bang the Amiga HW in C but unfortunately he stopped after making 3 of them.
https://m.youtube.com/user/weiju
kamelito is offline  
Old 18 October 2019, 21:51   #4
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
If you're going to use C, use the system C headers. You've already bypassed the assembly programmer's argument about minimising assembly times and external dependencies.
idrougge is offline  
Old 18 October 2019, 22:09   #5
redblade
Zone Friend
 
redblade's Avatar
 
Join Date: Mar 2004
Location: Middle Earth
Age: 40
Posts: 2,127
Good work and keep it up , I don't think it will compile with freeDICE as freeDICE does not allow bit manipulations, but I will try it with NorthC
redblade is offline  
Old 18 October 2019, 22:22   #6
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Quote:
Originally Posted by redblade View Post
Good work and keep it up , I don't think it will compile with freeDICE as freeDICE does not allow bit manipulations, but I will try it with NorthC
I'm cross compiling - I've gone though 3 compilers so far lol

Started with vbcc, then tried bebbo's GCC 6.5, now on Bartman's GCC 8.3, which I think I'll maybe stick to due to the VSCode integrated debugging.

I do already know 68k, but I've not used C for years so figured using C on this would be 2 birds one stone.
Spec-Chum is offline  
Old 18 October 2019, 22:28   #7
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
custom.vhposr is probably (correctly) marked volatile, which means the compiler needs to read all 16 bits and thus can't skip the shift instruction, I suppose.
hooverphonique is offline  
Old 18 October 2019, 22:38   #8
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Quote:
Originally Posted by hooverphonique View Post
custom.vhposr is probably (correctly) marked volatile, which means the compiler needs to read all 16 bits and thus can't skip the shift instruction, I suppose.
Yeah, I'm possibly expecting a little too much from the compiler since it is a UWORD, you can happily move.b any byte from a hardware register tho, so it's not a hardware limitation.

EDIT: Scrap that, I was wrong, the tutorial code is doing btst #0,$dff005 and cmp.b #$2c,$dff006, not a move!
Spec-Chum is offline  
Old 18 October 2019, 23:04   #9
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
Quote:
Originally Posted by Spec-Chum View Post
Yeah, I'm possibly expecting a little too much from the compiler since it is a UWORD, you can happily move.b any byte from a hardware register tho, so it's not a hardware limitation.
It's not about expectations or hardware limitations. Since the register is 16 bits, the compiler has no choice, as it has to obey it being volatile.
hooverphonique is offline  
Old 18 October 2019, 23:07   #10
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Quote:
Originally Posted by hooverphonique View Post
It's not about expectations or hardware limitations. Since the register is 16 bits, the compiler has no choice, as it has to obey it being volatile.
I agree, yeah, I was wrong. Realised right after posting lol
Spec-Chum is offline  
Old 19 October 2019, 15:57   #11
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Had a bit of spare time (how rare is that nowadays!) so tut7 done, obviously can't do much with the tutorial parts about ORG and labels etc so 100% anyone reading my source to watch the video, which goes without saying for all of them, really.

The single .c file is getting a little larger now and I'm contempating splitting it, putting the #define's into a header file at least, but that goes further from the asm source, so I'm divided.

That said, this isn't a C coding tutorial, as such, so I'm not trying to show best practices or anything, so I might just leave it so it's easier to compare to the original source.

Anyway, here's tut7:
Code:
#include "support/gcc8_c_support.h"

#include <proto/exec.h>
#include <proto/graphics.h>
#include <hardware/cia.h>
#include <hardware/custom.h>
#include <graphics/copper.h>
#include <graphics/gfxbase.h>

#define HIBYTE(theword) (theword >> 8)
#define LOBYTE(theword) (theword & 0xff)

#define CMOVE(addr, data) addr, data
#define CWAIT(vhpos, flags) vhpos, flags
#define CEND 0xffff, 0xfffe

#define WAITRAS1 28

struct ExecBase *SysBase;
struct GfxBase *GfxBase;
struct copinit *oldCopinit;

volatile struct Custom *custom = (struct Custom *)0xdff000;
volatile struct CIA *ciaa  = (struct CIA *)0xbfe001;

// __attribute__((section("tut.MEMF_CHIP")))
UWORD copperlist[] =
{
	CMOVE(0x01fc, 0x0000),		// set FMODE to slow for AGA
	CMOVE(0x0100, 0x0200),		// no bitplanes, but need color burst

	CMOVE(0x0180, 0x0349),
	CWAIT(0x2b07, 0xfffe),
	CMOVE(0x0180, 0x056c),
	CWAIT(0x2c07, 0xfffe),
	CMOVE(0x0180, 0x0113),

// waitras1:
	CWAIT(0x8007, 0xfffe),
	CMOVE(0x0180, 0x0055),

// waitras2:
	CWAIT(0x8107, 0xfffe),
	CMOVE(0x0180, 0x00aa),

// waitras3:
	CWAIT(0x8207, 0xfffe),
	CMOVE(0x0180, 0x00ff),

// waitras4:
	CWAIT(0x8307, 0xfffe),
	CMOVE(0x0180, 0x00aa),

// waitras5:
	CWAIT(0x8407, 0xfffe),
	CMOVE(0x0180, 0x0055),

// waitras6:
	CWAIT(0x8507, 0xfffe),
	CMOVE(0x0180, 0x0113),

	CWAIT(0xffdf, 0xfffe),
	CWAIT(0x2c07, 0xfffe),
	CMOVE(0x0180, 0x056c),
	CWAIT(0x2d07, 0xfffe),
	CMOVE(0x0180, 0x0349),

	CEND		
};

int main()
{
	SysBase = *(struct ExecBase**)4L;

	UBYTE *clptr = AllocMem(sizeof(copperlist), MEMF_CHIP);
	CopyMem(copperlist, clptr, sizeof(copperlist));

	// open gfx lib and save original copperlist
	GfxBase = (struct GfxBase*)OldOpenLibrary("graphics.library");
	oldCopinit = GfxBase->copinit;
	CloseLibrary((struct Library *)GfxBase);
	
	// line starting position
	UWORD yPos = 0xac;

	// line direction
	WORD yDir = 1;

	// Save interrupts and DMA
	UWORD oldInt = custom->intenar;

	// disable all interrupts
	custom->intena = 0x7fff;

	// initiate our copper
	custom->cop1lc = (ULONG)clptr;

	// loop until mouse clicked
	while(ciaa->ciapra & CIAF_GAMEPORT0)
	{
		// wait for start of frame ** wframe **
		if((custom->vposr & 1) == 0 && HIBYTE(custom->vhposr) == 0x2a)
		{
			while(HIBYTE(custom->vhposr) == 0x2a)
			{ } // wframe2
			
			// update line y position
			yPos += yDir;

			// bounce line
			if(yPos > 0xf0 || yPos < 0x40)
			{
				yDir = -yDir;
			}

			for(UWORD waitras = 0; waitras < 6; waitras++)
			{
				clptr[WAITRAS1 + (waitras * 8)] = yPos + waitras;
			}
		}
	}

	// restore original copper
	custom->cop1lc = (ULONG)oldCopinit;

	// free copperlist memory
	FreeMem(clptr, sizeof(copperlist));

	// restore interrupts
	custom->intena = oldInt | 0xc000;

	return 0;
}
Thoughts?
Spec-Chum is offline  
Old 19 October 2019, 21:30   #12
kamelito
Zone Friend
 
kamelito's Avatar
 
Join Date: May 2006
Location: France
Posts: 1,801
Is all your translation to C here or do you have them elsewhere?
kamelito is offline  
Old 19 October 2019, 22:35   #13
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Quote:
Originally Posted by kamelito View Post
Is all your translation to C here or do you have them elsewhere?
If there's an interest, I'll put them all on github at some point, but the source is a bit all over currently; for example tuts 2 to 4 are for bebbo's GCC 6.5, 5 to 7 are for Bartman's GCC 8.3.

Actually, I think tut 2 is for vbcc lol

I need to rework the others so they're all Bartman's GCC 8.3 as that's what I've settled on, mainly for the debugging feature.

I might even #ifdef so it compiles on all 3, but that seems a bit overkill for now.

I'm just after opinions on the structure for now, as I'd hate to get like 20 tuts in then decide I want to do something different and have to change all the others to conform.
Spec-Chum is offline  
Old 20 October 2019, 00:37   #14
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
OK, I've updated and attached all the original ones I did to use Bartman's GCC 8.3 now - this one here

All you need to do is install his VSCode extension, which is fully self contained, initialise a folder as per his instructions, replace the main.c he provides as an example with one of mine and press F5, which should, hopefully, run first time.

When I upload to git I'll only do the .c files as the VSCode extension customises the .d files to the initialised directory.
Attached Files
File Type: 7z Scoopex in C.7z (2.0 KB, 168 views)
Spec-Chum is offline  
Old 20 October 2019, 20:15   #15
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
I've done a .gitignore file to remove all the unneeded files and uploaded to GitHub

You should be able to just install Bartman's VSCode GCC extension, open one of my folders and press F5 for it to run.

Hopefully.
Spec-Chum is offline  
Old 21 October 2019, 03:21   #16
JuanLuis
Registered User
 
Join Date: Dec 2018
Location: Málaga
Posts: 61
Quote:
Originally Posted by Spec-Chum View Post
I've done a .gitignore file to remove all the unneeded files and uploaded to GitHub

You should be able to just install Bartman's VSCode GCC extension, open one of my folders and press F5 for it to run.

Hopefully.
Spec, I implemented tutorial 9 for Bebbo GCC 6.4.0 a time ago. The code should work fine with Bartman GCC too.

Code:
// Scoopex Tutorial 9 for Bebbo GCC 6.4.0

#include <clib/exec_protos.h>
#include <graphics/gfxbase.h>

#include <cstdio>
#include <cstdint>
#include <cstring>

volatile uint16_t* const DMACONR     = (uint16_t* const) 0xDFF002;

volatile uint32_t* const VPOS32      = (uint32_t* const) 0xDFF004;

volatile uint16_t* const VPOSR       = (uint16_t* const) 0xDFF004;
volatile uint8_t*  const VPOSR_LOW   = (uint8_t*  const) 0xDFF005;

volatile uint16_t* const VPOSHR      = (uint16_t* const) 0xDFF006;
volatile uint8_t*  const VPOSHR_HIGH = (uint8_t*  const) 0xDFF006;
volatile uint8_t*  const VPOSHR_LOW  = (uint8_t*  const) 0xDFF007;

volatile uint16_t* const INTENAR     = (uint16_t* const) 0xDFF01C;

volatile uint32_t* const COP1LC32    = (uint32_t* const) 0xDFF080;
volatile uint16_t* const COP1LCH     = (uint16_t* const) 0xDFF080;
volatile uint16_t* const COP1LCL     = (uint16_t* const) 0xDFF082;

volatile uint16_t* const COP2LCH     = (uint16_t* const) 0xDFF084;
volatile uint16_t* const COP2LCL     = (uint16_t* const) 0xDFF086;

volatile uint16_t* const DMACONW     = (uint16_t* const) 0xDFF096;
volatile uint16_t* const INTENAW     = (uint16_t* const) 0xDFF09A;
volatile uint16_t* const INTREQW     = (uint16_t* const) 0xDFF09C;

volatile uint8_t*  const CIAA_PRA    = (uint8_t* const ) 0xBFE001;

static const uint16_t WIDTH      = 320;
static const uint16_t HEIGHT     = 256;
uint8_t*              screen_ptr =   0;
uint8_t*              smile_sprite_ptr = 0;

uint16_t*             copper_list = 0;
uint16_t*             copper_list_end = 0;

const uint16_t SMILE_SPRITE[] = {
	0x2C40,0x3C00, // Vstart.b,Hstart/2.b,Vstop.b,%A0000SEH
        
	0x07C0,0x0000, // dc.w %     *****      ,%                
	0x1FF0,0x0000, // dc.w %   *********    ,%                
	0x3FF8,0x0000, // dc.w %  ***********   ,%                
	0x7FFC,0x0000, // dc.w % *************  ,%                
	0x67CC,0x1830, // dc.w % **  *****  **  ,%   **     **    
	0xE7CE,0x1830, // dc.w %***  *****  *** ,%   **     **    
	0xFFFE,0x0000, // dc.w %*************** ,%                
	0xFFFE,0x0000, // dc.w %*************** ,%                
	0xFFFE,0x2008, // dc.w %*************** ,%  *         *   
	0xFFFE,0x1830, // dc.w %*************** ,%   **     **    
	0x7FFC,0x07C0, // dc.w % *************  ,%     *****      
	0x7FFC,0x0000, // dc.w % *************  ,%                
	0x3FF8,0x0000, // dc.w %  ***********   ,%                
	0x1FF0,0x0000, // dc.w %   *********    ,%                
	0x07C0,0x0000, // dc.w %     *****      ,%                
	0x0000,0x0000, // dc.w %                ,%                
	0,0
};

const uint16_t NULL_SPRITE[] = {
	0x2a20,0x2b00,
	0,0,
	0,0
};

const uint16_t COPPER_LIST_BEGIN[] = {
//Copper:
	0x1fc,0, // slow fetch mode, AGA compatibility
	0x100,0x0200,
	0x8e,0x2c81,
	0x90,0x2cc1,
	0x92,0x38,
	0x94,0xd0,
	0x108,0,
	0x10a,0,
	0x102,0,
	0x1a2,0xe22,
	0x1a4,0xff0,
	0x1a6,0xfff
};

const uint16_t SPR_P[] = {
//SprP:
	0x120, 0x0000, // Sprite 0 SMILE_SPRITE_HIGH (value is defined later)
	0x122, 0x0000, // Sprite 0 SMILE_SPRITE_LOW
        
	0x124, 0x0000, // Sprite 1 NULL_SPRITE_HIGH
	0x126, 0x0000, // Sprite 1 NULL_SPRITE_LOW
        
	0x128, 0x0000, // Sprite 2 NULL_SPRITE_HIGH
	0x12a, 0x0000, // Sprite 2 NULL_SPRITE_LOW
        
	0x12c, 0x0000, // Sprite 3 NULL_SPRITE_HIGH
	0x12e, 0x0000, // Sprite 3 NULL_SPRITE_LOW
        
	0x130, 0x0000, // Sprite 4 NULL_SPRITE_HIGH
	0x132, 0x0000, // Sprite 4 NULL_SPRITE_LOW
        
	0x134, 0x0000, // Sprite 5 NULL_SPRITE_HIGH
	0x136, 0x0000, // Sprite 5 NULL_SPRITE_LOW
        
	0x138, 0x0000, // Sprite 6 NULL_SPRITE_HIGH
	0x13a, 0x0000, // Sprite 6 NULL_SPRITE_LOW
        
	0x13c, 0x0000, // Sprite 7 NULL_SPRITE_HIGH
	0x13e, 0x0000  // Sprite 7 NULL_SPRITE_LOW
};

const uint16_t COPPER_LIST_END[] = {
//CopBplP:
	0xe0, 0x0006, // Screen HIGH WORD 0x0006 default
	0xe2, 0x0000, // Screen LOW  WORD 0x0000 default
	0x180,0x349,
	0x2b07,0xfffe,
	0x180,0x56c,
	0x2c07,0xfffe,
	0x180,0x113,
	0x100,0x1200,
	0x182,0x379,
	
//waitras1: // COPPER_LIST_END[18]
	0x8007,0xfffe,
	0x180,0x055, // Adjusting color entry 0 of palette for horizontal bouncing bar
	
//waitras2: // COPPER_LIST_END[22]
	0x8107,0xfffe,
	0x180,0x0aa, // Adjusting color entry 0 again for next color of gradient
	
//waitras3: // COPPER_LIST_END[26]
	0x8207,0xfffe,
	0x180,0x0ff, // Next color
	
//waitras4: // COPPER_LIST_END[30]
	0x8307,0xfffe,
	0x180,0x0aa, // Next color
	
//waitras5: // COPPER_LIST_END[34]
	0x8407,0xfffe,
	0x180,0x055, // Next color
	
//waitras6: // COPPER_LIST_END[38]
	0x8507,0xfffe,
	0x180,0x113, // Next color
        
	0xffdf,0xfffe,
	0x2c07,0xfffe,
	0x180,0x56c, // Next color
	0x2d07,0xfffe,
	0x180,0x349, // Last color of horizontal bar
	0xffff,0xfffe 
};

void waitRaster(uint32_t value) {
    uint32_t mask = 0x1FF00;
    uint32_t maskedValue = (value << 8) & mask;
    
    while ((*VPOS32 & mask) != maskedValue);
}

void createScreenBuffer() {
    size_t bitplane_size = WIDTH * HEIGHT / 8;
    screen_ptr = (uint8_t*) AllocMem(bitplane_size, MEMF_CHIP);
    uint8_t* helper = screen_ptr;
    
    // Inicialización del hardware     
    for (uint32_t i = 0; i < bitplane_size; i++) {
        // Filling frame buffer with horizontal position of beam. Assembler version of Scoopex
        // is developed in assembler so it's faster. The look is different by this reason.
        *helper++ = *VPOSHR_LOW;
    }
}

void destroyScreenBuffer() {
    size_t bitplane_size = WIDTH * HEIGHT / 8;
    FreeMem(screen_ptr, bitplane_size);
}

void createCopperList() {
    size_t size = sizeof(COPPER_LIST_BEGIN) +
                  sizeof(SPR_P) +
                  sizeof(COPPER_LIST_END) +
                  sizeof(SMILE_SPRITE) +
                  sizeof(NULL_SPRITE);
    
    uint16_t* helper = copper_list = (uint16_t*) AllocMem(size, MEMF_CHIP);
    
    memcpy(helper, COPPER_LIST_BEGIN, sizeof(COPPER_LIST_BEGIN));
    helper += sizeof(COPPER_LIST_BEGIN) / sizeof(uint16_t);

    uint16_t* spr_p_ptr = helper;    
    memcpy(helper, SPR_P, sizeof(SPR_P));
    helper += sizeof(SPR_P) / sizeof(uint16_t);    
    
    copper_list_end = helper;
    memcpy(helper, COPPER_LIST_END, sizeof(COPPER_LIST_END));
    helper += sizeof(COPPER_LIST_END) / sizeof(uint16_t);
    
    smile_sprite_ptr = (uint8_t*) helper;
    memcpy(helper, SMILE_SPRITE, sizeof(SMILE_SPRITE));
    helper += sizeof(SMILE_SPRITE) / sizeof(uint16_t);
    
    uint16_t* null_sprite_ptr = helper;
    memcpy(helper, NULL_SPRITE, sizeof(NULL_SPRITE));
    
    uint16_t lo_smile_sprite_ptr = ((uint32_t) smile_sprite_ptr) & 0xFFFF;
    uint16_t hi_smile_sprite_ptr = ((uint32_t) smile_sprite_ptr) >> 16;
    
    uint16_t lo_null_sprite_ptr = ((uint32_t) null_sprite_ptr) & 0xFFFF;
    uint16_t hi_null_sprite_ptr = ((uint32_t) null_sprite_ptr) >> 16;
    
    spr_p_ptr[1] = hi_smile_sprite_ptr;
    spr_p_ptr[3] = lo_smile_sprite_ptr;

    for (int i = 0; i < 7; i++) {
        spr_p_ptr[5 + i * 4] = hi_null_sprite_ptr;
        spr_p_ptr[7 + i * 4] = lo_null_sprite_ptr;
    }
    
    uint16_t lo_screen_ptr = ((uint32_t) screen_ptr) & 0xFFFF;
    uint16_t hi_screen_ptr = ((uint32_t) screen_ptr) >> 16;
    copper_list_end[1] = hi_screen_ptr;
    copper_list_end[3] = lo_screen_ptr;
}

void destroyCopperList() {
    size_t size = sizeof(COPPER_LIST_BEGIN) +
                  sizeof(SPR_P) +
                  sizeof(COPPER_LIST_END) +
                  sizeof(SMILE_SPRITE) +
                  sizeof(NULL_SPRITE);
    
    FreeMem(copper_list, size);
}

void setCopperList(uint16_t* cl) {
    *COP1LCH =((uint32_t) cl) >> 16;
    *COP1LCL =((uint32_t) cl) & 0xFFFF;
}

void waitFrame() {
    do {
        while (*VPOSR_LOW & 1);
    } while (*VPOSHR_HIGH != 0x2a);
}

void waitFrame2() {
    while (*VPOSHR_HIGH != 0x2a);
}

bool leftClick() {
    return (*CIAA_PRA & (1 << 6)) == 0;
}

int main(int argc, char** argv) {   
    struct Library* gfxLib = OpenLibrary("graphics.library", 0);
    GfxBase* gfxBase = (GfxBase*) gfxLib;
    
    if (gfxBase) {
        struct copinit* copinit = gfxBase->copinit;
        CloseLibrary(gfxLib);
        
        uint16_t old_INTENA = *INTENAR;
        uint16_t old_DMACON = *DMACONR;
        
        waitRaster(0x0138);
        
        *INTENAW = 0x7FFF; // Disable all bits in INTENA
        *INTREQW = 0x7FFF; // Idem
        //*INTREQW = 0x7FFF; // Idem. Original Scoopex code do this twice. I have removed without problems.
        *DMACONW = 0x7FFF; // Disable all bits in DMACON
        *DMACONW = 0x87E0; // Setting DMA channels
        
        createScreenBuffer(); // It's important to create screen buffer before Copper list
        createCopperList();
        setCopperList(copper_list);
        
        // Wait loop
        bool bar_lowering  = true;
        uint8_t bar_y_position = 0xAC;
        
        while (true) {
            waitFrame();
            waitFrame2();
            
            // Add 1 to sprite position (Smile icon)
            smile_sprite_ptr[1]++;
            bar_y_position = bar_lowering ? bar_y_position + 1 : bar_y_position - 1;
            
            if (bar_y_position >= 0xF0)
                bar_lowering = false;
            
            if (bar_y_position <= 0x40)
                bar_lowering = true;
            
            *((uint8_t*) &copper_list_end[18]) = bar_y_position;
            *((uint8_t*) &copper_list_end[22]) = bar_y_position + 1;
            *((uint8_t*) &copper_list_end[26]) = bar_y_position + 2;
            *((uint8_t*) &copper_list_end[30]) = bar_y_position + 3;
            *((uint8_t*) &copper_list_end[34]) = bar_y_position + 4;
            *((uint8_t*) &copper_list_end[38]) = bar_y_position + 5;
            
            // Detecting left click to exit
            if (leftClick())
                break;
        }
        destroyCopperList();
        destroyScreenBuffer();
        
        *DMACONW = 0x7FFF; // Disabling DMACON
        *DMACONW = old_DMACON | 0x8200;
        *COP1LC32 = (uint32_t) copinit;
        *INTENAW = old_INTENA | 0xC000;
    } else {
        fprintf(stderr, "Error opening graphics.library\n");
        return 1;
    }
    return 0;
}
JuanLuis is offline  
Old 21 October 2019, 09:37   #17
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
Quote:
Originally Posted by JuanLuis View Post
Spec, I implemented tutorial 9 for Bebbo GCC 6.4.0 a time ago. The code should work fine with Bartman GCC too.

Code:
// Scoopex Tutorial 9 for Bebbo GCC 6.4.0

#include <clib/exec_protos.h>
#include <graphics/gfxbase.h>

#include <cstdio>
#include <cstdint>
#include <cstring>

volatile uint16_t* const DMACONR     = (uint16_t* const) 0xDFF002;

volatile uint32_t* const VPOS32      = (uint32_t* const) 0xDFF004;

volatile uint16_t* const VPOSR       = (uint16_t* const) 0xDFF004;
volatile uint8_t*  const VPOSR_LOW   = (uint8_t*  const) 0xDFF005;

volatile uint16_t* const VPOSHR      = (uint16_t* const) 0xDFF006;
volatile uint8_t*  const VPOSHR_HIGH = (uint8_t*  const) 0xDFF006;
volatile uint8_t*  const VPOSHR_LOW  = (uint8_t*  const) 0xDFF007;

volatile uint16_t* const INTENAR     = (uint16_t* const) 0xDFF01C;

volatile uint32_t* const COP1LC32    = (uint32_t* const) 0xDFF080;
volatile uint16_t* const COP1LCH     = (uint16_t* const) 0xDFF080;
volatile uint16_t* const COP1LCL     = (uint16_t* const) 0xDFF082;

volatile uint16_t* const COP2LCH     = (uint16_t* const) 0xDFF084;
volatile uint16_t* const COP2LCL     = (uint16_t* const) 0xDFF086;

volatile uint16_t* const DMACONW     = (uint16_t* const) 0xDFF096;
volatile uint16_t* const INTENAW     = (uint16_t* const) 0xDFF09A;
volatile uint16_t* const INTREQW     = (uint16_t* const) 0xDFF09C;

volatile uint8_t*  const CIAA_PRA    = (uint8_t* const ) 0xBFE001;

static const uint16_t WIDTH      = 320;
static const uint16_t HEIGHT     = 256;
uint8_t*              screen_ptr =   0;
uint8_t*              smile_sprite_ptr = 0;

uint16_t*             copper_list = 0;
uint16_t*             copper_list_end = 0;

const uint16_t SMILE_SPRITE[] = {
	0x2C40,0x3C00, // Vstart.b,Hstart/2.b,Vstop.b,%A0000SEH
        
	0x07C0,0x0000, // dc.w %     *****      ,%                
	0x1FF0,0x0000, // dc.w %   *********    ,%                
	0x3FF8,0x0000, // dc.w %  ***********   ,%                
	0x7FFC,0x0000, // dc.w % *************  ,%                
	0x67CC,0x1830, // dc.w % **  *****  **  ,%   **     **    
	0xE7CE,0x1830, // dc.w %***  *****  *** ,%   **     **    
	0xFFFE,0x0000, // dc.w %*************** ,%                
	0xFFFE,0x0000, // dc.w %*************** ,%                
	0xFFFE,0x2008, // dc.w %*************** ,%  *         *   
	0xFFFE,0x1830, // dc.w %*************** ,%   **     **    
	0x7FFC,0x07C0, // dc.w % *************  ,%     *****      
	0x7FFC,0x0000, // dc.w % *************  ,%                
	0x3FF8,0x0000, // dc.w %  ***********   ,%                
	0x1FF0,0x0000, // dc.w %   *********    ,%                
	0x07C0,0x0000, // dc.w %     *****      ,%                
	0x0000,0x0000, // dc.w %                ,%                
	0,0
};

const uint16_t NULL_SPRITE[] = {
	0x2a20,0x2b00,
	0,0,
	0,0
};

const uint16_t COPPER_LIST_BEGIN[] = {
//Copper:
	0x1fc,0, // slow fetch mode, AGA compatibility
	0x100,0x0200,
	0x8e,0x2c81,
	0x90,0x2cc1,
	0x92,0x38,
	0x94,0xd0,
	0x108,0,
	0x10a,0,
	0x102,0,
	0x1a2,0xe22,
	0x1a4,0xff0,
	0x1a6,0xfff
};

const uint16_t SPR_P[] = {
//SprP:
	0x120, 0x0000, // Sprite 0 SMILE_SPRITE_HIGH (value is defined later)
	0x122, 0x0000, // Sprite 0 SMILE_SPRITE_LOW
        
	0x124, 0x0000, // Sprite 1 NULL_SPRITE_HIGH
	0x126, 0x0000, // Sprite 1 NULL_SPRITE_LOW
        
	0x128, 0x0000, // Sprite 2 NULL_SPRITE_HIGH
	0x12a, 0x0000, // Sprite 2 NULL_SPRITE_LOW
        
	0x12c, 0x0000, // Sprite 3 NULL_SPRITE_HIGH
	0x12e, 0x0000, // Sprite 3 NULL_SPRITE_LOW
        
	0x130, 0x0000, // Sprite 4 NULL_SPRITE_HIGH
	0x132, 0x0000, // Sprite 4 NULL_SPRITE_LOW
        
	0x134, 0x0000, // Sprite 5 NULL_SPRITE_HIGH
	0x136, 0x0000, // Sprite 5 NULL_SPRITE_LOW
        
	0x138, 0x0000, // Sprite 6 NULL_SPRITE_HIGH
	0x13a, 0x0000, // Sprite 6 NULL_SPRITE_LOW
        
	0x13c, 0x0000, // Sprite 7 NULL_SPRITE_HIGH
	0x13e, 0x0000  // Sprite 7 NULL_SPRITE_LOW
};

const uint16_t COPPER_LIST_END[] = {
//CopBplP:
	0xe0, 0x0006, // Screen HIGH WORD 0x0006 default
	0xe2, 0x0000, // Screen LOW  WORD 0x0000 default
	0x180,0x349,
	0x2b07,0xfffe,
	0x180,0x56c,
	0x2c07,0xfffe,
	0x180,0x113,
	0x100,0x1200,
	0x182,0x379,
	
//waitras1: // COPPER_LIST_END[18]
	0x8007,0xfffe,
	0x180,0x055, // Adjusting color entry 0 of palette for horizontal bouncing bar
	
//waitras2: // COPPER_LIST_END[22]
	0x8107,0xfffe,
	0x180,0x0aa, // Adjusting color entry 0 again for next color of gradient
	
//waitras3: // COPPER_LIST_END[26]
	0x8207,0xfffe,
	0x180,0x0ff, // Next color
	
//waitras4: // COPPER_LIST_END[30]
	0x8307,0xfffe,
	0x180,0x0aa, // Next color
	
//waitras5: // COPPER_LIST_END[34]
	0x8407,0xfffe,
	0x180,0x055, // Next color
	
//waitras6: // COPPER_LIST_END[38]
	0x8507,0xfffe,
	0x180,0x113, // Next color
        
	0xffdf,0xfffe,
	0x2c07,0xfffe,
	0x180,0x56c, // Next color
	0x2d07,0xfffe,
	0x180,0x349, // Last color of horizontal bar
	0xffff,0xfffe 
};

void waitRaster(uint32_t value) {
    uint32_t mask = 0x1FF00;
    uint32_t maskedValue = (value << 8) & mask;
    
    while ((*VPOS32 & mask) != maskedValue);
}

void createScreenBuffer() {
    size_t bitplane_size = WIDTH * HEIGHT / 8;
    screen_ptr = (uint8_t*) AllocMem(bitplane_size, MEMF_CHIP);
    uint8_t* helper = screen_ptr;
    
    // Inicialización del hardware     
    for (uint32_t i = 0; i < bitplane_size; i++) {
        // Filling frame buffer with horizontal position of beam. Assembler version of Scoopex
        // is developed in assembler so it's faster. The look is different by this reason.
        *helper++ = *VPOSHR_LOW;
    }
}

void destroyScreenBuffer() {
    size_t bitplane_size = WIDTH * HEIGHT / 8;
    FreeMem(screen_ptr, bitplane_size);
}

void createCopperList() {
    size_t size = sizeof(COPPER_LIST_BEGIN) +
                  sizeof(SPR_P) +
                  sizeof(COPPER_LIST_END) +
                  sizeof(SMILE_SPRITE) +
                  sizeof(NULL_SPRITE);
    
    uint16_t* helper = copper_list = (uint16_t*) AllocMem(size, MEMF_CHIP);
    
    memcpy(helper, COPPER_LIST_BEGIN, sizeof(COPPER_LIST_BEGIN));
    helper += sizeof(COPPER_LIST_BEGIN) / sizeof(uint16_t);

    uint16_t* spr_p_ptr = helper;    
    memcpy(helper, SPR_P, sizeof(SPR_P));
    helper += sizeof(SPR_P) / sizeof(uint16_t);    
    
    copper_list_end = helper;
    memcpy(helper, COPPER_LIST_END, sizeof(COPPER_LIST_END));
    helper += sizeof(COPPER_LIST_END) / sizeof(uint16_t);
    
    smile_sprite_ptr = (uint8_t*) helper;
    memcpy(helper, SMILE_SPRITE, sizeof(SMILE_SPRITE));
    helper += sizeof(SMILE_SPRITE) / sizeof(uint16_t);
    
    uint16_t* null_sprite_ptr = helper;
    memcpy(helper, NULL_SPRITE, sizeof(NULL_SPRITE));
    
    uint16_t lo_smile_sprite_ptr = ((uint32_t) smile_sprite_ptr) & 0xFFFF;
    uint16_t hi_smile_sprite_ptr = ((uint32_t) smile_sprite_ptr) >> 16;
    
    uint16_t lo_null_sprite_ptr = ((uint32_t) null_sprite_ptr) & 0xFFFF;
    uint16_t hi_null_sprite_ptr = ((uint32_t) null_sprite_ptr) >> 16;
    
    spr_p_ptr[1] = hi_smile_sprite_ptr;
    spr_p_ptr[3] = lo_smile_sprite_ptr;

    for (int i = 0; i < 7; i++) {
        spr_p_ptr[5 + i * 4] = hi_null_sprite_ptr;
        spr_p_ptr[7 + i * 4] = lo_null_sprite_ptr;
    }
    
    uint16_t lo_screen_ptr = ((uint32_t) screen_ptr) & 0xFFFF;
    uint16_t hi_screen_ptr = ((uint32_t) screen_ptr) >> 16;
    copper_list_end[1] = hi_screen_ptr;
    copper_list_end[3] = lo_screen_ptr;
}

void destroyCopperList() {
    size_t size = sizeof(COPPER_LIST_BEGIN) +
                  sizeof(SPR_P) +
                  sizeof(COPPER_LIST_END) +
                  sizeof(SMILE_SPRITE) +
                  sizeof(NULL_SPRITE);
    
    FreeMem(copper_list, size);
}

void setCopperList(uint16_t* cl) {
    *COP1LCH =((uint32_t) cl) >> 16;
    *COP1LCL =((uint32_t) cl) & 0xFFFF;
}

void waitFrame() {
    do {
        while (*VPOSR_LOW & 1);
    } while (*VPOSHR_HIGH != 0x2a);
}

void waitFrame2() {
    while (*VPOSHR_HIGH != 0x2a);
}

bool leftClick() {
    return (*CIAA_PRA & (1 << 6)) == 0;
}

int main(int argc, char** argv) {   
    struct Library* gfxLib = OpenLibrary("graphics.library", 0);
    GfxBase* gfxBase = (GfxBase*) gfxLib;
    
    if (gfxBase) {
        struct copinit* copinit = gfxBase->copinit;
        CloseLibrary(gfxLib);
        
        uint16_t old_INTENA = *INTENAR;
        uint16_t old_DMACON = *DMACONR;
        
        waitRaster(0x0138);
        
        *INTENAW = 0x7FFF; // Disable all bits in INTENA
        *INTREQW = 0x7FFF; // Idem
        //*INTREQW = 0x7FFF; // Idem. Original Scoopex code do this twice. I have removed without problems.
        *DMACONW = 0x7FFF; // Disable all bits in DMACON
        *DMACONW = 0x87E0; // Setting DMA channels
        
        createScreenBuffer(); // It's important to create screen buffer before Copper list
        createCopperList();
        setCopperList(copper_list);
        
        // Wait loop
        bool bar_lowering  = true;
        uint8_t bar_y_position = 0xAC;
        
        while (true) {
            waitFrame();
            waitFrame2();
            
            // Add 1 to sprite position (Smile icon)
            smile_sprite_ptr[1]++;
            bar_y_position = bar_lowering ? bar_y_position + 1 : bar_y_position - 1;
            
            if (bar_y_position >= 0xF0)
                bar_lowering = false;
            
            if (bar_y_position <= 0x40)
                bar_lowering = true;
            
            *((uint8_t*) &copper_list_end[18]) = bar_y_position;
            *((uint8_t*) &copper_list_end[22]) = bar_y_position + 1;
            *((uint8_t*) &copper_list_end[26]) = bar_y_position + 2;
            *((uint8_t*) &copper_list_end[30]) = bar_y_position + 3;
            *((uint8_t*) &copper_list_end[34]) = bar_y_position + 4;
            *((uint8_t*) &copper_list_end[38]) = bar_y_position + 5;
            
            // Detecting left click to exit
            if (leftClick())
                break;
        }
        destroyCopperList();
        destroyScreenBuffer();
        
        *DMACONW = 0x7FFF; // Disabling DMACON
        *DMACONW = old_DMACON | 0x8200;
        *COP1LC32 = (uint32_t) copinit;
        *INTENAW = old_INTENA | 0xC000;
    } else {
        fprintf(stderr, "Error opening graphics.library\n");
        return 1;
    }
    return 0;
}
Nice. Interesting how we've taken very different approaches.

You've taken the traditional c coding style, with functions and stdlib, whereas I've gone the more direct asm source to c approach.

Sadly I don't think bartman's gcc will work with this as, apart from memcpy, there's no stdlib.
Spec-Chum is offline  
Old 21 October 2019, 10:47   #18
Steffest
Registered User
 
Join Date: Jan 2017
Location: Antwerp / Belgium
Posts: 189
This really is a super interesting thread.
Thanks guys!
Really appreciate it - I've been trying to get my head around "hardware banging with C" for some time :-)
Steffest is offline  
Old 21 October 2019, 14:15   #19
bebbo
bye
 
Join Date: Jun 2016
Location: Some / Where
Posts: 680
I adapted tutorial 9 a bit - less allocations, more use of headers...
Code:
// Scoopex Tutorial 9 for Bebbo GCC 6.5.0b

#include <proto/exec.h>
#include <graphics/gfxbase.h>
#include <hardware/cia.h>
#include <hardware/custom.h>

#include <stdint.h>
#include <string.h>

#define bool short
#define true 1
#define false 0

// omit command line parsing - smalle executable
extern void __initlibraries(void);
void __nocommandline (void){ __initlibraries();}

extern struct GfxBase * GfxBase;

extern struct Custom custom;
extern struct CIA ciaa;

#define WIDTH      320
#define HEIGHT     256
__chip uint8_t        screen_ptr[WIDTH*HEIGHT/8];
uint8_t*              smile_sprite_ptr = 0;

uint16_t*             copper_list = 0;
uint16_t*             copper_list_end = 0;

__chip uint16_t SMILE_SPRITE[] = {
	0x2C40,0x3C00, // Vstart.b,Hstart/2.b,Vstop.b,%A0000SEH

	0x07C0,0x0000, // dc.w %     *****      ,%
	0x1FF0,0x0000, // dc.w %   *********    ,%
	0x3FF8,0x0000, // dc.w %  ***********   ,%
	0x7FFC,0x0000, // dc.w % *************  ,%
	0x67CC,0x1830, // dc.w % **  *****  **  ,%   **     **
	0xE7CE,0x1830, // dc.w %***  *****  *** ,%   **     **
	0xFFFE,0x0000, // dc.w %*************** ,%
	0xFFFE,0x0000, // dc.w %*************** ,%
	0xFFFE,0x2008, // dc.w %*************** ,%  *         *
	0xFFFE,0x1830, // dc.w %*************** ,%   **     **
	0x7FFC,0x07C0, // dc.w % *************  ,%     *****
	0x7FFC,0x0000, // dc.w % *************  ,%
	0x3FF8,0x0000, // dc.w %  ***********   ,%
	0x1FF0,0x0000, // dc.w %   *********    ,%
	0x07C0,0x0000, // dc.w %     *****      ,%
	0x0000,0x0000, // dc.w %                ,%
	0,0
};

__chip uint16_t NULL_SPRITE[] = {
	0x2a20,0x2b00,
	0,0,
	0,0
};

__chip uint16_t COPPER_LIST_BEGIN[] = {
//Copper:
	0x1fc,0, // slow fetch mode, AGA compatibility
	0x100,0x0200,
	0x8e,0x2c81,
	0x90,0x2cc1,
	0x92,0x38,
	0x94,0xd0,
	0x108,0,
	0x10a,0,
	0x102,0,
	0x1a2,0xe22,
	0x1a4,0xff0,
	0x1a6,0xfff
};

__chip uint16_t SPR_P[] = {
//SprP:
	0x120, 0x0000, // Sprite 0 SMILE_SPRITE_HIGH (value is defined later)
	0x122, 0x0000, // Sprite 0 SMILE_SPRITE_LOW

	0x124, 0x0000, // Sprite 1 NULL_SPRITE_HIGH
	0x126, 0x0000, // Sprite 1 NULL_SPRITE_LOW

	0x128, 0x0000, // Sprite 2 NULL_SPRITE_HIGH
	0x12a, 0x0000, // Sprite 2 NULL_SPRITE_LOW

	0x12c, 0x0000, // Sprite 3 NULL_SPRITE_HIGH
	0x12e, 0x0000, // Sprite 3 NULL_SPRITE_LOW

	0x130, 0x0000, // Sprite 4 NULL_SPRITE_HIGH
	0x132, 0x0000, // Sprite 4 NULL_SPRITE_LOW

	0x134, 0x0000, // Sprite 5 NULL_SPRITE_HIGH
	0x136, 0x0000, // Sprite 5 NULL_SPRITE_LOW

	0x138, 0x0000, // Sprite 6 NULL_SPRITE_HIGH
	0x13a, 0x0000, // Sprite 6 NULL_SPRITE_LOW

	0x13c, 0x0000, // Sprite 7 NULL_SPRITE_HIGH
	0x13e, 0x0000  // Sprite 7 NULL_SPRITE_LOW
};

__chip uint16_t COPPER_LIST_END[] = {
//CopBplP:
	0xe0, 0x0006, // Screen HIGH WORD 0x0006 default
	0xe2, 0x0000, // Screen LOW  WORD 0x0000 default
	0x180,0x349,
	0x2b07,0xfffe,
	0x180,0x56c,
	0x2c07,0xfffe,
	0x180,0x113,
	0x100,0x1200,
	0x182,0x379,

//waitras1: // COPPER_LIST_END[18]
	0x8007,0xfffe,
	0x180,0x055, // Adjusting color entry 0 of palette for horizontal bouncing bar

//waitras2: // COPPER_LIST_END[22]
	0x8107,0xfffe,
	0x180,0x0aa, // Adjusting color entry 0 again for next color of gradient

//waitras3: // COPPER_LIST_END[26]
	0x8207,0xfffe,
	0x180,0x0ff, // Next color

//waitras4: // COPPER_LIST_END[30]
	0x8307,0xfffe,
	0x180,0x0aa, // Next color

//waitras5: // COPPER_LIST_END[34]
	0x8407,0xfffe,
	0x180,0x055, // Next color

//waitras6: // COPPER_LIST_END[38]
	0x8507,0xfffe,
	0x180,0x113, // Next color

	0xffdf,0xfffe,
	0x2c07,0xfffe,
	0x180,0x56c, // Next color
	0x2d07,0xfffe,
	0x180,0x349, // Last color of horizontal bar
	0xffff,0xfffe
};

void waitRaster(uint32_t value) {
    uint32_t mask = 0x1FF00;
    uint32_t maskedValue = (value << 8) & mask;

    while ((custom.vpos32 & mask) != maskedValue);
}

void fillScreenBuffer() {
    const size_t bitplane_size = WIDTH * HEIGHT / 8;
    uint8_t* helper = screen_ptr;

    // Inicialización del hardware
    for (uint32_t i = 0; i < bitplane_size; i++) {
        // Filling frame buffer with horizontal position of beam. Assembler version of Scoopex
        // is developed in assembler so it's faster. The look is different by this reason.
        *helper++ = custom.vhposr;
    }
}


void createCopperList() {
	copper_list = COPPER_LIST_BEGIN;

    uint16_t* spr_p_ptr = SPR_P;

    copper_list_end = COPPER_LIST_END;

    smile_sprite_ptr = (uint8_t*)SMILE_SPRITE;


    uint16_t* null_sprite_ptr = NULL_SPRITE;


    uint16_t lo_smile_sprite_ptr = ((uint32_t) smile_sprite_ptr) & 0xFFFF;
    uint16_t hi_smile_sprite_ptr = ((uint32_t) smile_sprite_ptr) >> 16;

    uint16_t lo_null_sprite_ptr = ((uint32_t) null_sprite_ptr) & 0xFFFF;
    uint16_t hi_null_sprite_ptr = ((uint32_t) null_sprite_ptr) >> 16;

    spr_p_ptr[1] = hi_smile_sprite_ptr;
    spr_p_ptr[3] = lo_smile_sprite_ptr;

    for (int i = 0; i < 7; i++) {
        spr_p_ptr[5 + i * 4] = hi_null_sprite_ptr;
        spr_p_ptr[7 + i * 4] = lo_null_sprite_ptr;
    }

    uint16_t lo_screen_ptr = ((uint32_t) screen_ptr) & 0xFFFF;
    uint16_t hi_screen_ptr = ((uint32_t) screen_ptr) >> 16;
    copper_list_end[1] = hi_screen_ptr;
    copper_list_end[3] = lo_screen_ptr;
}


void setCopperList(uint16_t* cl) {
    custom.cop1lc = (ULONG)cl;
}

void waitFrame() {
    do {
        while (custom.vposr & 1);
    } while (custom.vhposr_h != 0x2a);
}

void waitFrame2() {
    while (custom.vhposr_h != 0x2a);
}

bool leftClick() {
    return (ciaa.ciapra & (1 << 6)) == 0;
}

int main(int argc, char** argv) {
        struct copinit* copinit = GfxBase->copinit;

        uint16_t old_INTENA = custom.intenar;
        uint16_t old_DMACON = custom.dmaconr;

        waitRaster(0x0138);

        custom.intena = 0x7FFF; // Disable all bits in INTENA
        custom.intreq = 0x7FFF; // Idem
        custom.intreq = 0x7FFF; // Idem
        //*INTREQW = 0x7FFF; // Idem. Original Scoopex code do this twice. I have removed without problems.
        custom.dmacon = 0x7FFF; // Disable all bits in DMACON
        custom.dmacon = 0x87E0; // Setting DMA channels

        fillScreenBuffer(); // It's important to create screen buffer before Copper list
        createCopperList();
        setCopperList(copper_list);

        // Wait loop
        bool bar_lowering  = true;
        uint8_t bar_y_position = 0xAC;

        while (true) {
            waitFrame();
            waitFrame2();

            // Add 1 to sprite position (Smile icon)
            smile_sprite_ptr[1]++;
            bar_y_position = bar_lowering ? bar_y_position + 1 : bar_y_position - 1;

            if (bar_y_position >= 0xF0)
                bar_lowering = false;

            if (bar_y_position <= 0x40)
                bar_lowering = true;

            *((uint8_t*) &copper_list_end[18]) = bar_y_position;
            *((uint8_t*) &copper_list_end[22]) = bar_y_position + 1;
            *((uint8_t*) &copper_list_end[26]) = bar_y_position + 2;
            *((uint8_t*) &copper_list_end[30]) = bar_y_position + 3;
            *((uint8_t*) &copper_list_end[34]) = bar_y_position + 4;
            *((uint8_t*) &copper_list_end[38]) = bar_y_position + 5;

            // Detecting left click to exit
            if (leftClick())
                break;
        }

        custom.dmacon = 0x7FFF; // Disabling DMACON
        custom.dmacon = old_DMACON | 0x8200;
        custom.cop1lc = (uint32_t) copinit;
        custom.intena = old_INTENA | 0xC000;
    return 0;
}
Save as C-file tut9.c and use
Code:
m68k-amigaos-gcc -Os -msmall-code -fomit-frame-pointer -mcrt=nix13 tut9.c -o tut9
And you'll get a file with ~2688 file size. (stripped 1744, but no debug infos then)
[/code]

EDIT:
add -msmall-code and -fomit-frame-pointer saves few more bytes.

Last edited by bebbo; 21 October 2019 at 14:53.
bebbo is offline  
Old 21 October 2019, 14:46   #20
Spec-Chum
Registered User
 
Join Date: Dec 2016
Location: England
Posts: 87
If I get chance I'll do tut9 tonight.

Be interesting to compare file sizes.

As stated above, I've taken a different approach in that I'm consciously mirroring the asm source to a degree.

I do check the compiler output tho, and it's pretty good.
Spec-Chum is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
So I 'cracked' Photon Storm. What do you guys think? MethodGit Coders. General 3 05 August 2012 02:41
Photon's A1700 Photon Hardware mods 43 25 December 2011 15:30
Photon Storm Marlon request.Old Rare Games 11 07 September 2007 19:34
asm tuts BippyM Coders. Tutorials 61 12 January 2007 15:39
Photon Storm Tim Janssen request.Old Rare Games 9 12 September 2002 22:02

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 19:44.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.18040 seconds with 14 queries