|
|
1.1 root 1: #include "main.h"
2: #include "nd_sdl.h"
3: #include "configuration.h"
4: #include "dimension.h"
5: #include "screen.h"
1.1.1.2 ! root 6: #include "host.h"
! 7: #include "cycInt.h"
1.1 root 8:
9: /* Because of SDL time (in)accuracy, timing is very approximative */
10: const int DISPLAY_VBL_MS = 1000 / 68; // main display at 68Hz, actually this is 71.42 Hz because (int)1000/(int)68Hz=14ms
11: const int VIDEO_VBL_MS = 1000 / 60; // NTSC display at 60Hz, actually this is 62.5 Hz because (int)1000/(int)60Hz=16ms
12: const int BLANK_MS = 2; // Give some blank time for both
13:
14: static volatile bool doRepaint = true;
15: static SDL_Thread* repaintThread = NULL;
16: static SDL_Window* ndWindow = NULL;
1.1.1.2 ! root 17: static SDL_Renderer* ndRenderer = NULL;
! 18:
! 19: SDL_atomic_t blitNDFB;
1.1 root 20:
1.1.1.2 ! root 21: void blitDimension(SDL_Texture* tex);
1.1 root 22:
23: static int repainter(void* unused) {
1.1.1.2 ! root 24: SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
! 25:
1.1 root 26: SDL_Texture* ndTexture = NULL;
1.1.1.2 ! root 27:
! 28: SDL_Rect r = {0,0,1120,832};
1.1 root 29:
30: ndRenderer = SDL_CreateRenderer(ndWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
1.1.1.2 ! root 31:
! 32: if (!ndRenderer) {
1.1 root 33: fprintf(stderr,"[ND] Failed to create renderer!\n");
34: exit(-1);
35: }
1.1.1.2 ! root 36:
1.1 root 37: SDL_RenderSetLogicalSize(ndRenderer, r.w, r.h);
38: ndTexture = SDL_CreateTexture(ndRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, r.w, r.h);
39:
1.1.1.2 ! root 40: SDL_AtomicSet(&blitNDFB, 1);
! 41:
1.1 root 42: while(doRepaint) {
1.1.1.2 ! root 43: if (SDL_AtomicGet(&blitNDFB)) {
1.1 root 44: blitDimension(ndTexture);
45: SDL_RenderCopy(ndRenderer, ndTexture, NULL, NULL);
46: SDL_RenderPresent(ndRenderer);
47: } else {
1.1.1.2 ! root 48: host_sleep_ms(100);
1.1 root 49: }
50: }
51:
52: SDL_DestroyTexture(ndTexture);
53: SDL_DestroyRenderer(ndRenderer);
54: SDL_DestroyWindow(ndWindow);
55:
56: return 0;
57: }
58:
1.1.1.2 ! root 59: static bool ndVBLtoggle;
! 60: void nd_vbl_handler() {
! 61: CycInt_AcknowledgeInterrupt();
! 62:
! 63: host_blank(ND_SLOT, ND_DISPLAY, ndVBLtoggle);
! 64: ndVBLtoggle = !ndVBLtoggle;
! 65:
! 66: CycInt_AddRelativeInterruptUs((1000*1000)/136, 0, INTERRUPT_ND_VBL); // 136Hz with toggle gives 68Hz, blank time is 1/2 frame time
! 67: }
! 68:
! 69: bool ndVideoVBLtoggle;
! 70: void nd_video_vbl_handler() {
! 71: CycInt_AcknowledgeInterrupt();
! 72:
! 73: host_blank(ND_SLOT, ND_VIDEO, ndVideoVBLtoggle);
! 74: ndVideoVBLtoggle = !ndVideoVBLtoggle;
! 75:
! 76: CycInt_AddRelativeInterruptUs((1000*1000)/120, 0, INTERRUPT_ND_VIDEO_VBL); // 120Hz with toggle gives 60Hz NTSC, blank time is 1/2 frame time
! 77: }
! 78:
1.1 root 79: void nd_sdl_init() {
80: if(!(repaintThread)) {
81: int x, y, w, h;
82: SDL_GetWindowPosition(sdlWindow, &x, &y);
83: SDL_GetWindowSize(sdlWindow, &w, &h);
1.1.1.2 ! root 84: ndWindow = SDL_CreateWindow("NeXTdimension",(x-w)+1, y, 1120, 832, SDL_WINDOW_HIDDEN);
! 85:
! 86: if (!ndWindow) {
! 87: fprintf(stderr,"[ND] Failed to create window!\n");
! 88: exit(-1);
! 89: }
1.1 root 90: }
91:
92: if(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL) {
93: SDL_ShowWindow(ndWindow);
94: } else {
95: SDL_HideWindow(ndWindow);
96: }
97: }
98:
1.1.1.2 ! root 99: void nd_start_interrupts() {
! 100: if(!(repaintThread) && ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL)
! 101: repaintThread = SDL_CreateThread(repainter, "[ND] repainter", NULL);
! 102:
! 103: // if this is a cube and we have an ND configured, install ND VBL handlers
! 104: if (ConfigureParams.Dimension.bEnabled && (ConfigureParams.System.nMachineType == NEXT_CUBE030 || ConfigureParams.System.nMachineType == NEXT_CUBE040)) {
! 105: CycInt_AddRelativeInterruptUs(1000, 0, INTERRUPT_ND_VBL);
! 106: CycInt_AddRelativeInterruptUs(1000, 0, INTERRUPT_ND_VIDEO_VBL);
1.1 root 107: }
1.1.1.2 ! root 108: }
! 109:
! 110: void nd_sdl_uninit() {
1.1 root 111: SDL_HideWindow(ndWindow);
112: }
113:
1.1.1.2 ! root 114: void nd_sdl_pause(bool pause) {
! 115: if (pause) {
! 116: SDL_AtomicSet(&blitNDFB, 0);
! 117: } else {
! 118: SDL_AtomicSet(&blitNDFB, 1);
! 119: }
! 120: }
! 121:
1.1 root 122: void nd_sdl_destroy() {
123: doRepaint = false; // stop repaint thread
124: int s;
125: SDL_WaitThread(repaintThread, &s);
126: nd_sdl_uninit();
127: }
128:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.