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