English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 07 January 2023, 01:41   #1
Muzza
Registered User
 
Muzza's Avatar
 
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
Muzza is offline  
Old 07 January 2023, 02:15   #2
Cobe
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?
Cobe is offline  
Old 07 January 2023, 06:10   #3
a/b
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.
a/b is offline  
Old 07 January 2023, 13:30   #4
jotd
This cat is no more
 
jotd's Avatar
 
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.
jotd is online now  
 


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

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 22:42.

Top

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