/*
 * startup.S86  -  romcheck initialization and startup
 *
 * Copyright (C) 2003-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: startup.S86,v 1.7 2007/01/06 18:31:21 gkminix Exp $
 *
 *====================================================================
 */


#include <common.i86>

.file __FILE__
.line __LINE__




/*
 *====================================================================
 *
 * Definitions local to this module
 */

#define DOSEMU		0xE6		/* DOSEMU exit interrupt */




.line __LINE__
/*
 *====================================================================
 *
 * Start of the text segment and definition of all public entry points
 */

	.text

	.extern	_main			# define external symbols

	.global	_start			# define global symbols
	.global	_exit



/*
 *====================================================================
 *
 * Now start the game
 */

_start:

/*
 * First we set the data segment correctly and clear the BSS segment
 */

	cld
	push	bx
	mov	ax,cs
	mov	bx,offset __data_start
	or	bx,bx			# if the data segment starts at offset
	jnz	1f			# zero, we have seperate text and data
	mov	bx,offset __text_end	# segments
	add	bx,0x000F
	shr	bx,1
	shr	bx,1			# compute real start of data segment
	shr	bx,1
	shr	bx,1
	add	ax,bx
1:	pop	bx
	mov	ds,ax
	mov	es,ax
	mov	di,offset __bss_start
	mov	cx,offset __bss_end
	sub	cx,di			# clear BSS segment
	xor	al,al
	rep	stosb

/*
 * Check that we are running on the correct processor. After we have passed
 * this check, we can be sure to use 32-bit opcodes and registers.
 */

	call	chkcpu
	or	si,si
	jz	3f
	call	prnstr
	call	prcrlf
	jmp	_exit

/*
 * Switch to a local stack and call the main program
 */

3:	cli
	mov	bx,ds
	mov	ss,bx			# set new stack to end of free
	mov	sp,0xFFFE		# memory segment
	sti
	xor	ebp,ebp			# clear high part of EBP
	call	_main



/*
 *====================================================================
 *
 * Reboot the system
 * Input:  none
 * Output: Routine doesnt return
 * Changed registers: all
 */
_exit:

	xor	ax,ax
	mov	ds,ax
	mov	ax,cs
	mov	word ptr ds:[DOSEMU * 4 + 2],ax	# try to exit to DOSEMU
	mov	ax,offset iret_ins
	mov	word ptr ds:[DOSEMU * 4 + 0],ax
	mov	ax,0xFFFF
	int	DOSEMU
	mov	word ptr ds:[0x0472],0x1234	# warm reboot
	ljmp	0xFFFF,0

iret_ins:
	iret




/*
 *====================================================================
 *
 * String and constants definitions
 */
	_rodata


/*
 * Error messages
 */
cpuerr:	.asciz	"Not running on a 386+ processor"




/*
 *====================================================================
 */
	.end

