Jump to content
  • entries
  • comments
  • views

The Story of Stay Frosty 2, Part 6



The ARM in the Harmony/Melody can only interact with the Atari thru the 4K cartridge port. As such, it does not have access to TIA, RIOT, etc. The upshot of this is the ARM chip has no way to know if you hit GAME SELECT, moved the joystick left, and so on. The other thing is since the 6507 generates the display by updating TIA, the ARM chip doesn't know if the Vertical Blank or Overscan routines should be run.


When I created the Harmony DPC+ ARM programming example, I'd figured out a way to provide that information to the ARM chip by defining storage in Display Data like this:

;Display Data        ORG $6000        RORG $0000       ; NOTE the use of RORG $0000 instead of $F000 ; In this demo, the first set of bytes in Display Data are used to pass values; to the ARM codeARMsub		ds 1	; 0 for init, 1 for Over Scan, 2 for Vertical BlankARMswcha	ds 1	; controller input to ARMARMswchb	ds 1	; console switches to ARMARMcxm0p	ds 1	; pass TIA Read registers to ARMARMcxm1p	ds 1ARMcxp0fb	ds 1ARMcxp1fb	ds 1ARMcxm0fb	ds 1ARMcxm1fb	ds 1ARMcxblpf	ds 1ARMcxppmm	ds 1ARMinpt4	ds 1ARMinpt5	ds 1

I then had the 6507 put TIA, RIOT, etc information into Display Data before trigging the ARM code:

; prep for call to OverScan() 	lda #<ARMsub 	sta DF0LOW 	lda #>ARMsub 	sta DF0HI 	lda #1		; 1 = run ARM subroutine OverScan(); 	sta DF0WRITE 	; pass TIA and RIOT registers to the ARM code 	lda SWCHA       ; save joystick state 	sta DF0WRITE 	lda SWCHB       ; save state of console switches 	sta DF0WRITE 	lda CXM0P       ; save collision registers 	sta DF0WRITE 	lda CXM1P       ; ... 	sta DF0WRITE 	lda CXP0FB      ; ... 	sta DF0WRITE 	lda CXP1FB      ; ... 	sta DF0WRITE 	lda CXM0FB      ; ... 	sta DF0WRITE 	lda CXM1FB      ; ... 	sta DF0WRITE 	lda CXBLPF      ; ... 	sta DF0WRITE 	lda CXPPMM      ; ... 	sta DF0WRITE 	lda INPT4       ; save joystick 0 firebutton 	sta DF0WRITE 	lda INPT5       ; save joystick 1 firebutton 	sta DF0WRITE	lda #$FF	sta CALLFUNCTION ; triggers ARM code

In the C code, Display Data was defined as queue[] (I do not know why this name was chosen) so the C code used queue[0x0] to access ARMsub in order to know what should be run:

// main() is what gets called when you store $FF into DPC+ register CALLFUNCTION in your 6507 code.int main(){	// We're using the first byte of Display Data to tell the ARM code which subroutine we wish to run	// in the 6507 code this is defined as ARMsub	switch (queue[0x0])		{		case 0:			Initialize();			break;		case 1:			OverScan();			break;		case 2:			VerticalBlank();			break;	}	return 0;}

The other information was accessed like this:

int OverScan(){	int i;	unsigned char SWCHA		= queue[0x01];...	unsigned char INPT4		= queue[0x0b];...		// process joystick input	if (INPT4 & 0x80) 	{	// fire button not pressed		if (!(SWCHA & 0x80)) // joystick right			gXrotation++;		if (!(SWCHA & 0x40)) // joystick left			gXrotation--;		if (!(SWCHA & 0x20)) // joystick down			gYrotation--;		if (!(SWCHA & 0x10)) // joystick up			gYrotation++;	}	else 	{	// fire button pressed		if (!(SWCHA & 0x80)) // joystick right			gZrotation++;		if (!(SWCHA & 0x40)) // joystick left			gZrotation--;		if (!(SWCHA & 0x20)) // joystick down			gScale--;		if (!(SWCHA & 0x10)) // joystick up			gScale++;	}...}

While it worked for the demo it wasn't very efficient, plus keeping track of all those queue[] locations would become difficult as the program increased in size. So next up was to figure out how to easily keep that information in sync between DASM (for the 6507 code) and the C compiler (for the ARM code).



After some thinking I came up with the idea of using DASM's ECHO command. The C code would need to know more than just Display Data information, so the echo commands included things that might not be located in Display Data. The echo commands looked like this:

echo "#define SUB   queue[",ARMsub,"]" echo "#define SWCHA queue[",ARMswcha,"]" echo "#define SWCHB queue[",ARMswchb,"]" echo "#define INPT1 queue[",ARMinpt1,"]"         echo "#define INPT4 queue[",ARMinpt4,"]" echo "#define ElevatorHM26 ",ElevatorHM26 echo "#define ElevatorHM31 ",ElevatorHM31...

and would output the following when DASM was run:

#define SUB   queue[ $0 ] #define SWCHA queue[ $1 ] #define SWCHB queue[ $2 ] #define INPT1 queue[ $3 ] #define INPT4 queue[ $4 ] #define ElevatorHM26  $f7d1 #define ElevatorHM31  $f804 ...

I'd copy to that into a C file - originally main.c, but eventually defines.h. The C code already knew the definition for queue (Display Data RAM), as well as flashdata (the 29K of ROM for the cartridge), by including the file src/custom.h:

volatile unsigned char *queue=(unsigned char *)0x40000C00;volatile unsigned char *flashdata=(unsigned char *)0x0C00;

One minor problem was the C compiler expects 0x for hex values, so I'd have to do a mass find/replace of $/0x to get this, otherwise the C compiler would output a number of error messages:

#define SUB   queue[ 0x0 ] #define SWCHA queue[ 0x1 ] #define SWCHB queue[ 0x2 ] #define INPT1 queue[ 0x3 ] #define INPT4 queue[ 0x4 ] #define ElevatorHM26  0xf7d1 #define ElevatorHM31  0xf804 ...

This worked quite well, though for performance and ROM size reasons (to be covered later) those ECHO commands became this:

echo "#define SUB   ((unsigned char *)(0x40000C00 +",ARMsub,"))" echo "#define SWCHA ((unsigned char *)(0x40000C00 +",ARMswcha,"))" echo "#define SWCHB ((unsigned char *)(0x40000C00 +",ARMswchb,"))" echo "#define INPT1 ((unsigned char *)(0x40000C00 +",ARMinpt1,"))" echo "#define INPT4 ((unsigned char *)(0x40000C00 +",ARMinpt4,"))" echo "#define ElevatorHM26 ",ElevatorHM26 echo "#define ElevatorHM31 ",ElevatorHM31...

and eventually this, which eliminated the need to do the find/replace of $/0x.

echo "#define SUB   ((unsigned char *)(0x40000C00 +",[ARMsub]d,"))" echo "#define SWCHA ((unsigned char *)(0x40000C00 +",[ARMswcha]d,"))" echo "#define SWCHB ((unsigned char *)(0x40000C00 +",[ARMswchb]d,"))" echo "#define INPT1 ((unsigned char *)(0x40000C00 +",[ARMinpt1]d,"))" echo "#define INPT4 ((unsigned char *)(0x40000C00 +",[ARMinpt4]d,"))" echo "#define ElevatorHM26 ",[ElevatorHM26]d echo "#define ElevatorHM31 ",[ElevatorHM31]d...







SF2 20101016.zip


NOTE: While the ROM works on the Harmony, it does not work in Stella. It might also roll your TV as I'm generating more than 262 scanlines in order to display time-remaining in Vertical Blank and Overscan (the 15 and 14, respectively) for diagnostic purposes.


Blog entry covers October 13 - 16, 2010

  • Like 1


Recommended Comments

Probably, we're only thru reply 91 of a topic with 2553 replies - and there's a few other topics that will be added to the mix.

Share this comment

Link to comment
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...