commit a8caf9db75630242bf17261dea3dcd6e794c8870 Author: RuiFPB Date: Mon Sep 28 17:07:08 2026 +0100 Upload hello world template diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93e0b6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ +.kotlin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store + + +.idea/ \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fee836d --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +OUTPUT := example.bin +TARGET_CPU := 65c02 + +# Tool list +CC65 := cc65 +CA65 := ca65 +LD65 := ld65 +CL65 := cl65 + +# Searches directly under src and one level under. If a file is under 2 folders +#such as src/math/float/types.s, either one more level needs to be added, or +#switch these to a shell find $(shell find src -name '*.s') +C_SOURCES := $(wildcard src/*.c) $(wildcard src/*/*.s) +ASM_SOURCES := $(wildcard src/*.s) $(wildcard src/*/*.s) +OBJECTS := $(ASM_SOURCES:.s=.o) + +.PHONY: all clean + +all: $(OUTPUT) + +$(OUTPUT): $(C_SOURCES) $(ASM_SOURCES) + @mkdir -p $(dir $@) + $(CL65) -t none --cpu $(TARGET_CPU) -C computer.cfg -O -o $@ $^ + +clean: + rm -f $(OBJECTS) + rm -f $(OUTPUT) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8e8c1f9 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# 65C02 Assembly Project Template + +This template is based on the memory map for Mike42's computer/board. [Github](https://github.com/mike42/6502-computer/) + diff --git a/computer.cfg b/computer.cfg new file mode 100644 index 0000000..d7e60b7 --- /dev/null +++ b/computer.cfg @@ -0,0 +1,14 @@ +# Physical Memory configuration +MEMORY { + ZP: start = $00, size = $0100, type = rw, file = ""; + RAM: start = $0100, size = $7e00, type = rw, file = ""; + PRG: start = $C000, size = $4000, type = ro, file = %O, fill = yes, fillval = $00; +} + +# In-Code Segment separators +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + BSS: load = RAM, type = bss; + CODE: load = PRG, type = ro, start = $C000; + VECTORS: load = PRG, type = ro, start = $FFFA; +} \ No newline at end of file diff --git a/src/hardware/serial.s b/src/hardware/serial.s new file mode 100644 index 0000000..cbc858d --- /dev/null +++ b/src/hardware/serial.s @@ -0,0 +1,60 @@ +; Serial port helper function +; Serial is handled by the 65c51n (this thing has a few bugs) +.export serial_setup +.export serial_recv_char +.export serial_print_char + +SERIAL_DATA = $8400 +SERIAL_STATUS = $8401 +SERIAL_COMMAND = $8402 +SERIAL_CONTROL = $8403 + +serial_setup: + ; 65c51n has a few bugs. check http://forum.6502.org/viewtopic.php?f=4&t=2543&start=30#p29795 + lda #$00 + sta SERIAL_STATUS ; Write to the status register for program reset + + lda #$0b ; %0000 1011 + sta SERIAL_COMMAND ; || |||`- Data terminal ready (DTRB low) + ; || ||`-- IRQB disabled + ; || ``--- RTSB low, transmit interrupt disabled + ; |`------ Receiver normal mode + ; `------- Parity disabled + + lda #$1f ; %0001 1111 + sta SERIAL_CONTROL ; |||| ````- 19200 baud + ; |||`------ Receiver clock is baud rate + ; |``------- 8bit word + ; `--------- 1 stop bit + rts + +serial_print_char: + pha ; Save A to stack (character) + lda SERIAL_STATUS ; read status register and ignore the value + pla ; return character from stack + sta SERIAL_DATA ; send character + jsr serial_delay ; comment out for older 6551/65c51 + rts + +serial_recv_char: + lda SERIAL_STATUS ; read status + and #$08 ; mask receive status flag + beq serial_recv_char; if buffer is empty, loop + lda SERIAL_DATA ; get byte + rts + +serial_delay: + phy ; save y reg + phx ; save x register + ldy #6 ; delay value (clock rate in mhz 2 clock cycles) +@ydelay: + ldx #$68 ; Init x register +@xdelay: + dex ; decrement low index + bne @xdelay ; loop back until x is 0 + dey ; decrement high + bne @ydelay ; loop until y is 0 +@delay_done: + plx ; return x + ply ; return y + rts diff --git a/src/hardware/via.s b/src/hardware/via.s new file mode 100644 index 0000000..b31819a --- /dev/null +++ b/src/hardware/via.s @@ -0,0 +1,18 @@ +; Addresses for the VIA 65c22 + +VIA_PORTB = $8000 +VIA_PORTA = $8001 +VIA_DDRB = $8002 +VIA_DDRA = $8003 +VIA_T1C_L = $8004 +VIA_T1C_H = $8005 +VIA_T1L_L = $8006 +VIA_T1L_H = $8007 +VIA_T2C_L = $8008 +VIA_T2C_H = $8009 +VIA_SR = $800a +VIA_ACR = $800b +VIA_PCR = $800c +VIA_IFR = $800d +VIA_IER = $800e +VIA_PORTA_2 = $800f \ No newline at end of file diff --git a/src/main.s b/src/main.s new file mode 100644 index 0000000..e85d4e4 --- /dev/null +++ b/src/main.s @@ -0,0 +1,40 @@ +.import serial_setup +.import serial_print_char + +.segment "ZEROPAGE" +; Zero-page variables ($0000 - $00ff) + +.segment "BSS" +; RAM variables ($0100 - $7fff) + +.segment "CODE" +; Actual program code ($c000 - $fff9) + +reset: ; Program starts here + jsr serial_setup + + ldx #0 +hello_world_loop: + lda str_hello_world,x ; get char + beq hello_world_end ; IF char is 0, done + jsr serial_print_char ; send char to console + inx ; increment x (next char) + jmp hello_world_loop +hello_world_end: + jmp hello_world_end + + +irq: ; IRQ Handler + rti ; Do nothing + +nmi: ; NMI handler + rti ; Do nothing + +str_hello_world: +.asciiz "Hello, World!" + +.segment "VECTORS" +; NMI, RESET and IRQ vectors +.word nmi +.word reset +.word irq \ No newline at end of file