diff -ru a/src/cpu/newcpu.c b/src/cpu/newcpu.c
--- a/src/cpu/newcpu.c	2022-10-27 19:55:10.000000000 +0200
+++ b/src/cpu/newcpu.c	2022-10-27 19:48:25.000000000 +0200
@@ -6058,7 +6058,7 @@
 	set_special(SPCFLAG_CHECK);
 #else
 	write_log (_T("CPU halted: reason = %d PC=%08x\n"), id, M68K_GETPC);
-	if (!DlgAlert_Query("Fatal error: CPU halted!\n\nPress OK to restart CPU or cancel to quit."))
+//	if (!DlgAlert_Query("Fatal error: CPU halted!\n\nPress OK to restart CPU or cancel to quit."))
 		set_special(SPCFLAG_BRK);
 #endif
 }
diff -ru a/src/debug/debugInfo.c b/src/debug/debugInfo.c
--- a/src/debug/debugInfo.c	2022-10-02 12:11:52.000000000 +0200
+++ b/src/debug/debugInfo.c	2022-10-26 12:43:41.000000000 +0200
@@ -34,7 +34,6 @@
  * DebugInfo_Rtc : display the Videl registers values.
  */
 static void DebugInfo_Rtc(uint32_t dummy) {
-    Update_StatusBar();
 	fprintf(stdout,"%s",get_rtc_ram_info());
 }
 
diff -ru a/src/fast_screen.c b/src/fast_screen.c
--- a/src/fast_screen.c	2022-10-25 23:36:39.000000000 +0200
+++ b/src/fast_screen.c	2022-10-27 19:32:00.000000000 +0200
@@ -49,8 +49,6 @@
 static SDL_Rect      saveWindowBounds; /* Window bounds before going fullscreen. Used to restore window size & position. */
 static MONITORTYPE   saveMonitorType;  /* Save monitor type to restore on return from fullscreen */
 static void*         uiBuffer;         /* uiBuffer used for ui texture */
-static void*         uiBufferTmp;      /* Temporary uiBuffer used by repainter */
-static SDL_SpinLock  uiBufferLock;     /* Lock for concurrent access to UI buffer between m68k thread and repainter */
 static uint32_t      mask;             /* green screen mask for transparent UI areas */
 static volatile bool doRepaint = true; /* Repaint thread runs while true */
 static SDL_Rect      statusBar;
@@ -208,97 +206,34 @@
  Loop: Blits the NeXT framebuffer to the fbTexture, blends with the GUI surface and
  shows it.
  */
-static int repainter(void* unused) {
-    SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
-    
-    SDL_Texture*  uiTexture;
-    SDL_Texture*  fbTexture;
-    
-    uint32_t r, g, b, a;
-    
-    SDL_RenderSetLogicalSize(sdlRenderer, width, height);
-    
-    uiTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
-    SDL_SetTextureBlendMode(uiTexture, SDL_BLENDMODE_BLEND);
-    
-    fbTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
-    SDL_SetTextureBlendMode(fbTexture, SDL_BLENDMODE_NONE);
-    
-    uint32_t format;
-    int      d;
-    SDL_QueryTexture(uiTexture, &format, &d, &d, &d);
-    SDL_PixelFormatEnumToMasks(format, &d, &r, &g, &b, &a);
-    mask = g | a;
-    sdlscrn     = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, r, g, b, a);
-    uiBuffer    = malloc(sdlscrn->h * sdlscrn->pitch);
-    uiBufferTmp = malloc(sdlscrn->h * sdlscrn->pitch);
-    // clear UI with mask
-    SDL_FillRect(sdlscrn, NULL, mask);
-    
-    /* Exit if we can not open a screen */
-    if (!sdlscrn) {
-        fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
-        SDL_Quit();
-        exit(-2);
-    }
-    
-    Statusbar_Init(sdlscrn);
-    
-    /* Setup lookup tables */
-    SDL_PixelFormat* pformat = SDL_AllocFormat(format);
-    /* initialize BW lookup table */
-    for(int i = 0; i < 0x100; i++) {
-        BW2RGB[i*4+0] = bw2rgb(pformat, i>>6);
-        BW2RGB[i*4+1] = bw2rgb(pformat, i>>4);
-        BW2RGB[i*4+2] = bw2rgb(pformat, i>>2);
-        BW2RGB[i*4+3] = bw2rgb(pformat, i>>0);
-    }
-    /* initialize color lookup table */
-    for(int i = 0; i < 0x10000; i++)
-        COL2RGB[SDL_BYTEORDER == SDL_BIG_ENDIAN ? i : SDL_Swap16(i)] = col2rgb(pformat, i);
-    
-    /* Initialization done -> signal */
-    SDL_SemPost(initLatch);
-    
-    /* Start with framebuffer blit enabled */
-    SDL_AtomicSet(&blitFB, 1);
-    
-    /* Enter repaint loop */
-    while(doRepaint) {
-        bool updateFB = false;
-        bool updateUI = false;
-        
-        if (SDL_AtomicGet(&blitFB)) {
-            // Blit the NeXT framebuffer to texture
-            updateFB = blitScreen(fbTexture);
-        }
-        
-        // Copy UI surface to texture
-        SDL_AtomicLock(&uiBufferLock);
-        if(SDL_AtomicSet(&blitUI, 0)) {
-            // update full UI texture
-            memcpy(uiBufferTmp, uiBuffer, sdlscrn->h * sdlscrn->pitch);
-            updateUI = true;
-        }
-        SDL_AtomicUnlock(&uiBufferLock);
-        
-        if(updateUI) {
-            SDL_UpdateTexture(uiTexture, NULL, uiBufferTmp, sdlscrn->pitch);
-        }
-        
-        // Update and render UI texture
-        if (updateFB || updateUI) {
-            SDL_RenderClear(sdlRenderer);
-            // Render NeXT framebuffer texture
-            SDL_RenderCopy(sdlRenderer, fbTexture, NULL, &screenRect);
-            SDL_RenderCopy(sdlRenderer, uiTexture, NULL, &screenRect);
-            // SDL_RenderPresent sleeps until next VSYNC because of SDL_RENDERER_PRESENTVSYNC in ScreenInit
-            SDL_RenderPresent(sdlRenderer);
-        } else {
-            host_sleep_ms(10);
-        }
-    }
-    return 0;
+SDL_Texture*  uiTexture;
+SDL_Texture*  fbTexture;
+
+void Screen_Update(void) {
+	bool updateFB = false;
+	
+	if (SDL_AtomicGet(&blitFB)) {
+		// Blit the NeXT framebuffer to texture
+		updateFB = blitScreen(fbTexture);
+	}
+	
+	// Copy UI surface to texture
+	if(SDL_AtomicSet(&blitUI, 0)) {
+		// update full UI texture
+		SDL_UpdateTexture(uiTexture, NULL, uiBuffer, sdlscrn->pitch);
+		updateFB = true;
+	}
+	
+	if (updateFB) {
+		SDL_RenderClear(sdlRenderer);
+		// Render NeXT framebuffer texture
+		SDL_RenderCopy(sdlRenderer, fbTexture, NULL, &screenRect);
+		SDL_RenderCopy(sdlRenderer, uiTexture, NULL, &screenRect);
+		// SDL_RenderPresent sleeps until next VSYNC because of SDL_RENDERER_PRESENTVSYNC in ScreenInit
+		SDL_RenderPresent(sdlRenderer);
+	} else {
+		SDL_Delay(10);
+	}
 }
 
 /*-----------------------------------------------------------------------*/
@@ -318,6 +253,10 @@
  * Init Screen, creates window and starts repaint thread
  */
 void Screen_Init(void) {
+	uint32_t r, g, b, a;
+	uint32_t format;
+	int      d;
+
     /* Set initial window resolution */
     width  = NeXT_SCRN_WIDTH;
     height = NeXT_SCRN_HEIGHT;    
@@ -376,10 +315,48 @@
         exit(-1);
     }
 
-    initLatch     = SDL_CreateSemaphore(0);
-    repaintThread = SDL_CreateThread(repainter, "[Previous] screen repaint", NULL);
-    SDL_SemWait(initLatch);
-    
+	SDL_RenderSetLogicalSize(sdlRenderer, width, height);
+	
+	uiTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
+	SDL_SetTextureBlendMode(uiTexture, SDL_BLENDMODE_BLEND);
+	
+	fbTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
+	SDL_SetTextureBlendMode(fbTexture, SDL_BLENDMODE_NONE);
+	
+	SDL_QueryTexture(uiTexture, &format, &d, &d, &d);
+	SDL_PixelFormatEnumToMasks(format, &d, &r, &g, &b, &a);
+	mask = g | a;
+	
+	/* Setup lookup tables */
+	SDL_PixelFormat* pformat = SDL_AllocFormat(format);
+	/* initialize BW lookup table */
+	for(int i = 0; i < 0x100; i++) {
+		BW2RGB[i*4+0] = bw2rgb(pformat, i>>6);
+		BW2RGB[i*4+1] = bw2rgb(pformat, i>>4);
+		BW2RGB[i*4+2] = bw2rgb(pformat, i>>2);
+		BW2RGB[i*4+3] = bw2rgb(pformat, i>>0);
+	}
+	/* initialize color lookup table */
+	for(int i = 0; i < 0x10000; i++)
+		COL2RGB[SDL_BYTEORDER == SDL_BIG_ENDIAN ? i : SDL_Swap16(i)] = col2rgb(pformat, i);
+	
+	sdlscrn = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, r, g, b, a);
+	
+	/* Exit if we can not open a screen */
+	if (!sdlscrn) {
+		fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
+		SDL_Quit();
+		exit(-2);
+	}
+
+	uiBuffer = malloc(sdlscrn->h * sdlscrn->pitch);
+	
+	/* Clear UI with mask */
+	SDL_FillRect(sdlscrn, NULL, mask);
+	
+	/* Initialize statusbar */
+	Statusbar_Init(sdlscrn);
+		
     /* Configure some SDL stuff: */
     SDL_ShowCursor(SDL_DISABLE);
     Main_SetMouseGrab(bGrabMouse);
@@ -556,22 +533,10 @@
 static void statusBarUpdate(void) {
     if(shieldStatusBarUpdate) return;
     SDL_LockSurface(sdlscrn);
-    SDL_AtomicLock(&uiBufferLock);
     memcpy(&((uint8_t*)uiBuffer)[statusBar.y*sdlscrn->pitch], &((uint8_t*)sdlscrn->pixels)[statusBar.y*sdlscrn->pitch], statusBar.h * sdlscrn->pitch);
     SDL_AtomicSet(&blitUI, 1);
-    SDL_AtomicUnlock(&uiBufferLock);
     SDL_UnlockSurface(sdlscrn);
-}
-
-bool Update_StatusBar(void) {
-    shieldStatusBarUpdate = true;
-    Statusbar_OverlayBackup(sdlscrn);
-    Statusbar_Update(sdlscrn);
-    shieldStatusBarUpdate = false;
-
-    statusBarUpdate();
-    
-    return !bQuitProgram;
+	Screen_Update();
 }
 
 /*
@@ -583,14 +548,12 @@
     int     count = sdlscrn->w * sdlscrn->h;
     uint32_t* dst = (uint32_t*)uiBuffer;
     uint32_t* src = (uint32_t*)sdlscrn->pixels;
-    SDL_AtomicLock(&uiBufferLock);
     // poor man's green-screen - would be nice if SDL had more blending modes...
     for(int i = count; --i >= 0; src++)
         *dst++ = *src == mask ? 0 : *src;
-    SDL_Delay(10); // FIXME: Find a better way to prevent invisible GUI elements
     SDL_AtomicSet(&blitUI, 1);
-    SDL_AtomicUnlock(&uiBufferLock);
     SDL_UnlockSurface(sdlscrn);
+	Screen_Update();
 }
 
 void Screen_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
diff -ru a/src/includes/screen.h b/src/includes/screen.h
--- a/src/includes/screen.h	2022-10-15 17:42:57.000000000 +0200
+++ b/src/includes/screen.h	2022-10-26 12:44:21.000000000 +0200
@@ -27,10 +27,10 @@
 extern void Screen_SizeChanged(void);
 extern void Screen_ModeChanged(void);
 extern void Screen_StatusbarChanged(void);
-extern bool Update_StatusBar(void);
 extern void Screen_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);
 extern void Screen_UpdateRect(SDL_Surface *screen, int32_t x, int32_t y, int32_t w, int32_t h);
 extern void blitDimension(uint32_t* vram, SDL_Texture* tex);
+extern void Screen_Update(void);
 
 #ifdef __cplusplus
 }
diff -ru a/src/m68000.c b/src/m68000.c
--- a/src/m68000.c	2022-10-02 12:11:52.000000000 +0200
+++ b/src/m68000.c	2022-10-26 16:32:38.000000000 +0200
@@ -166,6 +166,7 @@
 void M68000_Stop(void)
 {
     M68000_SetSpecial(SPCFLAG_BRK);
+	bQuitProgram = true;
 }
 
 
diff -ru a/src/main.c b/src/main.c
--- a/src/main.c	2022-10-27 20:12:31.000000000 +0200
+++ b/src/main.c	2022-10-27 20:19:10.000000000 +0200
@@ -284,25 +284,7 @@
     bool bContinueProcessing;
     SDL_Event event;
     int events;
-    
-    if(++statusBarUpdate > 400) {
-        uint64_t vt;
-        uint64_t rt;
-        host_time(&rt, &vt);
-#if ENABLE_TESTING
-        fprintf(stderr, "[reports]");
-        for(int i = 0; i < sizeof(reports)/sizeof(report_t); i++) {
-            const char* msg = reports[i].report(rt, vt);
-            if(msg[0]) fprintf(stderr, " %s:%s", reports[i].label, msg);
-        }
-        fprintf(stderr, "\n");
-        fflush(stderr);
-#endif
-        Main_Speed(rt, vt);
-        Statusbar_UpdateInfo();
-        statusBarUpdate = 0;
-    }
-    
+        
     do {
         bContinueProcessing = false;
         
@@ -317,27 +299,21 @@
                 Main_UnPauseEmulation();
                 break;
         }
-        
-        if (bEmulationActive) {
-            int64_t time_offset = host_real_time_offset() / 1000;
-            if(time_offset > 10)
-                events = SDL_WaitEventTimeout(&event, time_offset);
-            else
-                events = SDL_PollEvent(&event);
-        }
-        else {
-            ShortCut_ActKey();
-            /* last (shortcut) event activated emulation? */
-            if ( bEmulationActive )
-                break;
-            events = SDL_WaitEvent(&event);
-        }
-        if (!events) {
-            /* no events -> if emulation is active or
-             * user is quitting -> return from function.
-             */
-            continue;
-        }
+
+		ShortCut_ActKey();
+
+		if (bEmulationActive) {
+			events = SDL_PollEvent(&event);
+		} else {
+			events = SDL_WaitEvent(&event);
+		}
+
+		if (!events) {
+			/* no events -> if emulation is active or
+			 * user is quitting -> return from function.
+			 */
+			continue;
+		}
         switch (event.type) {
             case SDL_WINDOWEVENT:
                 switch(event.window.event) {
@@ -420,16 +396,68 @@
     } while (bContinueProcessing || !(bEmulationActive || bQuitProgram));
 }
 
+static void Main_Loop(void) {
+	while (!bQuitProgram) {
+		Main_EventHandler();
+		Statusbar_Update(sdlscrn);
+		Screen_Update();      /* This waits until next VSYNC */
+	}
+}
+
+static int Main_Thread(void* unused) {
+	SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
+
+	DSP_Init();
+	M68000_Init();                /* Init CPU emulation */
+	Reset_Cold();
+
+	IoMem_Init();
+
+	/* done as last, needs CPU & DSP running... */
+	DebugUI_Init();
+
+	while (!bQuitProgram) {
+		CycInt_AddRelativeInterruptUs(1000, 0, INTERRUPT_EVENT_LOOP);
+		M68000_Start();               /* Start emulation */
+	}
+}
+
 
-void Main_EventHandlerInterrupt() {
+void Main_EventHandlerInterrupt(void) {
     CycInt_AcknowledgeInterrupt();
-    Main_EventHandler();
-    CycInt_AddRelativeInterruptUs((1000*1000)/200, 0, INTERRUPT_EVENT_LOOP); // poll events with 200 Hz
+	
+	while (!bEmulationActive) {
+		host_sleep_ms(10);
+	}
+	if(++statusBarUpdate > 400) {
+		uint64_t vt;
+		uint64_t rt;
+		host_time(&rt, &vt);
+#if ENABLE_TESTING
+		fprintf(stderr, "[reports]");
+		for(int i = 0; i < sizeof(reports)/sizeof(report_t); i++) {
+			const char* msg = reports[i].report(rt, vt);
+			if(msg[0]) fprintf(stderr, " %s:%s", reports[i].label, msg);
+		}
+		fprintf(stderr, "\n");
+		fflush(stderr);
+#endif
+		Main_Speed(rt, vt);
+		Statusbar_UpdateInfo();
+		statusBarUpdate = 0;
+	}
+
+	int64_t time_offset = host_real_time_offset();
+	if (time_offset > 0) {
+		host_sleep_us(time_offset);
+	}
+	
+	CycInt_AddRelativeInterruptUs((1000*1000)/200, 0, INTERRUPT_EVENT_LOOP); // poll events with 200 Hz
 }
 
 /*-----------------------------------------------------------------------*/
 /**
- * Set Hatari window title. Use NULL for default
+ * Set Previous window title. Use NULL for default
  */
 void Main_SetTitle(const char *title) {
     if (title)
@@ -438,6 +466,26 @@
         SDL_SetWindowTitle(sdlWindow, PROG_NAME);
 }
 
+
+static void Main_StartMenu(void) {
+	if (!File_Exists(sConfigFileName) || ConfigureParams.ConfigDialog.bShowConfigDialogAtStartup) {
+		Dialog_DoProperty();
+		if (bQuitProgram) {
+			SDL_Quit();
+			exit(-2);
+		}
+	}
+
+	Dialog_CheckFiles();
+	
+	if (bQuitProgram) {
+		SDL_Quit();
+		exit(-2);
+	}
+}
+
+SDL_Thread* nextThread = NULL;
+
 /*-----------------------------------------------------------------------*/
 /**
  * Initialise emulation
@@ -460,35 +508,13 @@
 	SDLGui_Init();
 	Screen_Init();
 	Main_SetTitle(NULL);
-	DSP_Init();
-	M68000_Init();                /* Init CPU emulation */
-	Keymap_Init();
 
     /* call menu at startup */
-    if (!File_Exists(sConfigFileName) || ConfigureParams.ConfigDialog.bShowConfigDialogAtStartup) {
-        Dialog_DoProperty();
-        if (bQuitProgram) {
-            SDL_Quit();
-            exit(-2);
-        }
-    }
-
-    Dialog_CheckFiles();
-    
-    if (bQuitProgram) {
-        SDL_Quit();
-        exit(-2);
-    }
-    
-    Reset_Cold();
-    
-	IoMem_Init();
+	DSP_Init(); // FIXME: required before cold reset
+	Main_StartMenu();
 	
-    /* Start EventHandler */
-    CycInt_AddRelativeInterruptUs(500*1000, 0, INTERRUPT_EVENT_LOOP);
-    
-	/* done as last, needs CPU & DSP running... */
-	DebugUI_Init();
+    /* Start emulator thread */
+	nextThread = SDL_CreateThread(Main_Thread, "[Previous] NeXT", NULL);
 }
 
 
@@ -497,6 +523,9 @@
  * Un-Initialise emulation
  */
 static void Main_UnInit(void) {
+	int d;
+	SDL_WaitThread(nextThread, &d);
+	
 	Screen_ReturnFromFullScreen();
 	IoMem_UnInit();
 	SDLGui_UnInit();
@@ -631,11 +660,10 @@
 	/* Check if SDL_Delay is accurate */
 	Main_CheckForAccurateDelays();
 
-
 	/* Run emulation */
 	Main_UnPauseEmulation();
-	M68000_Start();                 /* Start emulation */
 
+	Main_Loop();
 
 	/* Un-init emulation system */
 	Main_UnInit();
diff -ru a/src/video.c b/src/video.c
--- a/src/video.c	2022-10-02 12:11:52.000000000 +0200
+++ b/src/video.c	2022-10-26 12:41:27.000000000 +0200
@@ -14,7 +14,6 @@
 #include "cycInt.h"
 #include "ioMem.h"
 #include "m68000.h"
-#include "screen.h"
 #include "shortcut.h"
 #include "video.h"
 #include "dma.h"
@@ -62,12 +61,6 @@
 void Video_InterruptHandler_VBL ( void ) {
 	CycInt_AcknowledgeInterrupt();
     host_blank(0, MAIN_DISPLAY, true);
-    if(statusBarToggle) Update_StatusBar();
-    statusBarToggle = !statusBarToggle;
     Video_InterruptHandler();
     CycInt_AddRelativeInterruptUs((1000*1000)/NEXT_VBL_FREQ, 0, INTERRUPT_VIDEO_VBL);
 }
-
-
-
-
