|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: #include "generator.h"
4: #include "vdp.h"
5: #include "cpu68k.h"
6: #include "cpuz80.h"
7: #include "reg68k.h"
8: #include "ui.h"
9: #include "gensound.h"
10:
11: inline void event_nextevent(void)
12: {
13: switch(vdp_event++) {
14: case 0:
15: LOG_DEBUG1(("%08X due %08X, %d A: %d (cd=%d)",
16: cpu68k_clocks, vdp_event_start,
17: vdp_line - vdp_visstartline, vdp_reg[10],
18: vdp_hskip_countdown));
19: if (vdp_line == (vdp_visstartline-1)) {
20: vdp_vblank = 0;
21: }
22: if ((vdp_nextevent = vdp_event_vint - cpu68k_clocks) > 0)
23: break;
24: vdp_event++;
25: case 1:
26: LOG_DEBUG1(("%08X due %08X, %d B: %d (cd=%d)",
27: cpu68k_clocks, vdp_event_vint,
28: vdp_line - vdp_visstartline, vdp_reg[10],
29: vdp_hskip_countdown));
30: if (vdp_line == vdp_visendline) {
31: vdp_vblank = 1;
32: vdp_vsync = 1;
33: if (vdp_reg[1] & 1<<5)
34: reg68k_external_autovector(6); /* vertical interrupt */
35: }
36: if ((vdp_nextevent = vdp_event_hint - cpu68k_clocks) > 0)
37: break;
38: vdp_event++;
39: case 2:
40: LOG_DEBUG1(("%08X due %08X, %d C: %d (cd=%d)",
41: cpu68k_clocks, vdp_event_hint,
42: vdp_line - vdp_visstartline, vdp_reg[10],
43: vdp_hskip_countdown));
44: if (vdp_line >= vdp_visstartline && vdp_line < vdp_visendline)
45: vdp_hblank = 1;
46: if (vdp_line == (vdp_visstartline-1) || (vdp_line > vdp_visendline)) {
47: vdp_hskip_countdown = vdp_reg[10];
48: LOG_DEBUG1(("H counter reset to %d", vdp_hskip_countdown));
49: }
50: if (vdp_reg[0] & 1<<4) {
51: LOG_DEBUG1(("pre = %d", vdp_hskip_countdown));
52: if (vdp_hskip_countdown-- == 0) {
53: LOG_DEBUG1(("in = %d", vdp_hskip_countdown));
54: /* re-initialise counter */
55: vdp_hskip_countdown = vdp_reg[10];
56: LOG_DEBUG1(("H counter looped to %d", vdp_hskip_countdown));
57: if (vdp_line >= vdp_visstartline-1 && vdp_line < vdp_visendline-1)
58: reg68k_external_autovector(4); /* horizontal interrupt */
59: /* since this game is obviously timing sensitive, we sacrifice
60: executing the right number of 68k clocks this frame in order
61: to accurately do the moments following H-Int */
62: cpu68k_clocks = vdp_event_hint;
63: }
64: LOG_DEBUG1(("post = %d", vdp_hskip_countdown));
65: }
66: /* the 68k should be frozen for 68k ram to vram copies, so we need
67: to eat CPU cyles immediately - implement this at the same time
68: as re-working this event loop */
69: if (vdp_dmabytes) {
70: vdp_dmabytes-= (vdp_vblank || !(vdp_reg[1] & 1<<6)) /* blank mode ? */
71: ? ((vdp_reg[12] & 1) ? 205 : 167) : ((vdp_reg[12] & 1) ? 18 : 16);
72: if (vdp_dmabytes <= 0) {
73: vdp_dmabytes = 0;
74: vdp_dmabusy = 0;
75: }
76: }
77: if ((vdp_nextevent = vdp_event_hdisplay - cpu68k_clocks) > 0)
78: break;
79: vdp_event++;
80: case 3:
81: LOG_DEBUG1(("%08X due %08X, %d D: %d (cd=%d)",
82: cpu68k_clocks, vdp_event_hdisplay,
83: vdp_line - vdp_visstartline, vdp_reg[10],
84: vdp_hskip_countdown));
85: if (vdp_line >= vdp_visstartline-1 && vdp_line < vdp_visendline-1)
86: ui_line(vdp_line - vdp_visstartline + 1);
87: if ((vdp_nextevent = vdp_event_end - cpu68k_clocks) > 0)
88: break;
89: vdp_event++;
90: case 4:
91: /* end of line, do sound, platform stuff */
92: LOG_DEBUG1(("%08X due %08X, %d E: %d (cd=%d)",
93: cpu68k_clocks, vdp_event_end,
94: vdp_line-vdp_visstartline, vdp_reg[10],
95: vdp_hskip_countdown));
96: if (vdp_line >= vdp_visstartline && vdp_line < vdp_visendline)
97: vdp_hblank = 0;
98: cpuz80_sync();
99: sound_process();
100: vdp_line++;
101: if (vdp_line == vdp_totlines) {
102: ui_endfield();
103: sound_endfield();
104: cpuz80_interrupt();
105: vdp_endfield();
106: cpuz80_endfield();
107: cpu68k_endfield();
108: cpu68k_frames++;
109: }
110: vdp_event_start+= vdp_clksperline_68k;
111: vdp_event_vint+= vdp_clksperline_68k;
112: vdp_event_hint+= vdp_clksperline_68k;
113: vdp_event_hdisplay+= vdp_clksperline_68k;
114: vdp_event_end+= vdp_clksperline_68k;
115: vdp_event = 0;
116: vdp_nextevent = 0;
117: break;
118: } /* switch */
119: }
120:
121: /*** event_doframe - execute until the end of the current frame ***/
122:
123: void event_doframe(void)
124: {
125: unsigned int startframe;
126:
127: for (startframe = cpu68k_frames;
128: startframe == cpu68k_frames;
129: event_nextevent()) {
130: while (vdp_nextevent > 0) {
131: vdp_nextevent = -reg68k_external_execute(vdp_nextevent);
132: }
133: }
134: }
135:
136: /*** event_step - execute one instruction with no caching ***/
137:
138: void event_dostep(void)
139: {
140: while (vdp_nextevent <= 0)
141: event_nextevent();
142: vdp_nextevent-= reg68k_external_step();
143: }
144:
145: /*** event_freeze_clocks - freeze 68k for given clock cycles ***/
146:
147: void event_freeze_clocks(unsigned int clocks)
148: {
149: cpu68k_clocks+= clocks;
150:
151: /* now find out the new time to next event - just to make sure there is
152: an event to be generated by inreasing the clock */
153:
154: switch(vdp_event) {
155: case 0:
156: vdp_nextevent = vdp_event_start - cpu68k_clocks;
157: case 1:
158: vdp_nextevent = vdp_event_vint - cpu68k_clocks;
159: break;
160: case 2:
161: vdp_nextevent = vdp_event_hint - cpu68k_clocks;
162: break;
163: case 3:
164: vdp_nextevent = vdp_event_hdisplay - cpu68k_clocks;
165: break;
166: case 4:
167: vdp_nextevent = vdp_event_end - cpu68k_clocks;
168: break;
169: } /* switch */
170:
171: /* now play catch-up in events */
172:
173: while (vdp_nextevent <= 0)
174: event_nextevent();
175: }
176:
177: /*** event_freeze - freeze 68k for given VDP byte transfer ***/
178:
179: void event_freeze(unsigned int bytes)
180: {
181: int wide = vdp_reg[12] & 1;
182: unsigned int clocks, possible;
183: double percent_possible;
184:
185: do {
186: clocks = vdp_event_end - cpu68k_clocks;
187: percent_possible = clocks/vdp_clksperline_68k;
188: if (vdp_reg[1] & 1<<6 && !vdp_vblank) {
189: /* vdp active */
190: possible = (unsigned int)(percent_possible*(wide ? 18 : 16));
191: } else {
192: /* vdp inactive */
193: possible = (unsigned int)(percent_possible*(wide ? 205 : 167));
194: }
195: if (bytes >= possible) {
196: event_freeze_clocks(clocks);
197: bytes-= possible;
198: } else {
199: event_freeze_clocks(((double)bytes/possible)*clocks);
200: bytes = 0;
201: }
202: } while (bytes > 0);
203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.