From 40a91bfae14e43fc81d9502c4532bc500f9cc594 Mon Sep 17 00:00:00 2001 From: Celso Martinho Date: Wed, 3 Jan 2024 17:33:24 +0000 Subject: [PATCH 1/3] llvm version --- .gitignore | 3 ++ LICENSE => asm/LICENSE | 0 README.md => asm/README.md | 0 card.asm => asm/card.asm | 0 card.prg => asm/card.prg | Bin {img => asm/img}/assembly.png | Bin {img => asm/img}/debugger.png | Bin {img => asm/img}/demo.gif | Bin {img => asm/img}/emulator.png | Bin message.asm => asm/message.asm | 0 music.sid => asm/music.sid | Bin screen1.koa => asm/screen1.koa | Bin screen2.koa => asm/screen2.koa | Bin sidinfo.asm => asm/sidinfo.asm | 0 sprites.asm => asm/sprites.asm | 0 llvm-mos/.gitignore | 1 + llvm-mos/Makefile | 46 ++++++++++++++++ llvm-mos/README.md | 21 ++++++++ llvm-mos/demo.c | 89 ++++++++++++++++++++++++++++++ llvm-mos/macros.h | 42 +++++++++++++++ llvm-mos/music.s | 14 +++++ llvm-mos/music.sid | Bin 0 -> 3102 bytes llvm-mos/screen1.koa | Bin 0 -> 10003 bytes llvm-mos/screen2.koa | Bin 0 -> 10003 bytes llvm-mos/screens.s | 48 +++++++++++++++++ llvm-mos/tools.s | 7 +++ llvm-mos/tools/sidinfo.py | 96 +++++++++++++++++++++++++++++++++ 27 files changed, 367 insertions(+) create mode 100644 .gitignore rename LICENSE => asm/LICENSE (100%) rename README.md => asm/README.md (100%) rename card.asm => asm/card.asm (100%) rename card.prg => asm/card.prg (100%) rename {img => asm/img}/assembly.png (100%) rename {img => asm/img}/debugger.png (100%) rename {img => asm/img}/demo.gif (100%) rename {img => asm/img}/emulator.png (100%) rename message.asm => asm/message.asm (100%) rename music.sid => asm/music.sid (100%) rename screen1.koa => asm/screen1.koa (100%) rename screen2.koa => asm/screen2.koa (100%) rename sidinfo.asm => asm/sidinfo.asm (100%) rename sprites.asm => asm/sprites.asm (100%) create mode 100644 llvm-mos/.gitignore create mode 100644 llvm-mos/Makefile create mode 100644 llvm-mos/README.md create mode 100644 llvm-mos/demo.c create mode 100644 llvm-mos/macros.h create mode 100644 llvm-mos/music.s create mode 100644 llvm-mos/music.sid create mode 100644 llvm-mos/screen1.koa create mode 100644 llvm-mos/screen2.koa create mode 100644 llvm-mos/screens.s create mode 100644 llvm-mos/tools.s create mode 100755 llvm-mos/tools/sidinfo.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..26ac00d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +yarn-error.log +tokagetone/ diff --git a/LICENSE b/asm/LICENSE similarity index 100% rename from LICENSE rename to asm/LICENSE diff --git a/README.md b/asm/README.md similarity index 100% rename from README.md rename to asm/README.md diff --git a/card.asm b/asm/card.asm similarity index 100% rename from card.asm rename to asm/card.asm diff --git a/card.prg b/asm/card.prg similarity index 100% rename from card.prg rename to asm/card.prg diff --git a/img/assembly.png b/asm/img/assembly.png similarity index 100% rename from img/assembly.png rename to asm/img/assembly.png diff --git a/img/debugger.png b/asm/img/debugger.png similarity index 100% rename from img/debugger.png rename to asm/img/debugger.png diff --git a/img/demo.gif b/asm/img/demo.gif similarity index 100% rename from img/demo.gif rename to asm/img/demo.gif diff --git a/img/emulator.png b/asm/img/emulator.png similarity index 100% rename from img/emulator.png rename to asm/img/emulator.png diff --git a/message.asm b/asm/message.asm similarity index 100% rename from message.asm rename to asm/message.asm diff --git a/music.sid b/asm/music.sid similarity index 100% rename from music.sid rename to asm/music.sid diff --git a/screen1.koa b/asm/screen1.koa similarity index 100% rename from screen1.koa rename to asm/screen1.koa diff --git a/screen2.koa b/asm/screen2.koa similarity index 100% rename from screen2.koa rename to asm/screen2.koa diff --git a/sidinfo.asm b/asm/sidinfo.asm similarity index 100% rename from sidinfo.asm rename to asm/sidinfo.asm diff --git a/sprites.asm b/asm/sprites.asm similarity index 100% rename from sprites.asm rename to asm/sprites.asm diff --git a/llvm-mos/.gitignore b/llvm-mos/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/llvm-mos/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/llvm-mos/Makefile b/llvm-mos/Makefile new file mode 100644 index 0000000..6ac19ad --- /dev/null +++ b/llvm-mos/Makefile @@ -0,0 +1,46 @@ +# +# GNU Makefile +# + +VICE=/Applications/vice-arm64-sdl2-3.7.1/bin/x64sc -autostartprgmode 1 -statusbar + +all: demo + +demo: + @echo "Compiling demo" + # -c Only run preprocess, compile, and assemble steps, do not link + mos-c64-clang -c -o build/music.o music.s + mos-c64-clang -c -o build/screens.o screens.s + mos-c64-clang -c -o build/demo.o demo.c + mos-c64-clang -Os -flto \ + -Wl,--section-start=.sid=0x1000, \ + -Wl,--section-start=.bank0screen=0x0c00, \ + -Wl,--section-start=.bank0color=0x1c00, \ + -Wl,--section-start=.bank0bitmap=0x2000 \ + -Wl,--section-start=.bank1screen=0x4c00, \ + -Wl,--section-start=.bank1color=0x7f40, \ + -Wl,--section-start=.bank1bitmap=0x6000 \ + -o build/demo.prg build/demo.o build/music.o build/screens.o + mos-c64-clang -Os -flto \ + -Wl,--section-start=.sid=0x1000 \ + -Wl,--section-start=.bank0screen=0x0c00 \ + -Wl,--section-start=.bank0color=0x1c00 \ + -Wl,--section-start=.bank0bitmap=0x2000 \ + -Wl,--section-start=.bank1screen=0x4c00, \ + -Wl,--section-start=.bank1color=0x7f40, \ + -Wl,--section-start=.bank1bitmap=0x6000 \ + -Wl,--lto-emit-asm -o build/demo.s build/demo.o build/music.o build/screens.o + +run: demo + @echo "Running demo" + $(VICE) build/demo.prg + +sid: + @echo "SID file info" + ./tools/sidinfo.py music.sid +# deprecated: +# dd if=music.sid of=music.bin bs=1 skip=126 + +.PHONY: all demo run + +# EOF - Makefile diff --git a/llvm-mos/README.md b/llvm-mos/README.md new file mode 100644 index 0000000..a1edaba --- /dev/null +++ b/llvm-mos/README.md @@ -0,0 +1,21 @@ +# C64 Demo using llvm-mos + +This a follow up of my old [pure 6510 assembly demo](../asm), ported to llvm-mos. + +## Requirements + +* https://github.com/llvm-mos/llvm-mos - Port of LLVM to the MOS 6502 and related processors +* https://github.com/llvm-mos/llvm-mos-sdk - SDK for developing with the llvm-mos compiler + + +## Useful links + + * 6502 opcodes - http://6502.org/tutorials/6502opcodes.html + * 6502 / 6510 Instruction Set - https://c64os.com/post/6502instructions + * llm-mos Wiki - https://llvm-mos.org/wiki/Welcome + * Gnu Assembler - https://sourceware.org/binutils/docs/as + +## Other llvm-mos demos: + + * C64 sprite example: https://gist.github.com/juj/84fc977c7f928e9343bb6f5f74c45a57 + * sidplay: https://github.com/kklis/sidplay diff --git a/llvm-mos/demo.c b/llvm-mos/demo.c new file mode 100644 index 0000000..f908aa5 --- /dev/null +++ b/llvm-mos/demo.c @@ -0,0 +1,89 @@ +#include "macros.h" +#include <6502.h> +#include +#include +#include +#include + +extern char sid[]; +extern unsigned bank0bgcolor; +extern unsigned bank1bgcolor; + +unsigned char screen_state = 0; +unsigned char counter = 254; + +void background(unsigned char color) { + poke(&VIC.bordercolor, color); + poke(&VIC.bgcolor0, color); +} + +void recolor() { + counter++; + if (counter == 255) { + counter = 0; + if (screen_state == 0) { + screen_state = 1; + background(bank1bgcolor); + // https://www.c64-wiki.com/wiki/VIC_bank + vic_bank(0b0000010); + } else { + screen_state = 0; + background(bank0bgcolor); + vic_bank(0b0000011); + } + } +} + +// see https://llvm-mos.org/wiki/C_interrupts +__attribute__((interrupt,no_isr)) void play() { + interrupt_ack(); + recolor(); + sid_play($1021); + interrupt_exit(); +} + +int main(void) { + // we don't need the BASIC ROM after we start + // see https://www.c64-wiki.com/wiki/Zeropage + poke(0x0001, 0b00110110); + + // initialize the SID song + sid_init($1048); + + cls(); + + // switch to Standard Bitmap Mode now (bit 5 set to 1) + // Bit #5: 0 = Text mode; 1 = Bitmap mode. + // see https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode + poke(&VIC.ctrl1, 0b00111011); + // tells the VIC-II where to "look for graphics" + // in this case: + // 3 (%0011) * 1024 = $0c00 = address to start of color information + // bit 3 is set, then the bitmap starts at vic bank address + $2000 = $2000 or + // $6000 see https://www.c64-wiki.com/wiki/53272 + poke(&VIC.addr, 0b00111000); + // bit 5 must be cleared to enter Standard Bitmap Mode + // see https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode + poke(&VIC.ctrl2, 0b11011000); + + SEI(); + poke(&VIC.rasterline, 255); + pokew(IRQVec,(unsigned int)&play); + // interrupt control - enable all interrupts with $7b (icr=$DC0D) + // see http://sta.c64.org/cbm64mem.html + poke(&CIA1.icr, 0b01111011); + // interrupt control register - enable raster interrupt with $81 ($d01a) + // see http://sta.c64.org/cbm64mem.html + poke(&VIC.imr, 0b10000001); + CLI(); + + while (1) { + /* + if (raster_line == 255) { + recolor(); + // call sid play routing + sid_play($1021); + } + */ + } +} diff --git a/llvm-mos/macros.h b/llvm-mos/macros.h new file mode 100644 index 0000000..8e7494e --- /dev/null +++ b/llvm-mos/macros.h @@ -0,0 +1,42 @@ +#include +#include <6502.h> +#include <_vic2.h> + +#define IRQVec 0x0314 +#define BRKVec 0x0316 +#define NMIVec 0x0318 + +// https://github.com/cc65/cc65/blob/master/include/peekpoke.h + +#define poke(addr,val) (*(unsigned char*) (addr) = (val)) +#define pokew(addr,val) (*(unsigned*) (addr) = (val)) +#define peek(addr) (*(unsigned char*) (addr)) +#define peekw(addr) (*(unsigned*) (addr)) + +// various +#define sid_init(addr) __attribute__((leaf)) asm("LDA #$00\nTAX\nTAY\nJSR "#addr) +#define sid_play(addr) __attribute__((leaf)) asm("JSR "#addr) +#define raster_line (*((volatile unsigned char *)(struct __vic2 *)&VIC.rasterline)) + +// clear screen. See http://sta.c64.org/cbm64scrfunc.html +#define cls() __attribute__((leaf)) asm("JSR $e544") + +// https://www.c64-wiki.com/wiki/VIC_bank +#define vic_bank(pattern) (*((volatile unsigned char *)(struct __6526 *)&CIA2.pra))=0b11111100|pattern + +#define raster_interrupt(line, fn) \ + (*((volatile unsigned char *)(struct __vic2 *)&VIC.rasterline))=line; \ + (*(volatile unsigned char *)0x0314)=(unsigned int)fn & 0xffff; \ + (*(volatile unsigned char *)0x0315)=(unsigned int)fn >> 8; + +#define interrupts_disable() __attribute__((leaf)) asm("SEI") +#define interrupts_enable() __attribute__((leaf)) asm("CLI") + +// everytime an interrupt triggers, we need to acknowledge it by setting the +// corresponding VIC interrupt flag +// if we don't ack the irq, then it will be called again after we exit it +// see http://sta.c64.org/cbm64mem.html +#define interrupt_ack() (*((volatile unsigned char *)(struct __vic2 *)&VIC.irr)) = 0b11111111 + +// when exiting an irq, we need to restore the accumulator, and indexes y and x from the stack first +#define interrupt_exit() __attribute__((leaf)) asm("PLA\nTAY\nPLA\nTAX\nPLA\nRTI\n") diff --git a/llvm-mos/music.s b/llvm-mos/music.s new file mode 100644 index 0000000..b65f6c3 --- /dev/null +++ b/llvm-mos/music.s @@ -0,0 +1,14 @@ +# SID music section +# see --section-start=.sid=0x1000 in Makefile for sid address +# R flag is needed to avoid linker garbage collection +# see https://sourceware.org/binutils/docs/as/Section.html +# +# First 126 bytes of music.sid are header, so skip them +# .incbin "file"[,skip[,count]] +# https://www.hvsc.c64.org/download/C64Music/DOCUMENTS/SID_file_format.txt + +.global sid +.type sid,@object +.section .sid,"awR",@progbits +sid: +.incbin "music.sid", 126 diff --git a/llvm-mos/music.sid b/llvm-mos/music.sid new file mode 100644 index 0000000000000000000000000000000000000000..b5f385cd41f030b285405b816ef1672004f2ae59 GIT binary patch literal 3102 zcmb_edu&tJ89&$db?)_b;^TX5>?WGHWZ_{kkf}h%i|hI30VFsfS((ySeFTtOB5TA= zs9Ln5HYF|O5>Ly~;yldb7J)L6Bu3#|Gr6P}#4Q}`2V%x5+u8z*GZn5)4vFVlWjy+3s zEb1Klw_*PZysqg7Pd3zwHBXDpQuEH*9pa8HV%z#1>)Y0${?@(y!h)F&tf{%15t0NH+vErI5j3 zkUtZ^|3v#}Dx5o)x{4d2*#kLw0{7-lBwZHy0+ufc$={jfNi2WFkK`a&$*h_K-<1wA zTTkNOY9_SN?0?m~y|v!N>d&A#il*pA*L|Akhq?LHRJ`|7ZaT+JoDvhfPyx zTGDjTXqwjR^(7??!?FegXDlr(Ghs6?SgbaCdBwMui*BC9@1xG^Fwq- zJ+C2MW+a#V)C%X8yl9oD1bJ4NLuo@i5cwG&$B_Y&?;Msd<7Cwdp*4KCR<>hb>7mt^s5Q$Ap z?*uiRZJuc|LdPOqZw}M5S3|%bOXf9r+bTBx;dZvN()LDMAbq3!@0>7F9sE z2+>Gn7Y9IKxM1}GCBAGrB(TLnRKWK`_dTB=X$0X9Alx(RY=i`kBnp|0#28r+CK(Zo zRwIFd!dx*73J6+R$-O29xJI9n7*K808reGF|19#`MgFfMzf9Qr&YH?R`tVGFUu6MSDo{rc(KoRT(rY*?idD}@XLDa!y}A*pE{D)_ z)G_JV7ZAD&c1c{UX04?A7@;*!`&ovmsWj=1NT2%n$|uk@RsI$Fd6EC5$lHqisKmfN zjrJXB@=J(k$gk$hYM8^!t%^}hQ5vll>5%$~x{v{J$k1X487P%5t_UUqint|CJDYk`ulp?l8F9PvMpTOIl+yWz(r14+fMa$V zIu|1Ycmhzazl!ctVH##+zK9TBMXM^FMU@^8-S1h7aYf`1(Oue=ekXm%X)aLssSYm{ zlDX1vr^BG2QspfY0@xy)*aZFvMr2hqxQmJr}FhNE$L# z>bY$knRrd(;9XG$f&nMzJ;R=cB!_2oP0I0rhZhjZ3qMP5|fuX##LM;iY|aBIW`LanmQqm0+;X z2Sz|>8V?4&oR{%xh>{PyB!V7LB8G_zpdeOlfenx=i6A5kIjh~vRjZK(h#%-6hY*ihq}PW#k_Pi1YHfZ5EmrprWJ4(`QK_#kU&vOH3xYO1bkpO1|dUn6N$cH!9Af6 zbv0BJis$Cs;07kpp!hC`PgQ`ZA1D;WN`%xBb{0Dgc~ln*KsLF!7#x}cRU=)kN0C=^ zN?$DpI}`O>0w(ovXQHf literal 0 HcmV?d00001 diff --git a/llvm-mos/screen1.koa b/llvm-mos/screen1.koa new file mode 100644 index 0000000000000000000000000000000000000000..f1371aac11edf92df239eae93eec022b07d27414 GIT binary patch literal 10003 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 literal 0 HcmV?d00001 diff --git a/llvm-mos/screen2.koa b/llvm-mos/screen2.koa new file mode 100644 index 0000000000000000000000000000000000000000..764f9c7925897ceb117e3196edf78d1684d010a0 GIT binary patch literal 10003 zcmeI0F^kkd6vtmSLRY+SMm#$!@nt3x*~Pe#?5?+Q-fZ$RGyi!r@5e9+3k;Mg0*Zhlpa^V*fNq$) z+@`fX359VOvRV2SEir(`eENcQ7TNA_!(deeHVQP3Nch4I`@fDSpEU z3>)3-Khm5-<*;b|M~~(F6B!>E!oU33pTIEXSoq2FkA;lY*DxymM=O5)S^Z8qHhz!q zA3vis$-bxchiza2lwlD?88qK%2X8BEf571M)#=H}y$|s8(GfPJH}OX4bAXWLS)3*? z3k=iLClD4a%Ci(qBXHd+1>D``*)Nh~;}@}lzd|OO#*@tBI8M-Ho@dxwV$m8);ylmL zB$29e-5NCrSy|0pthw_v&Lf5-rA~Somrsf}*}iYSJ^xq{WeKGK6J0ZKVd5MGRO)T6zi)OF_-O_R7Rbq%-NY@Vbzya?kYt&n8>ek#k56W-Y1yx*O_=U$FCtqHG3**os# zZ7lp`K7GC9$KfHszT;MP|1G};#2ew0rux^u;YauV{9D}@>*^ZR1%SVHH{dzHb(5-o zML-cy1QY>9KoRI9Fm;y9TXZO=hf5v)mD4%>*5`cfr<;14)_IQaeVck%oGEnk^S^lh z-AfOq7oHD)(0Lf|;?i+EjOeY`dA{?*@w;^*Tbx%|=lVqVt@Fm#=oW|47ENH~{tW?p z+4P>PxNZG9Y!*v!RmTv3#vxyGf@pP~(3;WTds9Q&fZ2{OA k%qFB;N5o_{u?gUS?sy_m*)RPHhPEnkuhX>y#`tjUC+g}8$N&HU literal 0 HcmV?d00001 diff --git a/llvm-mos/screens.s b/llvm-mos/screens.s new file mode 100644 index 0000000..d85fe45 --- /dev/null +++ b/llvm-mos/screens.s @@ -0,0 +1,48 @@ +# https://www.c64-wiki.de/wiki/Koala_Painter + +.global bank0bitmap +.type bank0bitmap,@object +.section .bank0bitmap,"awR",@progbits +bank0bitmap: +.incbin "screen1.koa", 2, 8000 + +.global bank0screen +.type bank0screen,@object +.section .bank0screen,"awR",@progbits +bank0screen: +.incbin "screen1.koa", 8002, 1000 + +.global bank0color +.type bank0color,@object +.section .bank0color,"awR",@progbits +bank0color: +.incbin "screen1.koa", 9002, 1000 + +.global bank0bgcolor +.type bank0bgcolor,@object +bank0bgcolor: +.incbin "screen1.koa", 10002, 1 + +.global bank1bitmap +.type bank1bitmap,@object +.section .bank1bitmap,"awR",@progbits +bank1bitmap: +.incbin "screen2.koa", 2, 8000 + +.global bank1screen +.type bank1screen,@object +.section .bank1screen,"awR",@progbits +bank1screen: +.incbin "screen2.koa", 8002, 1000 + +.global bank1color +.type bank1color,@object +.section .bank1color,"awR",@progbits +bank1color: +.incbin "screen2.koa", 9002, 1000 + +.global bank1bgcolor +.type bank1bgcolor,@object +bank1bgcolor: +.incbin "screen2.koa", 10002, 1 + diff --git a/llvm-mos/tools.s b/llvm-mos/tools.s new file mode 100644 index 0000000..a32edbf --- /dev/null +++ b/llvm-mos/tools.s @@ -0,0 +1,7 @@ +.include "c64.inc" + +.global ack +.type ack,@function +ack: +STA VIC_IRR +RTS diff --git a/llvm-mos/tools/sidinfo.py b/llvm-mos/tools/sidinfo.py new file mode 100755 index 0000000..d6544cd --- /dev/null +++ b/llvm-mos/tools/sidinfo.py @@ -0,0 +1,96 @@ +#!/opt/homebrew/bin/python3.12 + +import sys +import os + +if len(sys.argv) <= 1: + print(f"{sys.argv[0]} sid_file.sid") + sys.exit() + +try: + f = open(sys.argv[1], 'rb') +except FileNotFoundError: + print(f"file {sys.argv[1]} does not exist") +else: + with f: + data = f.read(126) + fs = os.stat(sys.argv[1]) + print(f"00-03, magicID: ", end="") + print(f"{data[0:4].hex()} ({data[0:4]})") + version = int.from_bytes(data[4:6], byteorder='big') + print(f"04-05, version: {data[4:6].hex()}") + dataOffset = int.from_bytes(data[6:8], byteorder='big') + print(f"06-07, dataOffset: {dataOffset} (0x{data[6:8].hex()})") + loadAddress = int.from_bytes(data[8:10], byteorder='big') + print(f"08-09, loadAddress: ", end="") + if(loadAddress==0): + print(f"0 - specified in the two first two bytes of the data: (0x{data[dataOffset:dataOffset+2][::-1].hex()})") + else: + print(f"{loadAddress} (0x{data[8:10].hex()})") + initAddress = int.from_bytes(data[0xa:0xc], byteorder='big') + print(f"0A-0B, initAddress: ", end="") + if(initAddress==0): + print(f"0 - same as loadAddress") + else: + print(f"0x{data[0xa:0xc].hex()}") + playAddress = int.from_bytes(data[0xc:0xd], byteorder='big') + print(f"0C-0D, playAddress: ", end="") + if(initAddress==0): + print(f"0 - init sub installs interrupt handler") + else: + print(f"0x{data[0xc:0xe].hex()}") + print(f"0E-0F, # of songs: {int.from_bytes(data[0xe:0x10], byteorder='big')} 0x{data[0xe:0x10].hex()}") + print(f"10-11, startSong: {int.from_bytes(data[0x10:0x12], byteorder='big')} 0x{data[0x10:0x12].hex()}") + speed = int.from_bytes(data[0x12:0x16], byteorder='big') + print(f"12-15, speed: { speed }") + print(f"16-35, name: {data[0x16:0x36]}") + print(f"36-55, author: {data[0x36:0x56]}") + print(f"56-75, released: {data[0x56:0x76]}") + if(version==1): + print(f"76-{ hex(fs.st_size-1)[2:] }, data from 0x76 (118) to { hex(fs.st_size-1) } ({ fs.st_size })") + else: + flags = int.from_bytes(data[0x76:0x78],'big') + print(f"76-77, flags: { bin(flags) }") + print(f" bit 0 (musPlayer): { 'Compute Sidplayer MUS data' if (flags & 0b1) else 'built-in player' }") + print(f" bit 1 (compatiblity): { 'PlaySID specific or C64 Basic' if (flags & 0b10) else 'C64 compatible' }") + print(f" bit 2-3 (clock): ", end="") + v = (flags & 0b1100)>>2 + match v: + case 0b00: print("Unknown") + case 0b01: print("PAL") + case 0b10: print("NTSC") + case 0b11: print("PAL & NTSC") + print(f" bit 4-5 (sidModel): ", end="") + v = (flags & 0b110000)>>4 + match v: + case 0b00: print("Unknown") + case 0b01: print("MOS6581") + case 0b10: print("MOS8580") + case 0b11: print("MOS6581 and MOS8580") + print(f" bit 6-7 (sidModel 2): ", end="") + v = (flags & 0b11000000)>>6 + match v: + case 0b00: print("Unknown") + case 0b01: print("MOS6581") + case 0b10: print("MOS8580") + case 0b11: print("MOS6581 and MOS8580") + print(f" bit 8-9 (sidModel 3): ", end="") + v = (flags & 0b1100000000)>>8 + match v: + case 0b00: print("Unknown") + case 0b01: print("MOS6581") + case 0b10: print("MOS8580") + case 0b11: print("MOS6581 and MOS8580") + startPage = int.from_bytes(data[0x78:0x79]) + print(f"78, startPage: ", end="") + if(startPage==0): + print("0x00 - clean (does not write outside its data range)") + else: + print(f"0x{ data[0x78:0x79].hex() }") + print(f"79, pageLength: 0x{ data[0x79:0x7a].hex() }") + print(f"7A, secondSIDAddress: 0x{ data[0x7a:0x7b].hex() }") + print(f"7B, thirdSIDAddress: 0x{ data[0x7b:0x7c].hex() }") + if(loadAddress==0): + print(f"7E-{ hex(fs.st_size-1)[2:] }, data from 0x7E (126) to { hex(fs.st_size-1) } ({ fs.st_size })") + else: + print(f"7C-{ hex(fs.st_size-1)[2:] }, data from 0x7C (124) to { hex(fs.st_size-1) } ({ fs.st_size })") From 2bc82bb38a897baecec178a5ad294be02d959d52 Mon Sep 17 00:00:00 2001 From: Celso Martinho Date: Fri, 5 Jan 2024 20:30:18 +0000 Subject: [PATCH 2/3] fix --- llvm-mos/Makefile | 15 +++---- llvm-mos/demo.c | 102 +++++++++++++++++++++++++++++++------------ llvm-mos/screens.s | 20 ++++----- llvm-mos/strings.cpp | 6 +++ 4 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 llvm-mos/strings.cpp diff --git a/llvm-mos/Makefile b/llvm-mos/Makefile index 6ac19ad..760d6a9 100644 --- a/llvm-mos/Makefile +++ b/llvm-mos/Makefile @@ -12,24 +12,21 @@ demo: mos-c64-clang -c -o build/music.o music.s mos-c64-clang -c -o build/screens.o screens.s mos-c64-clang -c -o build/demo.o demo.c - mos-c64-clang -Os -flto \ + mos-c64-clang++ -std=c++20 -finput-charset=utf-8 -c -o build/strings.o strings.cpp + mos-c64-clang++ -std=c++20 -Os -flto \ -Wl,--section-start=.sid=0x1000, \ -Wl,--section-start=.bank0screen=0x0c00, \ - -Wl,--section-start=.bank0color=0x1c00, \ -Wl,--section-start=.bank0bitmap=0x2000 \ -Wl,--section-start=.bank1screen=0x4c00, \ - -Wl,--section-start=.bank1color=0x7f40, \ -Wl,--section-start=.bank1bitmap=0x6000 \ - -o build/demo.prg build/demo.o build/music.o build/screens.o - mos-c64-clang -Os -flto \ + -o build/demo.prg build/demo.o build/music.o build/screens.o build/strings.o + mos-c64-clang++ -std=c++20 -Os -flto \ -Wl,--section-start=.sid=0x1000 \ -Wl,--section-start=.bank0screen=0x0c00 \ - -Wl,--section-start=.bank0color=0x1c00 \ -Wl,--section-start=.bank0bitmap=0x2000 \ -Wl,--section-start=.bank1screen=0x4c00, \ - -Wl,--section-start=.bank1color=0x7f40, \ -Wl,--section-start=.bank1bitmap=0x6000 \ - -Wl,--lto-emit-asm -o build/demo.s build/demo.o build/music.o build/screens.o + -Wl,--lto-emit-asm -o build/demo.s build/demo.o build/music.o build/screens.o build/strings.o run: demo @echo "Running demo" @@ -38,8 +35,6 @@ run: demo sid: @echo "SID file info" ./tools/sidinfo.py music.sid -# deprecated: -# dd if=music.sid of=music.bin bs=1 skip=126 .PHONY: all demo run diff --git a/llvm-mos/demo.c b/llvm-mos/demo.c index f908aa5..79d0799 100644 --- a/llvm-mos/demo.c +++ b/llvm-mos/demo.c @@ -5,40 +5,98 @@ #include #include -extern char sid[]; extern unsigned bank0bgcolor; extern unsigned bank1bgcolor; +extern char bank0bitmap; +extern char bank1bitmap; + +extern char *message; +extern unsigned char messageLength; unsigned char screen_state = 0; unsigned char counter = 254; +unsigned char raster_h_offset = 7; +unsigned char msg_offset = 0; + void background(unsigned char color) { poke(&VIC.bordercolor, color); poke(&VIC.bgcolor0, color); } void recolor() { + // switch to Standard Bitmap Mode now (bit 5 set to 1) + // Bit #5: 0 = Text mode; 1 = Bitmap mode. + // see https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode + poke(&VIC.ctrl1, 0b00111011); + // tells the VIC-II where to "look for graphics" + // in this case: + // 3 (%0011) * 1024 = $0c00 = address to start of color information + // bit 3 is set, then the bitmap starts at vic bank address + $2000 = $2000 or + // $6000 see https://www.c64-wiki.com/wiki/53272 + poke(&VIC.addr, 0b00111000); + // bit 5 must be cleared to enter Standard Bitmap Mode + // see https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode + poke(&VIC.ctrl2, 0b11011000); + if (screen_state == 0) { + background(bank1bgcolor); + vic_bank(0b0000010); + } else { + background(bank0bgcolor); + vic_bank(0b0000011); + } counter++; if (counter == 255) { counter = 0; - if (screen_state == 0) { - screen_state = 1; - background(bank1bgcolor); - // https://www.c64-wiki.com/wiki/VIC_bank - vic_bank(0b0000010); - } else { - screen_state = 0; - background(bank0bgcolor); - vic_bank(0b0000011); + screen_state = screen_state == 1 ? 0 : 1; + } +} + +void scrollMessage() { + // use bank 0 $0000-$3FFF, ROM chars available at $1000-$1FFF + // see https://www.c64-wiki.com/wiki/VIC_bank + vic_bank(0b00000011); + // switch to Standard Character Mode now (bit 5 set to 0) + // Bit #5: 0 = Text mode; 1 = Bitmap mode. + // see https://www.c64-wiki.com/wiki/Standard_Character_Mode and + // http://sta.c64.org/cbm64mem.html + poke(&VIC.ctrl1, 0b00011011); + // tells the VIC-II where to "look for graphics" + // in this case: + // 15 (%1111) * 1024 = $3c00 = address to screen character RAM + // 2 (%010) * 2048 = $1000 = where to access the character set ROM address + // see https://www.c64-wiki.com/wiki/53272 + poke(&VIC.addr, 0b11110100); + + raster_h_offset--; + poke(&VIC.ctrl2, raster_h_offset); + if (raster_h_offset == 0) { + raster_h_offset = 7; + + if (msg_offset == messageLength) { + msg_offset = 0; + } + + for (uint8_t i = 0; i < 40; i++) { + poke(0x3fc0 + i, message[msg_offset + i]); } + + msg_offset++; + } +} + +void clearBitmapLines(char *bitmap, uint16_t start, uint16_t end) { + for (uint16_t i = start; i < end; i = i + 1) { + bitmap[i] = 0; } } // see https://llvm-mos.org/wiki/C_interrupts -__attribute__((interrupt,no_isr)) void play() { +__attribute__((interrupt, no_isr)) void play() { interrupt_ack(); - recolor(); + scrollMessage(); sid_play($1021); + recolor(); interrupt_exit(); } @@ -52,23 +110,13 @@ int main(void) { cls(); - // switch to Standard Bitmap Mode now (bit 5 set to 1) - // Bit #5: 0 = Text mode; 1 = Bitmap mode. - // see https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode - poke(&VIC.ctrl1, 0b00111011); - // tells the VIC-II where to "look for graphics" - // in this case: - // 3 (%0011) * 1024 = $0c00 = address to start of color information - // bit 3 is set, then the bitmap starts at vic bank address + $2000 = $2000 or - // $6000 see https://www.c64-wiki.com/wiki/53272 - poke(&VIC.addr, 0b00111000); - // bit 5 must be cleared to enter Standard Bitmap Mode - // see https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode - poke(&VIC.ctrl2, 0b11011000); + // C64 bitmaps are 320x200 pixels, or 8000 bytes. Each line is 40 bytes. + clearBitmapLines(&bank0bitmap, 8000 - 40 * 16, 8000); + clearBitmapLines(&bank1bitmap, 8000 - 40 * 16, 8000); SEI(); - poke(&VIC.rasterline, 255); - pokew(IRQVec,(unsigned int)&play); + poke(&VIC.rasterline, 240); + pokew(IRQVec, (unsigned int)&play); // interrupt control - enable all interrupts with $7b (icr=$DC0D) // see http://sta.c64.org/cbm64mem.html poke(&CIA1.icr, 0b01111011); diff --git a/llvm-mos/screens.s b/llvm-mos/screens.s index d85fe45..05b345d 100644 --- a/llvm-mos/screens.s +++ b/llvm-mos/screens.s @@ -12,11 +12,11 @@ bank0bitmap: bank0screen: .incbin "screen1.koa", 8002, 1000 -.global bank0color -.type bank0color,@object -.section .bank0color,"awR",@progbits -bank0color: -.incbin "screen1.koa", 9002, 1000 +# .global bank0color +# .type bank0color,@object +# .section .bank0color,"awR",@progbits +# bank0color: +# .incbin "screen1.koa", 9002, 1000 .global bank0bgcolor .type bank0bgcolor,@object @@ -35,11 +35,11 @@ bank1bitmap: bank1screen: .incbin "screen2.koa", 8002, 1000 -.global bank1color -.type bank1color,@object -.section .bank1color,"awR",@progbits -bank1color: -.incbin "screen2.koa", 9002, 1000 +# .global bank1color +# .type bank1color,@object +# .section .bank1color,"awR",@progbits +# bank1color: +# .incbin "screen2.koa", 9002, 1000 .global bank1bgcolor .type bank1bgcolor,@object diff --git a/llvm-mos/strings.cpp b/llvm-mos/strings.cpp new file mode 100644 index 0000000..cc888e9 --- /dev/null +++ b/llvm-mos/strings.cpp @@ -0,0 +1,6 @@ +// and https://llvm-mos.org/wiki/Character_set +// custom version - official isn't working with wide \0 terminated strings +#include + +const char *message = U"THIS C64 DEMO USES VIC-II GRAPHICS, SPRITES, RASTER INTERRUPTS, A RANDOM GENERATOR AND SID MUSIC - MORE AT HTTPS://HITHUB.COM/CELSO/C64 "_uv; +unsigned char messageLength = 136; From ec34c0a7eb1578b6e4cee215ed832bd1851d744a Mon Sep 17 00:00:00 2001 From: Celso Martinho Date: Fri, 5 Jan 2024 20:31:07 +0000 Subject: [PATCH 3/3] fix --- llvm-mos/strings.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm-mos/strings.cpp b/llvm-mos/strings.cpp index cc888e9..4386184 100644 --- a/llvm-mos/strings.cpp +++ b/llvm-mos/strings.cpp @@ -1,5 +1,4 @@ -// and https://llvm-mos.org/wiki/Character_set -// custom version - official isn't working with wide \0 terminated strings +// https://llvm-mos.org/wiki/Character_set #include const char *message = U"THIS C64 DEMO USES VIC-II GRAPHICS, SPRITES, RASTER INTERRUPTS, A RANDOM GENERATOR AND SID MUSIC - MORE AT HTTPS://HITHUB.COM/CELSO/C64 "_uv;