|
|
1.1 root 1: #include "main.h"
2: #include "nd_sdl.h"
3: #include "configuration.h"
4: #include "dimension.h"
5: #include "screen.h"
6:
7: /* Because of SDL time (in)accuracy, timing is very approximative */
8: const int DISPLAY_VBL_MS = 1000 / 68; // main display at 68Hz, actually this is 71.42 Hz because (int)1000/(int)68Hz=14ms
9: const int VIDEO_VBL_MS = 1000 / 60; // NTSC display at 60Hz, actually this is 62.5 Hz because (int)1000/(int)60Hz=16ms
10: const int BLANK_MS = 2; // Give some blank time for both
11:
12: extern Uint32 nd_display_blank_start();
13: extern Uint32 nd_display_blank_end();
14: extern Uint32 nd_video_vbl(Uint32 interval, void* param);
15:
16: static SDL_TimerID videoVBL = NULL;
17: static volatile bool doRepaint = true;
18: static SDL_Thread* repaintThread = NULL;
19: static SDL_Window* ndWindow = NULL;
20:
21: extern void blitDimension(SDL_Texture* tex);
22:
23: static int repainter(void* unused) {
24: SDL_Texture* ndTexture = NULL;
25: SDL_Renderer* ndRenderer = NULL;
26:
27: ndRenderer = SDL_CreateRenderer(ndWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
28: if (!ndWindow || !ndRenderer) {
29: fprintf(stderr,"[ND] Failed to create renderer!\n");
30: exit(-1);
31: }
32: SDL_Rect r = {0,0,1120,832};
33: SDL_RenderSetLogicalSize(ndRenderer, r.w, r.h);
34: ndTexture = SDL_CreateTexture(ndRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, r.w, r.h);
35:
36: while(doRepaint) {
37: if(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL) {
38: blitDimension(ndTexture);
39: SDL_RenderCopy(ndRenderer, ndTexture, NULL, NULL);
40: SDL_RenderPresent(ndRenderer);
41: } else {
42: SDL_Delay(VIDEO_VBL_MS - BLANK_MS);
43: }
44: // if this is a cube, then do ND blank emulation.
45: if(ConfigureParams.System.nMachineType == NEXT_CUBE030 || ConfigureParams.System.nMachineType == NEXT_CUBE040) {
46: nd_display_blank_start();
47: SDL_Delay(BLANK_MS);
48: nd_display_blank_end();
49: }
50: }
51:
52: SDL_DestroyTexture(ndTexture);
53: SDL_DestroyRenderer(ndRenderer);
54: SDL_DestroyWindow(ndWindow);
55:
56: return 0;
57: }
58:
59: void nd_sdl_init() {
60: if(!(repaintThread)) {
61: int x, y, w, h;
62: SDL_GetWindowPosition(sdlWindow, &x, &y);
63: SDL_GetWindowSize(sdlWindow, &w, &h);
64: ndWindow = SDL_CreateWindow("NeXT Dimension",(x-w)+1, y, 1120, 832, SDL_WINDOW_HIDDEN);
65: repaintThread = SDL_CreateThread(repainter, "[ND] repainter", NULL);
66: }
67: if(videoVBL) SDL_RemoveTimer(videoVBL);
68: // NTSC video at 60Hz
69: videoVBL = SDL_AddTimer(VIDEO_VBL_MS, nd_video_vbl, NULL);
70:
71: if(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL) {
72: SDL_ShowWindow(ndWindow);
73: } else {
74: SDL_HideWindow(ndWindow);
75: }
76: }
77:
78: void nd_sdl_uninit() {
79: if(videoVBL) {
80: SDL_RemoveTimer(videoVBL);
81: videoVBL = NULL;
82: }
83: SDL_HideWindow(ndWindow);
84: }
85:
86: void nd_sdl_destroy() {
87: doRepaint = false; // stop repaint thread
88: int s;
89: SDL_WaitThread(repaintThread, &s);
90: nd_sdl_uninit();
91: }
92:
93: //----- SDL abstractions for ND implementation
94:
95: void lock(lock_t* lock) {
96: SDL_AtomicLock(lock);
97: }
98:
99: int trylock(lock_t* lock) {
100: return SDL_AtomicTryLock(lock);
101: }
102:
103: void unlock(lock_t* lock) {
104: SDL_AtomicUnlock(lock);
105: }
106:
107: void checklock(lock_t* lock) {
108: SDL_AtomicLock(lock);
109: SDL_AtomicUnlock(lock);
110: }
111:
112: Uint32 time_ms() {
113: return SDL_GetTicks();
114: }
115:
116: void sleep_ms(Uint32 ms) {
117: SDL_Delay(ms);
118: }
119:
120: thread_t* thread_create(thread_func_t func, void* data) {
121: return SDL_CreateThread(func, "[ND] Thread", data);
122: }
123:
124: int thread_wait(thread_t* thread) {
125: int status;
126: SDL_WaitThread(thread, &status);
127: return status;
128: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.