1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
utils = {}
-- Returns the root path for the project.
function utils.RootPath()
local fullpath = debug.getinfo(1,"S").source:sub(2)
fullpath = io.popen("realpath '"..fullpath.."'", 'r'):read()
fullpath = fullpath:gsub('[\n\r]*$','')
local dirname, filename = fullpath:match('^(.*/)([^/]-)$')
dirname = dirname or ''
if dirname == '' then
return ''
end
return io.popen("realpath '"..dirname.."/..'", 'r'):read()
end
-- At a `label` that exists on the assembly code grab the values for the given
-- addresses and write it all into the `test-results.txt` file. The `addresses`
-- array is made up of two-sized arrays, where the first element contains the
-- memory you are trying to test, and the second element is the value that we
-- are expecting.
function utils.MemTest(label, addresses)
local cmd = "cat ".. utils.RootPath() .. "/out/labels.txt | grep .".. label .." | awk '{ print $2; }' | cut -c3-"
local file = assert(io.popen(cmd, 'r'))
local result = file:read("*a")
-- Double check that the address that we grabbed has at least a good format.
if string.len(result) ~= 5 then
error("Error on '" .. label .. "': got a bad address! (".. result ..")")
end
-- Register a function to execute on the given test address. The function will
-- simply iterate over the given `addresses` and compare them with the
-- expected result. Everything will be saved into the `test-results.txt` file.
memory.registerexecute(tonumber(result, 16), function()
local expected = ""
local got = ""
for _, vals in ipairs(addresses) do
expected = expected .. "$" .. string.format("%04X", vals[1]) .. " -> " .. vals[2] .. "; "
got = got .. "$" .. string.format("%04X", vals[1]) .. " -> " .. string.format("%02X", memory.readbyte(vals[1])) .. "; "
end
file = io.open(utils.RootPath() .. "/out/test-results.txt", "a")
io.output(file)
if expected == got then
io.write("OK\n")
else
io.write("FAIL\n")
io.write("Expected: ".. expected .. "\n")
io.write("Got: ".. got .. "\n")
end
io.close(file)
end)
end
function utils.StartRun(title)
file = io.open(utils.RootPath() .. "/out/test-results.txt", "a")
io.output(file)
io.write(title .. ": ")
io.close(file)
end
-- Ends the given test run. That is, it will exit from the emulator so we can
-- turn back to the runner.
function utils.EndRun()
-- I'm not entirely sure why this is needed, but if we don't advance for
-- several frames fceux won't exit. Thus, let's advance for some frames and
-- then quit.
for i = 0, 10, 1 do
emu.frameadvance();
end
emu.exit()
end
return utils
|