14 January 2021, 11:11 | #1 |
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 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 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 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) 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) 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 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 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 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. |
14 January 2021, 11:41 | #2 |
Defendit numerus
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! |
14 January 2021, 12:00 | #3 |
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) |
14 January 2021, 12:39 | #4 |
Defendit numerus
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 |
14 January 2021, 13:06 | #5 |
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.
|
14 January 2021, 13:25 | #6 |
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. |
14 January 2021, 14:36 | #7 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
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. |
|
14 January 2021, 15:15 | #8 |
Defendit numerus
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 |
14 January 2021, 17:22 | #9 |
OCS forever!
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. |
14 January 2021, 17:57 | #10 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
Code:
jsr (_LVOWaitTOF,a6) movea.l (gb_copinit,a6),a2 ; move.l (a2),d7 ; save somewhere move.l #$00960200,(a2) jsr (_LVOWaitTOF,a6) |
|
14 January 2021, 18:09 | #11 |
OCS forever!
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
|
14 January 2021, 18:20 | #12 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
|
14 January 2021, 19:34 | #13 |
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 |
14 January 2021, 19:41 | #14 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
http://eab.abime.net/showpost.php?p=1453858&postcount=8 How did it happen, a space-time shift? |
|
14 January 2021, 20:39 | #15 | |
Registered User
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
|
Quote:
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 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) 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 |
|
14 January 2021, 20:57 | #16 | ||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
Quote:
|
||
14 January 2021, 22:41 | #17 |
Registered User
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
|
Have dropped you a PM ross.
|
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 |
|
|