698 lines
11 KiB
NASM
698 lines
11 KiB
NASM
|
|
.include "m128def.inc"
|
|
|
|
;.equ DEBUG = 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;------------------------------------------------------
|
|
|
|
|
|
;BIAS CONTROL
|
|
.equ bias_port = PORTG
|
|
.equ bias_ctrl = 3
|
|
.equ bias_adj = 4
|
|
|
|
|
|
;LCD
|
|
.equ A0 = 7
|
|
.equ WR = 5
|
|
.equ LCS = 6
|
|
.equ RD = 4
|
|
.equ LCD_RST = 7 (port D)
|
|
.equ lcd_pins = PORTE
|
|
.equ lcd_data = PORTB
|
|
|
|
|
|
;constants
|
|
.equ chars_line = 80 ;characters per line on lcd (virtual screen)
|
|
.equ lines_screen= 25 ;number of lines on screen
|
|
|
|
.def buff_head = r9
|
|
.def buff_tail = r10
|
|
.def cus_x = r11
|
|
.def cus_y = r12
|
|
|
|
|
|
;SRAM VARIABLES
|
|
.dseg
|
|
.org 0x100
|
|
|
|
serial_buff: .BYTE 256 ;buffers
|
|
|
|
|
|
vram_text: .BYTE chars_line*lines_screen ;one screen of text, should be in sync with display
|
|
vram_address: .BYTE 2 ;16 bit address of current pos in vram, should be same as display cursor address
|
|
|
|
|
|
;------EQU and DEF for Emulator---
|
|
.equ kernal_start = 0xE000
|
|
.equ basic_start = 0xC000
|
|
.equ char_start = 0x8000
|
|
.equ game_start = 0xA000
|
|
|
|
.equ Os = 6 ;overflow bit
|
|
.equ Ds = 3 ;Decimal
|
|
.equ Is = 7 ;Interupt
|
|
.equ Bs = 4 ;Break
|
|
|
|
.equ Cs = 0
|
|
.equ Zs = 1
|
|
.equ Ns = 2
|
|
|
|
.def stack = r15 ;stack pointer
|
|
.def Pstat1 = r13 ;the Processor status byte is split into 2 registers, this reg deals with C,Z,N
|
|
.def Pstat2 = r14 ;..this one deals with Int,Dec, Break ,(and now O(V) bit)
|
|
;this is done so I can simply save the AVR Status Reg to r13 for speed, and use native branch instructions
|
|
;bit 0=O
|
|
.def A = r21 ;accumulator
|
|
.def Xr = r22 ;X reg
|
|
.def Yr = r23 ;Y reg
|
|
.def PL = r26 ;XL
|
|
.def PH = r27 ;XH
|
|
.def retL = r24
|
|
.def retH = r25
|
|
.def zero_reg= r3 ;always 0
|
|
|
|
|
|
;DEBUG
|
|
.def breakL = r4
|
|
.def breakH = r5
|
|
|
|
emu_status: .BYTE 1 ;various bits to run emulator
|
|
;0 = LCD refresh toggle (refreshes every other interupt (30fps)
|
|
;1 = Next instuction is do interupt
|
|
|
|
;DEBUG
|
|
last_I: .BYTE 4 ;last 4 executed instructions
|
|
|
|
last_PC: .BYTE 2
|
|
|
|
last_rsbyte: .BYTE 1 ;last rs232 byte recived
|
|
.include "macros.asm"
|
|
.cseg
|
|
.org 0x00
|
|
rjmp start
|
|
;setup stack
|
|
.org 0x1E
|
|
rjmp timer0_cmp
|
|
|
|
.org 0x0024 ;received a rs232
|
|
rjmp rx_rs232_0
|
|
|
|
start:
|
|
LDI R16, HIGH(RAMEND) ;Upper byte
|
|
OUT SPH,R16 ;to stack pointer
|
|
LDI R16, LOW(RAMEND) ;Lower byte
|
|
OUT SPL,R16
|
|
|
|
|
|
|
|
k:
|
|
add r16,r17
|
|
|
|
; rjmp k
|
|
; rjmp skip
|
|
|
|
|
|
|
|
|
|
|
|
rcall init_hardware
|
|
|
|
rcall load_chars_lcd
|
|
|
|
rcall load_kernal
|
|
rcall load_basic
|
|
rcall load_chars
|
|
rcall load_game
|
|
|
|
skip:
|
|
|
|
|
|
;---setup timer--
|
|
ldi r16,7
|
|
out TCCR0,r16
|
|
ldi r16,2
|
|
out TIMSK,r16
|
|
|
|
; sei
|
|
|
|
|
|
|
|
|
|
clr zero_reg
|
|
ldi r16,0xff
|
|
mov stack,r16
|
|
sts last_rsbyte,r16
|
|
sts emu_status,zero_reg
|
|
|
|
|
|
ldi ZL,0xFC
|
|
ldi ZH,0xFF
|
|
ld PL,Z+
|
|
ld PH,Z
|
|
|
|
|
|
|
|
; ldi PL,0x00
|
|
; ldi PH,0x11
|
|
|
|
ldi r16,'G'
|
|
; rcall rs232_0_tx
|
|
ldi r16,'O'
|
|
; rcall rs232_0_tx
|
|
|
|
|
|
lds r16,0xffff
|
|
; rcall rs232_0_tx
|
|
|
|
lds r16,0xffff
|
|
; rcall rs232_0_tx
|
|
|
|
lds r16,0xe000
|
|
; rcall rs232_0_tx
|
|
|
|
lds r16,0xfffe
|
|
; rcall rs232_0_tx
|
|
|
|
LDI R17,0X40
|
|
CLR ZH
|
|
ldi ZL, 0xc5
|
|
st_cpuZ r17
|
|
ldi ZL, 0xcB
|
|
st_cpuZ r17
|
|
|
|
in r16,SREG
|
|
mov Pstat1,r16
|
|
next_op:
|
|
|
|
|
|
;rjmp op_ADC
|
|
sei
|
|
|
|
clr r16
|
|
lds r16,emu_status ;check if Interupt
|
|
sbrc r16,1
|
|
rcall Interupt_IRQ
|
|
|
|
ldi ZL,low(opcode_jmps<<1)
|
|
ldi ZH,high(opcode_jmps<<1)
|
|
|
|
.IFDEF DEBUG
|
|
cp PL,breakL
|
|
cpc PH,breakH
|
|
breq breakp
|
|
sts last_PC,PL
|
|
sts last_PC+1,PH
|
|
.ENDIF
|
|
|
|
|
|
|
|
|
|
breakpret:
|
|
|
|
|
|
get_pc_mem retL ;GET OPCODE
|
|
|
|
|
|
.IFDEF DEBUG
|
|
lds r16,last_I+2
|
|
sts last_I+3,r16
|
|
|
|
lds r16,last_I+1
|
|
sts last_I+2,r16
|
|
|
|
lds r16,last_I
|
|
sts last_I+1,r16
|
|
|
|
sts last_I,retL
|
|
.ENDIF
|
|
|
|
clr r16
|
|
|
|
lsl retL ;mul opcde by 2 because jump table is 2 bytes per entry
|
|
adc r16,zero_reg ;if carry, then save carry to r16
|
|
|
|
|
|
add ZL,retL
|
|
adc ZH,r16 ;add carry from last add, also add any carry from lsl
|
|
|
|
lpm YL,Z+ ;have to use Z for both lpm and IJMP unfortunatly
|
|
lpm YH,Z
|
|
|
|
movw ZL,YL ;copy value to ZL
|
|
|
|
cli
|
|
ijmp ;now jump to copcode subroutine
|
|
|
|
breakp:
|
|
nop
|
|
nop
|
|
nop
|
|
rjmp breakpret
|
|
|
|
;-------LOAD KERNAL INTO MEMORY------------
|
|
load_kernal:
|
|
ldi ZL,low(kernal_rom<<1)
|
|
ldi ZH,high(kernal_rom<<1)
|
|
ldi YL,low(kernal_start)
|
|
ldi YH,high(kernal_start)
|
|
clr r16
|
|
load_kernal_loop1:
|
|
ldi r17,32
|
|
load_kernal_loop2:
|
|
lpm r18,Z+
|
|
st Y+,r18
|
|
dec r17
|
|
brne load_kernal_loop2
|
|
dec r16
|
|
brne load_kernal_loop1
|
|
ret
|
|
;-------LOAD BASIC INTO MEMORY------------
|
|
load_basic:
|
|
ldi ZL,low(basic_rom<<1)
|
|
ldi ZH,high(basic_rom<<1)
|
|
ldi YL,low(basic_start)
|
|
ldi YH,high(basic_start)
|
|
clr r16
|
|
load_basic_loop1:
|
|
ldi r17,32
|
|
load_basic_loop2:
|
|
lpm r18,Z+
|
|
st Y+,r18
|
|
dec r17
|
|
brne load_basic_loop2
|
|
dec r16
|
|
brne load_basic_loop1
|
|
ret
|
|
;-------LOAD GAME INTO MEMORY------------
|
|
load_game:
|
|
ldi ZL,low(game_rom<<1)
|
|
ldi ZH,high(game_rom<<1)
|
|
ldi YL,low(game_start)
|
|
ldi YH,high(game_start)
|
|
clr r16
|
|
load_game_loop1:
|
|
ldi r17,32
|
|
load_game_loop2:
|
|
lpm r18,Z+
|
|
st Y+,r18
|
|
dec r17
|
|
brne load_game_loop2
|
|
dec r16
|
|
brne load_game_loop1
|
|
ret
|
|
|
|
;-------LOAD CHARACTER INTO MEMORY------------
|
|
load_chars:
|
|
ldi ZL,low(char_rom<<1)
|
|
ldi ZH,high(char_rom<<1)
|
|
ldi YL,low(char_start)
|
|
ldi YH,high(char_start)
|
|
clr r16
|
|
load_char_loop1:
|
|
ldi r17,16
|
|
load_char_loop2:
|
|
lpm r18,Z+
|
|
st Y+,r18
|
|
dec r17
|
|
brne load_char_loop2
|
|
dec r16
|
|
brne load_char_loop1
|
|
ret
|
|
|
|
|
|
|
|
;-------LOAD CHARACTER INTO LCD MEMORY------------
|
|
|
|
load_chars_lcd:
|
|
ldi ZL,low(char_rom<<1)
|
|
ldi ZH,high(char_rom<<1)
|
|
ldi YL,low(char_start)
|
|
ldi YH,high(char_start)
|
|
|
|
;-- set address to start of CGRAM
|
|
ldi r17,1 ;command
|
|
ldi r16,0x46
|
|
rcall lcd_send_data
|
|
|
|
clr r17
|
|
|
|
ldi r16,0x00
|
|
rcall lcd_send_data
|
|
|
|
ldi r16,0xf0
|
|
rcall lcd_send_data
|
|
;--
|
|
|
|
ldi r17,1
|
|
ldi r16,0x42 ;send data to cgram
|
|
rcall lcd_send_data
|
|
|
|
clr r17
|
|
|
|
clr r19
|
|
load_chars_lcd_loop1:
|
|
ldi r18,16
|
|
load_chars_lcd_loop2:
|
|
lpm r16,Z+
|
|
rcall lcd_send_data
|
|
|
|
|
|
dec r18
|
|
brne load_chars_lcd_loop2
|
|
dec r19
|
|
brne load_chars_lcd_loop1
|
|
ret
|
|
|
|
;----------------------------------------------------------------------
|
|
;lcd_refresh
|
|
|
|
;purpose: copies VRAM to LCD
|
|
;Takes: na
|
|
;Give: na
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
|
|
lcd_refresh:
|
|
push r0
|
|
push r1
|
|
push r16
|
|
push r17
|
|
push r18
|
|
push r19
|
|
push r20
|
|
push ZL
|
|
push ZH
|
|
|
|
ldi ZL,LOW(0x1000)
|
|
ldi ZH,HIGH(0x1000)
|
|
|
|
|
|
|
|
ldi r19,22
|
|
ldi r20,23
|
|
|
|
clr cus_y
|
|
lcd_refresh_loop1:
|
|
clr cus_x
|
|
rcall cursor_address
|
|
rcall lcd_set_cursor
|
|
|
|
ldi r17,1 ;setup to send data
|
|
ldi r16,0x42
|
|
rcall lcd_send_data
|
|
|
|
clr r17
|
|
lcd_refresh_loop2:
|
|
ld_cpuZp r18
|
|
mov r16,r18
|
|
rcall lcd_send_data
|
|
inc cus_x
|
|
cp cus_x,r19
|
|
brne lcd_refresh_loop2
|
|
inc cus_y
|
|
|
|
|
|
|
|
cp cus_y,r20
|
|
brne lcd_refresh_loop1
|
|
|
|
|
|
pop ZH
|
|
pop ZL
|
|
pop r20
|
|
pop r19
|
|
pop r18
|
|
pop r17
|
|
pop r16
|
|
pop r1
|
|
pop r0
|
|
|
|
|
|
ret
|
|
|
|
|
|
timer0_cmp:
|
|
push r1
|
|
|
|
in r1,SREG ;preserve main OS status reg.
|
|
push r16
|
|
push r17
|
|
|
|
lds r16,emu_status
|
|
|
|
sbrs r16,0 ;toggle lcd bit
|
|
rjmp PC + 3
|
|
cbr r16,1
|
|
rjmp PC+2
|
|
sbr r16,1
|
|
|
|
sbrs r16,0
|
|
rcall lcd_refresh
|
|
|
|
mov r17,Pstat2 ;check if interupts enabled
|
|
|
|
cbr r16,2
|
|
sbrs r17,Is
|
|
sbr r16,2 ;if Interupt disable is 0, then set bit 1 in emu_status to next intruction is interupt
|
|
|
|
sts emu_status,r16
|
|
|
|
pop r17
|
|
pop r16
|
|
out SREG,r1
|
|
pop r1
|
|
reti
|
|
|
|
|
|
|
|
rx_rs232_0:
|
|
push r1
|
|
|
|
in r1,SREG ;preserve main OS status reg.
|
|
|
|
|
|
push r16
|
|
push r17
|
|
push ZL
|
|
push ZH
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
in r17,UDR0 ;get the incomming char
|
|
|
|
; sts last_rsbyte,r17
|
|
|
|
ldi ZL,low(0x277)
|
|
ldi ZH,high(0x277)
|
|
st_cpuZ r17
|
|
|
|
ldi r17,1
|
|
ldi ZL,low(0xc6)
|
|
ldi ZH,high(0xc6)
|
|
st_cpuZ r17
|
|
|
|
|
|
|
|
; mov r16,PL
|
|
; rcall rs232_0_tx
|
|
; mov r16,PH
|
|
; rcall rs232_0_tx
|
|
|
|
|
|
qwe:
|
|
pop ZH
|
|
pop ZL
|
|
pop r17
|
|
|
|
pop r16
|
|
|
|
out SREG,r1 ;restore previous status reg
|
|
|
|
pop r1
|
|
|
|
reti
|
|
;return to normal pgm status.
|
|
rs232_0_tx:
|
|
sbis UCSR0A,UDRE0
|
|
rjmp rs232_0_tx
|
|
|
|
out UDR0,r16
|
|
rcall delay_1ms
|
|
ret
|
|
|
|
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
;Interupt_IRQ
|
|
|
|
;purpose: called when IRQ
|
|
;Takes: na
|
|
;Give: na
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
|
|
Interupt_IRQ:
|
|
stack_push PH
|
|
stack_push PL
|
|
rcall stack_build
|
|
stack_push retL
|
|
|
|
mov r16,Pstat2 ;clear interupt so cant do interupt in interupt
|
|
sbr r16,EXP2(Is)
|
|
mov Pstat2,r16
|
|
|
|
|
|
lds r16,emu_status
|
|
cbr r16,2
|
|
sts emu_status,r16
|
|
|
|
|
|
ldi YL,low(0xFFFE)
|
|
ldi YH,high(0xFFFE)
|
|
ld PL,Y+
|
|
ld PH,Y
|
|
|
|
ret
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
;vias_access
|
|
|
|
;purpose: called when a read to the vias has occurded (from Z)
|
|
;Takes: Z
|
|
;Give: retL is result
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
|
|
vias_access:
|
|
push r17
|
|
push r18
|
|
push r19
|
|
|
|
|
|
|
|
cpi ZL,0x21 ;keyboard scan being read
|
|
breq keyboard_read
|
|
|
|
|
|
ld retL,Z
|
|
|
|
vias_access_exit:
|
|
pop r19
|
|
pop r18
|
|
pop r17
|
|
ret
|
|
|
|
|
|
keyboard_read:
|
|
ldi retL,0xff
|
|
|
|
lds r17,last_rsbyte ;should be 0-63
|
|
|
|
cpi r17,255
|
|
breq vias_access_exit
|
|
|
|
mov r18,r17
|
|
lsr r18 ;divide by 8 to get which column
|
|
lsr r18
|
|
lsr r18
|
|
|
|
lds r19,0x9120 ;read column byte
|
|
|
|
keyboard_read_loop1:
|
|
tst r18 ;test if 18(prob dont need)
|
|
breq keyboard_read_loop1_exit
|
|
lsr r19 ;shift right, so column to check is at 0
|
|
dec r18
|
|
rjmp keyboard_read_loop1
|
|
|
|
keyboard_read_loop1_exit:
|
|
sbrs r19,0 ;test if key column is 0
|
|
rjmp keyboard_read_set_row ;so set appropriate row
|
|
|
|
; ldi retL,0xff ; if here, then a colum with no key is pressed
|
|
rjmp vias_access_exit
|
|
|
|
|
|
|
|
keyboard_read_set_row:
|
|
andi r17,0b00000111 ;get lower 3 bits
|
|
ldi retL,0xFE ;set bit 0
|
|
|
|
keyboard_read_loop2:
|
|
tst r17
|
|
breq keyboard_read_loop2_exit
|
|
sec
|
|
rol retL
|
|
dec r17
|
|
rjmp keyboard_read_loop2
|
|
|
|
keyboard_read_loop2_exit:
|
|
rjmp vias_access_exit
|
|
|
|
|
|
;-------------------------------
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
;delay_1ms
|
|
|
|
;purpose: delays 1ms
|
|
;Takes: na
|
|
;Give: na
|
|
;----------------------------------------------------------------------
|
|
;----------------------------------------------------------------------
|
|
|
|
delay_1ms:
|
|
push r19
|
|
push r18
|
|
|
|
ldi r18,20
|
|
delay_1ms1:
|
|
ldi r19,133
|
|
delay_1ms1_loop:
|
|
dec r19
|
|
nop
|
|
nop
|
|
nop
|
|
brne delay_1ms1_loop
|
|
dec r18
|
|
brne delay_1ms1
|
|
|
|
pop r18
|
|
pop r19
|
|
ret
|
|
|
|
delay_100ms:
|
|
push r18
|
|
ldi r18,100
|
|
delay_100ms_loop:
|
|
rcall delay_1ms
|
|
dec r18
|
|
brne delay_100ms_loop
|
|
pop r18
|
|
ret
|
|
|
|
|
|
.include "6502cpu.asm"
|
|
.include "io.asm"
|
|
.include "init.asm"
|
|
|
|
.CSEG
|
|
;.org 0x7000
|
|
opcode_jmps:
|
|
.include "dbops.asm"
|
|
kernal_rom:
|
|
.include "kernal.asm"
|
|
basic_rom:
|
|
.include "basic.asm"
|
|
char_rom:
|
|
.include "chars.asm"
|
|
game_rom:
|
|
.include "game.asm"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|