base:using_a_running_vice_session_for_development
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
base:using_a_running_vice_session_for_development [2016-06-27 20:31] – compyx | base:using_a_running_vice_session_for_development [2016-07-01 13:35] (current) – compyx | ||
---|---|---|---|
Line 1: | Line 1: | ||
===== Using a running VICE session for development ===== | ===== Using a running VICE session for development ===== | ||
+ | |||
+ | **note: work in progress** | ||
==== Introduction ==== | ==== Introduction ==== | ||
Line 9: | Line 11: | ||
This article attempts to explain that process. For now, only for *nix systems. | This article attempts to explain that process. For now, only for *nix systems. | ||
+ | Please note that I use a SVN snapshot of VICE, installed into /usr/local, so you may have to adjust a few paths, such as the location of the C64 kernal image. | ||
+ | |||
==== Requirements ==== | ==== Requirements ==== | ||
Line 19: | Line 23: | ||
* make for making things easier | * make for making things easier | ||
- | Obviously we need an assembler, one which can output VICE labels if you want to use that feature. I personally use 64tass (again, build a current version). | + | Obviously we need an assembler, one which can output VICE labels if you want to use that feature. I personally use 64tass (again, build a current version, r1184 added support for scoped labels, eg: .foo:bar). |
- | And of course a decent editor, one which can at least syntax highlight Makefile' | + | And of course a decent editor, one which can at least syntax highlight Makefile' |
Line 28: | Line 32: | ||
Getting VICE to act as a ' | Getting VICE to act as a ' | ||
- | < | + | < |
This will tell VICE to listen on port 6510 for connections. Now we can use netcat or telnet to send commands: | This will tell VICE to listen on port 6510 for connections. Now we can use netcat or telnet to send commands: | ||
- | < | + | < |
compyx@aspire-7740 ~ $ telnet localhost 6510 | compyx@aspire-7740 ~ $ telnet localhost 6510 | ||
Trying 127.0.0.1... | Trying 127.0.0.1... | ||
Line 45: | Line 49: | ||
We just told VICE to perform a soft reset. By using telnet we started an interactive session with the monitor, which halted the emulation, we can also send commands while the emulation keeps going, using netcat: | We just told VICE to perform a soft reset. By using telnet we started an interactive session with the monitor, which halted the emulation, we can also send commands while the emulation keeps going, using netcat: | ||
- | < | + | < |
Same thing, but this command returns immediately, | Same thing, but this command returns immediately, | ||
Line 58: | Line 62: | ||
We need to store $9f in $fd69 in the KERNAL to achieve this. This cannot be done using the monitor, we need to patch the actual KERNAL file of VICE and then tell VICE to use the patched KERNAL. Patching goes something like this: | We need to store $9f in $fd69 in the KERNAL to achieve this. This cannot be done using the monitor, we need to patch the actual KERNAL file of VICE and then tell VICE to use the patched KERNAL. Patching goes something like this: | ||
- | < | + | < |
- | cp /usr/lib/ | + | cp /usr/local/lib64/ |
echo "1d69: 9f" | xxd -r - kernal-quick-memtest | echo "1d69: 9f" | xxd -r - kernal-quick-memtest | ||
</ | </ | ||
Any method of altering a binary can be used, I prefer to do it this way, so I can stick it in a Makefile and never have to worry about whether I patched the KERNAL or not. | Any method of altering a binary can be used, I prefer to do it this way, so I can stick it in a Makefile and never have to worry about whether I patched the KERNAL or not. | ||
- | This makes the BASIC memtest finish immediately and still report the correct number of bytes free. (Thanks a lot to iAN CooG for suggesting this!) | + | This makes the BASIC memtest finish |
VICE still needs to know about this new KERNAL, so the command to start VICE becomes: | VICE still needs to know about this new KERNAL, so the command to start VICE becomes: | ||
- | < | + | < |
These are all the commands VICE needs to start a proper session, the rest we can do with the remote monitor. | These are all the commands VICE needs to start a proper session, the rest we can do with the remote monitor. | ||
Line 80: | Line 84: | ||
To automate the tedious process of patching the kernal and starting VICE with the proper arguments, I use a Makefile. For now it looks like this: | To automate the tedious process of patching the kernal and starting VICE with the proper arguments, I use a Makefile. For now it looks like this: | ||
- | < | + | < |
+ | # VICE's x64 binary | ||
+ | X64=/ | ||
+ | # Standard flags to pass to VICE during startup | ||
+ | X64_FLAGS= | ||
# Original KERNAL | # Original KERNAL | ||
- | KERNAL=/ | + | KERNAL=/ |
# Patched KERNAL | # Patched KERNAL | ||
KERNAL_PATCHED=kernal-quick-memtest | KERNAL_PATCHED=kernal-quick-memtest | ||
+ | |||
# Generate patched KERNAL for faster reset (skip BASIC memtest) | # Generate patched KERNAL for faster reset (skip BASIC memtest) | ||
Line 91: | Line 100: | ||
cp $(KERNAL) $(KERNAL_PATCHED) | cp $(KERNAL) $(KERNAL_PATCHED) | ||
echo "1d69: 9f" | xxd -r - $(KERNAL_PATCHED) | echo "1d69: 9f" | xxd -r - $(KERNAL_PATCHED) | ||
+ | |||
+ | |||
+ | # Start VICE session with remote monitor and patched KERNAL | ||
+ | session: $(KERNAL_PATCHED) | ||
+ | $(X64) -remotemonitor -kernal $(KERNAL_PATCHED) | ||
+ | |||
</ | </ | ||
+ | |||
+ | This creates two rules: one to generate a patched KERNAL, and one to start the VICE remote monitor session. The session depends on the patched KERNAL, which is created if it doesn' | ||
+ | |||
+ | So now the VICE session start up is as simple as: | ||
+ | <code bash> | ||
+ | |||
+ | Of course this will keep your shell busy until you quit VICE, so if you just want to set up the session and return to the shell, you can do something like this: | ||
+ | <code bash> | ||
+ | This will run the the session in the background while redirecting VICE's stdout and stderr to /dev/null, this avoids having to open another shell for running other commands, and keeping the shell clean. You can also adjust the Makefile to do this for you: | ||
+ | |||
+ | <code make> | ||
+ | # Start VICE session with remote monitor and patched KERNAL in the background | ||
+ | session: $(KERNAL_PATCHED) | ||
+ | $(X64) -remotemonitor -kernal $(KERNAL_PATCHED) \ | ||
+ | > /dev/null 2>&1 & | ||
+ | </ | ||
+ | |||
+ | == Access VICE's output == | ||
+ | |||
+ | If you want to see VICE's messages, you redirect stdout and stderr to log files, which you inspect later, or just '' | ||
+ | |||
+ | <code make> | ||
+ | # VICE's x64 binary | ||
+ | X64=/ | ||
+ | # Standard flags to pass to VICE during startup | ||
+ | X64_FLAGS= | ||
+ | |||
+ | # Log file for x64's stdout (VICE' | ||
+ | X64_STDOUT=vice.log | ||
+ | # Log file for x64's stderr | ||
+ | X64_STDERR=vice.err (useful when debug VICE itself) | ||
+ | |||
+ | |||
+ | # Rule to start VICE with remote monitor, with patched KERNAl for quicker | ||
+ | # reset and running it in the background with any output of VICE redirected to | ||
+ | # log files | ||
+ | session: $(KERNAL_PATCHED) | ||
+ | $(X64) $(X64_FLAGS) -remotemonitor -kernal $(KERNAL_PATCHED) \ | ||
+ | 1> | ||
+ | </ | ||
+ | |||
+ | ==== Setting up the client side ==== | ||
+ | |||
+ | Now that we have a running VICE session, we can start with the client side of things, that is, assembling our binary and injecting it into VICE and start it. And if need be, loading labels into the monitor for debugging and/or attaching disk images to VICE. | ||
+ | |||
+ | This is where netcat comes in, we can send commands to VICE with netcat. Let's assume we have a single source file ' | ||
+ | <code bash> | ||
+ | 64tass -a -C -o demo.prg demo.s | ||
+ | </ | ||
+ | We can now insert this into VICE and run it: | ||
+ | <code bash> | ||
+ | # first reset VICE | ||
+ | echo 'reset 0' | netcat localhost 6510 | ||
+ | # insert binary into VICE | ||
+ | echo 'l " | ||
+ | # run demo.prg | ||
+ | echo 'g 080d' | netcat localhost 6510 | ||
+ | </ | ||
+ | |||
+ | Again, this becomes tedious, having to type this again and again, so we update our Makefile (just the new parts for now): | ||
+ | <code make> | ||
+ | ASM=64tass | ||
+ | |||
+ | |||
+ | # Default make target: just assemble the program: | ||
+ | all: demo.prg | ||
+ | |||
+ | |||
+ | # Assemble program | ||
+ | demo.prg: demo.s | ||
+ | $(ASM) -a -C -o demo.prg demo.s | ||
+ | |||
+ | |||
+ | # Inject program into VICE session and run it | ||
+ | run: demo.prg | ||
+ | # we need to wait one second for the reset to finish, so we use -q 1 | ||
+ | echo 'reset 0' | netcat -q 1 localhost 6510 | ||
+ | # load demo.prg from the virtual FS, our host OS | ||
+ | echo 'l " | ||
+ | # this assumes demo.prg starts at $080d | ||
+ | echo 'g 080d' | netcat localhost 6510 | ||
+ | </ | ||
+ | |||
+ | The `-q 1` argument to netcat is required to allow the reset to properly finish. netcat does not wait for VICE to complete its task, it immediately exits on EOF, so we use `-q 1` to tell netcat to wait one second after EOF. You could also use `sleep 1` after issuing 'reset 0', it has the same effect (adjust to sleep 3 when using a non-patched KERNAL). | ||
+ | |||
+ | Since the ' | ||
+ | |||
+ | |||
+ | === Loading labels into VICE === | ||
+ | |||
+ | The same goes for loading labels into VICE: since we use a running instance, when we do ' | ||
+ | <code bash> | ||
+ | echo ' | ||
+ | echo ' | ||
+ | </ | ||
+ | Again giving VICE time to process the ' | ||
+ | |||
+ | So, lets update our Makefile once again (nearly complete Makefile now): | ||
+ | <code make> | ||
+ | # vim: noet ts=8 sw=8 sts=8 | ||
+ | # | ||
+ | # Makefile for CB64 article 'Using a running VICE session for development' | ||
+ | |||
+ | # This uses an SVN build of VICE, so adjust the paths to the x64 binary and | ||
+ | # the KERNAL if using the 2.4 stable build (which is way too old) | ||
+ | |||
+ | |||
+ | # Assembler (Soci' | ||
+ | ASM=64tass | ||
+ | # Assembler flags (see the 64tass manual) | ||
+ | ASM_FLAGS=--ascii --case-sensitive --shadow-check --m6502 | ||
+ | # Flags needed to output VICE labels (see the 64tass manual) | ||
+ | ASM_LABELS=--vice-labels -l $(LABEL_FILE) | ||
+ | |||
+ | # file to output VICE labels to | ||
+ | LABEL_FILE=labels.txt | ||
+ | |||
+ | |||
+ | # VICE's x64 binary | ||
+ | X64=/ | ||
+ | # Standard flags to pass to VICE during startup | ||
+ | X64_FLAGS= | ||
+ | # Log file for x64's stdout output | ||
+ | X64_STDOUT=vice.log | ||
+ | # Log file for x64's stderr output | ||
+ | X64_STDERR=vice.err | ||
+ | |||
+ | |||
+ | # Our demo binary | ||
+ | TARGET=demo.prg | ||
+ | |||
+ | # Original KERNAL | ||
+ | KERNAL=/ | ||
+ | # Patched KERNAL | ||
+ | KERNAL_PATCHED=kernal-quick-memtest | ||
+ | |||
+ | |||
+ | # Default make target, just our binary | ||
+ | all: $(TARGET) | ||
+ | |||
+ | |||
+ | # Rule to assemble our binary and output labels for VICE | ||
+ | $(TARGET): demo.s | ||
+ | $(ASM) $(ASM_FLAGS) $(ASM_LABELS) -o $@ $< | ||
+ | |||
+ | |||
+ | # Rule to patch the KERNAL for quicker reset | ||
+ | $(KERNAL_PATCHED): | ||
+ | cp $(KERNAL) $(KERNAL_PATCHED) | ||
+ | echo "1d69: 9f" | xxd -r - $(KERNAL_PATCHED) | ||
+ | |||
+ | |||
+ | # Rule to start VICE with remote monitor, with patched KERNAl for quicker | ||
+ | # reset and running it in the background with any output of VICE redirected to | ||
+ | # log file files | ||
+ | session: $(KERNAL_PATCHED) | ||
+ | $(X64) $(X64_FLAGS) -remotemonitor -kernal $(KERNAL_PATCHED) \ | ||
+ | 1> | ||
+ | |||
+ | |||
+ | # Rule to inject the program file and run it | ||
+ | run: $(TARGET) | ||
+ | # reset machine and wait for 1 second after EOF from machine | ||
+ | echo 'reset 0' | netcat -q1 localhost 6510 | ||
+ | |||
+ | # optional: load labels (we have to wait for one second to allow the | ||
+ | # command to complete) | ||
+ | echo ' | ||
+ | echo ' | ||
+ | |||
+ | # load binary | ||
+ | echo 'l " | ||
+ | # execute binary, ignoring BASIC interpreter | ||
+ | echo 'g 080d' | netcat localhost 6510 | ||
+ | |||
+ | |||
+ | # Clean up | ||
+ | .PHONY: clean | ||
+ | clean: | ||
+ | rm -f demo.prg | ||
+ | rm -f $(KERNAL_PATCHED) | ||
+ | </ | ||
+ | |||
+ | There you have it, running and debugging code with a live VICE session, avoiding a lot of start up time. Unfortunately, | ||
+ | |||
+ | |||
+ | == Proper BASIC initialization == | ||
+ | |||
+ | Since we bypass the C64's OS (the BASIC interpreter), | ||
+ | |||
+ | So we need a way to do a proper ' | ||
+ | |||
+ | Let's assume our demo.s looks like this: | ||
+ | <code 6502tasm> | ||
+ | * = $0801 | ||
+ | | ||
+ | ; BASIC section: this becomes "2016 sys2061" | ||
+ | .word (+), 2016 | ||
+ | .null $9e, ^start | ||
+ | + .word 0 | ||
+ | |||
+ | start ; this is $080d | ||
+ | lda #0 | ||
+ | sta $d020 | ||
+ | sta $d021 | ||
+ | rts | ||
+ | </ | ||
+ | |||
+ | When we run this using the Makefile shown, the border and background turn black, but we get a blinking cursor. So we need to somehow force BASIC to properly run this SYS line. This can be done with a little tweaking: | ||
+ | (Thanks to Groepaz for coming up with the suggestion of simply putting ' | ||
+ | |||
+ | First we load the binary into VICE, then we set the end-of-basic pointer to $080d, fill the keyboard buffer with " | ||
+ | <code bash> | ||
+ | # reset, and wait, otherwise the BASIC start-of-basic pointer gets overwritten to $0000 while loading | ||
+ | echo 'reset 0' | netcat -q 1 localhost 6510 | ||
+ | # load binary | ||
+ | echo 'l " | ||
+ | # put ' | ||
+ | echo 'f 0277 027a 52 55 4e 0d' | netcat localhost 6510 | ||
+ | # set keyboard buffer size to $04 -> strlen(" | ||
+ | echo 'f 00c6 00c6 04' | netcat localhost 6510 | ||
+ | </ | ||
+ | |||
+ | Putting this in our Makefile, we end up with this: | ||
+ | <code make> | ||
+ | # vim: noet ts=8 sw=8 sts=8 | ||
+ | # | ||
+ | # Makefile for CB64 article 'Using a running VICE session for development' | ||
+ | |||
+ | # This uses an SVN build of VICE, so adjust the paths to the x64 binary and | ||
+ | # the KERNAL if using the 2.4 stable build (which is way too old) | ||
+ | |||
+ | |||
+ | # Assembler (Soci' | ||
+ | ASM=64tass | ||
+ | # Assembler flags (see the 64tass manual) | ||
+ | ASM_FLAGS=--ascii --case-sensitive --shadow-check --m6502 | ||
+ | # Flags needed to output VICE labels (see the 64tass manual) | ||
+ | ASM_LABELS=--vice-labels -l $(LABEL_FILE) | ||
+ | |||
+ | # file to output VICE labels to | ||
+ | LABEL_FILE=labels.txt | ||
+ | |||
+ | |||
+ | # VICE's x64 binary | ||
+ | X64=/ | ||
+ | # Standard flags to pass to VICE during startup | ||
+ | X64_FLAGS= | ||
+ | # Log file for x64's stdout output | ||
+ | X64_STDOUT=vice.log | ||
+ | # Log file for x64's stderr output | ||
+ | X64_STDERR=vice.err | ||
+ | |||
+ | |||
+ | # Our demo binary | ||
+ | TARGET=demo.prg | ||
+ | |||
+ | # Original KERNAL | ||
+ | KERNAL=/ | ||
+ | # Patched KERNAL | ||
+ | KERNAL_PATCHED=kernal-quick-memtest | ||
+ | |||
+ | |||
+ | # Default make target, just our binary | ||
+ | all: $(TARGET) | ||
+ | |||
+ | |||
+ | # Rule to assemble our binary and output labels for VICE | ||
+ | $(TARGET): demo.s | ||
+ | $(ASM) $(ASM_FLAGS) $(ASM_LABELS) -o $@ $< | ||
+ | |||
+ | |||
+ | # Rule to patch the KERNAL for quicker reset | ||
+ | $(KERNAL_PATCHED): | ||
+ | cp $(KERNAL) $(KERNAL_PATCHED) | ||
+ | echo "1d69: 9f" | xxd -r - $(KERNAL_PATCHED) | ||
+ | |||
+ | |||
+ | # Rule to start VICE with remote monitor, with patched KERNAl for quicker | ||
+ | # reset and running it in the background with any output of VICE redirected to | ||
+ | # log file files | ||
+ | session: $(KERNAL_PATCHED) | ||
+ | $(X64) $(X64_FLAGS) -remotemonitor -kernal $(KERNAL_PATCHED) \ | ||
+ | 1> | ||
+ | |||
+ | |||
+ | # Rule to inject the program file and run it | ||
+ | run: $(TARGET) | ||
+ | # reset machine and wait for 1 second after EOF from machine | ||
+ | echo 'reset 0' | netcat -q1 localhost 6510 | ||
+ | |||
+ | # optional: load labels (we have to wait for one second to allow the | ||
+ | # command to complete) | ||
+ | echo ' | ||
+ | echo ' | ||
+ | |||
+ | # load binary | ||
+ | echo 'l " | ||
+ | # run binary by putting ' | ||
+ | echo 'f 0277 027a 52 55 4e 0d' | netcat localhost 6510 | ||
+ | echo 'f 00c6 00c6 04' | netcat localhost 6510 | ||
+ | # now the BASIC interpreter notices it has data in its buffer and parses that, | ||
+ | # resulting in a proper RUN being executed for our program. Even the KERNAL | ||
+ | # itself does it, just look at $e5ee, the handler for Shift+Run/ | ||
+ | |||
+ | |||
+ | .PHONY: clean | ||
+ | clean: | ||
+ | rm -f $(KERNAL_PATCHED) | ||
+ | rm -f $(LABEL_FILE) $(X64_STDOUT) $(X64_STDERR) | ||
+ | rm -f $(TARGET) | ||
+ | </ | ||
+ | |||
+ | |||
+ | More later.. | ||
+ | |||
+ | TODO: | ||
+ | * attaching disk images | ||
+ | * debugging via telnet | ||
+ | * < | ||
+ | * VIM integration | ||
base/using_a_running_vice_session_for_development.1467052269.txt.gz · Last modified: 2016-06-27 20:31 by compyx