Howdy
Trying to getting an 6502 emulator working using a basic that has no bytes/words/dwords, only signed integers of 32bit size, nothing else.
I think this is a convert from Pascal to start with, and so I tried found that and compare the sources but no luck yet.
ADC and SBC being a bit complex , does anyone know if C64 KERNAL uses decimal mode? the pascal original source does not use decimal mode and are supposed to be able to run c64 kernal nonetheless, nonetheless it would be nice to have it confirmed.
Tried finding the bug for sometime now without luck, It does run C64 kernel but shows weird characters and actually its an basic error message. You get the blinking cursor and this, not the introduction text C64 BASIC FREE etc.. as you are supposed to.
Any luck any of you spot the bug?
This is how it looks like this, cursor is alive blinking as should and as routine feeds keyboard to kernal buffer, you may type and it respond just with wierd characters/graphics and error messages.
This is how it looks like: (it says OUT OF MEMORY ERROR IN READY if you subtract value of 64 from the ascii this is should not be needed and are probably part of the bug in some instruction logic)
UPDATED CREDITS GOES TO
- Marc Dendooven made tutorials and Pascal version
- Blitz conversion and optimizations by Jimmy
- Debugged by Lee Davison and Danny Olsson.
Here included is the fixed full source BASIC sourcecode, enjoy!
UPDATE
Last years hard work on CartAdore showed fruitful finally. It begins coming close to be what it is supposed to be;
The goal is to be an open source emulator covering only a few sheets of paper, for an easy overview learning about emulators.
Special thanks goes to Lee and Danny for doing emense work on this the last few days.
Code:
;************************************************************************************
; Commodore 64 emulator
;
; Translated and corrected sourcecodes
; originally Pascal source by Ed64 ( Marc Dendooven )
;
; Blitz3D Conversion by Jimmy
; 2007 - 2011
; 6502 emulator "CartAdore"
; Official webpage but soon to come
;
; Debugged by Lee Davison and Danny Olsson
; bugfixed to a running state and commented by Lee Davison 2011/06/05
;
; visit: <a href="http://www.themotionstore.com/leeedavison/" target="_blank">http://www.themotionstore.com/leeedavison/</a>
;
; Sorry, the text is formatted for TAB stops at six characters not four characters
; as used by the Blitz IDE but the Blitz syntax highlighting colours make me want to
; stab my eyes out. So I used another, monochrome, text editor.
;
; Version 0.53
;
;************************************************************************************
;
; Emulates a 6502 (without secret opcodes and extra 6510 opcodes, just standard C64
; opcodes)
; Does not emulate SID or CIA(input/output 2 6526 adapters w16bit parallel IO 8bit
; seraial IO, TOD clock with alarm)
; Does an crudly simple VIC II emulation (40x25 textmode 1024 area without colourmap,
; and vbl interrupt) nothing else
; 2Joystickports, userport, cartridge, disk, datasette
; Improved but as of yet unused C64 colour palette:
;
; $000000 black
; $FFFFFF white
; $68372B red
; $70A4B2 cyan
; $6F3D86 purple
; $588D43 green
; $352879 blue
; $B8C76F yellow
; $6F4F25 lt brown
; $433900 brown
; $9A6759 pink
; $444444 dark grey
; $6C6C6C grey
; $9AD284 lt green
; $6C5EB5 lt blue
; $959595 lt grey
;************************************************************************************
;
; Constants
Const n = $80 ; status bits in p: NV..DIZC
Const v = $40
Const b = $10 ; b isn't a real bit, don't set it
Const d = $08
Const i = $04
Const z = $02
Const c = $01
;************************************************************************************
;
; Global variables
; 8 bit registers
Global a ; Accumulator
Global x ; X register
Global y ; Y register
Global s ; the low 8 bits of the stack pointer
Global p ; processor status register
Global op ; the current opcode
; 16 bit register
Global pc ; program counter
Dim ram(65536) ; Arrays are global
Dim basic_rom(65536) ; $A000-$BFFF
Dim char_rom(65536) ; $D000-$DFFF
Dim kernal_rom(65536) ; $E000-$FFFF
;************************************************************************************
;
; start of code
Graphics 640,400 ; a big enough window for no borders
; Load the roms
f = ReadFile("BASIC.ROM")
For index = $A000 To $A000 + $1FFF
basic_rom(index) = ReadByte(f)
Next
CloseFile f
f = ReadFile("CHAR.ROM")
For index = $D000 To $D000 + $0FFF
char_rom(index) = ReadByte(f)
Next
CloseFile f
f = ReadFile("KERNAL.ROM")
For index = $E000 To $E000 + $1FFF
kernal_rom(index) = ReadByte(f)
Next
CloseFile f
; start up the processor
reset() ; set the initial pc and disable interrupts
; Main loop
Repeat
cycle = cycle + 2 ; all instructions are a minimum of two cycles
op = peek(pc) ; get the next opcode
pc = (pc + 1) And $FFFF ; increment the program counter
Select op
Case $69 : adc(imm()) ; was broken, now ok
Case $65 : adc(zp()) ; was broken, now ok
Case $75 : adc(zpx()) ; was broken, now ok
Case $6D : adc(abs_()) ; was broken, now ok
Case $7D : adc(abs_x()) ; was broken, now ok
Case $79 : adc(abs_y()) ; was broken, now ok
Case $61 : adc(indx()) ; was broken, now ok
Case $71 : adc(indy()) ; was broken, now ok
Case $29 : and_(imm()) ; ok
Case $25 : and_(zp()) ; ok
Case $35 : and_(zpx()) ; ok
Case $2D : and_(abs_()) ; ok
Case $3D : and_(abs_x()) ; ok
Case $39 : and_(abs_y()) ; ok
Case $21 : and_(indx()) ; ok
Case $31 : and_(indy()) ; ok
Case $0A : asl_A() ; ok
Case $06 : asl(zp()) ; ok
Case $16 : asl(zpx()) ; ok
Case $0E : asl(abs_()) ; ok
Case $1E : asl(abs_x()) ; ok
Case $90 : bfc(c) ; ok ; bcc
Case $B0 : bfs(c) ; ok ; bcs
Case $F0 : bfs(z) ; ok ; beq
Case $24 : bit(zp()) ; was broken, now ok
Case $2C : bit(abs_()) ; was broken, now ok
Case $30 : bfs(n) ; ok ; bmi
Case $D0 : bfc(z) ; ok ; bne
Case $10 : bfc(n) ; ok ; bpl
Case $00 : brk() ; ok
Case $50 : bfc(v) ; ok ; bvc
Case $70 : bfs(v) ; ok ; bvs
Case $18 : setflag(c,False) ; ok ; clc
Case $D8 : setflag(d,False) ; ok ; cld
Case $58 : setflag(i,False) ; ok ; cli
Case $B8 : setflag(v,False) ; ok ; clv
Case $C9 : cmp(imm()) ; ok
Case $C5 : cmp(zp()) ; ok
Case $D5 : cmp(zpx()) ; ok
Case $CD : cmp(abs_()) ; ok
Case $DD : cmp(abs_x()) ; ok
Case $D9 : cmp(abs_y()) ; ok
Case $C1 : cmp(indx()) ; ok
Case $D1 : cmp(indy()) ; ok
Case $E0 : cpx(imm()) ; ok
Case $E4 : cpx(zp()) ; ok
Case $EC : cpx(abs_()) ; ok
Case $C0 : cpy(imm()) ; ok
Case $C4 : cpy(zp()) ; ok
Case $CC : cpy(abs_()) ; ok
Case $C6 : dec_(zp()) ; ok
Case $D6 : dec_(zpx()) ; ok
Case $CE : dec_(abs_()) ; ok
Case $DE : dec_(abs_x()) ; ok
Case $CA : dex() ; ok
Case $88 : dey() ; ok
Case $49 : eor(imm()) ; ok
Case $45 : eor(zp()) ; ok
Case $55 : eor(zpx()) ; ok
Case $4D : eor(abs_()) ; ok
Case $5D : eor(abs_x()) ; ok
Case $59 : eor(abs_y()) ; ok
Case $41 : eor(indx()) ; ok
Case $51 : eor(indy()) ; ok
Case $E6 : inc_(zp()) ; ok
Case $F6 : inc_(zpx()) ; ok
Case $EE : inc_(abs_()) ; ok
Case $FE : inc_(abs_x()) ; ok
Case $E8 : inx() ; ok
Case $C8 : iny() ; ok
Case $4C : jmp(abs_()) ; ok
Case $6C : jmp(ind()) ; ok
Case $20 : jsr(abs_()) ; ok
Case $A9 : lda(imm()) ; ok
Case $A5 : lda(zp()) ; ok
Case $B5 : lda(zpx()) ; ok
Case $AD : lda(abs_()) ; ok
Case $BD : lda(abs_x()) ; ok
Case $B9 : lda(abs_y()) ; ok
Case $A1 : lda(indx()) ; ok
Case $B1 : lda(indy()) ; ok
Case $A2 : ldx(imm()) ; ok
Case $A6 : ldx(zp()) ; ok
Case $B6 : ldx(zpy()) ; ok
Case $AE : ldx(abs_()) ; ok
Case $BE : ldx(abs_y()) ; ok
Case $A0 : ldy(imm()) ; ok
Case $A4 : ldy(zp()) ; ok
Case $B4 : ldy(zpx()) ; ok
Case $AC : ldy(abs_()) ; ok
Case $BC : ldy(abs_x()) ; ok
Case $4A : lsr_A() ; ok
Case $46 : lsr(zp()) ; ok
Case $56 : lsr(zpx()) ; ok
Case $4E : lsr(abs_()) ; ok
Case $5E : lsr(abs_x()) ; ok
Case $EA : ; nop ; ok
Case $09 : ora(imm()) ; ok
Case $05 : ora(zp()) ; ok
Case $15 : ora(zpx()) ; ok
Case $0D : ora(abs_()) ; ok
Case $1D : ora(abs_x()) ; ok
Case $19 : ora(abs_y()) ; ok
Case $01 : ora(indx()) ; ok
Case $11 : ora(indy()) ; ok
Case $48 : push(a) ; ok ; pha
Case $08 : php() ; was broken, now ok
Case $68 : pla() ; ok
Case $28 : plp() ; was broken, now ok
Case $2A : rol_A() ; ok
Case $26 : rol(zp()) ; ok
Case $36 : rol(zpx()) ; ok
Case $2E : rol(abs_()) ; ok
Case $3E : rol(abs_x()) ; ok
Case $6A : ror_A() ; ok
Case $66 : ror(zp()) ; ok
Case $76 : ror(zpx()) ; ok
Case $6E : ror(abs_()) ; ok
Case $7E : ror(abs_x()) ; ok
Case $40 : rti() ; ok
Case $60 : rts() ; ok
Case $E9 : sbc(imm()) ; was broken, now ok
Case $E5 : sbc(zp()) ; was broken, now ok
Case $F5 : sbc(zpx()) ; was broken, now ok
Case $ED : sbc(abs_()) ; was broken, now ok
Case $FD : sbc(abs_x()) ; was broken, now ok
Case $F9 : sbc(abs_y()) ; was broken, now ok
Case $E1 : sbc(indx()) ; was broken, now ok
Case $F1 : sbc(indy()) ; was broken, now ok
Case $38 : setflag(c,True) ; ok ; sec
Case $F8 : setflag(d,True) ; ok ; sed
Case $78 : setflag(i,True) ; ok ; sei
Case $85 : sta(zp()) ; ok
Case $95 : sta(zpx()) ; ok
Case $8D : sta(abs_()) ; ok
Case $9D : sta(abs_x()) ; ok
Case $99 : sta(abs_y()) ; ok
Case $81 : sta(indx()) ; ok
Case $91 : sta(indy()) ; ok
Case $86 : stx(zp()) ; ok
Case $96 : stx(zpy()) ; ok
Case $8E : stx(abs_()) ; ok
Case $84 : sty(zp()) ; ok
Case $94 : sty(zpx()) ; ok
Case $8C : sty(abs_()) ; ok
Case $AA : tax() ; ok
Case $A8 : tay() ; ok
Case $BA : tsx() ; ok
Case $8A : txa() ; ok
Case $9A : txs() ; ok
Case $98 : tya() ; ok
Case $3F ; use opcode $3F to drop into the debugger
Stop
Case $7F ; use opcode $7F to output a value
Print peek(pc)
pc = (pc + 1) And $FFFF
Default ; an invalid opcode tells you where it is
Write pc - 1
Write " "
Write op
Print " unknown instruction"
WaitKey
End
End Select
; 1000000 cycles / vertical blanking
If cycle > 1000000/50 Then cycle = cycle - 1000000/50 : VWait : irq()
Until MouseDown(2)
End
;************************************************************************************
;
; functions that read/write memory
; return a word from (address)
Function peek2(address)
peek2 = peek(address) + peek(address + 1) Shl 8
Return peek2
End Function
; pokes a byte into memory
Function poke(address,value)
ram(address) = value And $FF
If (address=>$0400) And (address=<$07E7) Then VicText(address-$0400,value)
End Function
; get a byte from memory
Function peek(address)
If address=>$A000 And address=<$BFFF Then
peek = basic_rom(address)
Else If address=>$D000 And address=<$DFFF Then
peek = io(address)
Else If address=>$E000 And address=<$FFFF Then
peek = kernal_rom(address)
Else
peek = ram(address)
End If
Return peek
End Function
; read a byte from an i/o device
Function io(address)
If address = $D012 Then io=$00 Else io=$FF ; fake rasterinterrupt (rasterline 0 or 255)
Return io
End Function
;************************************************************************************
;
; functions which return address for the instructions to work with
; return the address of the immediate byte
Function imm()
imm = pc
pc = (pc + 1) And $FFFF
Return imm
End Function
; return the address of the zero page byte
Function zp()
zp = peek(pc)
pc = (pc + 1) And $FFFF
Return zp
End Function
; return the address of the zero page byte indexed by X
Function zpx()
zpx = (peek(pc) + x) And $FF
pc = (pc + 1) And $FFFF
Return zpx
End Function
; return the address of the zero page byte indexed by Y
Function zpy()
zpy = (peek(pc) + y) And $FF
pc = (pc + 1) And $FFFF
Return zpy
End Function
; return the absolute address
Function abs_()
abs_ = peek2(pc) And $FFFF
pc = (pc + 2) And $FFFF
Return abs_
End Function
; return the absolute address indexed by X
Function abs_x()
absx = (peek2(pc) + x) And $FFFF
pc = (pc + 2) And $FFFF
Return absx
End Function
; return the absolute address indexed by Y
Function abs_y()
absy = (peek2(pc) + y) And $FFFF
pc = (pc + 2) And $FFFF
Return absy
End Function
; return the indirect address, this is broken on the NMOS 6502 if it crosses a page
; boundary
Function ind()
ind = peek2(peek2(pc))
pc = (pc + 2) And $FFFF
Return ind
End Function
; return the (indirect,X) address
Function indx()
indx = peek2(lo(peek(pc) + x)) And $FFFF
pc = (pc + 1) And $FFFF
Return indx
End Function
; return the (indirect),Y address
Function indy()
indy = (peek2(peek(pc)) + y) And $FFFF
pc = (pc + 1) And $FFFF
Return indy
End Function
;************************************************************************************
;
; flags, bits, words and bytes
; set the flag bit in the status byte
;
; never use this routine to set the b flag as it won't get cleared and everything will
; then go pear shaped
Function setflag(flag,status)
If status Then p = (p Or flag) Else p = (p And (flag Xor $FF))
End Function
; return the 0 or 1 state of a flag bit
Function flagset(flag)
flagset = (p And flag) <> 0 ; the <> 0 ensures only 0 or 1 is returned
Return flagset
End Function
; return the low byte of a word
Function lo(value)
Return value And $FF
End Function
; return the high byte of a word
Function hi(value)
value = (value Shr 8) And $FF
Return value
End Function
; push a byte onto the stack and decrement the stack pointer
Function push(byte)
poke($100 + s,byte)
s = (s - 1) And $FF
End Function
; increment the stack pointer and pull a byte from the stack
Function pull()
s = (s + 1) And $FF
pull = peek($100 + s)
Return pull
End Function
; sign extend a byte to 32 bits
Function signedbyte(byte)
h = byte
If h => 128 Then h = h - $100
Return h
End Function
;************************************************************************************
;
; the opcodes
; branch if the flag bit is set
Function bfs(flag)
If flagset(flag) Then pc = pc + signedbyte(peek(pc))
pc = (pc + 1) And $FFFF
End Function
; branch if the flag bit is clear
Function bfc(flag)
If Not flagset(flag) Then pc = pc + signedbyte(peek(pc))
pc = (pc + 1) And $FFFF
End Function
; decimal mode is not needed to run the C64 firmware
Function adc(address)
val = peek(address) ; get the value from memory
bit = flagset(c) ; get the carry value in bit
hc = (((a And $7F) + (val And $7F) + bit) And $80) = $80
; calculate the carry from b6 to b7
h = a + val + bit ; calculate the new value and new carry
a = h And $FF ; and copy the value part to A
h = (h And $100) = $100 ; calculate the carry from b7
setflag(c,h) ; set the carry bit in the status
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
setflag(v,h Xor hc) ; set the overflow bit in the status
; overflow is true when hc and h differ
End Function
; decimal mode is not needed to run the C64 firmware
Function sbc(address)
val = peek(address) ; get the value from memory
bit = Not flagset(c) ; get the inverted carry value in bit
hc = Not (((a And $7F) - (val And $7F) - bit) And $80)
; calculate the inverted carry from b6 to b7
h = a - val - bit ; calculate the new value and new carry
a = h And $FF ; and copy the value part to A
h = Not (h And $100) ; calculate the inverted carry from b7
setflag(c,h) ; set the carry bit in the status
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
setflag(v,h Xor hc) ; set the overflow bit in the status
; overflow is true when hc and h differ
End Function
Function asl(address)
byte = peek(address) Shl 1 ; get and shift the value
setflag(c,byte And $100) ; set the carry bit in the status
byte = byte And $FF ; mask the result to byte size
poke(address,byte) ; save the result back to memory
setflag(z,Not byte) ; set the zero bit in the status
setflag(n,byte And n) ; set the negative bit in the status
End Function
Function asl_A()
a = a Shl 1 ; shift the value
setflag(c,a And $100) ; set the carry bit in the status
a = a And $FF ; mask the result to byte size
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function rol(address)
byte = (peek(address) Shl 1) + flagset(c)
; get shift and add the carry to the value
setflag(c,byte And $100) ; set the carry bit in the status
byte = byte And $FF ; mask the result to byte size
poke(address,byte) ; save the result back to memory
setflag(z,Not byte) ; set the zero bit in the status
setflag(n,byte And n) ; set the negative bit in the status
End Function
Function rol_A()
a = (a Shl 1) + flagset(c) ; shift and add the carry to the value
setflag(c,a And $100) ; set the carry bit in the status
a = a And $FF ; mask the result to byte size
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function ror(address)
byte = peek(address) ; get the value from memory
bit = flagset(c) Shl 7 ; get the carry value in b7
setflag(c,byte And 1) ; set the carry bit in the status
byte = (byte Shr 1) Or bit ; shift and add the carry to the value
poke(address,byte) ; save the result back to memory
setflag(z,Not byte) ; set the zero bit in the status
setflag(n,byte And n) ; set the negative bit in the status
End Function
Function ror_A()
bit = flagset(c) Shl 7 ; get the carry value in b7
setflag(c,a And 1) ; set the carry bit in the status
a = (a Shr 1) Or bit ; shift and add the carry to the value
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function lsr(address)
byte = peek(address) ; get the value from memory
setflag(c,byte And 1) ; set the carry bit in the status
byte = byte Shr 1 ; shift the value
poke(address,byte) ; save the result back to memory
setflag(z,Not byte) ; set the zero bit in the status
setflag(n,False) ; clear the negative bit in the status
End Function
Function lsr_A()
setflag(c,a And 1) ; set the carry bit in the status
a = a Shr 1 ; shift the value
setflag(z,Not a) ; set the zero bit in the status
setflag(n,False) ; clear the negative bit in the status
End Function
Function bit(address)
h = peek(address) ; get the value from memory
setflag(n,h And n) ; set the negative bit in the status
setflag(v,h And v) ; set the overflow bit in the status
setflag(z,Not(h And a)) ; set the zero bit in the status
End Function
Function brk()
pc = (pc + 1) And $FFFF ; increment the pc
push(hi(pc)) ; push the pc high byte
push(lo(pc)) ; push the pc low byte
push(p Or b) ; push the status byte with the break bit set
setflag(i,True) ; set the interrupt disable bit
pc = peek2($FFFE) ; get the IRQ vector
End Function
Function and_(address)
a = a And peek(address) ; AND the address contents with A
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function ora(address)
a=a Or peek(address) ; OR the address contents with A
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function eor(address)
a = a Xor peek(address) ; EOR the address contents with A
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function cmp(address)
h = a - peek(address) ; calculate A = the address contents
setflag(c,Not (h And $100)) ; set the carry bit in the status
setflag(z,Not (h And $FF)) ; set the zero bit in the status
setflag(n,h And n) ; set the negative bit in the status
End Function
Function cpx(address)
h = x - peek(address) ; calculate X = the address contents
setflag(c,Not (h And $100)) ; set the carry bit in the status
setflag(z,Not (h And $FF)) ; set the zero bit in the status
setflag(n,h And n) ; set the negative bit in the status
End Function
Function cpy(address)
h = y - peek(address) ; calculate Y = the address contents
setflag(c,Not (h And $100)) ; set the carry bit in the status
setflag(z,Not (h And $FF)) ; set the zero bit in the status
setflag(n,h And n) ; set the negative bit in the status
End Function
Function dec_(address)
h = (peek(address) - 1) And $FF ; calculate the address contents - 1
poke(address,h) ; save the result back to memory
setflag(z,Not h) ; set the zero bit in the status
setflag(n,h And n) ; set the negative bit in the status
End Function
Function inc_(address)
h = (peek(address) + 1) And $FF ; calculate the address contents + 1
poke(address,h) ; save the result back to memory
setflag(z,Not h) ; set the zero bit in the status
setflag(n,h And n) ; set the negative bit in the status
End Function
Function dex()
x = (x - 1) And $FF ; calculate X - 1
setflag(z,Not x) ; set the zero bit in the status
setflag(n,x And n) ; set the negative bit in the status
End Function
Function inx()
x = (x + 1) And $FF ; calculate X + 1
setflag(z,Not x) ; set the zero bit in the status
setflag(n,x And n) ; set the negative bit in the status
End Function
Function dey()
y = (y - 1) And $FF ; calculate Y - 1
setflag(z,Not y) ; set the zero bit in the status
setflag(n,y And n) ; set the negative bit in the status
End Function
Function iny()
y = (y + 1) And $FF ; calculate Y + 1
setflag(z,Not y) ; set the zero bit in the status
setflag(n,y And n) ; set the negative bit in the status
End Function
Function jmp(address)
pc = address ; copy the address to the pc
End Function
Function jsr(address)
pc = (pc - 1) And $FFFF ; decrement the address
push(hi(pc)) ; push the pc high byte
push(lo(pc)) ; push the pc low byte
pc = address ; copy the address to the pc
End Function
Function rts()
pc = 1 + pull() ; pull the pc low byte
pc = pc + pull() Shl 8 ; pull the pc high byte
End Function
Function rti()
p = pull() ; pull the status byte
pc = pull() ; pull the pc low byte
pc = pc + pull() Shl 8 ; pull the pc high byte
End Function
Function lda(address)
a = peek(address) ; get the value from memory
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function ldx(address)
x = peek(address) ; get the value from memory
setflag(z,Not x) ; set the zero bit in the status
setflag(n,x And n) ; set the negative bit in the status
End Function
Function ldy(address)
y = peek(address) ; get the value from memory
setflag(z,Not y) ; set the zero bit in the status
setflag(n,y And n) ; set the negative bit in the status
End Function
Function pla()
a = pull() ; pull a byte from the stack
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function php()
push(p Or b) ; push the status byte with the break bit set
End Function
Function plp()
p = pull() AND (b Xor $FF) ; pull the status byte and clear the break bit
End Function
Function sta(address)
poke(address,a) ; save A to the memory
End Function
Function stx(address)
poke(address,x) ; save X to the memory
End Function
Function sty(address)
poke(address,y) ; save Y to the memory
End Function
Function tax()
x = a ; copy X to A
setflag(z,Not x) ; set the zero bit in the status
setflag(n,x And n) ; set the negative bit in the status
End Function
Function tay()
y = a ; copy Y to A
setflag(z,Not y) ; set the zero bit in the status
setflag(n,y And n) ; set the negative bit in the status
End Function
Function tsx()
x = s ; copy X to the stack pointer
setflag(z,Not x) ; set the zero bit in the status
setflag(n,x And n) ; set the negative bit in the status
End Function
Function txa()
a = x ; copy A to X
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
Function txs()
s = x ; copy the stack pointer to X
End Function
Function tya()
a = y ; copy A to Y
setflag(z,Not a) ; set the zero bit in the status
setflag(n,a And n) ; set the negative bit in the status
End Function
;************************************************************************************
;
; the minimal hardware emulation
; interrupts
Function nmi()
push(hi(pc)) ; push the pc high byte
push(lo(pc)) ; push the pc low byte
push(p) ; push the status byte with the break bit clear
setflag(i,True) ; set the interrupt disable bit
pc = peek2($FFFA) ; get the NMI vector
End Function
Function reset()
setflag(i,True) ; set the interrupt disable bit
pc = peek2($FFFC) ; get the RESET vector
End Function
; vertical blanking interrupt
Function irq()
If flagset(i) Goto noint ; if the disable bit is set just exit
push(hi(pc)) ; push the pc high byte
push(lo(pc)) ; push the pc low byte
push(p) ; push the status byte with the break bit clear
setflag(i,True) ; set the interrupt disable bit
pc = peek2($FFFE) ; get the IRQ vector
addkey() ; pretend to scan the keyboard
.noint
End Function
; VIC chip peek
Function vicPeek(address)
If address=>$1000 And address=<$1FFF Then
peek = char_rom(address + $C000)
Else If address=>$9000 And address=<$9FFF Then
peek = char_rom(address + $4000)
Else
peek = ram(address)
End If
Return peek
End Function
; output a text byte to the screen
Function vicText(pos,val)
LockBuffer()
val = $1000 + val * 8 ; this will change if banks are implemented
x0 = (pos Mod 40) * 8 ; left edge x co-ordinate from pos
y0 = Int((pos / 40)) * 8 ; top edge y co-ordinate from pos
For yyy = 0 To 7 ; for each character row
byte = vicPeek(val + yyy) ; get the row byte from the character ROM
y1 = (y0 + yyy) Shl 1 ; calculate the screen y co-ordinate
For xxx = 0 To 7 ; for each pixel in the row
x1 = (x0 + xxx) Shl 1 ; calculate the screen x co-ordinate
If (byte And ($80 Shr xxx)) Then ; if the bit is set
colour = $6C5EB5 ; set the foreground colour
Else ; else if the bit is clear
colour = $352879 ; set the background colour
End If
WritePixelFast x1 , y1, colour ; write one pixel
WritePixelFast x1 + 1, y1, colour ; and the one next to it on the same row
; it makes for a stripey screen
Next
Next
UnlockBuffer()
End Function
; keyboard routine. shift lock doesn't seem to work and shift is the wrong sense
Function addkey()
kb = GetKey() And $FF ; get a key
If kb Then ; if there is a key
buff = peek($C6) ; get the keyboard buffer index
If buff < peek($0289) Then ; if there's room in the buffer
poke($0277 + buff,kb) ; save the key
poke($C6,buff + 1) ; save the updated buffer index
End If
End If
End Function
;************************************************************************************
I include the original full source BASIC sourcecode here
Code:
;---------------------------------------
; Commodore 64 emulator
;
; Translated and corrected sourcecodes
; originally by unknown author
;
; Version 0.2
;---------------------------------------
; Emulates a 6502 (without secret opcodes and extra 6510 opcodes, just standard C64 opcodes)
; Does not emulate SID or Joystickports, userport, cartridge, disk, datasette, CIA(input/output 2 6526 adapters w16bit parallel IO 8bit serial IO, clock with alarm)
; Does an simple VIC II emulation (40x25 textmode 1024 area without colourmap, and vbl interrupt) nothing else
; Notes: 100 - 1FF is stack page
; Improved C64 palette: black, white, red, cyan, purple, green, blue, yellow, lt brown, brown, pink, dark gray, gray, lt green, lt blue, lt gray
; $000000, $FFFFFF, $68372B, $70A4B2, $6F3D86, $588D43, $352879, $B8C76F, $6F4F25, $433900, $9A6759, $444444, $6C6C6C, $9AD284, $6C5EB5, $959595
Graphics 1024,600
; Global variables
Global a,x,y,s,p,op ; Bytes
Global pc ; Words
Dim ram(65536) ; Arrays are global
Dim basic_rom(65536); $A000-$BFFF
Dim char_rom(65536) ; $D000-$DFFF
Dim kernal_rom(65536);$E000-$FFFF
; Load roms
f=ReadFile("BASIC.ROM") : For temp=0 To 8191 : byte=ReadByte(f) : basic_rom($A000+temp)=byte : Next : CloseFile f
f=ReadFile("CHAR.ROM") : For temp=0 To 4095 : byte=ReadByte(f) : char_rom($D000+temp)=byte : Next : CloseFile f
f=ReadFile("KERNAL.ROM") : For temp=0 To 8191 : byte=ReadByte(f) : kernal_rom($E000+temp)=byte : Next : CloseFile f
; Constants
Const c=1, z=2, i=4, d=8, b=16, v=64, n=128 ; statusreg p: NV.BDIZC
; Processor
reset()
; Main loop OKAY
Repeat
cycle=cycle+1 : op=peek(pc) : pc=pc+1
Select op
Case $69 : adc(imm()) ; OKAY
Case $65 : adc(zp()) ; OKAY
Case $75 : adc(zpx()) ; OKAY
Case $6D : adc(abs_()) ; OKAY
Case $7D : adc(abs_x()) ; OKAY
Case $79 : adc(abs_y()) ; OKAY
Case $61 : adc(indx()) ; OKAY
Case $71 : adc(indy()) ; OKAY
Case $29 : and_(imm()) ; OKAY
Case $25 : and_(zp()) ; OKAY
Case $35 : and_(zpx()) ; OKAY
Case $2D : and_(abs_()) ; OKAY
Case $3D : and_(abs_x()) ; OKAY
Case $39 : and_(abs_y()) ; OKAY
Case $21 : and_(indx()) ; OKAY
Case $31 : and_(indy()) ; OKAY
Case $0A : asl_A() ; OKAY
Case $06 : asl(zp()) ; OKAY
Case $16 : asl(zpx()) ; OKAY
Case $0E : asl(abs_()) ; OKAY
Case $1E : asl(abs_x()) ; OKAY
Case $90 : bfc(c) ; bcc ; OKAY
Case $B0 : bfs(c) ; bcs ; OKAY
Case $F0 : bfs(z) ; beq ; OKAY
Case $24 : bit(zp()) ; OKAY
Case $2C : bit(abs_()) ; OKAY
Case $30 : bfs(n) ; bmi ; OKAY
Case $D0 : bfc(z) ; bne ; OKAY
Case $10 : bfc(n) ; bpl ; OKAY
Case $00 : brk() ; OKAY
Case $50 : bfc(v) ; bvc ; OKAY
Case $70 : bfs(v) ; bvs ; OKAY
Case $18 : setflag(c,False) ; clc ; OKAY
Case $D8 : setflag(d,False) ; cld ; OKAY
Case $58 : setflag(i,False) ; cli ; OKAY
Case $B8 : setflag(v,False) ; clv ; OKAY
Case $C9 : cmp(imm()) ; OKAY
Case $C5 : cmp(zp()) ; OKAY
Case $D5 : cmp(zpx()) ; OKAY
Case $CD : cmp(abs_()) ; OKAY
Case $DD : cmp(abs_x()) ; OKAY
Case $D9 : cmp(abs_y()) ; OKAY
Case $C1 : cmp(indx()) ; OKAY
Case $D1 : cmp(indy()) ; OKAY
Case $E0 : cpx(imm()) ; OKAY
Case $E4 : cpx(zp()) ; OKAY
Case $EC : cpx(abs_()) ; OKAY
Case $C0 : cpy(imm()) ; OKAY
Case $C4 : cpy(zp()) ; OKAY
Case $CC : cpy(abs_()) ; OKAY
Case $C6 : dec_(zp()) ; OKAY
Case $D6 : dec_(zpx()) ; OKAY
Case $CE : dec_(abs_()) ; OKAY
Case $DE : dec_(abs_x()) ; OKAY
Case $CA : dex() ; OKAY
Case $88 : dey() ; OKAY
Case $49 : eor(imm()) ; OKAY
Case $45 : eor(zp()) ; OKAY
Case $55 : eor(zpx()) ; OKAY
Case $4D : eor(abs_()) ; OKAY
Case $5D : eor(abs_x()) ; OKAY
Case $59 : eor(abs_y()) ; OKAY
Case $41 : eor(indx()) ; OKAY
Case $51 : eor(indy()) ; OKAY
Case $E6 : inc_(zp()) ; OKAY
Case $F6 : inc_(zpx()) ; OKAY
Case $EE : inc_(abs_()) ; OKAY
Case $FE : inc_(abs_x()) ; OKAY
Case $E8 : inx() ; OKAY
Case $C8 : iny() ; OKAY
Case $4C : jmp(abs_()) ; OKAY
Case $6C : jmp(ind()) ; OKAY
Case $20 : jsr(abs_()) ; OKAY
Case $A9 : lda(imm()) ; OKAY
Case $A5 : lda(zp()) ; OKAY
Case $B5 : lda(zpx()) ; OKAY
Case $AD : lda(abs_()) ; OKAY
Case $BD : lda(abs_x()) ; OKAY
Case $B9 : lda(abs_y()) ; OKAY
Case $A1 : lda(indx()) ; OKAY
Case $B1 : lda(indy()) ; OKAY
Case $A2 : ldx(imm()) ; OKAY
Case $A6 : ldx(zp()) ; OKAY
Case $B6 : ldx(zpy()) ; OKAY
Case $AE : ldx(abs_()) ; OKAY
Case $BE : ldx(abs_y()) ; OKAY
Case $A0 : ldy(imm()) ; OKAY
Case $A4 : ldy(zp()) ; OKAY
Case $B4 : ldy(zpx()) ; OKAY
Case $AC : ldy(abs_()) ; OKAY
Case $BC : ldy(abs_x()) ; OKAY
Case $4A : lsr_A() ; OKAY
Case $46 : lsr(zp()) ; OKAY
Case $56 : lsr(zpx()) ; OKAY
Case $4E : lsr(abs_()) ; OKAY
Case $5E : lsr(abs_x()) ; OKAY
Case $EA : ; nop ; OKAY
Case $09 : ora(imm()) ; OKAY
Case $05 : ora(zp()) ; OKAY
Case $15 : ora(zpx()) ; OKAY
Case $0D : ora(abs_()) ; OKAY
Case $1D : ora(abs_x()) ; OKAY
Case $19 : ora(abs_y()) ; OKAY
Case $01 : ora(indx()) ; OKAY
Case $11 : ora(indy()) ; OKAY
Case $48 : push(a) ; pha ; OKAY
Case $08 : push(p) ; php ; OKAY
Case $68 : pla() ; OKAY
Case $28 : p=pull() ; plp ; OKAY
Case $2A : rol_A() ; OKAY
Case $26 : rol(zp()) ; OKAY
Case $36 : rol(zpx()) ; OKAY
Case $2E : rol(abs_()) ; OKAY
Case $3E : rol(abs_x()) ; OKAY
Case $6A : ror_A() ; OKAY
Case $66 : ror(zp()) ; OKAY
Case $76 : ror(zpx()) ; OKAY
Case $6E : ror(abs_()) ; OKAY
Case $7E : ror(abs_x()) ; OKAY
Case $40 : rti() ; OKAY
Case $60 : rts() ; OKAY
Case $E9 : sbc(imm()) ; OKAY
Case $E5 : sbc(zp()) ; OKAY
Case $F5 : sbc(zpx()) ; OKAY
Case $ED : sbc(abs_()) ; OKAY
Case $FD : sbc(abs_x()) ; OKAY
Case $F9 : sbc(abs_y()) ; OKAY
Case $E1 : sbc(indx()) ; OKAY ; OKAY
Case $F1 : sbc(indy()) ; OKAY
Case $38 : setflag(c,True) ; sec ; OKAY
Case $F8 : setflag(d,True) ; sed ; OKAY
Case $78 : setflag(i,True) ; sei ; OKAY
Case $85 : sta(zp()) ; OKAY
Case $95 : sta(zpx()) ; OKAY
Case $8D : sta(abs_()) ; OKAY
Case $9D : sta(abs_x()) ; OKAY
Case $99 : sta(abs_y()) ; OKAY
Case $81 : sta(indx()) ; OKAY
Case $91 : sta(indy()) ; OKAY
Case $86 : stx(zp()) ; OKAY
Case $96 : stx(zpy()) ; OKAY
Case $8E : stx(abs_()) ; OKAY
Case $84 : sty(zp()) ; OKAY
Case $94 : sty(zpx()) ; OKAY
Case $8C : sty(abs_()) ; OKAY
Case $AA : tax() ; OKAY
Case $A8 : tay() ; OKAY
Case $BA : tsx() ; OKAY
Case $8A : txa() ; OKAY
Case $9A : txs() ; OKAY
Case $98 : tya() ; OKAY
Default Print "unknown instruction":WaitKey:End
End Select
If cycle>1000000/50 Then cycle=cycle-1000000/50:VWait:irq() ; 1000000 instructions / vertical blanking
Until MouseDown(2) ; quit when pressing right mousebutton
Function peek2(address) : peek2 = peek(address) + peek(address+1)*256 : Return peek2 : End Function ; OKAY
Function poke(address,value) ; pokes a byte
ram(address)=value : If address=>$400 And address=<$7E7 Then VicText(address-$400,value)
End Function
Function peek(address) ; returns a byte ; OKAY
peek=ram(address)
If address=>$A000 And address=<$BFFF Then peek=basic_rom(address)
If address=>$D000 And address=<$DFFF Then peek=io(address)
If address=>$E000 And address=<$FFFF Then peek=kernal_rom(address)
Return peek
End Function
Function io(address) ; OKAY
If address = $D012 Then io=$00 Else io=$FF ; fake rasterinterrupt (rasterline 0 or 256)
Return io
End Function
Function signedbyte(byte) ; Checked, reads byte as 2nd complement byte, outputs -128 to 127
temp=byte:If temp=>128 Then temp=temp-256
Return temp
End Function
; Addressing modes: functions which return address for instructions to work upon ; 99%
Function imm() : imm=pc : pc=pc+1 : pc=pc And 65535 : Return imm : End Function ; returns normal word
Function zp() : zp=peek(pc) : pc=pc+1 : pc = pc And 65535 : Return zp : End Function ; returns normal byte
Function zpx() : zpx=peek(pc)+x : zpx = zpx and 255 : pc=pc+1 : pc=pc And 65535 : Return zpx : End Function
Function zpy() : zpy=peek(pc)+y : zpy = zpy and 255 : pc=pc+1 : pc=pc And 65535 : Return zpy : End Function
Function abs_() : abs_=peek2(pc) : pc=pc+2 : abs_=Abs_ And 65535 : pc = pc And 65535 : Return abs_ : End Function
Function abs_x() : absx=peek2(pc)+x : absx = absx and 65535 : pc=pc+2 : pc = pc and 65535 : Return absx : End Function
Function abs_y() : absy=peek2(pc)+y : absy = absy and 65535 : pc=pc+2 : pc = pc and 65535 : Return absy : End Function
Function ind() : ind=peek2(peek2(pc)) : pc=pc+2 : pc = pc and 65535 : Return ind : End Function
Function indx() : indx=peek2(lo(peek(pc)+x)) : indx = indx And 65535 : pc=pc+1 : pc = pc And 65535 : Return indx : End Function
Function indy() : indy=peek2(peek(pc))+y : indy = indy and 65535 : pc=pc+1 : pc = pc and 65535 : Return indy : End Function
Function setflag(flag,status) ; OKAY
If status Then p=(p Or flag) Else p=(p And (flag Xor 255))
End Function
Function flagset(flag) : flagset=(p And flag) : Return flagset : End Function ; OKAY
Function lo(value) : Return value And 255 : End Function ; OKAY
Function hi(value) : value=value Shr 8 : Return value And 255 : End Function
Function push(byte) : poke (256+s,byte) : s=s-1 : s=Abs(s+256) And 255 : End Function ; OKAY
Function pull() : s=s+1 : s=Abs(s+256) And 255 : pull=peek(256+s) : Return pull : End Function ; OKAY
Function bfs(flag) ; 99%
If flagset(flag) Then pc=pc+signedbyte(peek(pc))+1 Else pc=pc+1
pc=Abs (pc+65536) And 65535
End Function
Function bfc(flag) ; 99%
If flagset(flag) Then pc=pc+1 Else pc=pc+signedbyte(peek(pc))+1
pc=Abs (pc+65536) And 65535
End Function
Function adc(address) ; 99% ; DECIMAL MODE NOT NEEDED?
val=peek(address) : h=a+val : If flagset(c) Then h=h+1
a=h : setflag(c,h>$FF) : a=Abs(a+256) And 255 : setflag(z,a=0) : setflag(n,a And n)
h=h+$80
setflag(v, ( (h>$FF) Or (h<0)) ) ; SetFlag(v,( (((a Xor val) And $80) And ((a Xor h) And $80)) Xor 65535) And 65536 )
End Function
Function sbc (address) ; 99% ; DECIMAL MODE NOT NEEDED?
val=peek(address) : h=a-val : If Not flagset(c) Then h=h-1
a=h :setflag(c,h<=$FF) : a=Abs(a+256) And 255 : setflag(z,a=0) : setflag(n,a And n)
h=h+$80
setflag(v, ((h>$FF) Or (h<0)) ) ; SetFlag(v,(((a Xor val) And $80) And ((a Xor h) And $80)) And 65536)
End Function
Function asl(address) ; 99%
byte=peek(address) : setflag(c,(byte And $80)) : byte=byte Shl 1 : byte=byte And 255 : poke(address,byte) : setflag(z,byte=0) : setflag(n,byte And n)
End Function
Function rol_A() ; 99%
bit=flagset(c) : setflag(c,(a And $80)) : a=a Shl 1 : a=a And 255
If bit Then a=a Or $01
setflag(z,a=0) : setflag(n,a And n)
End Function
Function rol(address) ; 99%
byte=peek(address) : bit=flagset(c) : setflag(c,(byte And $80)) : byte=byte Shl 1 : byte=byte And 255
If bit Then byte=byte Or $01
poke(address,byte) : setflag(z,byte=0) : setflag(n,byte And n)
End Function
Function ror_A() ; 99%
bit=flagset(c) : setflag(c,(a And $01)) : a=a Shr 1 : a=a And 255
If bit Then a=a Or $80
setflag(z,a=0) : setflag(n,a And n)
End Function
Function ror(address) ; 99%
byte=peek(address) : bit=flagset(c) : setflag(c,(byte And $01)) : byte=byte Shr 1 : byte=byte And 255
If bit Then byte=byte Or $80
poke(address,byte) : setflag(z,byte=0) : setflag(n,byte And n)
End Function
Function lsr_A() : setflag(c,(a And $01)) : a=a Shr 1 : a=a And 255 : setflag(z,a=0) : setflag(n,False) : End Function ; OKAY
Function lsr(address) : byte=peek(address) : setflag(C,(byte And $01)) : byte=byte Shr 1 : byte=byte And 255 : poke(address,byte) : setflag(z,byte=0) : setflag(n,False) : End Function ; 99%
Function bit(address) : h=peek(address) : setflag(n,(h And $80)) : setflag(v,(h And $40)) : setflag(z,((h And a)=0) ) : End Function ; 99%
Function brk() : setflag(b,True) : pc=pc+1 : pc=pc And 65535 : push(hi(pc)) : push(lo(pc)) : push(p) : setflag(i,True) : pc=peek2($FFFE) : End Function ; 99%
Function and_(address) : a=a And peek(address) : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY!
Function ora(address) : a=a Or peek(address) : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY!
Function asl_A() : setflag(c,(a And $80)) : a=a Shl 1 : a=a And 255 : setflag(z,a=0) : setflag(n,a And n) : End Function ; 99%
Function cmp(address) : h=a-peek(address) : setflag(c,h<=$FF) : h=Abs(h+256) And 255 : setflag(z,h=0) : setflag(n,h And n) : End Function ; 99% + 256 as could be negative? carry measuring correct?
Function cpx(address) : h=x-peek(address) : setflag(c,h<=$FF) : h=Abs(h+256) And 255 : setflag(z,h=0) : setflag(n,h And n) : End Function ; 99% + 256 as could be negative? carry measuring correct?
Function cpy(address) : h=y-peek(address) : setflag(c,h<=$FF) : h=Abs(h+256) And 255 : setflag(z,h=0) : setflag(n,h And n) : End Function ; 99% + 256 as could be negative? carry measuring correct?
Function dec_(address) :h=peek(address)-1 : h=Abs(h+256) And 255 : poke (address,h) : setflag(z,h=0) : setflag(n,h And n) : End Function ; 99%
Function dex() : x=x-1 : x=Abs(x+256) And 255 : setflag(z,x=0) : setflag(n,x And n) : End Function ; 99%
Function dey() : y=y-1 : y=Abs(y+256) And 255 : setflag(z,y=0) : setflag(n,y And n) : End Function ; 99%
Function eor(address) : a=a Xor peek(address) : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY!
Function inc_(address) : h=peek(address)+1 : h=h And 255 : poke (address,h) : setflag(z,h=0) : setflag(n,h And n) : End Function ; 99%
Function inx() : x=(x+1) And 255 : setflag(z,x=0) : setflag(n,x And n) : End Function ; OKAY
Function iny() : y=(y+1) And 255 : setflag(z,y=0) : setflag(n,y And n) : End Function ; OKAY
Function jmp(address) : pc=address : End Function ; OKAY
Function jsr(address) : pc=pc-1 : pc=Abs(pc+65536) And 65535 : push(hi(pc)) : push(lo(pc)) : pc=address : End Function ; OKAY
Function rts() : pc=pull() : pc=pc+pull()*256+1 : End Function ; OKAY!
Function rti() : p=pull() : pc=pull() : pc=pc+pull()*256 : End Function ; OKAY!
Function lda(address) : a=peek(address) : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY!
Function ldx(address) : x=peek(address) : setflag(z,x=0) : setflag(n,x And n) : End Function ; OKAY!
Function ldy(address) : y=peek(address) : setflag(z,y=0) : setflag(n,y And n) : End Function ; OKAY!
Function pla() : a=pull() : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY
Function sta(address) : poke (address,a) : End Function ; OKAY!
Function stx(address) : poke (address,x) : End Function ; OKAY!
Function sty(address) : poke (address,y) : End Function ; OKAY!
Function tax() : x=a : setflag(z,x=0) : setflag(n,x And n) : End Function ; OKAY!
Function tay() : y=a : setflag(z,y=0) : setflag(n,y And n) : End Function ; OKAY!
Function tsx() : x=s : setflag(z,x=0) : setflag(n,x And n) : End Function ; OKAY!
Function txa() : a=x : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY!
Function txs() : s=x : End Function ; OKAY!
Function tya() : a=y : setflag(z,a=0) : setflag(n,a And n) : End Function ; OKAY!
Function vicPeek(address) ; returns byte OKAY
peek=ram(address)
If address=>$1000 And address=<$1FFF Then peek=char_rom(address+$C000)
If address=>$9000 And address=<$9FFF Then peek=char_rom(address+$4000)
Return peek
End Function
Function vicText(pos,val) ; OKAY
LockBuffer() : x0=(pos Mod 40)*8 : y0=Int((pos / 40))*8
For xxx=0 To 7 : For yyy=0 To 7
colour=$352879 : If (vicPeek($1000+val*8+yyy) And ($80 Shr xxx)) Then colour = $6C5EB5
WritePixelFast (x0+xxx) Shl 1,(y0+yyy) Shl 1,colour : WritePixelFast 1+(x0+xxx) Shl 1,(y0+yyy) Shl 1,colour ; with abit retro feeling
Next : Next : UnlockBuffer()
End Function
Function reset() : pc=peek2($FFFC) : setflag(i,True) : End Function ; OKAY
Function irq() ; VERTCIAL BLANKING INTERUPT ; OKAY
If Not flagset(i) Then setflag(B,False) : push(hi(pc)) : push(lo(pc)) : push(p) : setflag(i,True) : pc=peek2($FFFE) : addkey()
End Function
Function nmi() : setflag(b,False) : push(hi(pc)) : push(lo(pc)) : push(p) : setflag(i,True) : pc=peek2($FFFA) : End Function ; OKAY
Function addkey() ; Keyboard routine ; OKAY (SCANCODE might need uppercase or other conversion or not)
buff = peek($C6) ; If ch = 0 Then ch=ord(readkey), ch = 145 ; up, ch = 157 ; left, ch = 17 ; down, ch = 29 ; right, ch = 148 ; inst-del
If buff < 10 Then kb=GetKey() : If kb Then poke($0277+buff,kb) : poke ($c6,buff+1)
End Function
UPDATED code to reflect proposed changes