English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 14 January 2021, 11:11   #1
mcgeezer
Registered User
 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
Correct order for system shutdown and startup

In my project I'm trying to put the OS to sleep and wake it back up again, I largely have it working but I'm finding I have stability issues once the system has woke back up again.

Can someone give me a hand and tell me what the correct order is for system shutdown and startup please?

Here's what I'm currently doing.

ALLOCATE RAM
(lots of _LVOAlloc)


SAVE_SYSTEM_STATE

Code:
	lea	$dff000,a5
	move.w	DMACONR(a5),sysDMACON		
	or.w	#$8000,sysDMACON
	move.w	INTENAR(a5),sysINTENA
	or.w	#$8000,sysINTENA	
	move.w	INTREQR(a5),sysINTREQ
	or.w	#$8000,sysINTREQ
	move.w	ADKCONR(a5),sysADKCON
	or.w	#$8000,sysADKCON

SAVE_COPPER
Code:
	move.l	a6,-(a7)
	move.l	ExecBase,a6
	lea	GFXNAME(pc),a1
	moveq	#0,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,GFXBASE
	move.l	d0,a6
	move.l	34(a6),sysView
	move.l	$26(a6),sysCopper1
	move.l	$32(a6),sysCopper2
	sub.l	a1,a1
	IFEQ	ENABLE_DEBUG
	jsr	_LVOLoadView(a6)
	jsr	_LVOWaitTOF(a6)
	jsr	_LVOWaitTOF(a6)
	ENDC
	move.l	(a7)+,a6

DISABLE_OS
Code:
	;move.l	$4,a6
	;jsr	FORBID(a6)	; FORBID	
	        
	move.l	a6,-(a7)
	move.l  ExecBase,a6
        sub.l   a1,a1            ; Zero - Find current task
        jsr     _LVOFindTask(a6)

        move.l  d0,a1
        moveq   #127,d0		 ; task priority to very high...
        jsr     _LVOSetTaskPri(a6)
	move.l	(a7)+,a6
INIT_DMA
Code:
lea	$dff000,a5
	IFEQ	ENABLE_DEBUG
	move.w	#$7fff,DMACON(a5)		;in DMACON,
	move.w	#$7fff,INTENA(a5)		;INTENA,
	move.w	#$7fff,INTREQ(a5)		;and INTREQ
	move.w	#$7fff,INTREQ(a5)		;twice 
	ENDC
INSTALL INTERUPTS
Code:
InstallInterupts:
	tst.w	INT3_INSTALLED(a6)
	bmi	.exit
	move.w	#-1,INT3_INSTALLED(a6)
	
	move.l	a6,-(a7)
	move.l	a5,-(a7)

; Get the VB Base
	lea	getvbr(pc),a5 
	move.l	ExecBase,a6
	jsr	_LVOSupervisor(a6)			; returns vbr in d0 
	lea	vbroffset(a6),a0 
	move.l	d0,(a0)			
	move.l	d0,a0					; VB Base in a0
 
	lea 	Level3IntHandler(pc),a1 
	move.l	intVectorLevel3(a0),saveLevel3
	move.l	a1,intVectorLevel3(a0)
	lea 	Level2IntHandler(pc),a1 
	move.l	intVectorLevel2(a0),saveLevel2
	move.l	a1,intVectorLevel2(a0)
	
	lea 	CIAA,a1	
	move.b	#CIAICRF_SETCLR!CIAICRF_SP,ciaicr(a1); Interrupt control register 
;clear all ciaa-interrupts
	tst.b	ciaicr(a1)
;set input mode
	and.b	#~(CIACRAF_SPMODE),ciacra(a1)		; 

	move.l	(a7)+,a5
	move.l	(a7)+,a6
.exit	rts
Code:
INSTALL AUDIO PLAYER
; Initialise Music / SFX routines
	tst.w	AUDIO_INSTALLED(a6)
	bmi	.exit
	move.w	#-1,AUDIO_INSTALLED(a6)
	move.l	a6,-(a7)	
	move.l	vbroffset(a6),a0	
	lea	CHIPBASE,a6		
	moveq	#0,d0			 
	bsr	_mt_install_cia
	clr.b	_mt_Enable
	moveq	#0,d0
	bsr	_mt_musicmask
	move.l	(a7)+,a6
... game code...

REMOVE AUDIO PLAYER
Code:
	clr.b	_mt_Enable
	move.l	a6,-(a7)
	lea	CHIPBASE,a6
	bsr	_mt_remove_cia
	move.l	(a7)+,a6
	clr.w	AUDIO_INSTALLED(a6)
RESTORE INTERUPTS
Code:
	move.l	a6,-(a7)
	move.l	a5,-(a7)
;--- get the vbr which is most probably somewhere in fast-ram 
	lea	getvbr(pc),a5 
	move.l	ExecBase,a6
	jsr	_LVOSupervisor(a6)			; returns vbr in d0 
	move.l	d0,a0

;--- register our own level 3 interrupt (vertical blanc and blitter) 
	move.l	saveLevel3,intVectorLevel3(a0)
	move.l	saveLevel2,intVectorLevel2(a0)	
	
	move.l	(a7)+,a5
	move.l	(a7)+,a6
	clr.w	INT3_INSTALLED(a6)
RESTORE SYSTEM STATE
Code:
	IFEQ	ENABLE_DEBUG
	lea	$dff000,a5
	move.w	sysDMACON,DMACON(a5)		
	move.w	sysINTENA,INTENA(a5)		
	move.w	sysINTREQ,INTREQ(a5)		
	move.w	sysINTREQ,INTREQ(a5)	
	move.w	sysADKCON,ADKCONR(a5)
	ENDC
RESTORE_COPPER
Code:
	move.l	a6,-(a7)
	move.l	ExecBase,a6
	lea	GFXNAME(pc),a1
	moveq	#0,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,GFXBASE
	move.l	d0,a6
	move.l	34(a6),sysView
	move.l	$26(a6),sysCopper1
	move.l	$32(a6),sysCopper2
	sub.l	a1,a1
	IFEQ	ENABLE_DEBUG
	jsr	_LVOLoadView(a6)
	jsr	_LVOWaitTOF(a6)
	jsr	_LVOWaitTOF(a6)
	ENDC
	move.l	(a7)+,a6
FREE RAM

INIT_PERMIT_OS
Code:
	IFEQ	ENABLE_DEBUG
	lea	$dff000,a5	
	;bsr	WaitEOF				
	move.l	a6,-(a7)
	move.l	ExecBase,a6
	jsr	_LVOPermit(a6)			
	move.l	(a7)+,a6
	ENDC
EXIT GAME


Like I said, it largely works, if the order I'm doing things is correct then it's likely I have a memory leak somewhere in the game but I've done a lot of work in that area as I can run through over 100 tracks without the game completely stable which makes me think I'm doing something wrong in the startup/shutdown.

Also note, this code largely came from my work on Bomb Jack - I'm unsure why I don't call Forbid() but do call Permit, I'm pretty sure I saw a recommendation for that somewhere about setting the task priority instead.

Any help appreciated,
Graeme

Edit: Sorry I've already seen what I think are a couple of mistakes I will retest, if I could delete the thread then I would but I can't seem to be able to do that.

Last edited by mcgeezer; 14 January 2021 at 11:28.
mcgeezer is offline  
Old 14 January 2021, 11:41   #2
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Hi Graeme, only a few hints, I looked at it very quickly.

- your code lack a _OwnBlitter call.
- what's the point in raising the task priority? If you completely disable system IRQs there is no reason to do so, I think.
- no reason to clear twice INTREQ on setup
- be sure to use the new copper pointer and reactivate the DMAs immediately after a wait for the VB

Cheers!
ross is offline  
Old 14 January 2021, 12:00   #3
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,502
It is not a good idea to save custom register contents when system interrupts are enabled.

Better order in my opinion:

- Forbid() first. (Prevents other tasks from modifying system state during loadview stuff)

- LoadView stuff. Interrupts should be enabled at this point, some RTG boards might need working vblank interrupt.

- OwnBlitter/WaitBlitter (things can get nasty if blitter was active when you disable DMA. Blitter will continue immediately when you re-enable DMA later.. Yes, these are extremely rare edge case but they can still happen)

- Disable()

- Save custom registers (now it is guaranteed nothing else can change them behind your back, like some expansion hardware interrupt)

- Disable DMA/interrupts

and restore in opposite order.

I'd also recommend not to call any OS routine after system has been taken over, including Supervisor(). (Yes, it most likely works but still)
Toni Wilen is online now  
Old 14 January 2021, 12:39   #4
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
I don't remember the exact reason anymore, and maybe I talked about it in another thread somewhere, my sequence is identical to what Toni indicated but with a small difference, which I probably found out as an extreme case in a situation.

I call the OwnBlitter before the Forbid:
- OwnBlitter()/WaitBlitter()
- Forbid()
- LoadView stuff
- hw_WaitBlitter

I can only assume that I did because some programs may still have an incomplete blitter queue, with register settings maintained between BLTSIZE calls (and therefore your future blitter registers modification would lead to unexpected results at system recovery). This way this edge case task have the opportunity to complete the queue.

[I don't remember if Forbid () followed by OwnBlitter () puts the active task to sleep in any case and restart the scheduler and therefore it would work even in the case indicated by Toni.]

Your task then wakes up from sleep, own the blitter and then freezes the scheduler.
The second hw_WaitBlitter is for those programs that are actually not calling OwnBlitter/WaitBlitter (there are extreme cases of simultaneous execution that in fact hardly happens..) Furthermore, the double wait of the LoadView should be enough to have any completed operation of the blitter, but hey extra secutity

Ah!, and I've even startups blocking the floppy motor, just in case you start it from there
ross is offline  
Old 14 January 2021, 13:06   #5
mcgeezer
Registered User
 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
Thank you ever so much for the tips gentelmen, I'll implement them asap and see if I get better stability after the game exits.
mcgeezer is offline  
Old 14 January 2021, 13:25   #6
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
To be fair, I usually just use Photon's startup code. It seems to work very well to me. AFAIK it does things in a similar way to how Toni/Ross do it. Although it doesn't actually allocate memory. I've personally always done that after the IRQ's are already disabled (you can still use several OS functions at that time, memory allocation being one of them).

I also seem to recall reading there could be a need to either do LoadView() twice, or to do two full vblank waits on either shutdown or restore somewhere on this forum, but I can't remember where. I do recall it was intended to fix some issues with Amiga's that had RTG graphics cards installed.
roondar is online now  
Old 14 January 2021, 14:36   #7
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by roondar View Post
I also seem to recall reading there could be a need to either do LoadView() twice, ..
It's usually because of interlace mode.

WaitTOF() do it per field and not per frame.

---

Forgotten in previous messages.

There is also the whole question of WB message handling that should be considered in the case.
ross is offline  
Old 14 January 2021, 15:15   #8
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Just to be very picky you could also avoid the "first frame glitch" (LoadView() do not internally call WaitTOF so you could end with a partial view and custom_registers changes in the middle of a frame, meaning some visible glitches for a flash).

This is what I happened to use:
Code:
		; a3 custom_base, a5 exec_base, a6 gfx_base

		jsr	(_LVOOwnBlitter,a6)
		jsr	(_LVOWaitBlit,a6)
		exg	a5,a6
		jsr	(_LVOForbid,a6)
		exg	a5,a6
		jsr	(_LVODisownBlitter,a6)	; OwnBlitter is task based
		jsr	(_LVOWaitTOF,a6)
		movea.l	(gb_copinit,a6),a2
;		move.l	(a2),d7			; save somewhere
		move.l	#$00960200,(a2)
		jsr	(_LVOWaitTOF,a6)
		moveq	#-2,d0
		move.l	d0,(a2)
		suba.l	a1,a1
		move.w	a1,($180,a3)		; black
;		move.l	(gb_Actiview,a6),d6	; save somewhere
		jsr	(_LVOLoadView,a6)
		jsr	(_LVOWaitTOF,a6)	; change safely copperptr and reactivate DMA
ross is offline  
Old 14 January 2021, 17:22   #9
Antiriad_UK
OCS forever!
 
Antiriad_UK's Avatar
 
Join Date: Mar 2019
Location: Birmingham, UK
Posts: 418
Mine is similar, as expected as it's a combo of my 90s code, Photon, Stingray, Kalms code where I dug into why/how and picked what I liked. I tested in a lot of configs for last intro

The only additional thing where I had issues where generally with sprites. In one case the system IRQ was taking too long and _LVOWaitTOF returns _after_ vblank processing so in some cases you could still get sprite corruption with LVOWaitTOF followed by turning off DMA. My solution to that was to disable IRQs first, then my own HW WaitTOF then disable DMA.

The other issue I had was that I had sprite DMA flags in my copper list. My default "framework" copper list has a sprite disable operation at the start. On restoring the OS on certain super fast/slow machines I was having a race condition where I was enabling DMA (which would include mouse pointer sprite) then restoring the system CL. But in rare cases my custom CL was executing in between turning on the DMA and restoring system copper so then the sprite got disabled again. My solution was to install a dummy "$ffff,$fffe" CL during system restore. I'll have to revisit that because now I'm thinking why didn't I just restore the system CL first

Last edited by Antiriad_UK; 14 January 2021 at 17:27.
Antiriad_UK is offline  
Old 14 January 2021, 17:57   #10
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Antiriad_UK View Post
The only additional thing where I had issues where generally with sprites. In one case the system IRQ was taking too long and _LVOWaitTOF returns _after_ vblank processing so in some cases you could still get sprite corruption with LVOWaitTOF followed by turning off DMA. My solution to that was to disable IRQs first, then my own HW WaitTOF then disable DMA.
Or, without IRQs disabling, what my piece of code do here :
Code:
		jsr	(_LVOWaitTOF,a6)
		movea.l	(gb_copinit,a6),a2
;		move.l	(a2),d7			; save somewhere
		move.l	#$00960200,(a2)
		jsr	(_LVOWaitTOF,a6)
Then you simply clean sprite registers (even with the CPU).
ross is offline  
Old 14 January 2021, 18:09   #11
Antiriad_UK
OCS forever!
 
Antiriad_UK's Avatar
 
Join Date: Mar 2019
Location: Birmingham, UK
Posts: 418
Is that overwriting the first command in the system CL? Ok that's too far for me haha
Antiriad_UK is offline  
Old 14 January 2021, 18:20   #12
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Antiriad_UK View Post
Is that overwriting the first command in the system CL? Ok that's too far for me haha
Yes, it does it.

But copinit is unique and irremovable and before exiting I fix everything
ross is offline  
Old 14 January 2021, 19:34   #13
mcgeezer
Registered User
 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
OK, I think I know now why the game is crashing on exit.

If I do anything with BEAMCON0 it crashes it, it's a write only register so I'm guess there is some OS way I can put the Amiga into NTSC mode?

Cheers,
Graeme
mcgeezer is offline  
Old 14 January 2021, 19:41   #14
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by mcgeezer View Post
OK, I think I know now why the game is crashing on exit.

If I do anything with BEAMCON0 it crashes it, it's a write only register so I'm guess there is some OS way I can put the Amiga into NTSC mode?

Cheers,
Graeme
ehehe, some mod need to fix this :
http://eab.abime.net/showpost.php?p=1453858&postcount=8

How did it happen, a space-time shift?
ross is offline  
Old 14 January 2021, 20:39   #15
mcgeezer
Registered User
 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
Quote:
Originally Posted by ross View Post
ehehe, some mod need to fix this :
http://eab.abime.net/showpost.php?p=1453858&postcount=8

How did it happen, a space-time shift?
Sorry I posted in the wrong thread.

So, if I do this I don't get a crash:

Code:
	move.w	#0,BEAMCON0(a5)

move.l	a6,-(a7)	
	move.l	GFXBASE,a6
	IFEQ	ENABLE_DEBUG
	jsr	_LVOWaitTOF(a6)
	move.l	gb_ActiView(a6),sysView
	move.l	gb_copinit(a6),sysCopper1
	sub.l	a1,a1
	jsr	_LVOLoadView(a6)
	jsr	_LVOWaitTOF(a6)
	ENDC
	move.l	(a7)+,a6
And if I do this I get a crash.

Code:
move.l	a6,-(a7)	
	move.l	GFXBASE,a6
	IFEQ	ENABLE_DEBUG
	jsr	_LVOWaitTOF(a6)
	move.l	gb_ActiView(a6),sysView
	move.l	gb_copinit(a6),sysCopper1
	sub.l	a1,a1
	jsr	_LVOLoadView(a6)
	jsr	_LVOWaitTOF(a6)
	ENDC
	move.l	(a7)+,a6

	move.w	#0,BEAMCON0(a5)
So while I have a solution now I don't think I fully understand the PAL/NTSC configuration.

From recollection, PAL Amiga's can run in both PAL and NTSC mode, NTSC mode offering 60hz refresh. NTSC mode is what I want the game to run in so do I simply need to work out what mode the Amiga is in, write 0 to bit 5 of BEAMCON and then prior to exiting to Workbench set the mode back.

As I can't read BEAMCON I guess I can count how many scanlines there are and determine the mode that way?

Cheers,
Graeme
mcgeezer is offline  
Old 14 January 2021, 20:57   #16
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by mcgeezer View Post
So, if I do this I don't get a crash:
---
And if I do this I get a crash.
--
I think the problem lies elsewhere, from those code snippets I can't understand.

Quote:
As I can't read BEAMCON I guess I can count how many scanlines there are and determine the mode that way?
Yes, this is what I usually do to differentiate which video mode I am in, but I do it for a completely different reason: to adapt the copper list that I am going to use.
ross is offline  
Old 14 January 2021, 22:41   #17
mcgeezer
Registered User
 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
Have dropped you a PM ross.

mcgeezer is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Startup code, taking over the system deimos Coders. General 12 05 October 2019 09:13
Problems with startup, setting correct interrupts and protracker cia fstarred Coders. Asm / Hardware 12 22 June 2018 09:19
System takeover/shutdown alpine9000 Coders. Asm / Hardware 5 07 June 2016 09:03
startup/system takeover sidewinder Coders. General 15 28 February 2016 16:33
Order software from DiscreetFX in Aug and Sept 2004 and get a free SGI system! Pyromania MarketPlace 0 25 August 2004 15:26

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 11:13.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.09520 seconds with 13 queries