#include <exec/exec.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <proto/intuition.h>
#include <proto/exec.h>

extern void __asm __regargs hst2gsp32(	register __d0 BYTE *gsp_addr,
										register __d6 ULONG screen_width,
										register __a0 BYTE *src_addr);

extern ULONG __asm __regargs MemCmpCpy(	register __a5 ULONG width_in_bytes,
										register __a0 BYTE *src_addr,
										register __a1 BYTE *dst_addr);

void __asm __regargs refresh(	register __d0 UWORD delta_used,
								register __d1 BYTE *delta_base,
								register __d6 ULONG screen_width,
								register __d7 UWORD page_number,
								register __a0 BYTE *scr_base,
								register __a1 ULONG amount,
								register __a2 UWORD num_pages)
{
	ULONG full_scan_lines, left_over_bytes1, left_over_bytes2, 
	      actual_page, remainder;
	BYTE *buffer_address, *gsp_addr, *delta_address;
	int loop = 0;
	
	if(amount == 0)
		return;

	/* page_number is given as 128, total pages is 158, actual page
	   is 30-1 = 29!!! */
	actual_page = (num_pages - page_number) - 1;
	
	/* Find position in screen buffer memory:
	   - amount is MMU page size
	   - scr_base is base address of screen buffer
	   - actual_page is index */
	buffer_address = (BYTE *)(actual_page * amount + scr_base);
	delta_address  = (BYTE *)(actual_page * amount + delta_base);
		
	if(actual_page)
		left_over_bytes1 = screen_width-((ULONG)(buffer_address - scr_base) % screen_width);
	else
		left_over_bytes1 = 0;
	remainder = amount - left_over_bytes1;
	left_over_bytes2 = remainder % screen_width;
	remainder -= left_over_bytes2;
	full_scan_lines = remainder / screen_width;
	
	if(left_over_bytes1) // Not a complete scan-line to transfer
		gsp_addr = (BYTE *)( 0xFE000000 + (screen_width - left_over_bytes1)*8 +
		( (buffer_address - scr_base) / screen_width )*8192 );
	else // Complete scan-line to transfer
		gsp_addr = (BYTE *)(0xFE000000+((buffer_address-scr_base)/screen_width)*8192);

	if(left_over_bytes1)
	{
		hst2gsp32(gsp_addr,left_over_bytes1,buffer_address);
		gsp_addr += (1024 - (screen_width - left_over_bytes1))*8;
		buffer_address += left_over_bytes1;
		delta_address  += left_over_bytes1;
	}
	
	for(loop;loop<full_scan_lines;loop++)
	{
		if(delta_used==3)
		{
			if(MemCmpCpy(screen_width,buffer_address,delta_address))
				hst2gsp32(gsp_addr,screen_width,buffer_address);
		}
		else
		{
			hst2gsp32(gsp_addr,screen_width,buffer_address);
		}
		gsp_addr += 1024*8;
		buffer_address += screen_width;
		delta_address  += screen_width;
	}

	if(left_over_bytes2)
	{
		hst2gsp32(gsp_addr,left_over_bytes2,buffer_address);
	}
}
