User Tools

Site Tools


base:using_a_running_vice_session_for_development

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
base:using_a_running_vice_session_for_development [2016-06-27 20:07] compyxbase:using_a_running_vice_session_for_development [2016-06-30 14:44] 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 10: Line 12:
  
  
-==== The basics ==== +==== Requirements ====
- +
-=== Requirements ===+
  
 A few tools are needed to get this working: A few tools are needed to get this working:
Line 26: Line 26:
  
  
-=== Setting up VICE ===+==== Setting up VICE ====
  
 Getting VICE to act as a 'server' isn't hard: Getting VICE to act as a 'server' isn't hard:
  
-<code>x64 -remotemonitor</code>+<code bash>x64 -remotemonitor</code>
  
 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:
-<code>+<code bash>
 compyx@aspire-7740 ~ $ telnet localhost 6510 compyx@aspire-7740 ~ $ telnet localhost 6510
 Trying 127.0.0.1... Trying 127.0.0.1...
Line 47: Line 47:
 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:
  
-<code>echo 'reset 0' | netcat localhost 6510</code> +<code bash>echo 'reset 0' | netcat localhost 6510</code> 
  
 Same thing, but this command returns immediately, it doesn't wait for the reset to finish, which is actually a bit of a nuisance (more on that later). The advantage is with other commands, such as clearing or loading labels, attaching disk images, injecting code/data, etc. Same thing, but this command returns immediately, it doesn't wait for the reset to finish, which is actually a bit of a nuisance (more on that later). The advantage is with other commands, such as clearing or loading labels, attaching disk images, injecting code/data, etc.
  
  
-== Patching the KERNAL for faster reset ==+=== Patching the KERNAL for faster reset ===
  
 This is optional, but makes a big difference when it comes to eliminating start-up time. This is optional, but makes a big difference when it comes to eliminating start-up time.
Line 60: Line 60:
 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:
  
-<code>+<code bash>
 cp /usr/lib/vice/C64/kernal kernal-quick-memtest cp /usr/lib/vice/C64/kernal kernal-quick-memtest
 echo "1d69: 9f" | xxd -r - kernal-quick-memtest echo "1d69: 9f" | xxd -r - kernal-quick-memtest
Line 66: Line 66:
 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 to iAN CooG for suggesting this!)+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!)
  
 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:
-<code>x64 -remotemonitor -kernal kernal-quick-memtest</code>+<code bash>x64 -remotemonitor -kernal kernal-quick-memtest</code>
  
 +These are all the commands VICE needs to start a proper session, the rest we can do with the remote monitor.
  
 +But first, let's automate something.
 +
 +
 +=== Automatic session setup ===
 +
 +== Makefile ==
 +
 +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:
    
 +<code make>
 +# x64 binary
 +X64 = /usr/local/bin/x64
 +
 +# Original KERNAL
 +KERNAL=/usr/lib/vice/C64/kernal
 +# Patched KERNAL
 +KERNAL_PATCHED=kernal-quick-memtest
 +
 +
 +# Generate patched KERNAL for faster reset (skip BASIC memtest)
 +$(KERNAL_PATCHED): $(KERNAL)
 + cp $(KERNAL) $(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)
 +
 +</code>
 +
 +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't exist.
 +
 +So now the VICE session start up is as simple as:
 +<code bash>make session</code>
 +
 +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>make session > /dev/null 2>&1 &</code>
 +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 &
 +</code>
 +
 +
 +==== 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 'demo.s' which we assemble into 'demo.prg'. We assemble this using 64tass:
 +<code bash>
 +64tass -a -C -o demo.prg demo.s
 +</code>
 +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 "demo.prg" 0' | netcat localhost 6510
 +# run demo.prg
 +echo 'g 080d' | netcat localhost 6510
 +</code>
 +
 +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 "demo.prg 0"' | netcat localhost 6510
 +        # this assumes demo.prg starts at $080d
 +        echo 'g 080d' | netcat localhost 6510
 +</code>
 +
 +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 'run' target depends on 'demo.prg', that file automatically gets (re)built whenever we issue `make run`, and when the building fails no data is inserted into VICE.
 +
 +
 +=== Loading labels into VICE ===
 +
 +The same goes for loading labels into VICE: since we use a running instance, when we do 'load_labels', the old labels are still there, so when we've altered our binary, the labels might be different, but VICE keeps the old ones. So we do:
 +<code bash>
 +echo 'clear_labels' | netcat -q 1 localhost 6510
 +echo 'load_labels "labels.txt"' | netcat localhost 6510
 +</code>
 +Again giving VICE time to process the 'clear_labels' command before sending the 'load_labels' command. Obviously not needed when issuing these commands from the shell, but using a Makefile, this is required.
 +
 +So, lets update our Makefile once again (full Makefile now):
 +<code make>
 +# x64 binary
 +X64=/usr/local/bin/x64
 +# Assembler
 +ASM=64tass
 +
 +# Original KERNAL
 +KERNAL=/usr/lib/vice/C64/kernal
 +# Patched KERNAL
 +KERNAL_PATCHED=kernal-quick-memtest
 +
 +
 +# Generate patched KERNAL for faster reset (skip BASIC memtest)
 +$(KERNAL_PATCHED): $(KERNAL)
 + cp $(KERNAL) $(KERNAL_PATCHED)
 + echo "1d69: 9f" | xxd -r - $(KERNAL_PATCHED)
 +all: demo.prg
 +
 +
 +# Assemble program and output VICE labels file
 +demo.prg: demo.s
 +        $(ASM) -a -C -o demo.prg demo.s --vice-labels -l labels.txt
 +
 +
 +# 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
 +        # clear and (re)load labels
 +        echo 'clear_labels' | netcat -q 1 localhost 6510
 +        echo 'load_labels "labels.txt"' | netcat localhost 6510
 +        # load demo.prg from the virtual FS, our host OS
 +        echo 'l "demo.prg 0"' | netcat localhost 6510
 +        # this assumes demo.prg starts at $080d
 +        echo 'g 080d' | netcat localhost 6510
 +
 +
 +# Start VICE session with remote monitor and patched KERNAL in the background
 +# redirecting VICE's output to a black hole
 +session: $(KERNAL_PATCHED)
 +        $(X64) -remotemonitor -kernal $(KERNAL_PATCHED) \
 +                > /dev/null 2>&1 &
 +
 +# Clean up
 +.PHONY: clean
 +clean:
 +        rm -f demo.prg
 +        rm -f $(KERNAL_PATCHED)
 +</code>
 +
 +There you have it, running and debugging code with a live VICE session, avoiding a lot of start up time. Unfortunately, when using this for code that **doesn't** set up IRQ's, we have a little problem.
 +
 +
 +== Proper BASIC initialization ==
 +
 +Since we bypass the C64's OS (the BASIC interpreter), when we execute code using the above method, the C64 doesn't know we executed a program and keeps the IRQ of the interpreter running, resulting in a nice blinking cursor.
 +
 +So we need a way to do a proper 'RUN' after injecting our program. We can do this with a simple SYS line and some tweaking of the <del>BASIC end-of-program pointer and</del> keyboard buffer.
 +
 +Let's assume our demo.s looks like this:
 +<code 64tass>
 +        * = $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
 +</code>
 +
 +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 'RUN' into the keyboard buffer!)
 +
 +First we load the binary into VICE, then we set the end-of-basic pointer to $080d, fill the keyboard buffer with "RUN\r" and let the magic happen:
 +<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 "demo.prg" 0' localhost 6510
 +# put 'RUN\r' into the keyboard buffer
 +echo 'f 0277 027a 52 55 4e 0d' | netcat localhost 6510
 +# set keyboard buffer size to $04 -> strlen("RUN\r")
 +echo 'f 00c6 00c6 04' | netcat localhost 6510
 +</code>
 +
 +Putting this in our Makefile, we end up with this:
 +<code make>
 +# x64 binary
 +X64 = /usr/local/bin/x64
 +# Assembler
 +ASM=64tass
 +
 +# Original KERNAL
 +KERNAL=/usr/lib/vice/C64/kernal
 +# Patched KERNAL
 +KERNAL_PATCHED=kernal-quick-memtest
 +
 +
 +# Generate patched KERNAL for faster reset (skip BASIC memtest)
 +$(KERNAL_PATCHED): $(KERNAL)
 + cp $(KERNAL) $(KERNAL_PATCHED)
 + echo "1d69: 9f" | xxd -r - $(KERNAL_PATCHED)
 +all: demo.prg
 +
 +
 +# Assemble program and output VICE labels file
 +demo.prg: demo.s
 +        $(ASM) -a -C -o demo.prg demo.s --vice-labels -l labels.txt
 +
 +
 +# 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
 +        # clear and (re)load labels
 +        echo 'clear_labels' | netcat -q 1 localhost 6510
 +        echo 'load_labels "labels.txt"' | netcat localhost 6510
 +        # load demo.prg from the virtual FS, our host OS
 +        echo 'l "demo.prg 0"' | netcat localhost 6510
 +        # put 'RUN\r' into the keyboard buffer
 +        echo 'f 0277 027a 52 55 4e 0d' | netcat localhost 6510
 +        # set keyboard buffer size to $04 -> strlen("RUN\r")
 +        echo 'f 00c6 00c6 04' | netcat localhost 6510
 +
 +
 +# Start VICE session with remote monitor and patched KERNAL in the background
 +# redirecting VICE's output to a black hole
 +session: $(KERNAL_PATCHED)
 +        $(X64) -remotemonitor -kernal $(KERNAL_PATCHED) \
 +                > /dev/null 2>&1 &
 +
 +# Clean up
 +.PHONY: clean
 +clean:
 +        rm -f demo.prg
 +        rm -f $(KERNAL_PATCHED)
 +</code>
 +
 +
 +More later..
 +
 +TODO:
 +  * attaching disk images
 +  * debugging via telnet
 +  * writing a proper Makefile (perhaps putting all those echo's into a file, updating it with sed)
 +  * VIM integration
  
base/using_a_running_vice_session_for_development.txt · Last modified: 2016-07-01 13:35 by compyx