Compare commits

..

3 commits

Author SHA1 Message Date
shokre
94bc7f7401 fix: fix wav loading 2023-10-21 06:43:19 +02:00
shokre
3bd5c9ddc1 fix: fix python invocation 2023-10-21 05:35:17 +02:00
shokre
2ec18cc353 refactor: port to python3 2023-10-21 05:23:40 +02:00
62 changed files with 214 additions and 582 deletions

View file

@ -62,5 +62,7 @@ Then press F8 to load and start program.
Known bugs Known bugs
---------- ----------
- Pygame and Pulseaudio crash occasionally. Please report any issues you have. - Pygame and Pulseaudio crash occasionally. - it seems that this
fork is less prone to lock-ups and **pygame*** crashes.
Please report any issues you have.
- no error checking for input `.prg` file - no error checking for input `.prg` file

79
orao.py
View file

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf8 -*-
import pygame, numpy, sys, datetime import pygame, numpy, sys, datetime
from orao.cpu import CPU from orao.cpu import CPU
@ -27,7 +27,7 @@ pygame.init()
pygame.time.set_timer(pygame.USEREVENT + 1, 40) pygame.time.set_timer(pygame.USEREVENT + 1, 40)
# create CPU # create CPU
cpu = CPU(bytearray([0xFF] * 0xC000) + bytearray(open("ORAO13.ROM", "rb").read())) cpu = CPU(bytearray([0xFF]*0xC000) + bytearray(open('ORAO13.ROM', 'rb').read()))
cpu.channel = pygame.mixer.Channel(0) cpu.channel = pygame.mixer.Channel(0)
cpu.store_mem_listeners.append(video_mem_listener) cpu.store_mem_listeners.append(video_mem_listener)
cpu.store_mem_listeners.append(timer_mem_listener) cpu.store_mem_listeners.append(timer_mem_listener)
@ -38,46 +38,39 @@ chargen_init(cpu.memory[0xE000:])
view_cpu_state = CPUState() view_cpu_state = CPUState()
# ram zero page & stack # ram zero page & stack
view_zp = MicroMemView( view_zp = MicroMemView(start_addr=0x0000, size=0x0200, caption='ZP & stack', disp_width=64)
start_addr=0x0000, size=0x0200, caption="ZP & stack", disp_width=64
)
view_zp.listen(cpu) view_zp.listen(cpu)
# user ram view # user ram view
view_ram = MicroMemView(start_addr=0x0200, size=0x5E00, caption="RAM", disp_width=128) view_ram = MicroMemView(start_addr=0x0200, size=0x5E00, caption='RAM', disp_width=128)
view_ram.listen(cpu) view_ram.listen(cpu)
# rom access view # rom access view
view_rom = MicroMemView(start_addr=0xC000, size=0x4000, caption="ROM", disp_width=256) view_rom = MicroMemView(start_addr=0xC000, size=0x4000, caption='ROM', disp_width=256)
view_rom.listen(cpu) view_rom.listen(cpu)
view_screen = MicroMemView(start_addr=0x6000, size=0x2000, disp_width=32) view_screen = MicroMemView(start_addr=0x6000, size=0x2000, disp_width=32)
view_screen.listen(cpu) view_screen.listen(cpu)
# status lines # status lines
status_line = pygame.Surface((64 * 8, 4 * 8), depth=24) status_line = pygame.Surface((64 * 8, 4*8), depth=24)
status_line.fill((0, 0, 0)) status_line.fill((0, 0, 0))
chargen_draw_str(status_line, 0, 0, "Orao Emulator v0.1") chargen_draw_str(status_line, 0, 0, 'Orao Emulator v0.1')
# setup screen # setup screen
screen = pygame.display.set_mode( screen = pygame.display.set_mode((
( terminal.get_width() * 2 + 2 + int(max(view_rom.width, view_cpu_state.width * 2)),
terminal.get_width() * 2 terminal.get_height() * 2 + 3*8 + 2 + 30
+ 2 ))
+ int(max(view_rom.width, view_cpu_state.width * 2)), pygame.display.set_caption('Orao Emulator v0.1')
terminal.get_height() * 2 + 3 * 8 + 2 + 30,
)
)
pygame.display.set_caption("Orao Emulator v0.1")
lc = (0xFF, 0xCC, 0x00) lc = (0xff, 0xcc, 0x00)
chargen_draw_str(status_line, 0, 16, "F12:", color=lc) chargen_draw_str(status_line, 0, 16, 'F12:', color=lc)
chargen_draw_str(status_line, 24 + 8, 16, " SCREENSHOT") chargen_draw_str(status_line, 24+8, 16, ' SCREENSHOT')
if MEM_LOAD_PRG is not None: if MEM_LOAD_PRG is not None:
chargen_draw_str(status_line, 0, 24, "F8:", color=lc) chargen_draw_str(status_line, 0, 24, 'F8:', color=lc)
chargen_draw_str(status_line, 24, 24, " %s" % MEM_LOAD_PRG) chargen_draw_str(status_line, 24, 24, ' %s' % MEM_LOAD_PRG)
def render_frame(frame_time_ms): def render_frame(frame_time_ms):
view_cpu_state.render(cpu, frame_time_ms) view_cpu_state.render(cpu, frame_time_ms)
@ -89,8 +82,8 @@ def render_frame(frame_time_ms):
# blit # blit
screen.fill((0, 0, 0)) screen.fill((0, 0, 0))
screen.blit(pygame.transform.scale(terminal, (512, 512)), [0, 0]) screen.blit(pygame.transform.scale(terminal, (512, 512)), [0, 0])
chargen_draw_str(status_line, 0, 8, "Speed: {0:.2f} MHz".format(ratio)) chargen_draw_str(status_line, 0, 8, 'Speed: {0:.2f} MHz'.format(ratio))
screen.blit(status_line, [0, 512 + 1]) screen.blit(status_line, [0, 512+1])
x = 512 + 1 x = 512 + 1
y = 0 y = 0
cx, y = view_cpu_state.blit(screen, [x, y], scale=2) cx, y = view_cpu_state.blit(screen, [x, y], scale=2)
@ -102,13 +95,12 @@ def render_frame(frame_time_ms):
y2 += 5 y2 += 5
_, _ = view_rom.blit(screen, [x, y2], scale=1) _, _ = view_rom.blit(screen, [x, y2], scale=1)
screen.blit(pygame.transform.scale(view_screen.read_map.surf, (512, 512)), [0, 0]) screen.blit(pygame.transform.scale(view_screen.read_map.surf, (512,512)), [0,0])
screen.blit(pygame.transform.scale(view_screen.write_map.surf, (512, 512)), [0, 0]) screen.blit(pygame.transform.scale(view_screen.write_map.surf, (512,512)), [0,0])
# finish rendering # finish rendering
pygame.display.flip() pygame.display.flip()
clock = pygame.time.Clock() clock = pygame.time.Clock()
while running: while running:
@ -117,7 +109,7 @@ while running:
for i in range(5000): for i in range(5000):
cpu.step() cpu.step()
time_elapsed = (datetime.datetime.now() - before).microseconds + 1 time_elapsed = (datetime.datetime.now()-before).microseconds + 1
clock.tick() clock.tick()
for event in pygame.event.get(): for event in pygame.event.get():
@ -139,13 +131,13 @@ while running:
if pkeys[pygame.K_F8]: if pkeys[pygame.K_F8]:
if MEM_LOAD_PRG is None: if MEM_LOAD_PRG is None:
break break
print(("LOADING: %s" % MEM_LOAD_PRG)) print("LOADING: %s" % MEM_LOAD_PRG)
ba = bytearray(open(MEM_LOAD_PRG, "rb").read()) ba = bytearray(open(MEM_LOAD_PRG, "rb").read())
# read load address # read load address
addr = ba[1] * 256 + ba[0] addr = ba[1] * 256 + ba[0]
ba = ba[2:] ba = ba[2:]
print(("Loadaddr: %04x" % addr)) print('Loadaddr: %04x' % addr)
# load file to memory # load file to memory
for i in range(0, len(ba)): for i in range(0, len(ba)):
@ -158,33 +150,22 @@ while running:
if pkeys[pygame.K_F12]: if pkeys[pygame.K_F12]:
now = datetime.datetime.now() # current date and time now = datetime.datetime.now() # current date and time
pygame.image.save( pygame.image.save(screen, "assets/screenshot-%s.png" % now.strftime("%Y%m%d-%H%M%S"))
screen, "assets/screenshot-%s.png" % now.strftime("%Y%m%d-%H%M%S")
)
if event.type == pygame.USEREVENT + 1: if event.type == pygame.USEREVENT + 1:
render_frame(clock.get_time()) render_frame(clock.get_time())
cpu.tape_out = ( cpu.tape_out = None if cpu.cycles - cpu.last_sound_cycles > 20000 else cpu.tape_out
None if cpu.cycles - cpu.last_sound_cycles > 20000 else cpu.tape_out
)
if ( if len(cpu.sndbuf) > 4096 or cpu.sndbuf and cpu.cycles - cpu.last_sound_cycles > 20000:
len(cpu.sndbuf) > 4096
or cpu.sndbuf
and cpu.cycles - cpu.last_sound_cycles > 20000
):
while cpu.channel.get_queue(): while cpu.channel.get_queue():
if time_elapsed > 10000: if time_elapsed > 10000: break
break
cpu.channel.queue(pygame.sndarray.make_sound(numpy.uint8(cpu.sndbuf))) cpu.channel.queue(pygame.sndarray.make_sound(numpy.uint8(cpu.sndbuf)))
cpu.sndbuf = [] cpu.sndbuf = []
overshoot = cpu.cycles - previous_loop_cycles - time_elapsed overshoot = cpu.cycles - previous_loop_cycles - time_elapsed
pygame.time.wait( pygame.time.wait((overshoot > 0) * overshoot // 1000) # Pričekaj da budemo cycle exact
(overshoot > 0) * overshoot // 1000
) # Pričekaj da budemo cycle exact
ratio = 1.0 * (cpu.cycles - previous_loop_cycles) / time_elapsed ratio = 1.0 * (cpu.cycles - previous_loop_cycles) / time_elapsed

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
chars = None chars = None
@ -6,6 +5,7 @@ def chargen_init(char_data):
global chars global chars
chars = char_data chars = char_data
def chargen_draw_char(surf, px, py, ch, color=(0, 255, 0), bg=(0, 0, 0)): def chargen_draw_char(surf, px, py, ch, color=(0, 255, 0), bg=(0, 0, 0)):
char_loc = (ord(ch) - 32) * 8 char_loc = (ord(ch) - 32) * 8
for y in range(8): for y in range(8):

View file

@ -1,196 +1,61 @@
# -*- coding: utf-8 -*- # -*- coding: utf8 -*-
import wave import wave
class CPU(object): class CPU(object):
CARRY, ZERO, INTERRUPT, DECIMAL, BREAK, UNUSED, OVERFLOW, NEGATIVE = [ CARRY, ZERO, INTERRUPT, DECIMAL, BREAK, UNUSED, OVERFLOW, NEGATIVE = [2**i for i in range(8)]
2**i for i in range(8)
]
alphaarray = None alphaarray = None
store_mem_listeners = [] store_mem_listeners = []
read_mem_listeners = [] read_mem_listeners = []
def __init__(self, memory): def __init__(self, memory):
s, self.tape_out, self.filename, self.samples = self, None, None, 0 s, self.tape_out, self.filename, self.samples = self, None, None, 0
s.memory, s.tape, s.flipflop, s.last_sound_cycles, s.sndbuf = ( s.memory, s.tape, s.flipflop, s.last_sound_cycles, s.sndbuf = memory, None, 0, -20000, []
memory,
None,
0,
-20000,
[],
)
s.cycles, s.pc, s.flags, s.sp, s.a, s.x, s.y = 0, 0xFF89, 48, 0xFF, 0, 0, 0 s.cycles, s.pc, s.flags, s.sp, s.a, s.x, s.y = 0, 0xFF89, 48, 0xFF, 0, 0, 0
s.executed = [] s.executed = []
s._opcodes = { s._opcodes = { 0x00:(s.BRK,s.no,7), 0x01:(s.ORA,s.ix,6), 0x05:(s.ORA,s.zp,3),
0x00: (s.BRK, s.no, 7), 0x06:(s.ASL,s.zp,5), 0x08:(s.PHP,s.no,3), 0x09:(s.ORA,s.im,2), 0x0a:(s.ASL,s.no,2),
0x01: (s.ORA, s.ix, 6), 0x0d:(s.ORA,s.ab,4), 0x0e:(s.ASL,s.ab,6), 0x10:(s.BPL,s.re,2), 0x11:(s.ORA,s.iy,6),
0x05: (s.ORA, s.zp, 3), 0x15:(s.ORA,s.zx,4), 0x16:(s.ASL,s.zx,6), 0x18:(s.CLC,s.no,2), 0x19:(s.ORA,s.ay,5),
0x06: (s.ASL, s.zp, 5), 0x1d:(s.ORA,s.ax,5), 0x1e:(s.ASL,s.ax,7), 0x20:(s.JSR,s.jm,6), 0x21:(s.AND,s.ix,6),
0x08: (s.PHP, s.no, 3), 0x24:(s.BIT,s.zp,3), 0x25:(s.AND,s.zp,3), 0x26:(s.ROL,s.zp,5), 0x28:(s.PLP,s.no,4),
0x09: (s.ORA, s.im, 2), 0x29:(s.AND,s.im,2), 0x2a:(s.ROL,s.no,2), 0x2c:(s.BIT,s.ab,4), 0x2d:(s.AND,s.ab,4),
0x0A: (s.ASL, s.no, 2), 0x2e:(s.ROL,s.ab,6), 0x30:(s.BMI,s.re,2), 0x31:(s.AND,s.iy,6), 0x35:(s.AND,s.zx,4),
0x0D: (s.ORA, s.ab, 4), 0x36:(s.ROL,s.zx,6), 0x38:(s.SEC,s.no,2), 0x39:(s.AND,s.ay,5), 0x3d:(s.AND,s.ax,5),
0x0E: (s.ASL, s.ab, 6), 0x3e:(s.ROL,s.ax,7), 0x40:(s.RTI,s.no,6), 0x41:(s.EOR,s.ix,6), 0x45:(s.EOR,s.zp,3),
0x10: (s.BPL, s.re, 2), 0x46:(s.LSR,s.zp,5), 0x48:(s.PHA,s.no,3), 0x49:(s.EOR,s.im,2), 0x4a:(s.LSR,s.no,2),
0x11: (s.ORA, s.iy, 6), 0x4c:(s.JMP,s.jm,3), 0x4d:(s.EOR,s.ab,4), 0x4e:(s.LSR,s.ab,6), 0x50:(s.BVC,s.re,2),
0x15: (s.ORA, s.zx, 4), 0x51:(s.EOR,s.iy,6), 0x55:(s.EOR,s.zx,4), 0x56:(s.LSR,s.zx,6), 0x58:(s.CLI,s.no,2),
0x16: (s.ASL, s.zx, 6), 0x59:(s.EOR,s.ay,5), 0x5d:(s.EOR,s.ax,5), 0x5e:(s.LSR,s.ax,7), 0x60:(s.RTS,s.no,6),
0x18: (s.CLC, s.no, 2), 0x61:(s.ADC,s.ix,6), 0x65:(s.ADC,s.zp,3), 0x66:(s.ROR,s.zp,5), 0x68:(s.PLA,s.no,4),
0x19: (s.ORA, s.ay, 5), 0x69:(s.ADC,s.im,2), 0x6a:(s.ROR,s.no,2), 0x6c:(s.JMP,s.id,5), 0x6d:(s.ADC,s.ab,4),
0x1D: (s.ORA, s.ax, 5), 0x6e:(s.ROR,s.ab,6), 0x70:(s.BVS,s.re,2), 0x71:(s.ADC,s.iy,6), 0x75:(s.ADC,s.zx,4),
0x1E: (s.ASL, s.ax, 7), 0x76:(s.ROR,s.zx,6), 0x78:(s.SEI,s.no,2), 0x79:(s.ADC,s.ay,5), 0x7d:(s.ADC,s.ax,5),
0x20: (s.JSR, s.jm, 6), 0x7e:(s.ROR,s.ax,7), 0x81:(s.STA,s.ix,6), 0x84:(s.STY,s.zp,3), 0x85:(s.STA,s.zp,3),
0x21: (s.AND, s.ix, 6), 0x86:(s.STX,s.zp,3), 0x88:(s.DEY,s.no,2), 0x8a:(s.TXA,s.no,2), 0x8c:(s.STY,s.ab,4),
0x24: (s.BIT, s.zp, 3), 0x8d:(s.STA,s.ab,4), 0x8e:(s.STX,s.ab,4), 0x90:(s.BCC,s.re,2), 0x91:(s.STA,s.iy,6),
0x25: (s.AND, s.zp, 3), 0x94:(s.STY,s.zx,4), 0x95:(s.STA,s.zx,4), 0x96:(s.STX,s.zy,4), 0x98:(s.TYA,s.no,2),
0x26: (s.ROL, s.zp, 5), 0x99:(s.STA,s.ay,5), 0x9a:(s.TXS,s.no,2), 0x9d:(s.STA,s.ax,5), 0xa0:(s.LDY,s.im,2),
0x28: (s.PLP, s.no, 4), 0xa1:(s.LDA,s.ix,6), 0xa2:(s.LDX,s.im,2), 0xa4:(s.LDY,s.zp,3), 0xa5:(s.LDA,s.zp,3),
0x29: (s.AND, s.im, 2), 0xa6:(s.LDX,s.zp,3), 0xa8:(s.TAY,s.no,2), 0xa9:(s.LDA,s.im,2), 0xaa:(s.TAX,s.no,2),
0x2A: (s.ROL, s.no, 2), 0xac:(s.LDY,s.ab,4), 0xad:(s.LDA,s.ab,4), 0xae:(s.LDX,s.ab,4), 0xb0:(s.BCS,s.re,2),
0x2C: (s.BIT, s.ab, 4), 0xb1:(s.LDA,s.iy,6), 0xb4:(s.LDY,s.zx,4), 0xb5:(s.LDA,s.zx,4), 0xb6:(s.LDX,s.zy,4),
0x2D: (s.AND, s.ab, 4), 0xb8:(s.CLV,s.no,2), 0xb9:(s.LDA,s.ay,4), 0xba:(s.TSX,s.no,2), 0xbc:(s.LDY,s.ax,4),
0x2E: (s.ROL, s.ab, 6), 0xbd:(s.LDA,s.ax,4), 0xbe:(s.LDX,s.ay,4), 0xc0:(s.CPY,s.im,2), 0xc1:(s.CMP,s.ix,6),
0x30: (s.BMI, s.re, 2), 0xc4:(s.CPY,s.zp,3), 0xc5:(s.CMP,s.zp,3), 0xc6:(s.DEC,s.zp,5), 0xc8:(s.INY,s.no,2),
0x31: (s.AND, s.iy, 6), 0xc9:(s.CMP,s.im,2), 0xca:(s.DEX,s.no,2), 0xcc:(s.CPY,s.ab,4), 0xcd:(s.CMP,s.ab,4),
0x35: (s.AND, s.zx, 4), 0xce:(s.DEC,s.ab,6), 0xd0:(s.BNE,s.re,2), 0xd1:(s.CMP,s.iy,6), 0xd5:(s.CMP,s.zx,4),
0x36: (s.ROL, s.zx, 6), 0xd6:(s.DEC,s.zx,6), 0xd8:(s.CLD,s.no,2), 0xd9:(s.CMP,s.ay,5), 0xdd:(s.CMP,s.ax,5),
0x38: (s.SEC, s.no, 2), 0xde:(s.DEC,s.ax,7), 0xe0:(s.CPX,s.im,2), 0xe1:(s.SBC,s.ix,6), 0xe4:(s.CPX,s.zp,3),
0x39: (s.AND, s.ay, 5), 0xe5:(s.SBC,s.zp,3), 0xe6:(s.INC,s.zp,5), 0xe8:(s.INX,s.no,2), 0xe9:(s.SBC,s.im,2),
0x3D: (s.AND, s.ax, 5), 0xea:(s.NOP,s.no,2), 0xec:(s.CPX,s.ab,4), 0xed:(s.SBC,s.ab,4), 0xee:(s.INC,s.ab,6),
0x3E: (s.ROL, s.ax, 7), 0xf0:(s.BEQ,s.re,2), 0xf1:(s.SBC,s.iy,6), 0xf5:(s.SBC,s.zx,4), 0xf6:(s.INC,s.zx,6),
0x40: (s.RTI, s.no, 6), 0xf8:(s.SED,s.no,2), 0xf9:(s.SBC,s.ay,5), 0xfd:(s.SBC,s.ax,5), 0xfe:(s.INC,s.ax,7)}
0x41: (s.EOR, s.ix, 6),
0x45: (s.EOR, s.zp, 3),
0x46: (s.LSR, s.zp, 5),
0x48: (s.PHA, s.no, 3),
0x49: (s.EOR, s.im, 2),
0x4A: (s.LSR, s.no, 2),
0x4C: (s.JMP, s.jm, 3),
0x4D: (s.EOR, s.ab, 4),
0x4E: (s.LSR, s.ab, 6),
0x50: (s.BVC, s.re, 2),
0x51: (s.EOR, s.iy, 6),
0x55: (s.EOR, s.zx, 4),
0x56: (s.LSR, s.zx, 6),
0x58: (s.CLI, s.no, 2),
0x59: (s.EOR, s.ay, 5),
0x5D: (s.EOR, s.ax, 5),
0x5E: (s.LSR, s.ax, 7),
0x60: (s.RTS, s.no, 6),
0x61: (s.ADC, s.ix, 6),
0x65: (s.ADC, s.zp, 3),
0x66: (s.ROR, s.zp, 5),
0x68: (s.PLA, s.no, 4),
0x69: (s.ADC, s.im, 2),
0x6A: (s.ROR, s.no, 2),
0x6C: (s.JMP, s.id, 5),
0x6D: (s.ADC, s.ab, 4),
0x6E: (s.ROR, s.ab, 6),
0x70: (s.BVS, s.re, 2),
0x71: (s.ADC, s.iy, 6),
0x75: (s.ADC, s.zx, 4),
0x76: (s.ROR, s.zx, 6),
0x78: (s.SEI, s.no, 2),
0x79: (s.ADC, s.ay, 5),
0x7D: (s.ADC, s.ax, 5),
0x7E: (s.ROR, s.ax, 7),
0x81: (s.STA, s.ix, 6),
0x84: (s.STY, s.zp, 3),
0x85: (s.STA, s.zp, 3),
0x86: (s.STX, s.zp, 3),
0x88: (s.DEY, s.no, 2),
0x8A: (s.TXA, s.no, 2),
0x8C: (s.STY, s.ab, 4),
0x8D: (s.STA, s.ab, 4),
0x8E: (s.STX, s.ab, 4),
0x90: (s.BCC, s.re, 2),
0x91: (s.STA, s.iy, 6),
0x94: (s.STY, s.zx, 4),
0x95: (s.STA, s.zx, 4),
0x96: (s.STX, s.zy, 4),
0x98: (s.TYA, s.no, 2),
0x99: (s.STA, s.ay, 5),
0x9A: (s.TXS, s.no, 2),
0x9D: (s.STA, s.ax, 5),
0xA0: (s.LDY, s.im, 2),
0xA1: (s.LDA, s.ix, 6),
0xA2: (s.LDX, s.im, 2),
0xA4: (s.LDY, s.zp, 3),
0xA5: (s.LDA, s.zp, 3),
0xA6: (s.LDX, s.zp, 3),
0xA8: (s.TAY, s.no, 2),
0xA9: (s.LDA, s.im, 2),
0xAA: (s.TAX, s.no, 2),
0xAC: (s.LDY, s.ab, 4),
0xAD: (s.LDA, s.ab, 4),
0xAE: (s.LDX, s.ab, 4),
0xB0: (s.BCS, s.re, 2),
0xB1: (s.LDA, s.iy, 6),
0xB4: (s.LDY, s.zx, 4),
0xB5: (s.LDA, s.zx, 4),
0xB6: (s.LDX, s.zy, 4),
0xB8: (s.CLV, s.no, 2),
0xB9: (s.LDA, s.ay, 4),
0xBA: (s.TSX, s.no, 2),
0xBC: (s.LDY, s.ax, 4),
0xBD: (s.LDA, s.ax, 4),
0xBE: (s.LDX, s.ay, 4),
0xC0: (s.CPY, s.im, 2),
0xC1: (s.CMP, s.ix, 6),
0xC4: (s.CPY, s.zp, 3),
0xC5: (s.CMP, s.zp, 3),
0xC6: (s.DEC, s.zp, 5),
0xC8: (s.INY, s.no, 2),
0xC9: (s.CMP, s.im, 2),
0xCA: (s.DEX, s.no, 2),
0xCC: (s.CPY, s.ab, 4),
0xCD: (s.CMP, s.ab, 4),
0xCE: (s.DEC, s.ab, 6),
0xD0: (s.BNE, s.re, 2),
0xD1: (s.CMP, s.iy, 6),
0xD5: (s.CMP, s.zx, 4),
0xD6: (s.DEC, s.zx, 6),
0xD8: (s.CLD, s.no, 2),
0xD9: (s.CMP, s.ay, 5),
0xDD: (s.CMP, s.ax, 5),
0xDE: (s.DEC, s.ax, 7),
0xE0: (s.CPX, s.im, 2),
0xE1: (s.SBC, s.ix, 6),
0xE4: (s.CPX, s.zp, 3),
0xE5: (s.SBC, s.zp, 3),
0xE6: (s.INC, s.zp, 5),
0xE8: (s.INX, s.no, 2),
0xE9: (s.SBC, s.im, 2),
0xEA: (s.NOP, s.no, 2),
0xEC: (s.CPX, s.ab, 4),
0xED: (s.SBC, s.ab, 4),
0xEE: (s.INC, s.ab, 6),
0xF0: (s.BEQ, s.re, 2),
0xF1: (s.SBC, s.iy, 6),
0xF5: (s.SBC, s.zx, 4),
0xF6: (s.INC, s.zx, 6),
0xF8: (s.SED, s.no, 2),
0xF9: (s.SBC, s.ay, 5),
0xFD: (s.SBC, s.ax, 5),
0xFE: (s.INC, s.ax, 7),
}
s.ticks = {
s.im: 1, s.ticks = {s.im: 1, s.zp: 1, s.zx: 1, s.zy: 1, s.ab: 2, s.ax: 2, s.no: 0,
s.zp: 1, s.ay: 2, s.jm: 2, s.id: 2, s.ix: 1, s.iy: 1, s.re: 1}
s.zx: 1,
s.zy: 1,
s.ab: 2,
s.ax: 2,
s.no: 0,
s.ay: 2,
s.jm: 2,
s.id: 2,
s.ix: 1,
s.iy: 1,
s.re: 1,
}
s.addr_fmt = { s.addr_fmt = {
s.im: lambda addr: "#$%02X" % s.memory[addr], s.im: lambda addr: "#$%02X" % s.memory[addr],
@ -208,8 +73,7 @@ class CPU(object):
s.re: lambda addr: "$%04X" % (addr + self.byte2signed(s.memory[addr]) + 1), s.re: lambda addr: "$%04X" % (addr + self.byte2signed(s.memory[addr]) + 1),
} }
def get_flag(self, flag): def get_flag(self, flag): return self.flags & flag != 0
return self.flags & flag != 0
def set_flag(self, flag, boolean): def set_flag(self, flag, boolean):
self.flags = self.flags | flag if boolean else self.flags & ~(flag) self.flags = self.flags | flag if boolean else self.flags & ~(flag)
@ -219,11 +83,9 @@ class CPU(object):
self.set_flag(self.NEGATIVE, src & 0x80) self.set_flag(self.NEGATIVE, src & 0x80)
return src return src
def get_word(self, addr): def get_word(self, addr): return 256 * self.get_byte(addr + 1) + self.get_byte(addr)
return 256 * self.get_byte(addr + 1) + self.get_byte(addr)
def get_filename(self): def get_filename(self): return 'wav/{0}.WAV'.format(str(self.memory[592:602], 'ASCII').rstrip())
return 'wav/{0}.WAV'.format(str(self.memory[592:602], 'ASCII').rstrip())
def speaker(self): def speaker(self):
self.flipflop ^= 1 self.flipflop ^= 1
@ -242,6 +104,7 @@ class CPU(object):
if addr == 0x87FF: # Adresa ulaza kasetofona if addr == 0x87FF: # Adresa ulaza kasetofona
if not self.tape: if not self.tape:
self.tape = self.tape_load_gen() self.tape = self.tape_load_gen()
try: try:
return next(self.tape) return next(self.tape)
@ -249,8 +112,7 @@ class CPU(object):
self.tape = None self.tape = None
return 0x00 return 0x00
if addr == 0x8800: if addr == 0x8800: self.speaker() # Zvucnik
self.speaker() # Zvucnik
if addr is not None: if addr is not None:
for listener in self.read_mem_listeners: for listener in self.read_mem_listeners:
@ -263,8 +125,7 @@ class CPU(object):
self.a = val & 0xFF self.a = val & 0xFF
return return
if addr == 0x8800: if addr == 0x8800: self.speaker() # Zvucnik
self.speaker() # Zvucnik
self.memory[addr] = val & 0xFF self.memory[addr] = val & 0xFF
@ -280,48 +141,24 @@ class CPU(object):
return self.get_byte(256 + self.sp) return self.get_byte(256 + self.sp)
def stack_push_word(self, val): def stack_push_word(self, val):
list(map(self.stack_push, [(val >> 8) & 0xFF, val & 0xFF])) self.stack_push((val >> 8) & 0xFF)
self.stack_push(val & 0xFF)
def stack_pop_word(self):
return self.stack_pop() + (self.stack_pop() << 8)
def stack_pop_word(self): return self.stack_pop() + (self.stack_pop() << 8)
########################################################################### ###########################################################################
# Adresni nacini # Adresni nacini
def im(self): def im(self): return self.pc
return self.pc def zp(self): return self.get_byte(self.pc)
def zx(self): return (self.zp() + self.x) & 0xFF
def zp(self): def zy(self): return (self.zp() + self.y) & 0xFF
return self.get_byte(self.pc) def ab(self): return self.get_word(self.pc)
def ax(self): return self._ab(self.x)
def zx(self): def ay(self): return self._ab(self.y)
return (self.zp() + self.x) & 0xFF def ix(self): return self.get_word((self.zp() + self.x) & 0xFF)
def iy(self): return (self.get_word(self.zp()) + self.y) & 0xFFFF
def zy(self): def id(self): return self.get_word(self.ab())
return (self.zp() + self.y) & 0xFF def jm(self): return self.ab()
def no(self): return None
def ab(self):
return self.get_word(self.pc)
def ax(self):
return self._ab(self.x)
def ay(self):
return self._ab(self.y)
def ix(self):
return self.get_word((self.zp() + self.x) & 0xFF)
def iy(self):
return (self.get_word(self.zp()) + self.y) & 0xFFFF
def id(self):
return self.get_word(self.ab())
def jm(self):
return self.ab()
def no(self):
return None
def _ab(self, diff): def _ab(self, diff):
a1 = self.ab() a1 = self.ab()
@ -340,89 +177,39 @@ class CPU(object):
########################################################################### ###########################################################################
# Instrukcije # Instrukcije
def TAX(self, d): def TAX(self, d): self.x = self.set_nz(self.a)
self.x = self.set_nz(self.a) def TXA(self, d): self.a = self.set_nz(self.x)
def TAY(self, d): self.y = self.set_nz(self.a)
def TYA(self, d): self.a = self.set_nz(self.y)
def TSX(self, d): self.x = self.set_nz(self.sp)
def TXS(self, d): self.sp = self.x
def TXA(self, d): def LDA(self, addr): self.a = self.set_nz(self.get_byte(addr))
self.a = self.set_nz(self.x) def LDX(self, addr): self.x = self.set_nz(self.get_byte(addr))
def LDY(self, addr): self.y = self.set_nz(self.get_byte(addr))
def STA(self, addr): self.store_byte(addr, self.a)
def STX(self, addr): self.store_byte(addr, self.x)
def STY(self, addr): self.store_byte(addr, self.y)
def TAY(self, d): def AND(self, addr): self.a = self.set_nz(self.get_byte(addr) & self.a)
self.y = self.set_nz(self.a) def ORA(self, addr): self.a = self.set_nz(self.get_byte(addr) | self.a)
def EOR(self, addr): self.a = self.set_nz(self.get_byte(addr) ^ self.a)
def TYA(self, d): def CLC(self, d): self.set_flag(self.CARRY, False)
self.a = self.set_nz(self.y) def SEC(self, d): self.set_flag(self.CARRY, True)
def CLD(self, d): self.set_flag(self.DECIMAL, False)
def SED(self, d): self.set_flag(self.DECIMAL, True)
def CLI(self, d): self.set_flag(self.INTERRUPT, False)
def SEI(self, d): self.set_flag(self.INTERRUPT, True)
def CLV(self, d): self.set_flag(self.OVERFLOW, False)
def TSX(self, d): def INX(self, d): self.x = self.set_nz((self.x + 1) & 0xFF)
self.x = self.set_nz(self.sp) def INY(self, d): self.y = self.set_nz((self.y + 1) & 0xFF)
def DEX(self, d): self.x = self.set_nz((self.x - 1) & 0xFF)
def DEY(self, d): self.y = self.set_nz((self.y - 1) & 0xFF)
def TXS(self, d): def INC(self, addr): self.store_byte(addr, self.set_nz(self.get_byte(addr) + 1))
self.sp = self.x def DEC(self, addr): self.store_byte(addr, self.set_nz(self.get_byte(addr) - 1))
def LDA(self, addr):
self.a = self.set_nz(self.get_byte(addr))
def LDX(self, addr):
self.x = self.set_nz(self.get_byte(addr))
def LDY(self, addr):
self.y = self.set_nz(self.get_byte(addr))
def STA(self, addr):
self.store_byte(addr, self.a)
def STX(self, addr):
self.store_byte(addr, self.x)
def STY(self, addr):
self.store_byte(addr, self.y)
def AND(self, addr):
self.a = self.set_nz(self.get_byte(addr) & self.a)
def ORA(self, addr):
self.a = self.set_nz(self.get_byte(addr) | self.a)
def EOR(self, addr):
self.a = self.set_nz(self.get_byte(addr) ^ self.a)
def CLC(self, d):
self.set_flag(self.CARRY, False)
def SEC(self, d):
self.set_flag(self.CARRY, True)
def CLD(self, d):
self.set_flag(self.DECIMAL, False)
def SED(self, d):
self.set_flag(self.DECIMAL, True)
def CLI(self, d):
self.set_flag(self.INTERRUPT, False)
def SEI(self, d):
self.set_flag(self.INTERRUPT, True)
def CLV(self, d):
self.set_flag(self.OVERFLOW, False)
def INX(self, d):
self.x = self.set_nz((self.x + 1) & 0xFF)
def INY(self, d):
self.y = self.set_nz((self.y + 1) & 0xFF)
def DEX(self, d):
self.x = self.set_nz((self.x - 1) & 0xFF)
def DEY(self, d):
self.y = self.set_nz((self.y - 1) & 0xFF)
def INC(self, addr):
self.store_byte(addr, self.set_nz(self.get_byte(addr) + 1))
def DEC(self, addr):
self.store_byte(addr, self.set_nz(self.get_byte(addr) - 1))
def ASL(self, addr): def ASL(self, addr):
operand = self.get_byte(addr) operand = self.get_byte(addr)
@ -436,20 +223,11 @@ class CPU(object):
self.set_flag(self.NEGATIVE, op & self.NEGATIVE) self.set_flag(self.NEGATIVE, op & self.NEGATIVE)
self.set_flag(self.OVERFLOW, op & self.OVERFLOW) self.set_flag(self.OVERFLOW, op & self.OVERFLOW)
def PHP(self, d): def PHP(self, d): self.stack_push(self.flags | self.BREAK | self.UNUSED)
self.stack_push(self.flags | self.BREAK | self.UNUSED) def PHA(self, d): self.stack_push(self.a)
def PLP(self, d): self.flags = self.stack_pop()
def PHA(self, d): def PLA(self, d): self.a = self.set_nz(self.stack_pop())
self.stack_push(self.a) def NOP(self, d): pass
def PLP(self, d):
self.flags = self.stack_pop()
def PLA(self, d):
self.a = self.set_nz(self.stack_pop())
def NOP(self, d):
pass
def ROR(self, addr): def ROR(self, addr):
value = self.get_byte(addr) >> 1 | self.get_flag(self.CARRY) * 128 value = self.get_byte(addr) >> 1 | self.get_flag(self.CARRY) * 128
@ -468,17 +246,14 @@ class CPU(object):
self.SEI(0) self.SEI(0)
self.pc = self.get_word(0xFFFE) # IRQ self.pc = self.get_word(0xFFFE) # IRQ
def JMP(self, addr): def JMP(self, addr): self.pc = addr - 2
self.pc = addr - 2
def JSR(self, addr): def JSR(self, addr):
if addr == 0xE7B7 and self.pc > 0xC000: # samo i jedino ako rutinu poziva ROM if addr == 0xE7B7 and self.pc > 0xC000: # samo i jedino ako rutinu poziva ROM
if not self.tape_out: if not self.tape_out:
self.tape_out = wave.open(self.get_filename(), "w") self.tape_out = wave.open(self.get_filename(), 'w')
self.tape_out.setparams((1, 1, 44100, 0, "NONE", "not compressed")) self.tape_out.setparams((1, 1, 44100, 0, 'NONE', 'not compressed'))
self.tape_out.writeframes( self.tape_out.writeframes(chr(255 * self.flipflop) * (1 + (self.y > 15)) * 10)
chr(255 * self.flipflop) * (1 + (self.y > 15)) * 10
)
self.stack_push_word((self.pc + 1) & 0xFFFF) self.stack_push_word((self.pc + 1) & 0xFFFF)
self.pc = addr - 2 self.pc = addr - 2
@ -498,80 +273,49 @@ class CPU(object):
self.pc = (self.pc + 1) & 0xFFFF self.pc = (self.pc + 1) & 0xFFFF
def ADDITION(self, arg): def ADDITION(self, arg):
result = (arg & 0xFF) + self.a + self.get_flag(self.CARRY) result = (arg & 0XFF) + self.a + self.get_flag(self.CARRY)
self.set_flag(self.OVERFLOW, (~(arg ^ self.a)) & (self.a ^ result) & 0x80) self.set_flag(self.OVERFLOW, (~(arg ^ self.a)) & (self.a ^ result) & 0x80)
self.set_flag(self.CARRY, result > 255) self.set_flag(self.CARRY, result > 255)
self.a = self.set_nz(result) & 0xFF self.a = self.set_nz(result) & 0xFF
def ADC(self, addr): def ADC(self, addr): self.ADDITION(self.get_byte(addr))
self.ADDITION(self.get_byte(addr)) def SBC(self, addr): self.ADDITION(~self.get_byte(addr))
def SBC(self, addr):
self.ADDITION(~self.get_byte(addr))
def COMPARE(self, what, addr): def COMPARE(self, what, addr):
self.set_flag(self.CARRY, self.set_nz(what - self.get_byte(addr)) >= 0) self.set_flag(self.CARRY, self.set_nz(what - self.get_byte(addr)) >= 0)
def CMP(self, addr): def CMP(self, addr): self.COMPARE(self.a, addr)
self.COMPARE(self.a, addr) def CPX(self, addr): self.COMPARE(self.x, addr)
def CPY(self, addr): self.COMPARE(self.y, addr)
def CPX(self, addr):
self.COMPARE(self.x, addr)
def CPY(self, addr):
self.COMPARE(self.y, addr)
def BRANCH(self, addr, flag, condition): def BRANCH(self, addr, flag, condition):
if self.get_flag(flag) is condition: if self.get_flag(flag) is condition:
self.pc = addr self.pc = addr
self.cycles += 1 # Ako se grana, to je 1 ekstra ciklus self.cycles += 1 # Ako se grana, to je 1 ekstra ciklus
def BCS(self, addr):
self.BRANCH(addr, self.CARRY, True)
def BCC(self, addr): def BCS(self, addr): self.BRANCH(addr, self.CARRY, True)
self.BRANCH(addr, self.CARRY, False) def BCC(self, addr): self.BRANCH(addr, self.CARRY, False)
def BEQ(self, addr): self.BRANCH(addr, self.ZERO, True)
def BEQ(self, addr): def BNE(self, addr): self.BRANCH(addr, self.ZERO, False)
self.BRANCH(addr, self.ZERO, True) def BMI(self, addr): self.BRANCH(addr, self.NEGATIVE, True)
def BPL(self, addr): self.BRANCH(addr, self.NEGATIVE, False)
def BNE(self, addr): def BVS(self, addr): self.BRANCH(addr, self.OVERFLOW, True)
self.BRANCH(addr, self.ZERO, False) def BVC(self, addr): self.BRANCH(addr, self.OVERFLOW, False)
def BMI(self, addr):
self.BRANCH(addr, self.NEGATIVE, True)
def BPL(self, addr):
self.BRANCH(addr, self.NEGATIVE, False)
def BVS(self, addr):
self.BRANCH(addr, self.OVERFLOW, True)
def BVC(self, addr):
self.BRANCH(addr, self.OVERFLOW, False)
# dissasemble address # dissasemble address
def disasm(self, addr): def disasm(self, addr):
instruction, addressing, cycles = self._opcodes[self.memory[addr]] instruction, addressing, cycles = self._opcodes[self.memory[addr]]
return ( return "%04X %s %s" % (addr, instruction.__name__.lower(), self.addr_fmt[addressing](addr+1)), addr + self.ticks[addressing] + 1
"%04X %s %s"
% (addr, instruction.__name__.lower(), self.addr_fmt[addressing](addr + 1)),
addr + self.ticks[addressing] + 1,
)
def step(self): def step(self):
opcode = self.memory[self.pc] opcode = self.memory[self.pc]
if opcode not in self._opcodes: if opcode not in self._opcodes:
print("HALT") print('HALT')
for addr in self.executed: for addr in self.executed:
code, _ = self.disasm(addr) code, _ = self.disasm(addr)
print((" - %s" % code)) print(" - %s" % code)
print( print(" > %04x %02x %02x" % (self.pc, self.memory[self.pc], self.memory[self.pc+1]))
(
" > %04x %02x %02x"
% (self.pc, self.memory[self.pc], self.memory[self.pc + 1])
)
)
self.executed.append(self.pc) self.executed.append(self.pc)
self.pc = self.pc + 1 & 0xFFFF self.pc = self.pc + 1 & 0xFFFF
@ -584,3 +328,4 @@ class CPU(object):
self.executed = self.executed[1:] self.executed = self.executed[1:]
self.cycles += cycles self.cycles += cycles

View file

@ -1,37 +1,26 @@
# -*- coding: utf-8 -*- # -*- coding: utf8 -*-
# defines orao keyboard # defines orao keyboard
import pygame, numpy import pygame, numpy
_kbd = { _kbd = {
0x83FE: (112, 240, 185, 39), 0x83FE: (112, 240, 185, 39), 0x83FF: (45, 48), # [p đ š ;] [- 0]
0x83FF: (45, 48), # [p đ š ;] [- 0] 0x85FE: (232, 230, 190, 43), 0x85FF: (8, 94), # [č ć ž :] [BS ^]
0x85FE: (232, 230, 190, 43), 0x86FE: (102, 104, 103, 110), 0x86FF: (98, 118), # [f h g n] [b v]
0x85FF: (8, 94), # [č ć ž :] [BS ^] 0x877E: (100, 97, 115, 122), 0x877F: (120, 99), # [d a s z] [x c]
0x86FE: (102, 104, 103, 110), 0x87BE: (108, 106, 107, 109), 0x87BF: (44, 46), # [l j k m] [, .]
0x86FF: (98, 118), # [f h g n] [b v] 0x87DE: (101, 113, 119, 49), 0x87DF: (50, 51), # [e q w l] [2 3]
0x877E: (100, 97, 115, 122), 0x87EE: (111, 105, 117, 55), 0x87EF: (56, 57), # [o i u 7] [8 9]
0x877F: (120, 99), # [d a s z] [x c] 0x87F6: (114, 121, 116, 54), 0x87F7: (53, 52), # [r y t 6] [5 4]
0x87BE: (108, 106, 107, 109), 0x87FA: (282, 283, 284, pygame.K_RCTRL), 0x87FD: (13, pygame.K_LCTRL), # [f1f2f3f4] [cr l_ctrl]
0x87BF: (44, 46), # [l j k m] [, .]
0x87DE: (101, 113, 119, 49),
0x87DF: (50, 51), # [e q w l] [2 3]
0x87EE: (111, 105, 117, 55),
0x87EF: (56, 57), # [o i u 7] [8 9]
0x87F6: (114, 121, 116, 54),
0x87F7: (53, 52), # [r y t 6] [5 4]
0x87FA: (282, 283, 284, pygame.K_RCTRL),
0x87FD: (13, pygame.K_LCTRL), # [f1f2f3f4] [cr l_ctrl]
0x87FC: (pygame.K_LEFT, pygame.K_UP, pygame.K_DOWN, pygame.K_RIGHT), 0x87FC: (pygame.K_LEFT, pygame.K_UP, pygame.K_DOWN, pygame.K_RIGHT),
0x87FB: (32, pygame.K_RSHIFT), # [spc l_shift] 0x87FB: (32, pygame.K_RSHIFT) # [spc l_shift]
} }
def listener(event, cpu): def listener(event, cpu):
if event.type in [pygame.KEYDOWN, pygame.KEYUP]: if event.type in [pygame.KEYDOWN, pygame.KEYUP]:
for address, keycodes in _kbd.items(): for address, keycodes in _kbd.items():
keys = list(map(pygame.key.get_pressed().__getitem__, keycodes)) keys = list(map(pygame.key.get_pressed().__getitem__, keycodes))
cpu.memory[address] = ( cpu.memory[address] = ~numpy.dot(keys, [16, 32, 64, 128][:len(keys)]) & 0xFF
~numpy.dot(keys, [16, 32, 64, 128][: len(keys)]) & 0xFF
)

View file

@ -1,25 +1,14 @@
# -*- coding: utf-8 -*-
timer = {} timer = {}
timer_pos = {} timer_pos = {}
def mem_listener(addr, val, cpu): def mem_listener(addr, val, cpu):
if addr >= 0xA000 and addr <= 0xA0FF: if addr >= 0xa000 and addr <= 0xa0ff:
timer_ix = addr & 0xFF timer_ix = addr & 0xff
if timer_ix in timer: if timer_ix in timer:
print( print('timer(%3d:%04x-%04x):duration %d cy' % (timer_ix, timer_pos[timer_ix], cpu.pc-1, cpu.cycles - timer[timer_ix] - 4))
(
"timer(%3d:%04x-%04x):duration %d cy"
% (
timer_ix,
timer_pos[timer_ix],
cpu.pc - 1,
cpu.cycles - timer[timer_ix] - 4,
)
)
)
del timer[timer_ix] del timer[timer_ix]
del timer_pos[timer_ix] del timer_pos[timer_ix]
else: else:
timer[timer_ix] = cpu.cycles timer[timer_ix] = cpu.cycles
timer_pos[timer_ix] = cpu.pc + 2 timer_pos[timer_ix] = cpu.pc+2

View file

@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
import pygame import pygame
terminal = pygame.Surface((256, 256), pygame.SRCALPHA, depth=32) terminal = pygame.Surface((256, 256), pygame.SRCALPHA, depth=32)
terminal.fill((255, 255, 255)) terminal.fill((255, 255, 255))
alphaarray = pygame.surfarray.pixels_alpha(terminal) alphaarray = pygame.surfarray.pixels_alpha(terminal)
def mem_listener(addr, val, cpu): def mem_listener(addr, val, cpu):
if 0x6000 <= addr <= 0x7FFF: # Video RAM if 0x6000 <= addr <= 0x7FFF: # Video RAM
y, x = divmod((addr - 0x6000) * 8, 256) y, x = divmod((addr - 0x6000) * 8, 256)

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pygame import pygame
from .view import View from .view import View

View file

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
import pygame import pygame
from .view import View from .view import View
from ..chargen import chargen_draw_str from ..chargen import chargen_draw_str
class CPUState(View): class CPUState(View):
def __init__(self): def __init__(self):
self.init_surface(pygame.Surface((2 * 8 * 8, 3 * 8), depth=24)) self.init_surface(pygame.Surface((2 * 8 * 8, 3 * 8), depth=24))
#self.set_smooth_scale() #self.set_smooth_scale()

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import pygame import pygame
import numpy import numpy
from .view import View from .view import View
@ -32,3 +30,4 @@ class MemHeatmap(View):
mem = cpu.memory[self.start_addr:self.start_addr + (w * h)] mem = cpu.memory[self.start_addr:self.start_addr + (w * h)]
arr = numpy.reshape(mem, (h, w)) arr = numpy.reshape(mem, (h, w))
pygame.surfarray.blit_array(self.surf, numpy.transpose(arr)) pygame.surfarray.blit_array(self.surf, numpy.transpose(arr))

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from .heatmap import MemHeatmap from .heatmap import MemHeatmap
from .access_map import AccessMap from .access_map import AccessMap

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import pygame import pygame
from .view import View from .view import View
from ..chargen import chargen_draw_str from ..chargen import chargen_draw_str

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import pygame import pygame
class View: class View:

3
requirements.txt Normal file
View file

@ -0,0 +1,3 @@
numpy==1.26.1
pygame==2.5.2
Wave==0.0.2

View file

@ -1,66 +0,0 @@
# TOSEC: Pel Varazdin Orao
via https://archive.org/details/Pel_Varazdin_Orao_TOSEC_2012_04_23
Orao (en. Eagle) was an 8-bit computer developed by PEL Varaždin in 1984. It was used as a standard primary school computer in Croatia and Vojvodina from 1985 to 1991. Orao (code named YU102) was designed by Miroslav Kocijan to supersede Galeb (code named YU101). The goal was to make a better computer, yet with less components, easier to produce and less expensive. Originally the Motorola 6809 microprocessor was planned for the CPU but was abandoned for MOS 6502 due to its significantly lower cost.
There are 50 images of disks for the Pel Varazdin Orao, including games, applications, and firmware.
Added on: 2013-02-28 05:29:33
Identifier: Pel_Varazdin_Orao_TOSEC_2012_04_23
# listing
## Firmware
- Eagle Extended Basic v1.0 (1985)(PEL Varazdin).rom
- Monitor ROM v1.2 (19xx)(PEL Varazdin).rom
- Monitor ROM v1.3 (19xx)(PEL Varazdin).rom
- Orao Basic 1.2 (19xx)(PEL Varazdin).rom
## Games
- Ajnc (19xx)(PEL Soft)(YU).tap
- Avion (1986)(Herceg, Emil - Kos, Igor)(YU).tap
- Boulder Dash (19xx)(Mihailovic, Nenad - Dapjas, Mihajlo)(YU)(en).tap
- Breakout (19xx)(Stan Rimox Software)(YU)(en).tap
- Brojke (19xx)(-)(YU).tap
- Crvic (1986)(PEL Soft)(YU).tap
- Eagle (1986)(KMI Borovo)(YU).tap
- Figure Chess (1986)(KMI Borovo)(YU)(en).tap
- Internacional Karate (19xx)(KMI Borovo)(YU).tap
- Jugador (19xx)(Vuletic, Mario)(YU)(en).tap
- Jumping Jack (1986)(KMI Borovo)(YU)(en).tap
- Kuki (1986)(KMI Borovo)(YU).tap
- Labirint (1985)(Bibi Soft)(YU).tap
- Labirint M (19xx)(-)(YU).tap
- Magicni Kvadrat (1985)(Ranogajec, Mario - Korpar, Boris)(YU).tap
- Manic Miner (19xx)(Mihailovic, Nenad)(YU)(en).tap
- Match Fishing (1986)(KMI Borovo)(YU)(en).tap
- Memo (19xx)(PEL Soft)(YU).tap
- Memo (19xx)(PEL Soft)(YU)[a].tap
- Nevidljivi (1987)(Suzy Soft)(YU)[orao no.1].tap
- Obelix (19xx)(KMI Borovo)(YU)(en).tap
- Othello (1985)(Ivkovic, Sasa)(YU).tap
- Pac-Man (19xx)(Ivkovic, Sasa)(YU).tap
- Pcelica Maja (19xx)(-)(YU).tap
- Pomorska Bitka (19xx)(-)(YU).tap
- Reversi (19xx)(-)(YU)(en).tap
- Sokoban (19xx)(J.P.)(YU)(en).tap
- Space Invaders (19xx)(PEL Soft)(YU).tap
- Strip Ainc (1985)(Bistrovic, Z.)(YU).tap
- Strip Game Ainc (19xx)(KMI Borovo)(YU).tap
- Ukleti Dvorac (19xx)(-)(YU).tap
- Zid (1985)(PEL Zabavni Programi)(YU).tap
## Various
- 6502 Step v1.0 (19xx)(-).tap
- Crtanje (1987)(Suzy Soft)(YU)[orao no.1].tap
- Demo Grafika (1985)(KMI Borovo)(YU).tap
- Mikroracunalo Orao (1988)(PEL Varazdin)(YU)(Tape 1 of 2).tap
- Mikroracunalo Orao (1988)(PEL Varazdin)(YU)(Tape 2 of 2).tap
- Podsjetnik (1987)(Suzy Soft)(YU)[orao no.1].tap
- Porno (19xx)(-)(YU).tap
- Sintetizator Zvuka (1987)(Suzy Soft)(YU)[orao no.1].tap
- Tornjevi (19xx)(Tom)(YU).tap
- Znakovi (1987)(Suzy Soft)(YU)[orao no.1].tap