1 /* -*- indent-tabs-mode:nil -*-
2 * Copyright (c) 2007 Jeremy English <jhe@jeremyenglish.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
12 * Created: 07-May-2007
18 #if defined(HAVE_STDINT_H)
20 #elif defined(HAVE_INTTYPES_H)
24 #include "screenhack.h"
29 __extension__ /* don't warn about "string length is greater than the length
30 ISO C89 compilers are required to support" when includng
31 the following data file... */
33 static const char * const demo_files[] = {
43 /* We want to paint on a 32 by 32 grid of pixels. We will needed to
44 divided the screen up into chuncks */
46 SCREEN_W = ANALOGTV_VIS_LEN,
47 SCREEN_H = ANALOGTV_VISLINES,
57 machine_6502 *machine;
61 analogtv_reception reception;
62 int pixw; /* pixel width */
63 int pixh;/* pixel height */
64 int topb;/* top boarder */
65 int field_ntsc[4];/* used for clearing the screen*/
66 double dt;/* how long to wait before changing the demo*/
67 int which;/* the program to run*/
68 int demos;/* number of demos included */
72 double last_frame, last_delay;
77 plot6502(Bit8 x, Bit8 y, Bit8 color, void *closure)
79 struct state *st = (struct state *) closure;
80 st->pixels[x][y] = color;
84 #define countof(x) (sizeof((x))/sizeof((*x)))
88 start_rand_bin_prog(machine_6502 *machine, struct state *st){
91 n = random() % st->demos;
93 m6502_start_eval_string(machine, demo_files[st->which], plot6502, st);
100 * returns the current time as a floating-point value
102 static double double_time(void) {
105 #if GETTIMEOFDAY_TWO_ARGS
106 gettimeofday(&t, NULL);
110 f = ((double)t.tv_sec) + t.tv_usec*1e-6;
115 m6502_init (Display *dpy, Window window)
117 struct state *st = (struct state *) calloc (1, sizeof(*st));
118 int n = get_float_resource(dpy, "displaytime", "Displaytime");
120 st->demos = countof(demo_files);
121 st->which = random() % st->demos;
125 st->tv=analogtv_allocate(st->dpy, st->window);
126 analogtv_set_defaults(st->tv, "");
128 st->machine = m6502_build();
129 st->inp=analogtv_input_allocate();
130 analogtv_setup_sync(st->inp, 1, 0);
132 st->reception.input = st->inp;
133 st->reception.level = 2.0;
136 st->reception.multipath=0.0;
137 st->pixw = SCREEN_W / 32;
138 st->pixh = SCREEN_H / 32;
142 st->last_frame = double_time();
144 st->ips = get_integer_resource(dpy, "ips", "IPS");
147 st->file = get_string_resource (dpy, "file", "File");
152 analogtv_lcp_to_ntsc(ANALOGTV_BLACK_LEVEL, 0.0, 0.0, st->field_ntsc);
154 analogtv_draw_solid(st->inp,
155 ANALOGTV_VIS_START, ANALOGTV_VIS_END,
156 ANALOGTV_TOP, ANALOGTV_BOT,
163 paint_pixel(struct state *st, int x, int y, int idx)
165 double clr_tbl[16][3] = {
185 /* RGB conversion taken from analogtv draw xpm */
186 rawy=( 5*clr_tbl[idx][0] + 11*clr_tbl[idx][1] + 2*clr_tbl[idx][2]) / 64;
187 rawi=(10*clr_tbl[idx][0] - 4*clr_tbl[idx][1] - 5*clr_tbl[idx][2]) / 64;
188 rawq=( 3*clr_tbl[idx][0] - 8*clr_tbl[idx][1] + 5*clr_tbl[idx][2]) / 64;
195 for (i=0; i<4; i++) {
196 if (ntsc[i]>ANALOGTV_WHITE_LEVEL) ntsc[i]=ANALOGTV_WHITE_LEVEL;
197 if (ntsc[i]<ANALOGTV_BLACK_LEVEL) ntsc[i]=ANALOGTV_BLACK_LEVEL;
204 analogtv_draw_solid(st->inp,
205 ANALOGTV_VIS_START + x, ANALOGTV_VIS_START + x + st->pixw,
206 ANALOGTV_TOP + y, ANALOGTV_TOP + y + st->pixh, ntsc);
210 m6502_draw (Display *dpy, Window window, void *closure)
212 struct state *st = (struct state *) closure;
213 unsigned int x = 0, y = 0;
214 double now, last_delay = st->last_delay >= 0 ? st->last_delay : 0;
215 double insno = st->ips * ((1 / 29.97) + last_delay - st->last_delay);
216 const analogtv_reception *reception = &st->reception;
218 if (st->reset_p){ /* do something more interesting here XXX */
220 for(x = 0; x < 32; x++)
221 for(y = 0; y < 32; y++)
222 st->pixels[x][y] = 0;
223 st->start_time = st->last_frame + last_delay;
226 if (st->file && *st->file)
227 m6502_start_eval_file(st->machine, st->file, plot6502, st);
230 start_rand_bin_prog(st->machine,st);
235 else if (insno > 100000) /* Real 6502 went no faster than 3 MHz. */
237 m6502_next_eval(st->machine,insno);
239 for (x = 0; x < 32; x++)
240 for (y = 0; y < 32; y++)
241 paint_pixel(st,x,y,st->pixels[x][y]);
243 analogtv_reception_update(&st->reception);
244 analogtv_draw(st->tv, 0.04, &reception, 1);
246 st->last_delay = (1 / 29.97) + st->last_frame + last_delay - now;
247 st->last_frame = now;
249 if (now - st->start_time > st->dt)
252 return st->last_delay >= 0 ? st->last_delay * 1e6 : 0;
258 static const char *m6502_defaults [] = {
259 ".background: black",
260 ".foreground: white",
262 "*displaytime: 30.0", /* demoscene: 24s, dmsc: 48s, sierpinsky: 26s
263 sflake, two runs: 35s
265 "*ips: 15000", /* Actual MOS 6502 ran at least 1 MHz. */
270 static XrmOptionDescRec m6502_options [] = {
271 { "-file", ".file", XrmoptionSepArg, 0 },
272 { "-displaytime", ".displaytime", XrmoptionSepArg, 0},
273 { "-ips", ".ips", XrmoptionSepArg, 0},
279 m6502_reshape (Display *dpy, Window window, void *closure,
280 unsigned int w, unsigned int h)
282 struct state *st = (struct state *) closure;
283 analogtv_reconfigure (st->tv);
287 m6502_event (Display *dpy, Window window, void *closure, XEvent *event)
289 struct state *st = (struct state *) closure;
290 if (screenhack_event_helper (dpy, window, event))
299 m6502_free (Display *dpy, Window window, void *closure)
301 struct state *st = (struct state *) closure;
302 analogtv_release(st->tv);
307 XSCREENSAVER_MODULE ("m6502", m6502)