1 /**
2 Copyright: Copyright (c) 2014 Andrey Penechko.
3 License: a$(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module emulator.dcpu.memoryview;
8 
9 import std..string;
10 import std.array;
11 import std.format;
12 import std.stdio;
13 import std.math : ceil;
14 
15 public import anchovy.gui.databinding.list;
16 
17 import emulator.dcpu.dcpu;
18 
19 class MemoryView(Cpu) : List!dstring
20 {
21 	Cpu* dcpu;
22 	ushort itemsPerLine = 8;
23 	bool collapseZeros = false;
24 	Appender!(ushort[]) nonZeroLines;
25 
26 	this(Cpu* dcpu)
27 	{
28 		this.dcpu = dcpu;
29 	}
30 
31 	private ushort valueAt(size_t index)
32 	{
33 		if (index >= 0x10000)
34 			return 0;
35 		else
36 			return dcpu.mem[index];
37 	}
38 
39 	void update()
40 	{
41 		if (!collapseZeros) return;
42 
43 		size_t pointer;
44 		nonZeroLines.shrinkTo(0);
45 
46 		while (pointer < 0x10000)
47 		{
48 			bool allZeros = true;
49 			foreach(i; 0..itemsPerLine)
50 			{
51 				if (valueAt(pointer + i) != 0)
52 				{
53 					allZeros = false;
54 					break;
55 				}
56 			}
57 
58 			if (!allZeros)
59 			{
60 				nonZeroLines ~= cast(ushort)pointer;
61 			}
62 
63 			pointer += itemsPerLine;
64 		}
65 	}
66 
67 	override dstring opIndex(size_t index)
68 	{
69 		auto writer = appender!dstring();
70 		ushort address;
71 
72 		if (collapseZeros)
73 		{
74 			if (index >= nonZeroLines.data.length) return "";
75 
76 			address = nonZeroLines.data[index];
77 		}
78 		else
79 		{
80 			address = cast(ushort)(index * itemsPerLine);
81 		}
82 
83 		formattedWrite(writer, "%04x: ", address);
84 
85 		foreach(i; 0..itemsPerLine)
86 		{
87 			size_t itemIndex = address + i;
88 			
89 			if (itemIndex < 0x10000)
90 				formattedWrite(writer, "%04X ", dcpu.mem[itemIndex]);
91 		}
92 		
93 		return writer.data;
94 	}
95 
96 	override dstring opIndexAssign(dstring data, size_t index)
97 	{
98 		return "";
99 	}
100 
101 	override size_t length() @property
102 	{
103 		if (collapseZeros)
104 			return nonZeroLines.data.length;
105 		else
106 			return cast(size_t)ceil(cast(float)0x10000 / itemsPerLine);
107 	}
108 
109 	override size_t push(dstring item)
110 	{
111 		return 0;
112 	}
113 
114 	override dstring remove(size_t index)
115 	{
116 		return "";
117 	}
118 }