|
|
1.1 root 1: #include "main.h"
2: #include "configuration.h"
3: #include "m68000.h"
4: #include "sysdeps.h"
5: #include "sysReg.h"
6: #include "adb.h"
7: #include "tmc.h"
8:
9: #define LOG_TMC_LEVEL LOG_DEBUG
10:
11: /* NeXT TMC emulation */
12:
13: #define TMC_ADB_ADDR_MASK 0x02208000
14:
15: #define TMC_REGS_MASK 0x0000FFFF
16:
17: /* TMC registers */
18:
19: struct {
20: Uint32 scr1;
21: Uint32 control;
22: Uint32 horizontal;
23: Uint32 vertical;
24: Uint8 video_intr;
25: Uint32 nitro;
26: } tmc;
27:
28: /* Additional System Control Register for Turbo systems:
29: * -------- -------- -------- -----xxx bits 0:2 --> cpu speed
30: * -------- -------- -------- --xx---- bits 4:5 --> main memory speed
31: * -------- -------- -------- xx------ bits 6:7 --> video memory speed
32: * -------- -------- ----xxxx -------- bits 8:11 --> cpu revision
33: * -------- -------- xxxx---- -------- bits 12:15 --> cpu type
34: * xxxx---- -------- -------- -------- bits 28:31 --> slot id
35: * ----xxxx xxxxxxxx -------- ----x--- all other bits: 1
36: *
37: * cpu speed: 7 = 33MHz?
38: * main mem speed: 0 = 60ns, 1 = 70ns, 2 = 80ns, 3 = 100ns
39: * video mem speed: 3 on all Turbo systems (100ns)?
40: * cpu revision: 0xF = rev 0
41: * 0xE = rev 1
42: * 0xD = rev 2
43: * 0xC - 0x0: rev 3 - 15
44: * cpu type: 4 = NeXTstation turbo monochrome
45: * 5 = NeXTstation turbo color
46: * 8 = NeXTcube turbo
47: */
48:
49: #define TURBOSCR_FMASK 0x0FFF0F08
50:
51: void TurboSCR1_Reset(void) {
52: Uint8 memory_speed;
53: Uint8 cpu_speed = 0x07; // 33 MHz
54:
55: if (ConfigureParams.System.nCpuFreq<20) {
56: cpu_speed = 4;
57: } else if (ConfigureParams.System.nCpuFreq<25) {
58: cpu_speed = 5;
59: } else if (ConfigureParams.System.nCpuFreq<33) {
60: cpu_speed = 6;
61: } else {
62: cpu_speed = 7;
63: }
64:
65: switch (ConfigureParams.Memory.nMemorySpeed) {
66: case MEMORY_120NS: memory_speed = 0x00; break;
67: case MEMORY_100NS: memory_speed = 0x50; break;
68: case MEMORY_80NS: memory_speed = 0xA0; break;
69: case MEMORY_60NS: memory_speed = 0xF0; break;
70: default: Log_Printf(LOG_WARN, "Turbo SCR1 error: unknown memory speed\n"); break;
71: }
72: tmc.scr1 = ((memory_speed&0xF0)|(cpu_speed&0x07));
73: if (ConfigureParams.System.nMachineType == NEXT_CUBE040)
74: tmc.scr1 |= 0x8000;
75: else if (ConfigureParams.System.bColor) {
76: tmc.scr1 |= 0x5000;
77: } else {
78: tmc.scr1 |= 0x4000;
79: }
80: tmc.scr1 |= TURBOSCR_FMASK;
81: }
82:
83:
84:
85: /* Register read/write functions */
86:
87: Uint8 tmc_ill_read(void) {
88: Log_Printf(LOG_WARN, "[TMC] Illegal read!\n");
89: return 0;
90: }
91:
92: void tmc_ill_write(Uint8 val) {
93: Log_Printf(LOG_WARN, "[TMC] Illegal write!\n");
94: }
95:
96: Uint8 tmc_unimpl_read(void) {
97: Log_Printf(LOG_WARN, "[TMC] Unimplemented read!\n");
98: return 0;
99: }
100:
101: void tmc_unimpl_write(Uint8 val) {
102: Log_Printf(LOG_WARN, "[TMC] Unimplemented write!\n");
103: }
104:
105: Uint8 tmc_void_read(void) {
106: return 0;
107: }
108:
109: void tmc_void_write(Uint8 val) {
110: }
111:
112: /* SCR1 */
113: Uint8 tmc_scr1_read0(void) {
114: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200000 PC=$%08x\n",m68k_getpc());
115: return (tmc.scr1>>24);
116: }
117: Uint8 tmc_scr1_read1(void) {
118: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200001 PC=$%08x\n",m68k_getpc());
119: return (tmc.scr1>>16);
120: }
121: Uint8 tmc_scr1_read2(void) {
122: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200002 PC=$%08x\n",m68k_getpc());
123: return (tmc.scr1>>8);
124: }
125: Uint8 tmc_scr1_read3(void) {
126: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200003 PC=$%08x\n",m68k_getpc());
127: return tmc.scr1;
128: }
129:
130: /* TMC Control Register */
131:
132: Uint8 tmc_ctrl_read0(void) {
133: return (tmc.control>>24);
134: }
135: Uint8 tmc_ctrl_read1(void) {
136: return (tmc.control>>16);
137: }
138: Uint8 tmc_ctrl_read2(void) {
139: return (tmc.control>>8);
140: }
141: Uint8 tmc_ctrl_read3(void) {
142: return tmc.control;
143: }
144:
145: void tmc_ctrl_write0(Uint8 val) {
146: tmc.control &= 0x00FFFFFF;
147: tmc.control |= (val&0xFF)<<24;
148: }
149: void tmc_ctrl_write1(Uint8 val) {
150: tmc.control &= 0xFF00FFFF;
151: tmc.control |= (val&0xFF)<<16;
152: }
153: void tmc_ctrl_write2(Uint8 val) {
154: val &= ~0x04; /* no parity memory */
155:
156: tmc.control &= 0xFFFF00FF;
157: tmc.control |= (val&0xFF)<<8;
158: }
159: void tmc_ctrl_write3(Uint8 val) {
160: tmc.control &= 0xFFFFFF00;
161: tmc.control |= val&0xFF;
162: }
163:
164:
165: /* Video Interrupt Register */
166: #define TMC_VI_INTERRUPT 0x01
167: #define TMC_VI_INT_MASK 0x02
168:
169: /* Horizontal and Vertical Configruation Registers */
170: #define HFPORCH 0x18
171: #define HSYNC 0x20
172: #define HBPORCH 0x48
173: #define HDISCNT 0x118
174:
175: #define VFPORCH 0x08
176: #define VSYNC 0x08
177: #define VBPORCH 0x30
178: #define VDISCNT 0x340
179:
180: void tmc_video_reg_reset(void) {
181: tmc.video_intr = 0x00;
182: tmc.horizontal = (HFPORCH<<25)|(HSYNC<<19)|(HBPORCH<<12)|HDISCNT;
183: tmc.vertical = (VFPORCH<<25)|(VSYNC<<19)|(VBPORCH<<12)|VDISCNT;
184: }
185:
186: void tmc_video_interrupt(void) {
187: if (tmc.video_intr&TMC_VI_INT_MASK) {
188: set_interrupt(INT_DISK, SET_INT);
189: tmc.video_intr |= TMC_VI_INTERRUPT;
190: }
191: }
192:
193: Uint8 tmc_vir_read0(void) {
194: return tmc.video_intr;
195: }
196:
197: void tmc_vir_write0(Uint8 val) {
198: tmc.video_intr = val;
199: if (tmc.video_intr&TMC_VI_INTERRUPT) {
200: tmc.video_intr &= ~TMC_VI_INTERRUPT;
201: set_interrupt(INT_DISK, RELEASE_INT);
202: }
203: }
204:
205: Uint8 tmc_hcr_read0(void) {
206: return (tmc.horizontal>>24);
207: }
208: Uint8 tmc_hcr_read1(void) {
209: return (tmc.horizontal>>16);
210: }
211: Uint8 tmc_hcr_read2(void) {
212: return (tmc.horizontal>>8);
213: }
214: Uint8 tmc_hcr_read3(void) {
215: return tmc.horizontal;
216: }
217:
218: void tmc_hcr_write0(Uint8 val) {
219: tmc.horizontal &= 0x00FFFFFF;
220: tmc.horizontal |= (val&0xFF)<<24;
221: }
222: void tmc_hcr_write1(Uint8 val) {
223: tmc.horizontal &= 0xFF00FFFF;
224: tmc.horizontal |= (val&0xFF)<<16;
225: }
226: void tmc_hcr_write2(Uint8 val) {
227: tmc.horizontal &= 0xFFFF00FF;
228: tmc.horizontal |= (val&0xFF)<<8;
229: }
230: void tmc_hcr_write3(Uint8 val) {
231: tmc.horizontal &= 0xFFFFFF00;
232: tmc.horizontal |= val&0xFF;
233: }
234:
235: Uint8 tmc_vcr_read0(void) {
236: return (tmc.vertical>>24);
237: }
238: Uint8 tmc_vcr_read1(void) {
239: return (tmc.vertical>>16);
240: }
241: Uint8 tmc_vcr_read2(void) {
242: return (tmc.vertical>>8);
243: }
244: Uint8 tmc_vcr_read3(void) {
245: return tmc.vertical;
246: }
247:
248: void tmc_vcr_write0(Uint8 val) {
249: tmc.vertical &= 0x00FFFFFF;
250: tmc.vertical |= (val&0xFF)<<24;
251: }
252: void tmc_vcr_write1(Uint8 val) {
253: tmc.vertical &= 0xFF00FFFF;
254: tmc.vertical |= (val&0xFF)<<16;
255: }
256: void tmc_vcr_write2(Uint8 val) {
257: tmc.vertical &= 0xFFFF00FF;
258: tmc.vertical |= (val&0xFF)<<8;
259: }
260: void tmc_vcr_write3(Uint8 val) {
261: tmc.vertical &= 0xFFFFFF00;
262: tmc.vertical |= val&0xFF;
263: }
264:
265:
266: /* Read register functions */
267: static Uint8 (*tmc_read_reg[36])(void) = {
268: tmc_scr1_read0, tmc_scr1_read1, tmc_scr1_read2, tmc_scr1_read3,
269: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
270: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
271: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
272: tmc_ctrl_read0, tmc_ctrl_read1, tmc_ctrl_read2, tmc_ctrl_read3,
273: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
274: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
275: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
276: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read
277: };
278:
279: static Uint8 (*tmc_read_vid_reg[16])(void) = {
280: tmc_vir_read0, tmc_void_read, tmc_void_read, tmc_void_read,
281: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read,
282: tmc_hcr_read0, tmc_hcr_read1, tmc_hcr_read2, tmc_hcr_read3,
283: tmc_vcr_read0, tmc_vcr_read1, tmc_vcr_read2, tmc_vcr_read3
284: };
285:
286: /* Write register functions */
287: static void (*tmc_write_reg[36])(Uint8) = {
288: tmc_ill_write, tmc_ill_write, tmc_ill_write, tmc_ill_write,
289: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
290: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
291: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
292: tmc_ctrl_write0, tmc_ctrl_write1, tmc_ctrl_write2, tmc_ctrl_write3,
293: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
294: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
295: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
296: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write
297: };
298:
299: static void (*tmc_write_vid_reg[16])(Uint8) = {
300: tmc_vir_write0, tmc_void_write, tmc_void_write, tmc_void_write,
301: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write,
302: tmc_hcr_write0, tmc_hcr_write1, tmc_hcr_write2, tmc_hcr_write3,
303: tmc_vcr_write0, tmc_vcr_write1, tmc_vcr_write2, tmc_vcr_write3
304: };
305:
306:
307: Uint32 tmc_lget(uaecptr addr) {
308: Uint32 val = 0;
309:
310: if (addr%4) {
311: Log_Printf(LOG_WARN, "[TMC] Unaligned access.");
312: abort();
313: }
314:
315: if (addr==0x02210000) {
316: Log_Printf(LOG_WARN, "[TMC] Nitro register lget from $%08X",addr);
317: if (ConfigureParams.System.nCpuFreq==40) {
318: val = tmc.nitro;
319: } else {
320: Log_Printf(LOG_WARN, "[TMC] No nitro --> bus error!");
321: M68000_BusError(addr, 1);
322: }
323: return val;
324: }
325:
326: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) {
327: return adb_lget(addr);
328: }
329:
330: Log_Printf(LOG_TMC_LEVEL, "[TMC] lget from %08X",addr);
331:
332: addr &= TMC_REGS_MASK;
333:
334: if (addr<36) {
335: val = tmc_read_reg[addr]()<<24;
336: val |= tmc_read_reg[addr+1]()<<16;
337: val |= tmc_read_reg[addr+2]()<<8;
338: val |= tmc_read_reg[addr+3]();
339: } else if (addr>=128 && addr<144) {
340: val = tmc_read_vid_reg[addr&0xF]()<<24;
341: val |= tmc_read_vid_reg[(addr+1)&0xF]()<<16;
342: val |= tmc_read_vid_reg[(addr+2)&0xF]()<<8;
343: val |= tmc_read_vid_reg[(addr+3)&0xF]();
344: }
345:
346: return val;
347: }
348:
349: Uint32 tmc_wget(uaecptr addr) {
350: Uint32 val = 0;
351:
352: if (addr%2) {
353: Log_Printf(LOG_WARN, "[TMC] Unaligned access.");
354: abort();
355: }
356:
357: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) {
358: return adb_wget(addr);
359: }
360:
361: Log_Printf(LOG_TMC_LEVEL, "[TMC] wget from %08X",addr);
362:
363: addr &= TMC_REGS_MASK;
364:
365: if (addr<36) {
366: val = tmc_read_reg[addr]()<<8;
367: val |= tmc_read_reg[addr+1]();
368: } else if (addr>=128 && addr<144) {
369: val = tmc_read_vid_reg[addr&0xF]()<<8;
370: val |= tmc_read_vid_reg[(addr+1)&0xF]();
371: }
372:
373: return val;
374: }
375:
376: Uint32 tmc_bget(uaecptr addr) {
377: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) {
378: return adb_bget(addr);
379: }
380:
381: Log_Printf(LOG_TMC_LEVEL, "[TMC] bget from %08X",addr);
382:
383: addr &= TMC_REGS_MASK;
384:
385: if (addr<36) {
386: return tmc_read_reg[addr]();
387: } else if (addr>=128 && addr<144) {
388: return tmc_read_vid_reg[addr&0xF]();
389: }
390:
391: return 0;
392: }
393:
394: void tmc_lput(uaecptr addr, Uint32 l) {
395: if (addr%4) {
396: Log_Printf(LOG_WARN, "[TMC] Unaligned access.");
397: abort();
398: }
399:
400: if (addr==0x02210000) {
401: Log_Printf(LOG_WARN, "[TMC] Nitro register lput %08X at $%08X",l,addr);
402: if (ConfigureParams.System.nCpuFreq==40) {
403: tmc.nitro = l&0x0000011F;
404: } else {
405: Log_Printf(LOG_WARN, "[TMC] No nitro --> bus error!");
406: M68000_BusError(addr, 0);
407: }
408: return;
409: }
410:
411: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) {
412: adb_lput(addr, l);
413: return;
414: }
415:
416: Log_Printf(LOG_TMC_LEVEL, "[TMC] lput %08X to %08X",l,addr);
417:
418: addr &= TMC_REGS_MASK;
419:
420: if (addr<36) {
421: tmc_write_reg[addr](l>>24);
422: tmc_write_reg[addr+1](l>>16);
423: tmc_write_reg[addr+2](l>>8);
424: tmc_write_reg[addr+3](l);
425: } else if (addr>=128 && addr<144) {
426: tmc_write_vid_reg[addr&0xF](l>>24);
427: tmc_write_vid_reg[(addr+1)&0xF](l>>16);
428: tmc_write_vid_reg[(addr+2)&0xF](l>>8);
429: tmc_write_vid_reg[(addr+3)&0xF](l);
430: }
431: }
432:
433: void tmc_wput(uaecptr addr, Uint32 w) {
434: if (addr%2) {
435: Log_Printf(LOG_WARN, "[TMC] Unaligned access.");
436: abort();
437: }
438:
439: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) {
440: adb_wput(addr, w);
441: return;
442: }
443:
444: Log_Printf(LOG_TMC_LEVEL, "[TMC] wput %04X to %08X",w,addr);
445:
446: addr &= TMC_REGS_MASK;
447:
448: if (addr<36) {
449: tmc_write_reg[addr](w>>8);
450: tmc_write_reg[addr+1](w);
451: } else if (addr>=128 && addr<144) {
452: tmc_write_vid_reg[addr&0xF](w>>8);
453: tmc_write_vid_reg[(addr+1)&0xF](w);
454: }
455: }
456:
457: void tmc_bput(uaecptr addr, Uint32 b) {
458: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) {
459: adb_bput(addr, b);
460: return;
461: }
462:
463: Log_Printf(LOG_TMC_LEVEL, "[TMC] bput %02X to %08X",b,addr);
464:
465: addr &= TMC_REGS_MASK;
466:
467: if (addr<36) {
468: tmc_write_reg[addr](b);
469: } else if (addr>=128 && addr<144) {
470: tmc_write_vid_reg[addr&0xF](b);
471: }
472: }
473:
474:
475: /* TMC Reset */
476:
477: void TMC_Reset(void) {
478: TurboSCR1_Reset();
479:
480: tmc_video_reg_reset();
481: tmc.control = 0x0D17038F;
482: tmc.nitro = 0x00000000;
483: ADB_Reset();
484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.