*-------------------------------------------------------*
* Doom WAD file Parser					*
*-------------------------------------------------------*
* Written by Dave Murphy in October 1995		*
*-------------------------------------------------------*

	include		include\wad_tab.s

Angle_Scalar	=	11930465	(65536/360)*65536
Last_Entry		macro
	dc.l	-1
	endm

Dir_Entry		macro
	dc.l		\1,\2
	endm

Load_Entry		macro	type
	Lea		\1_Array,a6
	bsr		Load_Construct
	bsr		\1_Setup
	endm

*-----------------------------------------------------------*
OpenWad:

	Cconws	#Message

	Fopen	#WadName,#0
	bpl.s	open_ok
	moveq	#1,d0
	bra	Error

open_ok:
	move.w	d0,handle
	Fread	handle,#12,#Signature

	lea	IWAD_file,a0
	cmp.l	#'IWAD',Signature
	beq.s	read_file

	lea	PWAD_file,a0
	cmp.l	#'PWAD',Signature
	beq.s	read_file

	moveq	#3,d0			; WAD file error
	bra	Error

read_file:
	Cconws	a0

	Cconws	#Dir_info1
	move.l	Directories,d0
	Fixlong	d0
	move.l	d0,dircount
	bsr	Write_decimal
	Cconws	#Dir_info2
	move.l	Direct_Offset,d0
	Fixlong	d0
	Fseek	d0,handle,#0
	lea	Dir_Header,a6

	moveq	#0,d7
	
find_level_loop:
	Fread	handle,#Dir_Len,a6
	bsr	Search_Entry
	tst.w	d7
	bne.s	.found
	subq.l	#1,dircount
	bne.s	find_level_loop
	moveq	#4,d0			; WAD file error
	bra	Error
.found:


	moveq	#0,d7
read_dir_loop:
	Fread	handle,#Dir_Len,a6
	bsr	Scan_Entry
	cmp.w	#8,d7
	blt.s	read_dir_loop

*-------------------------------------------------------*
* Read in constructs found in WAD file			*
*-------------------------------------------------------*
	Load_Entry	Thing
	Load_Entry	Line	
	Load_Entry	Side
	Load_Entry	Vertex
	Load_Entry	Seg
	Load_Entry	SSector
	Load_Entry	Node
	Load_Entry	Sector
	Fclose		handle

*-------------------------------------------------------*
* Calculate size of all arrays allocated		*
*-------------------------------------------------------*
	lea	Thing_Array,a0
	moveq	#0,d0
	moveq	#8-1,d7
calc_sizes:
	add.l	Size(a0),d0
	lea	Construct_len(a0),a0
	dbf	d7,calc_sizes

	lsr.l	#8,d0		
	lsr.l	#2,d0			; round down to nearest 1k

	bsr	Write_decimal		; output result
	Cconws	#Allocated

	Crawcin

	rts
*-------------------------------------------------------*
* Reserve memory, load a constuct 			*
*-------------------------------------------------------*
		rsreset
Array		rs.l	1
Offset		rs.l	1
Size		rs.l	1
Number		rs.w	1
Construct_len	rs.w	1

Load_Construct:
	move.l	Size(a6),d0
	bsr	Malloc
	move.l	d0,Array(a6)
	Fseek	Offset(a6),handle,#0
	Fread	handle,Size(a6),Array(a6)
	rts

Malloc:	move.l	d0,-(sp)
	move.w	#72,-(sp)
	trap	#1
	addq.l	#6,sp
	tst.l	d0
	beq.s	Memory_Error
	rts

Memory_Error:
	moveq	#2,d0
	bra	Error

*-------------------------------------------------------*
* Scans Directory name and executes appropriate code	*
*-------------------------------------------------------*
* A6 - pointer to header				*
*-------------------------------------------------------*

Search_Entry:
	lea	WadLevel,a0
	cmp.l	#-1,(a0)
	beq.s	.got
	lea	Dir_Name(a6),a2
.next:	move.b	(a0)+,d0
	beq.s	.got
	fixcase	d0
	move.b	(a2)+,d1
	fixcase	d1
	cmp.b	d1,d0
	beq.s	.next
	moveq	#0,d7
	rts
.got:	moveq	#1,d7
	rts

Scan_Entry:
	lea	Dir_Table,a0
	move.l	Dir_Offset(a6),d5
	Fixlong	d5
	move.l	Dir_Size(a6),d6
	Fixlong	d6
Scan_loop:
	move.l	(a0)+,a1
	cmp.l	#-1,a1
	beq.s	not_found
	lea	Dir_Name(a6),a2
	move.l	(a0)+,a3
Try_name:
	move.b	(a3)+,d0
	beq.s	got_entry
	cmp.b	(a2)+,d0
	beq.s	Try_name
	bra.s	Scan_loop

got_entry:
	addq.w	#1,d7
	jmp	(a1)

not_found:
	Cconws	#Skipping
	lea	Dir_Name(a6),a0
	Cconws	a0
	Cconws	#CRLF
	rts

*-------------------------------------------------------*
* Outputs D0.l as unsigned decimal in ASCII		*
*-------------------------------------------------------*
Write_decimal:
	lea	Ascii_Output,a0
.convert_to_ascii:
	moveq	#0,d1
	divu.l	#10,d1:d0
	add.b	#'0',d1
	move.b	d1,-(a0)
	tst.l	d0
	bne.s	.convert_to_ascii

	Cconws	a0
	rts

*-------------------------------------------------------*
* Routines to initialise directory constructs		*
*-------------------------------------------------------*
Init_lines:
	lea	Line_Array,a5
	moveq	#Line_len,d0
	bra.s	Init_Entry
Init_sidedefs:
	lea	Side_Array,a5
	moveq	#Side_len,d0
	bra.s	Init_Entry
Init_vertexes:
	lea	Vertex_Array,a5
	moveq	#Vertex_len,d0
	bra.s	Init_Entry
Init_segs:
	lea	Seg_Array,a5
	moveq	#Seg_len,d0
	bra.s	Init_Entry
Init_ssectors:
	lea	SSector_Array,a5
	moveq	#Ssect_len,d0
	bra.s	Init_Entry
Init_nodes:
	lea	Node_Array,a5
	moveq	#Node_len,d0
	bra.s	Init_Entry
Init_sectors:
	lea	Sector_Array,a5
	moveq	#Sector_len,d0
	bra.s	Init_Entry
Init_things:
	lea	Thing_Array,a5
	moveq	#Thing_len,d0
Init_Entry
	move.l	d6,Size(a5)	
	move.l	d5,Offset(a5)
	divu.l	d0,d6
	move.w	d6,Number(a5)

	lea	Dir_Name(a6),a0
	Cconws	a0
	Cconws	#divider
	moveq	#0,d0
	move.w	Number(a5),d0
	bsr	Write_decimal
	Cconws	#CRLF
	rts

*-------------------------------------------------------*
* Setup Player start position and angle			*
*-------------------------------------------------------*
Thing_Setup:
	move.l	Array(a6),a0

Seek_Player:
	move.w	Thing_type(a0),d0
	Fixword	d0
	cmp.w	#1,d0		; Player 1 start
	beq.s	Got_Player
	lea	Thing_len(a0),a0
	bra.s	Seek_Player

Got_Player:
	move.w	Thing_x(a0),d0
	Fixword	d0
	move.w	d0,Px

	move.w	Thing_y(a0),d0
	Fixword	d0
	move.w	d0,Py

	moveq	#0,d0
	move.w	Thing_angle(a0),d0
	Fixword	d0
	mulu.l	#Angle_Scalar,d0	
	swap	d0
	move.w	d0,Pangle
	move.w	#40,Ph

	rts

*-------------------------------------------------------*
* Reformat Line Array to Big Endian			*
*-------------------------------------------------------*
Line_Setup:
	move.l	Array(a6),a0
	move.w	NumLines,d7
	bra.s	Fix_Lines
Fix_Line_Loop:
	moveq	#Line_len/2-1,d6
.Fix_one:
	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+
	dbf	d6,.Fix_one
Fix_Lines:
	dbf	d7,Fix_Line_Loop
	rts

*-------------------------------------------------------*
* Reformat Node array to Big Endian & setup Pnode array	*
*-------------------------------------------------------*
Node_Setup:
	moveq	#0,d0
	move.w	NumNodes,d0
	move.w	d0,d7
	subq.w	#1,d7
	move.w	d7,maxnode
	lsl.l	#2,d0
	bsr	Malloc
	move.l	d0,PNode_Array
	move.l	d0,a1
	move.l	Array(a6),a0
Fix_Nodes:
	move.l	a0,(a1)+		; insert node in Pnode array
	moveq	#Node_len/2-1,d6
.fix_one:
	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+
	dbf	d6,.fix_one
	dbf	d7,Fix_Nodes
	rts

*-------------------------------------------------------*
* Reformat Side array to Big Endian 			*
*-------------------------------------------------------*
Side_Setup:
	move.l	Array(a6),a0
	move.w	NumSides,d7
	bra.s	Fix_Sides
fix_side_loop:
	move.w	Side_tm_xoff(a0),d0
	Fixword	d0
	move.w	d0,Side_tm_xoff(a0)

	move.w	Side_tm_yoff(a0),d0
	Fixword	d0
	move.w	d0,Side_tm_yoff(a0)

	move.w	Side_sector(a0),d0
	Fixword	d0
	move.w	d0,Side_sector(a0)

	lea	Side_len(a0),a0
Fix_Sides:
	dbf	d7,fix_side_loop
	rts

*-------------------------------------------------------*
* Reformat Vertex array to Big Endian 			*
*-------------------------------------------------------*
Vertex_Setup:
	move.l	Array(a6),a0
	move.w	NumVertexs,d7
	bra.s	Fix_Vertexes
fix_vertex_loop:
	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+

	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+
Fix_Vertexes:
	dbf	d7,fix_vertex_loop
	rts

*-------------------------------------------------------*
* Reformat Seg array to Big Endian 			*
*-------------------------------------------------------*
Seg_Setup:
	move.l	Array(a6),a0
	move.w	NumSegs,d7
	bra.s	Fix_Segs
Fix_Seg_Loop:
	moveq	#Seg_len/2-1,d6
.Fix_one:
	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+
	dbf	d6,.Fix_one
Fix_Segs:
	dbf	d7,Fix_Seg_Loop
	rts

*-------------------------------------------------------*
* Reformat Ssector array to Big Endian 			*
*-------------------------------------------------------*
SSector_Setup:
	move.l	Array(a6),a0
	move.w	NumSSectors,d7
	bra.s	Fix_Ssectors
fix_ssector_loop:
	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+

	move.w	(a0),d0
	Fixword	d0
	move.w	d0,(a0)+
Fix_Ssectors:
	dbf	d7,fix_ssector_loop
	rts

*-------------------------------------------------------*
* Reformat Sector array to Big Endian 			*
*-------------------------------------------------------*
Sector_Setup:
	move.l	Array(a6),a0
	move.w	NumSectors,d7
	bra.s	Fix_Sectors
fix_sector_loop:
	move.w	Sector_floorht(a0),d0
	Fixword	d0
	move.w	d0,Sector_floorht(a0)	

	move.w	Sector_ceilht(a0),d0
	Fixword	d0
	move.w	d0,Sector_ceilht(a0)	

	move.w	Sector_light(a0),d0
	Fixword	d0
	move.w	d0,Sector_light(a0)	

	move.w	Sector_type(a0),d0
	Fixword	d0
	move.w	d0,Sector_type(a0)	

	move.w	Sector_trigger(a0),d0
	Fixword	d0
	move.w	d0,Sector_trigger(a0)	

	lea	Sector_len(a0),a0
Fix_Sectors:
	dbf	d7,fix_sector_loop
	rts


*-----------------------------------------------------------*
	Section Data
*-----------------------------------------------------------*

Message:	dc.b	27,'E',27,'f'
		dc.b	'Falcon Doom - a demo for the Bad Mood project.',13,10
		dc.b	'Rebuilt in 68030 by Doug Little & Dave Murphy.',13,10,13,10,0

IWAD_file:	dc.b	'Reading IWAD file.',13,10,0
PWAD_file:	dc.b	'Reading PWAD file.',13,10,0
Dir_info1:	dc.b	'This file contains ',0
Dir_info2:	dc.b	' Directory Entries.',13,10,0
Skipping:	dc.b	'Skipping: ',0
divider:	dc.b	9,': ',0
Allocated:	dc.b	'Kb Allocated for arrays!',13,10,0
CRLF:		dc.b	13,10,0

*-----------------------------------------------------------*

	ds.b	40
Ascii_Output:	dc.w	0

	even
Dir_Table:
	Dir_Entry	Init_things,Things
	Dir_Entry	Init_lines,Linedefs
	Dir_Entry	Init_sidedefs,Sidedefs
	Dir_Entry	Init_vertexes,Vertexes
	Dir_Entry	Init_segs,Segs
	Dir_Entry	Init_ssectors,Ssectors
	Dir_Entry	Init_nodes,Nodes
	Dir_Entry	Init_sectors,Sectors
	Last_Entry

Things:		dc.b	'THINGS',0
Linedefs:	dc.b	'LINEDEFS',0
Sidedefs:	dc.b	'SIDEDEFS',0
Vertexes:	dc.b	'VERTEXES',0
Segs:		dc.b	'SEGS',0
Ssectors:	dc.b	'SSECTORS',0
Nodes:		dc.b	'NODES',0
Sectors:	dc.b	'SECTORS',0

	even

*-----------------------------------------------------------*
* Directory Entry format
*-----------------------------------------------------------*
	rsreset
Dir_Offset:	rs.l	1
Dir_Size:	rs.l	1
Dir_Name:	rs.l	2
Dir_Len:	rs.l	1

Dir_Header:	ds.b	Dir_Len
		dc.b	0

	even

*-----------------------------------------------------------*
	Section Bss
*-----------------------------------------------------------*

dircount:	ds.l	1
Signature:	ds.l	1
Directories:	ds.l	1
Direct_Offset:	ds.l	1


handle:		ds.w	1


Structure	macro	name
\1_Array	ds.l	1
\1_Offset	ds.l	1
\1_Size		ds.l	1
Num\1s		ds.w	1
		endm

*-----------------------------------------------------------*
	Structure	Thing
	Structure	SSector
	Structure	Sector
	Structure	Side
	Structure	Node
	Structure	Line
	Structure	Seg
	Structure	Vertex
	
PNode_Array	ds.l	1
	
*-----------------------------------------------------------*
	Section Text
*-----------------------------------------------------------*

	include	errors.s



