Hi
I have been wanting to make a unit test suite of my c64 library code, and was thinking of using the awesome vice monitor for that.
Using the commandline, vice accepts a monitor-command script using the "-moncommand" switch, which seems perfect for this.
The problem is that some of the commands are not working properly. Some even crash vice. But they almost seem to work.
I realize that the manual states that some commands might not work properly from scripts, but there are a few quite central commands (for my use case at least) that does not work, so i am hoping this could be looked into. :)
To put this into context, this is what i am trying to do: (This section can be skipped)
My "test suite runner" code (made in some programming or batch language) should launch VICE with the prg to test and a monitor script. The purpose of the script is to get data out of vice (the "test result" values).
The monitor-script waits for certain condition (using the "until" command for example), then dumps the memory the c64 code has written its result to into a file (or dumps the current rasterline and cycle or both) - sometimes this is only 1 byte, sometimes much more.
The "test suite runner" code now checks if the bytes in the file written by VICE (the actual result) corresponds to what the bytes should be (the expected result).
(To avoid having to start/stop vice for each test, to decrease the time it takes running the tests, the monitor script should probably load and run the prg itself instead of autostarting the prg - and it should be a single monitor-script for all tests).
.
Let me give some examples.
In the examples below i just want to run a prg containing this c64 code:
.pc = $1000
ldx #0
loop: txa
sta $0400,x
inx
bne loop
jmp stop
.pc = $2000
stop: jmp * // <- when the cpu goes here, the monitor-script will proceed and save $0400-$0500 to a file (that memory contains the "result")
and dump the memory $0400-$04FF to a file after it has run (when it reaches the "stop" address). That is what i'm trying to do and this is what i can't get working.
.
This is an example where i specify the prg file to load on the commandline:
The monitor script:
until 2000
bsave "output" 0 0400 04ff
quit
ran by the command
x64.exe -moncommands "vice-monitor-input.txt" -logfile "vicelog.txt" -autostartprgmode 1 -keybuf "sys 4096\n" input.prg
Result:
The output file "output" contains all zeroes, instead of 0,1,2,...,255.
(i.e. "until" and "quit" works, but "bsave" does not save the correct data)
.
This is an example where i specify the prg file to load in the monitor-script itself (probably the superior approach):
The monitor script:
until e5cf
load "input.prg" 0
g 1000
until 2000
bsave "output" 0 0400 04ff
quit
ran by the command
x64.exe -moncommands "vice-monitor-input.txt" -logfile "vicelog.txt"
Result:
Vice crashes with the message "An unexpected error occurred. Received signal 11 ()." (see attached screenshot)
It seems to be the "load" command causing this. The "g" command seems to be ignored...
In fact, it seems like the initial "until" command is ignored in this case, because the error message appears instantly, it does not wait for whatever address is written after "until" (which is a bit strange, because the "until" seemed to work in the previous example - it probably has something to do with "load"..?).
.
If we forget about testing and just run some random commands, this works:
d 0800
But this crashes vice:
m 0800
and so does this:
> 0400 01 02 03 04 05
(both of these crashes show the same "An unexpected error occurred. Received signal 11 ()." as above)
.
.
Hope you guys will find the time and motivation to fix this. I know you're doing this amazing work in your spare time, so i'm of course not expecting anything. It would however be nice if you could give me a indication if you think this will be done, or if i should start looking for other ways to test. :)
Let me know if you need more info from me. (Or if you know of a better way of testing c64 code)
Thank you guys for the great emulator!
VICE version used (I did try with a few others too): WinVICE-2.4.32-x86-r32264
P.S. Also attached vice logs of the crash of "example 2" and of a normal run - note that the "video_dx9" error also happens on normal runs.
Same thing happens on Linux. I've been looking at this for a while now, and as far as I can see, things fail at 'load foo'. Unfortunately the monitor parser is written in flex/yacc, which I'm not familiar with.
As a workaround, you could try using the remote monitor feature of VICE, that makes VICE act like a sort of 'server', I did a write up on that on codebase64
Last edit: compyx 2016-11-16
Thank you for your answer and sorry for delay :)
Yeah, it seems "load" causes a crash - but it is not limited to "load" (see example 3). There is also the problem from example 1, where "bsave" saves the wrong bytes but doesn't cause vice to crash.
Thanks for your suggestion to use the remote monitor. Great article, btw :) I've tried, but it is very slow and no matter what i write in the terminal, it responds with "Wrong syntax" (but that is for another bug report).
(since it seems like the remote monitor freezes vice while connected, i suppose it won't support breakpoints or "until" - but i guess you could use some "polling" strategy instead (except for waiting for some rasterline/cycle))
Is the code for parsing the interactive monitor commands different from the code parsing the monitor commands from the commandline? I doubt i will have the time to look into it and learn the codebase, but just for couriositys sake, perhaps you could point to the part of the code responsible for this?
P.S. Unrelated: Do you know how to get the current rasterline/cycle or wait for/break on a specific rasterline/cycle in the monitor? My manual reading skills seems to fail me :)
I can confirm that these problems still persist.
I tried the same as you did, create a unit test environment and ran into the same bugs you did.
When I use the -moncommands option the following happens:
This crashes the emulator with a segfault.
The monitor executes the loaded program and the monitor correctly stops at the watchpoint.
But at that point the memory dump has already been saved and contains nothing but zeros except for the ROM areas.
My version of VICE is 3.4 on a Debian testing system. (amd64)
I have not found a workaround for this problem which renders VICE useless for unit testing as far as I can see.
Your second script sets a watchpoint, but setting a watchpoint does not imply continuing execution until it is hit. Therefore it is correct that the save command is executed immediately afterwards, before anything is executed by the emulated system.
Yes, I see it now.
I only have now figured out how to handle the monitor after your comment. Please ignore the second bug I mentioned.
If anybody is still interested: This is the monitor script I came up with for unit testing:
The program Test.prg is loaded to c000. A simple jsr-routine to that address with following rts is added at 803. It is then started with the rts being watched.
In order for that to work I simply watched a random address in the basic loop, which ensures that everything is properly set up before the program is loaded.
Taking a look at this. The way -moncommands is currently implemented, it's only really useful for setting labels, breakpoints etc.
I made some changes in r38968 that upgrades -moncommands to support all commands. For example you can now load a prg, set a breakpoint, return to the emulator via 'g' . When the emulator hits the breakpoint and returns to the monitor, further commands are executed from the script (such as saving memory and then quitting)
This should make the -moncommands mechanism suitable for unit testing.
I didn't see any of the crashes mentioned in the original report, these are likely long fixed. But if you can help me replicate them I will fix them.
I tried it again in vice 3.4
The segmentation fault I encounter occurs if the moncommands-file contains the following line:
Upon further testing I found out that the following line does not cause a crash:
The specified address seems to be important. Some work and some don't.
please use a nightly build for testing - using the old 3.4 build doesn't really help at this point
I pulled the code, compiled and installed it.
The problem does not occur anymore.
FYI
The default behaviour of
-moncommandshas changed again, to execute the moncommands script just before the machine reset routine starts executing. However, you can now control when the script runs using-initbreak <address>or-initbreak ready. For the case that you want to load something and execute it, you'll need to use-initbreakto delay the execution of the moncommands script.