;*******************************************************************
;*                                                                 *
;* Example of an external IO-Routine for the PowerCrawler:         *
;*                                                                 *
;* (done with the PhxAss!)                                         *
;*  ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ                                          *
;* 			RAW-LOADER/SAVER                           *
;*                                                                 *
;* Format:                                                         *
;*            Offset   Data                                        *
;*            ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ                                *
;*            0        Map-Width.w                                 *
;*            2        Map-Height.w                                *
;*            4        Map-Layers.w                                *
;*            6        Block-Width.w                               *
;*            8        Block-Height.w                              *
;*            10       Bytes per Block.b (1=Byte,2=Word)           *
;*            11       Transparent Block.b (0 = 0 ; 1 = -1)        *
;*            12       Map-Data:                                   *
;*                       Row 1 Layer 1                             *
;*                       Row 2 Layer 1				   *
;*                       Row . Layer 1				   *
;*			 Row n Layer 1				   *
;*								   *
;*			 Row 1 Layer 2				   *
;*			 Row 2 Layer 2				   *
;*			 Row . Layer 2				   *
;*			 Row n Layer 2				   *
;*			 					   *
;*			 Row 1 Layer .				   *
;*			 Row 2 Layer .				   *
;*			 Row . Layer .				   *
;*			 Row n Layer .				   *
;*			 					   *
;*			 Row 1 Layer n				   *
;*			 Row 2 Layer n				   *
;*			 Row . Layer n				   *
;*			 Row n Layer n				   *
;*                                                                 *
;*******************************************************************


	org	0				; ABSOLUTE MODE!

	FILE	"PowerCrawler:ExternalIO/raw.io"; absolute Code will be
						; saved into this file
	incdir	"include"
	include "exec/exec.i"
	include	"dos/dos.i"
	include "lvo/dos_lib.i"
	include "lvo/exec_lib.i"
	include	"misc/PowerCrawler.i"
	



;===================================================================

;-------------------------------------------------------------------
;			RECOGNITION
;-------------------------------------------------------------------


START:
	dc.b 	'PCEX'				; for RECOGNITION


;------------------------------------------------------------------
;			BRANCH INTO CODE
;
;Must be 4 Bytes long. If you use <bra.s    Main> then add a nop!!
;------------------------------------------------------------------


CODEENTRY:
	bra.s	MAIN
	nop

	

;-------------------------------------------------------------------
;			ACTION_CODE
;
;PowerCrawler will put PC_IO_LOADMAP or PC_IO_SAVEMAP here. Check it in
;your code to know whether you have to save or load a Map.
;------------------------------------------------------------------


ACTIONCODE:
	dc.w	0

	
;------------------------------------------------------------------
;			RETURN_CODE
;
;Put in PC_RETURN_???? before leaving
;------------------------------------------------------------------


RETURNCODE:
	dc.w	0
	
;------------------------------------------------------------------
;			RESERVED
;
;Is reserved !!!
;------------------------------------------------------------------

RESERVED1:	dc.l 0
RESERVED2:	dc.l 0
RESERVED3:	dc.l 0

;------------------------------------------------------------------
;			ACTION-VAR
;
; Points to the Filename the user wants to load/save.
;------------------------------------------------------------------

ACTIONVAR:
	dc.l	0		;will point to FileName


;------------------------------------------------------------------
;			MAIN-CODE
;
; Note: Everything must be PC-relative! Initialize the variables,
; 	cause the code is only loaded once and NOT each time
;	it is used.
;------------------------------------------------------------------


MAIN:
	lea	Vars(pc),a4
	move.l	4(sp),a5		;Get Pointer to PCInformation
					;Structure (see Powercrawler.i)
					
	move.l	pci_DosBase(a5),a6	;Get DosBase
	move	ACTIONCODE(pc),d0
	cmp	#PC_IO_LOADMAP,d0
	beq.s	LoadMap
	cmp	#PC_IO_SAVEMAP,d0
	beq.s	SaveMap
	cmp	#PC_IO_GETINFO,d0
	beq	GetInfo
	moveq	#PC_RETURN_ERROR,d0
ExitRoutine:
	lea	RETURNCODE(pc),a0
	move	d0,(a0)
	rts
	
LoadMap:
	move.l	ACTIONVAR(pc),d1
	move.l	#MODE_OLDFILE,d2
	jsr	_LVOOpen(a6)		;Open File
	move.l	d0,FileHandle-Vars(a4)
	tst.l	d0
	bne.s	LoadMap1
	moveq	#PC_RETURN_DOSERROR,d0
	bra.s	ExitRoutine
	
LoadMap1:
	move.l	d0,d1
	moveq	#0,d2
	move.l	#OFFSET_END,d3
	jsr	_LVOSeek(a6)

	move.l	FileHandle(pc),d1
	moveq	#0,d2
	move.l	#OFFSET_BEGINNING,d3
	jsr	_LVOSeek(a6)
	move.l	d0,FileSize-Vars(a4)	;Get File-Length
	
	move.l	FileHandle(pc),d1
	lea	FileHeader(pc),a2
	move.l	a2,d2
	moveq	#12,d3
	jsr	_LVORead(a6)		;Read File-Header
	cmp.l	#12,d0
	beq.s	LoadMap2
	bsr.s	CloseFH
	moveq	#PC_RETURN_READERROR,d0
	bra.s	ExitRoutine

LoadMap2:
	move.l	4.w,a6
	move.l	FileSize(pc),d0
	sub.l	#12,d0
	move.l	#MEMF_ANY,d1
	jsr	_LVOAllocVec(a6)	;Alloc new MapBuffer;
	move.l	d0,NewMapBuffer-Vars(a4)
	tst.l	d0
	bne.s	LoadMap3
	bsr	CloseFH
	moveq	#PC_RETURN_NOMEMORY,d0
	bra	ExitRoutine
	
LoadMap3:
	move.l	pci_DosBase(a5),a6
	move.l	FileHandle(pc),d1
	move.l	NewMapBuffer(pc),d2
	move.l	FileSize(pc),d3
	sub.l	#12,d3
	jsr	_LVORead(a6)		;Read new MapBuffer;
	sub.l	FileSize(pc),d0
	add.l	#12,d0
	beq.s	LoadMap4
	bsr	FreeBuffer
	bsr	CloseFH
	moveq	#PC_RETURN_READERROR,d0
	bra	ExitRoutine
	
LoadMap4:
	bsr	CloseFH
	move.l	pci_MapBuffer(a5),a1
	cmp.l	#0,a1
	beq.s	LoadMap5
	move.l	4.w,a6
	jsr	_LVOFreeVec(a6)		;Kill old MapBuffer

LoadMap5:
	move.l	NewMapBuffer(pc),d2
	move.l	d2,pci_MapBuffer(a5)	;Set to new pointer
	
	lea	FileHeader(pc),a0
	lea	pci_MapData(a5),a1
	moveq	#0,d0

	move	(a0)+,d0		;Fill-in pci_MapDat-Structure
	move.l	d0,pcd_MapWidth(a1)
	move	(a0)+,d0
	move.l	d0,pcd_MapHeight(a1)
	move	(a0)+,d0
	move.b	d0,pcd_Layers(a1)
	move	(a0)+,d0
	move.b	d0,pcd_BlockSizeX(a1)
	move	(a0)+,d0
	move.b	d0,pcd_BlockSizeY(a1)
	move.b	(a0)+,d0
	move.b	d0,pcd_MemoryType(a1)
	move.b	(a0)+,d0
	move.b	d0,pcd_TransparentBlock(a1)
	moveq	#PC_RETURN_OK,d0
	bra	ExitRoutine
	


;******************************************************************

SaveMap:
	move.l	pci_MapBuffer(a5),d0
	bne.s	SaveMap0
	
	moveq	#PC_RETURN_NOMAPBUFFER,d0
	bra	ExitRoutine
	
SaveMap0:
	
	move.l	pci_DosBase(a5),a6
	move.l	ACTIONVAR(pc),d1
	move.l	#MODE_NEWFILE,d2
	jsr	_LVOOpen(a6)		;Open new file

	move.l	d0,FileHandle-Vars(a4)
	tst.l	d0
	bne.s	SaveMap1
	moveq	#PC_RETURN_DOSERROR,d0
	bra	ExitRoutine
	
SaveMap1:
	lea	pci_MapData(a5),a0
	lea	FileHeader(pc),a1	;Fill in FileHeader
	move.l	a1,d2
	move.l	pcd_MapWidth(a0),d0
	move	d0,(a1)+
	move.l	pcd_MapHeight(a0),d0
	move	d0,(a1)+
	moveq	#0,d0
	move.b	pcd_Layers(a0),d0
	move	d0,(a1)+
	move.b	pcd_BlockSizeX(a0),d0
	move	d0,(a1)+
	move.b	pcd_BlockSizeY(a0),d0
	move	d0,(a1)+
	move.b	pcd_MemoryType(a0),d0
	move.b	d0,(a1)+
	move.b	pcd_TransparentBlock(a0),d0
	move.b	d0,(a1)+
	
	move.l	FileHandle(pc),d1
	move.l	#12,d3
	jsr	_LVOWrite(a6)
	cmp.l	#12,d0
	beq.s	SaveMap2
	
	bsr	CloseFH
	moveq	#PC_RETURN_WRITEERROR,d0
	bra	ExitRoutine

SaveMap2:
	move.l	FileHandle(pc),d1
	move.l	pci_MapBuffer(a5),d2
	lea	pci_MapData(a5),a0
	move.l	pcd_MapWidth(a0),d3
	move.l	pcd_MapHeight(a0),d4
	mulu	d4,d3
	move.l	d3,d5
	moveq	#0,d4
	move.b	pcd_Layers(a0),d4
	subq	#2,d4
	blt.s	SaveMap32

SaveMap3:
	add.l	d5,d3
	dbf	d4,SaveMap3
SaveMap32:
	moveq	#0,d4
	move.b	pcd_MemoryType(a0),d4
	subq	#2,d4
	blt.s	SaveMap4
SaveMap33:
	add.l	d3,d3
	dbf	d4,SaveMap33

SaveMap4:
	move.l	d3,d7
	jsr	_LVOWrite(a6)
	cmp.l	d0,d7
	beq.s	SaveMap5
	
	bsr	CloseFH
	moveq	#PC_RETURN_WRITEERROR,d0
	bra	ExitRoutine
	
SaveMap5:
	bsr	CloseFH
	moveq	#PC_RETURN_OK,d0
	bra	ExitRoutine
	
CloseFH:
	move.l	pci_DosBase(a5),a6
	move.l	FileHandle(pc),d1
	jsr	_LVOClose(a6)
	rts

FreeBuffer:
	move.l	4.w,a6
	move.l	NewMapBuffer(pc),a1
	jsr	_LVOFreeVec(a6)
	rts
	

;******************************************************************

GetInfo:
	lea	ACTIONVAR(pc),a0
	lea	MyInfoText(pc),a1
	move.l	a1,(a0)
	moveq	#PC_RETURN_OK,d0
	bra	ExitRoutine

;******************************************************************

Vars:

FileHandle:	dc.l 0
FileSize:	dc.l 0
FileHeader:	blk.w 6,0
FileBuffer:	dc.l 0
NewMapBuffer:	dc.l 0
MyInfoText:	dc.b '*** Raw.io by Steger Georg ***',10
		dc.b 10
		dc.b 'Format:',10
		dc.b '           Offset   Data',10
		dc.b '           ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ',10
		dc.b '           0        Map-Width.w',10
		dc.b '           2        Map-Height.w',10
		dc.b '           4        Map-Layers.w',10
		dc.b '           6        Block-Width.w',10
		dc.b '           8        Block-Height.w',10
		dc.b '           10       Bytes per Block.b (1=Byte, 2=Word)',10
		dc.b '           11       Transparent Block.b (0=0, 1=-1)',10
		dc.b '           12       Map-Data:',10
		dc.b '                      Layer 1 all',10
		dc.b '                      Layer 2 all',10
		dc.b '                      Layer . all',10
		dc.b '                      Layer n all',10
		dc.b 0