Skip to content

Commit

Permalink
added true C64 emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Sep 21, 2019
1 parent 7af0356 commit 66588e0
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 104 deletions.
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
... Or is it?

Well, it emulates the character mode *with sprites* quite well and thus you can display pretty PETSCII pictures if you want.
It's generally not possible to run actual C-64 software, but that's not the goal
It's generally not possible to run actual C-64 software, but that's not the real goal
of this project. (Look at actual c-64 emulators such as Vice or CCS64 if you want that)


Expand All @@ -19,15 +19,22 @@ you can only do the same things with it as what is supported
for the BASIC mode. So no fancy screen scrolling or rasterbars...


## can load and use real C64 ROMs
## Can run the real BASIC and KERNAL roms! True C64 emulation!

If basic/kernal/chargen ROM files are supplied in the roms folder,
the simulator will load these and make them part of the memory of the machine as ROM areas.
You can actually call machine code routines from the roms!
Such as the well-known reset routine, SYS 64738 .
The simulator will use this routine as well when the machine is reset!
(just a few slight kernel patches are made to make it compatible and to avoid ending
up in the actual ROM BASIC program loop - that doesn't work for now)
If you run the ``startreal64`` program, it will load the ``realemulator`` module
instead of the simulated one, and will *actually run the C64 BASIC ROM*.

You can type anything in BASIC that you could type on a real C64 too!

Unfortunately, the I/O is not emulated so it is not possible to load or save
your programs in this mode.

On my machine the current code runs at around 0.6 Mhz in regular Python
(around half the speed of a real c64),
and between 2 and 3 Mhz in Pypy (there is a lot more speed than this obtainable
with pypy, but that makes the c64's basic mode more or less unusable)


## BASIC V2 and the VIC-registers (video chip)
Expand Down Expand Up @@ -106,9 +113,12 @@ are included on the 'virtual disk' in this project)

PETSCII image:

![Screenshot two](demo_screenshot2.png)
![Screenshot](demo_screenshot2.png)

Python mode:

![Screenshot two](demo_screenshot3.png)
![Screenshot](demo_screenshot3.png)

Real emulation of a C64:

![Screenshot](demo_screenshot4.png)
Binary file added demo_screenshot4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 29 additions & 11 deletions pyc64/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import tkinter
import pkgutil
import threading
import time
import queue
import time
from collections import deque
Expand Down Expand Up @@ -127,8 +128,9 @@ def __init__(self, screen, title, roms_directory):
self.canvas.tag_raise(self.border3)
self.border4 = self.canvas.create_rectangle(*b4, outline="", fill="#000")
self.canvas.tag_raise(self.border4)
self.bind("<KeyPress>", self.keypress)
# self.bind("<KeyPress>", self.keypress)
self.bind("<KeyRelease>", self.keyrelease)
self.bind("<Key>", self.keypress)
self.canvas.pack()

def start(self):
Expand Down Expand Up @@ -234,6 +236,7 @@ def repaint(self):
if configure:
# reconfigure all changed properties in one go
self.canvas.itemconfigure(self.spritebitmaps[snum], **configure)
self.update_idletasks()
self.refreshtick.set()

def smoothscroll(self, xs, ys):
Expand Down Expand Up @@ -319,17 +322,20 @@ class C64EmulatorWindow(EmulatorWindowBase):
"use 'gopy' to enter Python mode\n\n\n\n" \
"(install the py64 library to be able to execute 6502 machine code)"

def __init__(self, screen, title, roms_directory):
def __init__(self, screen, title, roms_directory, run_real_roms):
super().__init__(screen, title, roms_directory)
self.screen.memory[0x00fb] = EmulatorWindowBase.update_rate
self.hertztick = threading.Event()
self.interpret_thread = None
self.interpreter = None
self.real_cpu_running = None
self.run_real_roms = run_real_roms

def start(self):
super().start()
self._cyclic_herztick()
self._cyclic_blink_cursor()
if not self.run_real_roms:
self._cyclic_herztick()
self._cyclic_blink_cursor()
self.reset_machine()

def _cyclic_herztick(self):
Expand Down Expand Up @@ -618,11 +624,19 @@ def _border_positions(self):
def reset_machine(self):
super().reset_machine()
self.screen.memory[0x00fb] = EmulatorWindowBase.update_rate
self.switch_interpreter("basic")
if not self.run_real_roms:
self.switch_interpreter("basic")
if self.screen.using_roms:
print("using actual ROM reset routine (sys 64738)")
do_sys(self.screen, 64738, self.interpret_thread._microsleep, use_rom_routines=True)
self.interpreter.write_prompt("\n\n\n\n\n")
reset = self.screen.memory.getword(0xfffc)
print("using actual ROM reset routine at", reset)
if self.run_real_roms:
if self.real_cpu_running is None:
threading.Thread(target=self.run_rom_code, args=(reset,), daemon=True).start()
else:
self.real_cpu_running.reset()
else:
do_sys(self.screen, reset, self.interpret_thread._microsleep, use_rom_routines=True)
self.interpreter.write_prompt("\n\n\n\n\n")


class InterpretThread(threading.Thread):
Expand Down Expand Up @@ -748,13 +762,17 @@ def runstop(self):
self.keybuffer.clear()


def start():
def start(run_real_roms):
rom_directory = "roms"
screen = ScreenAndMemory(columns=C64EmulatorWindow.columns,
rows=C64EmulatorWindow.rows,
sprites=C64EmulatorWindow.sprites,
rom_directory=rom_directory)
emu = C64EmulatorWindow(screen, "Commodore-64 simulator in pure Python!", rom_directory)
rom_directory=rom_directory,
run_real_roms=run_real_roms)
if run_real_roms:
emu = RealC64EmulatorWindow(screen, "Commodore-64 emulator in pure Python! - running actual roms", rom_directory)
else:
emu = C64EmulatorWindow(screen, "Commodore-64 simulator in pure Python!", rom_directory, False)
emu.start()
emu.mainloop()

Expand Down
Loading

0 comments on commit 66588e0

Please sign in to comment.