07 January 2023, 01:41 | #1 |
Registered User
Join Date: Sep 2019
Location: Sydney
Posts: 357
|
Enable DOS after system takeover - please check my code.
Hi,
Can someone poke holes in my EnableDOS/DisableDOS routines please? Code is below. I'm doing a system takeover at the start. When I need to load some data, I call EnableDOS, then do my loading, then DisableDOS. It mostly works. I can't get any problems on WinUAE running as a CD32, and my real A1200 had no problems either, but a real CD32 will occasionally hang. Thanks Code:
INCLUDE "registers.i" INCLUDE "cia.i" INCLUDE "exec/execbase.i" AUTOVEC1 EQU $64 STACKSIZE EQU $1000 ; 4K Supervisor EQU -30 ; entry point global_init:: ; store old stackpointer, replace with our stack move.l sp,oldStackPtr lea OurStack+STACKSIZE,sp ; get VBR (Vector Base can be moved on 68010+) jsr getAutoVecBase jsr OpenDosLibrary jsr OpenGraphicsLibrary jsr DisableOS_Graphics ; NOTE: must be called before starting interrupts jsr _InitAll movem.w d0,-(sp) ; save the result of this jsr DisableOS_Remainder jsr _EnableDebugMessage ; retrieve InitAll result movem.w (sp)+,d0 cmp.b #0,d0 if_equal jmp global_exit ; InitAll failed end_if jsr _AllocCopperLists jsr _DisableWarpMode jsr _RunProgram jmp global_exit WaitEndOfFrame:: lea $dff000,a6 ; wait until blitter is finished tst.w (a6) ; for compatibility with A1000 .waitBlitterLoop: btst #6,2(a6) bne.s .waitBlitterLoop jsr CheckNTSC cmp.w #1,d0 if_equal move.w #LAST_SCANLINE_NTSC,d0 else_if move.w #LAST_SCANLINE_PAL,d0 end_if ; Wait for scanline d0. Trashes d1. .waitScanLineLoop: move.l 4(a6),d1 lsr.l #1,d1 lsr.w #7,d1 cmp.w d0,d1 bne.s .waitScanLineLoop ; wait until it matches rts DisableOS_Graphics:: movem.l d0-d7/a0-a6,-(sp) ; forbid task rescheduling ; so that no other task can change graphics modes etc before interrupts get disabled move.l EXECBASE,a6 jsr -132(a6) ; Forbid ; save old view and copper move.l gfxbase,a6 move.l 34(a6),oldView move.l 38(a6),oldCopper ; set null view (important for Amigas with graphic cards) move.l #0,a1 bsr LoadView ; also waits two frames ; take over blitter move.l gfxbase,a6 jsr -456(a6) ; OwnBlitter jsr -228(a6) ; WaitBlit ; set some values in BPLCON0 - not clear on why this is needed, but experienced hang ; on real A1200 hardware without it when running from Workbench and in release builds! move.w #0,BPLCON0 move.w #0,BPLCON1 move.w #0,BPLCON2 move.w #0,BPLCON3 move.w #0,COLOR0 ; set an empty copper list lea.l _gEmptyCopperList,a0 move.l a0,COP1LCH movem.l (sp)+,d0-d7/a0-a6 rts DisableOS_Remainder:: movem.l d0-d7/a0-a6,-(sp) ; store data in hardware registers ORed with $8000 ; (bit 15 is a write-set bit when values are written back into the system) move.w DMACONR,d0 or.w #$8000,d0 move.w d0,oldDMACONR move.w INTENAR,d0 or.w #$8000,d0 move.w d0,oldINTENA move.w INTREQR,d0 or.w #$8000,d0 move.w d0,oldINTREQ move.w ADKCONR,d0 or.w #$8000,d0 move.w d0,oldADKCON bsr StopDmaAndInterruptsAtVBlank ; store old interrupt vectors move.l AutoVecBase,a1 add.w #AUTOVEC1,a1 lea oldVecs,a0 bsr copy6longs ; store cia timer B registers lea CIAA,a0 move.b CIACRB(a0),crb ;store state of control register bclr #0,CIACRB(a0) ;stop the timer nop move.b CIATBLO(a0),tblo ;store the actual timer values move.b CIATBHI(a0),tbhi bclr #3,CIACRB(a0) ;set continuous mode nop bclr #1,CIACRB(a0) ;clear PB operation mode nop bset #4,CIACRB(a0) ;force load latch->timer nop move.b CIATBLO(a0),ltblo ;store latch values move.b CIATBHI(a0),ltbhi ; set up DMA, note we let the audio components enable audio channel DMA as they require it move.w #%0000000000110000,DMACON ; DMA OFF Sprite/Disk move.w #%1000000111000000,DMACON ; DMA ON Blitter/Copper/Bitplane move.w #%1000000000100000,DMACON ; DMA set ON, 5:Sprite DMA enable move.w #%1000001000000000,DMACON ; enable DMAEN (master enable for bits [0,8]) ; Disable interrupts - NOTE: do this before setting display registers move.w #%1100000000000000,INTENA ; IRQ set ON move.w #%0011111111111111,INTENA ; IRQ set OFF ; start vert blank interrupt so we can count how many frames have passed jsr set_vertb_irq ; NOTE: AudioInit must have been called before we call this! ; start our own level 4 interrupt for audio jsr install_lev4_audio_interrupt ; start keyboard interrupts (if not using polling) jsr initKeyboard ; audio filter off move.b $bfe001,d0 ; Fetch CIAA PRA and.b #$2,d0 or.b #$2,d0 move.b d0,$bfe001 ; Disable audio filter ; Install a CIA-B interrupt for ptplayer/tfmx jsr install_level6_cia_interrupt ; start mixer jsr mixer_init movem.l (sp)+,d0-d7/a0-a6 rts EnableOS:: movem.l d0-d7/a0-a6,-(sp) WAIT_BLITTER bsr StopDmaAndInterruptsAtVBlank ; stop mixer jsr mixer_shutdown ; shut down ptplayer/tfmx interrupt jsr clear_level6_cia_interrupt ; stop keyboard interrupt jsr exitKeyboard ; stop audio interrupt jsr clear_lev4_audio_interrupt ; stop vertical blank interrupt jsr clr_vertb_irq ; restore interrupt vectors lea oldVecs,a1 move.l AutoVecBase,a0 add.w #AUTOVEC1,a0 bsr copy6longs ; restore hardware registers move.w #$7fff,DMACON move.w oldDMACONR,DMACON move.w #$7fff,INTENA move.w oldINTENA,INTENA move.w #$7fff,INTREQ move.w oldINTREQ,INTREQ move.w #$7fff,ADKCON move.w oldADKCON,ADKCON ; restore cia timer b lea CIAA,a0 clr.b CIACRB(a0) ;clear all CR values nop move.b tblo,CIATBLO(a0) ;set latch to original timer value move.b tbhi,CIATBHI(a0) nop bset #4,CIACRB(a0) ;move latch->timer nop move.b ltblo,CIATBLO(a0) ;set latch to original latch value move.b ltbhi,CIATBHI(a0) nop move.b crb,CIACRB(a0) ;restore the timer's work move.b #$8f,CIAICR(a0) ;enable CIA-A interrupts for AmigaOS ; load old view move.l oldView,a1 bsr LoadView move.l gfxbase,a6 jsr -228(a6) ; WaitBlit : wait for Blitter to finish running task (if any) move.l gfxbase,a6 jsr -462(a6) ; DisownBlitter : release Blitter to system ; Permit task rescheduling move.l EXECBASE,a6 jsr -138(a6) ; Permit (Undo the Forbid call) movem.l (sp)+,d0-d7/a0-a6 rts DisableDOS:: movem.l d0-d7/a0-a6,-(sp) ; forbid task rescheduling ; so that no other task can change graphics modes etc before interrupts get disabled move.l EXECBASE,a6 jsr -132(a6) ; Forbid ; save old view and copper ;move.l gfxbase,a6 ;move.l 34(a6),oldView ;move.l 38(a6),oldCopper ; set null view (important for Amigas with graphic cards) ;move.l #0,a1 ;jsr LoadView ; also waits two frames ; take over blitter move.l gfxbase,a6 jsr -456(a6) ; OwnBlitter jsr -228(a6) ; WaitBlit move.w INTENAR,d0 or.w #$8000,d0 move.w d0,oldINTENA move.w INTREQR,d0 or.w #$8000,d0 move.w d0,oldINTREQ move.w ADKCONR,d0 or.w #$8000,d0 move.w d0,oldADKCON bsr StopInterruptsAtVBlank ; store old interrupt vectors move.l AutoVecBase,a1 add.w #AUTOVEC1,a1 lea oldVecs,a0 bsr copy6longs ; store cia timer B registers lea CIAA,a0 move.b CIACRB(a0),crb ;store state of control register bclr #0,CIACRB(a0) ;stop the timer nop move.b CIATBLO(a0),tblo ;store the actual timer values move.b CIATBHI(a0),tbhi bclr #3,CIACRB(a0) ;set continuous mode nop bclr #1,CIACRB(a0) ;clear PB operation mode nop bset #4,CIACRB(a0) ;force load latch->timer nop move.b CIATBLO(a0),ltblo ;store latch values move.b CIATBHI(a0),ltbhi move.w #%0000000000010000,DMACON ; DMA OFF Disk ; Disable interrupts - NOTE: do this before setting display registers move.w #%1100000000000000,INTENA ; IRQ set ON move.w #%0011111111111111,INTENA ; IRQ set OFF ; start vert blank interrupt so we can count how many frames have passed jsr set_vertb_irq ; start our own level 4 interrupt for audio jsr install_lev4_audio_interrupt ; start keyboard interrupts (if not using polling) jsr initKeyboard ; audio filter off move.b $bfe001,d0 ; Fetch CIAA PRA and.b #$2,d0 or.b #$2,d0 move.b d0,$bfe001 ; Disable audio filter ; Install a CIA-B interrupt for ptplayer/tfmx jsr install_level6_cia_interrupt ; start mixer jsr mixer_init movem.l (sp)+,d0-d7/a0-a6 rts EnableDOS:: movem.l d0-d7/a0-a6,-(sp) WAIT_BLITTER bsr StopInterruptsAtVBlank ; stop mixer jsr mixer_shutdown ; shut down ptplayer/tfmx interrupt jsr clear_level6_cia_interrupt ; stop keyboard interrupt jsr exitKeyboard ; stop audio interrupt jsr clear_lev4_audio_interrupt ; stop vertical blank interrupt jsr clr_vertb_irq ; restore interrupt vectors lea oldVecs,a1 move.l AutoVecBase,a0 add.w #AUTOVEC1,a0 bsr copy6longs move.w #%1000000000010000,DMACON ; DMA ON Disk ; restore hardware registers move.w #$7fff,INTENA move.w oldINTENA,INTENA move.w #$7fff,INTREQ move.w oldINTREQ,INTREQ move.w #$7fff,ADKCON move.w oldADKCON,ADKCON ; restore cia timer b lea CIAA,a0 clr.b CIACRB(a0) ;clear all CR values nop move.b tblo,CIATBLO(a0) ;set latch to original timer value move.b tbhi,CIATBHI(a0) nop bset #4,CIACRB(a0) ;move latch->timer nop move.b ltblo,CIATBLO(a0) ;set latch to original latch value move.b ltbhi,CIATBHI(a0) nop move.b crb,CIACRB(a0) ;restore the timer's work move.b #$8f,CIAICR(a0) ;enable CIA-A interrupts for AmigaOS move.l gfxbase,a6 jsr -228(a6) ; WaitBlit : wait for Blitter to finish running task (if any) move.l gfxbase,a6 jsr -462(a6) ; DisownBlitter : release Blitter to system ; Permit task rescheduling move.l EXECBASE,a6 jsr -138(a6) ; Permit (Undo the Forbid call) movem.l (sp)+,d0-d7/a0-a6 rts ;----------------------------------------------------------------------------- ; a1 - view LoadView: move.l gfxbase,a6 jsr -222(a6) ; gfx LoadView(view) - Use a (possibly freshly created) coprocessor instruction list to create the current display. jsr WaitEndOfFrame ; NOTE: using this instead of WaitTOF because WaitTOF can undo the Forbid call jsr WaitEndOfFrame rts OpenGraphicsLibrary: ; open graphics.library move.l EXECBASE,a6 move.l #gfxname,a1 moveq #0,d0 jsr OpenLib(a6) move.l d0,gfxbase rts OpenDosLibrary: ; open dos.library move.l EXECBASE,a6 move.l #dosname,a1 moveq #0,d0 jsr OpenLib(a6) move.l d0,dosbase rts CloseGraphicsLibrary: move.l gfxbase,a1 ;library base move.l EXECBASE,a6 ;exec base jsr CloseLib(a6) ;exec CloseLibrary rts CloseDosLibrary: move.l dosbase,a1 ;library base move.l EXECBASE,a6 ;exec base jsr CloseLib(a6) ;exec CloseLibrary rts StopDmaAndInterruptsAtVBlank: jsr WaitEndOfFrame move.w #$7fff,d0 ; bits set to disable everything move.w d0,DMACON ; dma off move.w d0,INTENA ; disable interrupts move.w d0,INTREQ ; clear pending interrupts move.w d0,INTREQ ; twice for A4000 rts StopInterruptsAtVBlank: jsr WaitEndOfFrame move.w #$7fff,d0 ; bits set to disable everything move.w d0,INTENA ; disable interrupts move.w d0,INTREQ ; clear pending interrupts move.w d0,INTREQ ; twice for A4000 rts global_exit:: jsr _ShutDownAll jsr _FreeCopperLists jsr EnableOS ; restore copper move.l oldCopper,COP1LCH jsr CloseGraphicsLibrary jsr CloseDosLibrary movea.l oldStackPtr,sp ; restore stack pointer move.l #0,d0 ; set return code ; end program rts ;--------------------------------------------------------------------------- copy6longs: moveq #6-1,d1 .1: move.l (a1)+,(a0)+ dbf d1,.1 rts ; DATA Section __MERGED,BSS CNOP 0,4 oldVecs: ds.l 6 OurStack: ds.b STACKSIZE CPUtype: ds.b 1 crb: ds.b 1 tblo: ds.b 1 tbhi: ds.b 1 ltblo: ds.b 1 ltbhi: ds.b 1 ds.b 3 Section __MERGED,DATA CNOP 0,4 oldView: dc.l 0 oldCopper: dc.l 0 gfxbase: dc.l 0 dosbase:: dc.l 0 oldStackPtr: dc.l 0 AutoVecBase:: dc.l 0 ; This location holds a pointer to the interrupt auto vector base address (0 for 68000, read from VBR register for 68010+). CNOP 0,4 oldDMACONR: dc.w 0 oldINTREQ: dc.w 0 oldINTENA: dc.w 0 oldADKCON: dc.w 0 CNOP 0,4 gfxname: dc.b 'graphics.library',0 dosname: dc.b "dos.library",0 Section __MERGED,Data_c CNOP 0,4 _gEmptyCopperList:: dc.l $ffffffe |
07 January 2023, 02:15 | #2 |
Registered User
Join Date: Jan 2014
Location: Belgrade / Serbia
Age: 41
Posts: 999
|
Sorry to hijack this one too especially cause I dont know asm.
But could it be that you just need longer wait times for cd to finish activities? |
07 January 2023, 06:10 | #3 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,039
|
I think something similar had been asked not so long ago. Let me see...
http://eab.abime.net/showthread.php?t=105784 Since you are using a lvl2 keyboard interrpt, it looks like it could be the same problem. Also... 1. When you installing an empty copper list, and clearing all the control registers. A 0 is actually not a default value for some of those: $0c00 => $dff106 (con3, default colortable offset for bpls is 8) $0011 => $dff00c (con4, default colortable offset for sprites is 16) And set fetch mode to 0: $0000 => $dff01fc 2. audio filter off Was that meant to be and #~2 with or #2? I remember doing a simple bset #1 back in the day to take care or that. 3. StopDmaAndInterruptsAtVBlank I'd hit INTENA first, in case you get an interrupt right between DMACON and INTENA. |
07 January 2023, 13:30 | #4 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,161
|
are you aware that cd32 ciab sometimes issues a level 6 interrupt which is not emulated by winuae? that caused most John Twiddy's games to fail until properly patched.
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
System takeover crashes in some cases | sparhawk | Coders. Asm / Hardware | 26 | 31 January 2020 02:43 |
System takeover and multi floppy mess | ross | Coders. General | 8 | 15 September 2018 20:01 |
System takeover/shutdown | alpine9000 | Coders. Asm / Hardware | 5 | 07 June 2016 09:03 |
trackdisk.device after system takeover | alpine9000 | Coders. Asm / Hardware | 20 | 21 March 2016 09:17 |
startup/system takeover | sidewinder | Coders. General | 15 | 28 February 2016 16:33 |
|
|