Fusion-C Split Screen

By Wolverine_nl

Paragon (1145)

Wolverine_nl's picture

04-12-2019, 22:05

Hello all,

Did anybody achieve to create a split screen using Fusion-C?

I am busy trying to convert a few of the examples out there, MAP and some from this forum.
But with no luck yet..

Login or register to post comments

By Grauw

Ascended (9569)

Grauw's picture

05-12-2019, 16:47

A split screen by itself should be totally doable even with a simple H.KEYI hook. The trick will be to get it tight, stable and ideally also CPU speed independent.

I think it could be a good approach to write an ISR in assembly which on the split point does an OTIR to I/O port 99H from a buffer that is prepared in C. So let C queue up the registers to write in the split, and have a little assembly interrupt routine dispatch it.

﹡﹡﹡

For more advanced types of splits you probably also want some control over when it polls for HR sync, and which I/O port it outputs to (e.g. 9AH for palette). Using the same approach, instead of a plain OTIR you prepare a custom-tailored handler routine for each type of split (like I do here⁽¹⁾ with assembly macros), but still pass it the data in a struct from C for it to OUTI (like this one⁽²⁾).

The most advanced approach would be to generate the assembly code, but I don’t think the added complexity of that outweighs the benefit of full C control, and you lose some flexibility compared to hand tailored assembly code which for splits you kinda want.

⁽¹⁾ VDPRegister_SetDI_M and PaletteColor_SetDI_M are just two OUTIs, Split_PollHRStart_M, Split_PollHREnd_M and Split_PollHR_M do a little polling loop (or two in the last case).
⁽²⁾ VDPRegister and PaletteColor are two-byte structs (with my Glass assembler I use macros for structs).

By Grauw

Ascended (9569)

Grauw's picture

04-12-2019, 23:32

For a full-screen split effect you could take a similar approach. On the ISR runs an assembly routine which takes a buffer and on each line polls for HR and then outputs the next buffer value to 9BH (indirect register write). When VBlank is reached the ISR ends and control returns to C, which then has some (reasonably short) amount of time to prepare the buffer for the next screen.

By Wolverine_nl

Paragon (1145)

Wolverine_nl's picture

05-12-2019, 12:53

good read, thanks Grauw, will try something out this weekend. Wink

By wimpie3

Champion (340)

wimpie3's picture

15-01-2021, 10:07

I'm stuck at the same question. I was trying to have a look at an old idea of mine to convert Green Beret to the MSX2 but this needs horizontal scrolling and a screen split. I've done some experiments but I lack the assembler knowledge to get this working in Fusion C.

By aoineko

Expert (85)

aoineko's picture

15-01-2021, 16:09

It's not specific to Fusion-C but for a screen split, you need to :

- Write a callback function to check for H-Blank interruption (check VDP register S#1) ; see bellow
- Install this callback as the H.KEYI hook
- Enable H-Blank interruption (set IE1 flag in VDP register R#0) and set the desired interruption line (in R#19)
- That's all Smile

/// H_KEYI interrupt hook
void InterruptHook()
{
	__asm
		// Get S#1
		ld		a, #1
		out		(P_VDP_ADDR), a
		ld		a, #(0x80 + 15)
		out		(P_VDP_ADDR), a
		in		a, (P_VDP_STAT)
		//  Call H-Blank if bit #0 of S#1 is set 
		rrca
		jp		nc, _no_hblank
		call	_HBlankHook // call to C function HBlankHook() 
	_no_hblank:
		// Reset R#15 to S#0
		xor		a           		
		out		(P_VDP_ADDR), a
		ld		a, #(0x80 + 15)
		out		(P_VDP_ADDR),a
	__endasm;
}

This function will call HBlankHook() function when a H-Blank occured.

EDIT : And for information, there is a delay between the time a H-Blank really occured and the start of your H-Blank management function, that can generate an offset of a few lines. Since this offset is almost constant, you can simply trigger the H-Blank a little earlier. For example, if you want a split at line 106, you may need to put the interrupt on line 103 or 102.

By wimpie3

Champion (340)

wimpie3's picture

15-01-2021, 16:34

Thank you. There are plenty of other examples on the net and here on the forum. Unfortunately they are all in machine code, and I don't intend on learning that. Every previous attempt to make a mix between a machine code screen split or scroll, and Fusion C, has caused issues. And unfortunately my knowledge is limited to C, so... let's hope and pray someone will post an example here someday. :-)

By aoineko

Expert (85)

aoineko's picture

15-01-2021, 17:07

I'm pretty sure Fusion-C have functions to set VDP register values and to install a hook, so with the InterruptHook() function above, you have all you need to make a screen split.

By ericb59

Paragon (1041)

ericb59's picture

17-01-2021, 10:49

// HSYNC and H.KEYI interrupt example : Fusionc-C 1.3
//
// Works on MSX2 and Upper
//
Download from here

http://www.ebsoft.fr/msx/temp/ex_hsync.c

By wimpie3

Champion (340)

wimpie3's picture

17-01-2021, 14:48

Thanks! I suppose that when I want to exit the example properly, something like this is needed?

  while (Inkey()!=27)
  {  
  	FT_Wait(500);
  }
  EndInterruptHandler(); // Remove  H.KEYI interrupt
  Screen(0);
  Exit(0); 

But that doesn't seem to be enough. Should something more be done?

By ericb59

Paragon (1041)

ericb59's picture

17-01-2021, 17:25

It seems it also need to disable the Hsync Hook.
Use this function:

void EndHsyncHook(void) 
{
	char IE1;

	IE1=Peek(0xF3DF) & 0b11101111; // Disable the Hsynch Hook
	Poke(0xF3DF,IE1); 				
	VDPwriteNi(0,IE1);				
}

thus you can end the program like this

  EndHsyncHook();
  EndInterruptHandler(); 
  Screen(0);
  Exit(0);