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 +/