1 /**
2  * DCPU-16 hardware timer clock
3  *
4  * See_Also:
5  *  http://dcpu.com/highnerd/rc_1/clock.txt
6  */
7 module dcpu.lem1802;
8 
9 import std.math;
10 import dcpu.hardware;
11 
12 import std.stdio;
13 
14 /+
15 class TimerClock: Hardware {
16 
17 protected:
18   /// Default font
19   enum ushort[256] default_font = [
20     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36   ]; // TODO
37   
38   /// Default color palette
39   enum ushort[16] default_palette = [0x000, 0x00a, 0x0a0, 0x0aa, 0xa00, 0xa0a, 0xa50, 0xaaa,
40                                      0x555, 0x55f, 0x5f5, 0x5ff, 0xf55, 0xf5f, 0xff5, 0xfff];
41   
42   ubyte border_color;       /// Border color
43   
44   ushort video_addr;        /// Were map VRAM
45   ushort font_addr;         /// Were map font ram
46   ushort pal_addr;          /// Were map pallete ram
47 
48   ushort[256] font;         /// Font ram
49   ushort[384] video;        /// Video ram
50   ushort[16] pal;           /// Palette ram
51 
52   bool show_logo;
53   
54 public:
55 
56   static this() {
57     id     = 0x7349f615;
58     ver    = 1802;
59     vendor = 0x1c6c8b36; // NYA ELEKTRISKA
60   }
61 
62   /**
63    * What to do when it's loaded in the dcpu machine
64    */
65   override void init() {
66     f_hwi = false;
67     n_bus_ticks = cast(long)floor(100000.0 / BaseFreq);
68     show_logo = false;
69   }
70 
71   /**
72    * What to do when a Hardware interrupt to this hardware, has receive
73    * Params:
74    *  state   = CPU editable actual state
75    *  ram     = RAM of the machine
76    */
77   override void interrupt(ref CpuInfo state, ref ushort[0x10000] ram) {
78     super.interrupt(state, ram);
79     switch (state.a) {
80       case 0: // MEM_MAP_SCREEN
81         if (state.b != 0)  {
82           show_logo = video_addr == 0;
83         }
84         video_addr = state.b;
85         break;
86         
87       case 1: // MEM_MAP_FONT
88         font_addr = state.b;
89         break;
90         
91       case 2: // MEM_MAP_PALETTE
92         pal_addr = state.b;
93         break;
94         
95       case 3: // SET_BORDER_COLOR
96         border_color = state.b & 0xF;
97         break;
98         
99       case 4: // MEM_DUMP_FONT
100         ushort e = cast(ushort)(default_font.length + state.b);
101         if (e > state.b) {
102           ram[state.b..e] = default_font[0..$];
103         } else {
104           ushort b = 0x10000 - state.b;
105           ram[state.b..$] = default_font[0..b];
106           ram[0..e] = default_font[b..$];
107         }
108         break;
109         
110       case 5: // MEM_DUMP_PALETTE
111         ushort e = cast(ushort)(default_palette.length + state.b);
112         if (e > state.b) {
113           ram[state.b..e] = default_palette[0..$];
114         } else {
115           ushort b = 0x10000 - state.b;
116           ram[state.b..$] = default_palette[0..b];
117           ram[0..e] = default_palette[b..$];
118         }
119         break;
120 
121       default:
122         // Do nothing
123     }
124   }
125 
126   /**
127    * What to do each clock tick (at 60 hz)
128    * Params:
129    *  state   = CPU editable actual state
130    *  cpu     = CPU
131    *  ram     = RAM of the machine
132    */
133   override
134   void tick_60hz(ref CpuInfo state, ref DCpu cpu, ref ushort[0x10000] ram) {
135     if (video_addr != 0) {
136       // Update video ram
137       ushort emap = cast(ushort)(video_addr+ video.length);
138       if (emap > video_addr) {
139         video[0..$] = ram[video_addr..emap];
140       } else {
141         ushort bmap = 0x10000 - video_addr;
142         video[0..bmap] = ram[video_addr..$];
143         video[bmap..$] = ram[0..bmap];
144       }
145 
146       // Update font ram
147       if (font_addr != 0) {
148         emap = cast(ushort)(font_addr+ font.length);
149         if (emap > font_addr) {
150           font[0..$] = ram[font_addr..emap];
151         } else {
152           ushort bmap = 0x10000 - font_addr;
153           font[0..bmap] = ram[font_addr..$];
154           font[bmap..$] = ram[0..bmap];
155         }
156       }
157 
158       // Update palette ram
159       if (pal_addr != 0) {
160         emap = cast(ushort)(pal_addr+ pal.length);
161         if (emap > pal_addr) {
162           pal[0..$] = ram[pal_addr..emap];
163         } else {
164           ushort bmap = 0x10000 - pal_addr;
165           pal[0..bmap] = ram[pal_addr..$];
166           pal[bmap..$] = ram[0..bmap];
167         }
168       }
169     }
170   }
171 }
172 
173 +/