FireWidth	equ 32*4		;Because of the burning image data
FireHeight	equ 75			;these should not be changed.

	Section MainCode,Code

	incdir include:
	include "includes:libs/exec"
	include "includes:libs/graphics"
	include "includes:libs/intuition"
	include "includes:librarymacros"
	include "includes:startend"
	include "include:hardware/dmabits.i"
	include "include:exec/exec.i"
	include "include:dos/dos.i"
	include "include:graphics/gfxbase.i"
	include "include:graphics/gfx.i"
	include "include:intuition/intuition.i"
	include "includes:VBlankServer"
	include "c4p.s"
	Section MainCode,Code

DMACON	equ $096

Random macro					;Quick and dirty random numbers
	move.l d7,d6
	ror.l #5,d6
	eor.l d6,d7
	add.l #$1865275,d7
	endm

main:
	move.l #173267,LastRand		;This really should vary, but hey.
	OpenLib Graphics
	beq exit
	OpenLib Intuition
	beq exit

	move.l #-1,d0
	ExecLib AllocSignal			;Allocate the signal used to tell this task
	move.b d0,SigNum			;when to produce fire (sent during vblanks)
	tst.b d0
	bmi exit
	moveq.l #1,d1
	lsl.l d0,d1
	move.l d1,SigMask

	sub.l a1,a1
	ExecLib FindTask
	move.l d0,SigTask

	bsr InstallVBlankServer		;Adds a vblank server which calls a user
	tst.l d0					;function if one is specified.
	bne exit

	bsr HelloWorld

	bsr WaitMode				;This is the main wait for signal loop
exit:

	bsr GoodbyeWorld

	tst.b SigNum
	bmi exit_skipfreesig
	move.b SigNum,d0
	ExecLib FreeSignal
exit_skipfreesig:
	bsr RemoveVBlankServer
	CloseLib Intuition
	CloseLib Graphics
	rts

WaitMode:
	move.l #SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F,d0
	or.l SigMask,d0
	ExecLib Wait			;Wait for all 4 DOS signals, and our own do fire
	tst.l d0				;signal.  The DOS signals are QUIT,BLANK,UNBLANK
	beq WaitMode			;and PREFS, in that order.
	btst #SIGBREAKB_CTRL_C,d0
	bne QuitBlanker
	btst #SIGBREAKB_CTRL_D,d0
	beq NotBlankScreen
	move.l d0,-(a7)
	bsr BlankScreen
	move.l (a7)+,d0

NotBlankScreen:
	btst #SIGBREAKB_CTRL_E,d0
	beq NotUnblankScreen
	move.l d0,-(a7)
	bsr UnblankScreen
	move.l (a7)+,d0

NotUnblankScreen:
	btst #SIGBREAKB_CTRL_F,d0
	beq NotPrefsWindow
	move.l d0,-(a7)
	bsr PreferencesWindow
	move.l (a7)+,d0

NotPrefsWindow:
	move.b SigNum,d1
	btst d1,d0
	beq NotFireCalcSig
	bsr CalcSomeFire
NotFireCalcSig:
	bra WaitMode

QuitBlanker:				;When quitting, unblank if necessary.
	bsr UnblankScreen
	rts

BlankScreen:
	tst.w isBlanked			;if already blanked, ignore this request.
	beq BlankScreen_continue
	rts
BlankScreen_continue:
	move.w #1,isBlanked		;set mode as blanked

	lea $0,a0				;open a screen...should be a View really...
	lea ScreenTags,a1
	UseLib Intuition,OpenScreenTagList
	move.l d0,OpenedScreen
	tst.l d0
	beq BlankScreen_fail

	lea FireBuffer,a5
	move.w #FireWidth*FireHeight-1,d0
ClearFire:
	move.b #0,(a5)+
	dbf d0,ClearFire

	move.l #SigForFire,UserVBlankInterrupt		;Tell VBlank handler about
												;our user code.

	lea $dff000,a5
	move.w #DMAF_SPRITE,DMACON(a5)
BlankScreen_fail:
	rts

UnblankScreen:
	tst.w isBlanked					;If not blanked, ignore
	bne UnblankScreen_continue
	rts
UnblankScreen_continue:
	lea $dff000,a5
	move.w #$8000|DMAF_SPRITE,DMACON(a5)

	move.w #0,isBlanked				;Set as not blanked

	move.l #0,UserVBlankInterrupt	;Remove code pointer for VBlank Handler

	tst.l OpenedScreen				;if the screen was open, close it
	beq UnblankScreen_noscreen

	move.l OpenedScreen,a0
	UseLib Intuition,CloseScreen
	move.l #0,OpenedScreen			;remembering to say there is no screen.
UnblankScreen_noscreen:

	rts

PreferencesWindow:					;This is the really complex pref window.
	rts

SigForFire:		;interrupt call back - tell main task to do some funky fire
	movem.l d0-d1/a0-a1/a6,-(a7)
	move.l FrameCounter,d0
	and.l #$1,d0
	bne SigOff				;This limits it's CPU sucking power, somewhat,
	move.l SigMask,d0		;by only going 30Hz.
	move.l SigTask,a1
	ExecLib Signal
SigOff:
	movem.l (a7)+,d0-d1/a0-a1/a6
	rts

CalcSomeFire:	;Actually do the fire and c4p conversion.
				;fire is already calc'd from last frame, so just c4p it

;******************
;** DISPLAY FIRE **
;******************
	tst.l OpenedScreen
	bne CalcSomeFire_ok
	rts
CalcSomeFire_ok:

	move.l OpenedScreen,a1
	lea sc_RastPort(a1),a1
	move.l rp_BitMap(a1),a1			;dest bitmap

	lea FireBuffer,a0
	move.w #FireHeight-2,d7
	move.w #FireWidth/32,d4
	move.w #100-FireHeight/2,d6
	jsr _Chunky4Planar				;Convert chunky 4 bit to planar...slowly

	move.l LastRand,d7
	lea NewTable1,a2			;These are pointers to a table who's value
	lea NewTable1+2,a3			;is one greater or less than the index into
								;the table.  Used to brighten and dim fire
								;without the need to check overrunning values
;************************
;** CALCULATE NEW FIRE **
;************************

	moveq.l #0,d4				;ensure bytes are still valid as longs
	lea FireBuffer+1,a0			;since long index registers are faster.
	moveq.l #FireHeight-3,d0	;height-2 and -1 for dbf
FireNextLine:
	moveq.l #FireWidth-3,d1		;width-2 and -1 for dbf
FireNextPixel:

	Random						;leech a random num to d7

	move.b d7,d3
	and.l #3,d3
	bne FireCalc_skip			;values 1-3 are the pixels below and
	move.w #FireWidth+2,d3		;to the left right and middle.  A 0 value
FireCalc_skip:					;is straight down 2 pixels.
	add.w #FireWidth,d3
	lea -2(a0,d3.l),a1			;find pixel offset from current pixel

	move.b (a0),d4				;get the current pixel
	cmp.b (a1),d4				;check versus lower pixel (calc'd above)
	bge FireCalc_noadjust		;if the lower pixel is brighter, continue
	move.b (a3,d4.l),(a0)+		;get the one step brighter value for upper pix
	dbf d1,FireNextPixel		;pixel and loop back
	lea 2(a0),a0				;adjust for next line
	dbf d0,FireNextLine
	bra FireDoneUpdate
FireCalc_noadjust:
	move.b (a2,d4.l),(a0)+		;get the one step darker value for upper pixel
	dbf d1,FireNextPixel		;and loop
	lea 2(a0),a0				;adjusting for next line
	dbf d0,FireNextLine

FireDoneUpdate:

;*****************************
;** ADD HOTSPOTS TO TEXTMAP **
;*****************************

	lea FireBuffer+(FireHeight-50)*FireWidth,a0
	lea pixels,a1

	move.w #300,d0			;200 hotspots would do.
SeedFlames:

	Random

	move.l d7,d6
	and.w andval,d6			;get values into reasonable ranges
	cmp.w maxval,d6			;check if they are too big
	bgt SeedFlames
	moveq.l #0,d5			;d5 preparation for word->long assumption
	move.w d6,d5			;d5=long index to seed value
	swap d6					;get to untouched part of random value
	and.w #$7,d6			;calculate a hot value from 8 to 15
	or.w #$8,d6
	move.w (a1,d5.l),d5		;Find a place to heat
	move.b d6,(a0,d5.l)		;Apply heatvalue to hotspot
	dbf d0,SeedFlames
	move.l d7,LastRand
	rts




HelloWorld:
	ExecLib Forbid
	lea PMPortName,a1
	ExecLib FindPort
	tst.l d0
	beq HW_Fail
	move.l d0,PMPort
	move.l #MN_SIZE,d0
	move.l #$10000,d1
	ExecLib AllocMem
	tst.l d0
	beq HW_Fail
	move.l d0,a1
	move.l PMPort,a0
	move.w #MN_SIZE,MN_LENGTH(a1)
	move.l SigTask,LN_NAME(a1)
	ExecLib PutMsg
HW_Fail:
	ExecLib Permit
	rts

GoodbyeWorld:
	ExecLib Forbid
	lea PMPortName,a1
	ExecLib FindPort
	tst.l d0
	beq GW_Fail
	move.l d0,PMPort
	move.l #MN_SIZE,d0
	move.l #$10000,d1
	ExecLib AllocMem
	tst.l d0
	beq GW_Fail
	move.l d0,a1
	move.l PMPort,a0
	move.w #MN_SIZE,MN_LENGTH(a1)
	move.l #0,LN_NAME(a1)
	ExecLib PutMsg
GW_Fail:
	ExecLib Permit
	rts


	Section MainData,Data
PMPortName:	dc.b 'PowerManagerBlank',0
	CNOP 0,2
PMPort:	dc.l 0

LastRand:	dc.l 0
Graphics:
	dc.l 0
	dc.b 'graphics.library',0
	CNOP 0,2

Intuition:
	dc.l 0
	dc.b 'intuition.library',0
	CNOP 0,2

isBlanked:	dc.w 0
OpenedScreen:	dc.l 0

ScreenTags:
	dc.l	SA_Left,160-(FireWidth/2)
	dc.l	SA_Width,FireWidth
	dc.l	SA_Height,100+FireHeight/2+1
	dc.l	SA_Depth,4
	dc.l	SA_Colors,BlankerColorSpec
	dc.l	SA_Type,CUSTOMSCREEN
	dc.l	SA_ShowTitle,0
	dc.l	SA_Quiet,1
	dc.l	SA_Draggable,0
	dc.l	TAG_END,0

BlankerColorSpec:
	dc.w 0,0,0,0
	dc.w 1,2,0,0
	dc.w 2,4,0,0
	dc.w 3,6,0,0
	dc.w 4,8,0,0
	dc.w 5,10,0,0
	dc.w 6,12,0,0
	dc.w 7,14,2,0
	dc.w 8,15,4,0
	dc.w 9,15,6,0
	dc.w 10,15,8,0
	dc.w 11,15,10,0
	dc.w 12,15,12,0
	dc.w 13,15,13,0
	dc.w 14,15,14,0
	dc.w 15,15,15,0
	dc.w -1

SigNum:	dc.b -1,0

NewTable1:
	dc.b 0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15

	include "wci.i"

	Section FireBSS,BSS
SigTask:	ds.l 1
SigMask:	ds.l 1
FireBuffer:	ds.b FireWidth*FireHeight

	end
