]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/md/md.c
devcons: fix permissions for reboot and sysstat
[plan9front.git] / sys / src / games / md / md.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <draw.h>
5 #include <keyboard.h>
6 #include "../eui.h"
7 #include "dat.h"
8 #include "fns.h"
9
10 u16int *prg;
11 int nprg;
12 u8int *sram;
13 u32int sramctl, nsram, sram0, sram1;
14 int savefd = -1;
15
16 int dmaclock, vdpclock, z80clock, audioclock, ymclock, saveclock;
17
18 void
19 flushram(void)
20 {
21         if(savefd >= 0)
22                 pwrite(savefd, sram, nsram, 0);
23         saveclock = 0;
24 }
25
26 static void
27 loadbat(char *file)
28 {
29         static char buf[512];
30         
31         strncpy(buf, file, sizeof buf - 5);
32         strcat(buf, ".sav");
33         savefd = create(buf, ORDWR | OEXCL, 0666);
34         if(savefd < 0)
35                 savefd = open(buf, ORDWR);
36         if(savefd < 0)
37                 print("open: %r\n");
38         else
39                 readn(savefd, sram, nsram);
40 }
41
42 static void
43 loadrom(char *file)
44 {
45         static uchar hdr[512], buf[4096];
46         u32int v;
47         u16int *p;
48         int fd, rc, i;
49         
50         fd = open(file, OREAD);
51         if(fd < 0)
52                 sysfatal("open: %r");
53         if(readn(fd, hdr, 512) < 512)
54                 sysfatal("read: %r");
55         if(memcmp(hdr + 0x100, "SEGA MEGA DRIVE ", 16) != 0 && memcmp(hdr + 0x100, "SEGA GENESIS    ", 16) != 0)
56                 sysfatal("invalid rom");
57         v = hdr[0x1a0] << 24 | hdr[0x1a1] << 16 | hdr[0x1a2] << 8 | hdr[0x1a3];
58         if(v != 0)
59                 sysfatal("rom starts at nonzero address");
60         v = hdr[0x1a4] << 24 | hdr[0x1a5] << 16 | hdr[0x1a6] << 8 | hdr[0x1a7];
61         nprg = v = v+2 & ~1;
62         if(nprg == 0)
63                 sysfatal("invalid rom");
64         p = prg = malloc(v);
65         if(prg == nil)
66                 sysfatal("malloc: %r");
67         seek(fd, 0, 0);
68         while(v != 0){
69                 rc = readn(fd, buf, sizeof buf);
70                 if(rc == 0)
71                         break;
72                 if(rc < 0)
73                         sysfatal("read: %r");
74                 if(rc > v)
75                         rc = v;
76                 for(i = 0; i < rc; i += 2)
77                         *p++ = buf[i] << 8 | buf[i+1];
78                 v -= rc;
79         }
80         close(fd);
81         if(hdr[0x1b0] == 0x52 && hdr[0x1b1] == 0x41){
82                 sramctl = SRAM | hdr[0x1b2] >> 1 & ADDRMASK;
83                 if((hdr[0x1b2] & 0x40) != 0)
84                         sramctl |= BATTERY;
85                 sram0 = hdr[0x1b4] << 24 | hdr[0x1b5] << 16 | hdr[0x1b6] << 8 | hdr[0x1b7] & 0xfe;
86                 sram1 = hdr[0x1b8] << 24 | hdr[0x1b9] << 16 | hdr[0x1ba] << 8 | hdr[0x1bb] | 1;
87                 if(sram1 <= sram0){
88                         print("SRAM of size <= 0?\n");
89                         sramctl = 0;
90                 }else{
91                         nsram = sram1 - sram0;
92                         if((sramctl & ADDRMASK) != ADDRBOTH)
93                                 nsram >>= 1;
94                         sram = malloc(nsram);
95                         if(sram == nil)
96                                 sysfatal("malloc: %r");
97                         if((sramctl & BATTERY) != 0){
98                                 loadbat(file);
99                                 atexit(flushram);
100                         }
101                 }
102         }
103 }
104
105 void
106 usage(void)
107 {
108         fprint(2, "usage: %s [-a] [-x scale] rom\n", argv0);
109         exits("usage");
110 }
111
112 void
113 threadmain(int argc, char **argv)
114 {
115         int t;
116
117         ARGBEGIN{
118         case 'a':
119                 initaudio();
120                 break;
121         case 'x':
122                 fixscale = strtol(EARGF(usage()), nil, 0);
123                 break;
124         default:
125                 usage();
126         } ARGEND;
127         if(argc < 1)
128                 usage();
129         loadrom(*argv);
130         initemu(320, 224, 4, XRGB32, 1, nil);
131         regkey("a", 'c', 1<<5);
132         regkey("b", 'x', 1<<4);
133         regkey("y", 'z', 1<<12);
134         regkey("start", '\n', 1<<13);
135         regkey("up", Kup, 0x101);
136         regkey("down", Kdown, 0x202);
137         regkey("left", Kleft, 1<<2);
138         regkey("right", Kright, 1<<3);
139         cpureset();
140         vdpmode();
141         ymreset();
142         for(;;){
143                 if(paused != 0){
144                         qlock(&pauselock);
145                         qunlock(&pauselock);
146                 }
147                 if(dma != 1){
148                         t = step() * CPUDIV;
149                         if(dma != 0)
150                                 dmastep();
151                 }else{
152                         t = CPUDIV;
153                         dmastep();
154                 }
155                 z80clock -= t;
156                 vdpclock -= t;
157                 audioclock += t;
158                 ymclock += t;
159
160                 while(vdpclock < 0){
161                         vdpstep();
162                         vdpclock += 8;
163                 }
164                 while(z80clock < 0)
165                         z80clock += z80step() * Z80DIV;
166                 while(audioclock >= SAMPDIV){
167                         audiosample();
168                         audioclock -= SAMPDIV;
169                 }
170                 while(ymclock >= YMDIV){
171                         ymstep();
172                         ymclock -= YMDIV;
173                 }
174                 if(saveclock > 0){
175                         saveclock -= t;
176                         if(saveclock <= 0){
177                                 saveclock = 0;
178                                 flushram();
179                         }
180                 }
181         }
182 }
183
184 void
185 flush(void)
186 {
187         flushmouse(1);
188         flushscreen();
189         flushaudio(audioout);
190 }