diff --git a/.gitignore b/.gitignore index 17c3369..598ddd4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.asm *.vice-mon-list SHELL-CMDS +SHELL-FILES \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 67aede2..c9b88f4 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,13 +6,16 @@ { "label": "Build", "type": "shell", - "windows": { + /*"windows": { "command": "java", "args": [ "-jar", "${env:PROG8C}", "neofetch.p8", "-target", "cx16" ] + },*/ + "windows":{ + "command": ".\\compile.bat" }, "linux":{ "command": "p8compile", diff --git a/Makefile b/Makefile index 4372d5f..7550f9d 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,13 @@ all: neofetch.prg clean: - rm -f *.prg *.asm *.vice-* SHELL-CMDS/neofetch + rm -f *.prg *.asm *.vice-* SHELL-FILES/commands/neofetch neofetch.prg: neofetch.p8 p8compile $< -target cx16 install: neofetch.prg - if [ ! -d ./SHELL-CMDS ]; then - mkdir SHELL-CMDS + if [ ! -d ./SHELL-FILES/commands ]; then + mkdir SHELL-FILES/commands fi - mv ./neofetch.prg ./SHELL-CMDS/neofetch + mv ./neofetch.prg ./SHELL-FILES/commands/neofetch diff --git a/README.md b/README.md index 260352b..8d29e8d 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,30 @@ # cx16-neofetch -A program for Commander X16, that shows your system information in a decorative manner. Heavily inspired by [neofetch](https://github.com/dylanaraps/neofetch) +A program for Commander X16, that shows your system information in a decorative manner. Heavily inspired by [neofetch](https://github.com/dylanaraps/neofetch) This program's intended to be used with [cx16shell](https://github.com/irmen/cx16shell) ![neofetch screenshot](./.READMErsc/screenshot.png "Screenshot of the neofetch running in X16 emulator") -Compiled binary can be downloaded from [the official CX16 forum post](https://cx16forum.com/forum/viewtopic.php?t=6769). Now it's also distributed with the [cx16shell](https://cx16forum.com/forum/viewtopic.php?t=6293) itself! +A compiled binary can be downloaded from [the official CX16 forum post](https://cx16forum.com/forum/viewtopic.php?t=6769). Now it's also distributed with the [cx16shell](https://cx16forum.com/forum/viewtopic.php?t=6293) itself! ## Compiling -First, you must have the [prog8 compiler](https://github.com/irmen/prog8) (in version 9.8 or bigger) set up and ready for compiling. For more information go to the official page. +First, you must have the [prog8 compiler](https://github.com/irmen/prog8) (in version 9.8 or bigger) set up and ready for compiling. For more information, go to the official page. ### Linux -In linux, you should create an [alias](https://en.wikipedia.org/wiki/Alias_(command)#Creating_aliases) called `p8compile` that runs `java -jar "/path/to/your/prog8compiler.jar"`, then you can just run `make` command to compile it and `make install` to place the binary into `SHELL-CMDS` folder. +In Linux, you should create an [alias](https://en.wikipedia.org/wiki/Alias_(command)#Creating_aliases) called `p8compile` that runs `java -jar "/path/to/your/prog8compiler.jar"`, then you can just run `make` command to compile it and `make install` to place the binary into `SHELL-FILES/commands` folder. ### Windows -Before you'll run `compile.bat` script, you'll have to [create an Environment Variable](https://docs.oracle.com/en/database/oracle/machine-learning/oml4r/1.5.1/oread/creating-and-modifying-environment-variables-on-windows.html#GUID-DD6F9982-60D5-48F6-8270-A27EC53807D0) called `PROG8C` with its value being `"Drive:\path\to\your\prog8compiler.jar"`. If you don't want to do that, I guess you can just replace the `%PROG8C%` inside the `compile.bat` script with the path to your compiler. Then you can just run `compile.bat`. The outputted binary's going to be located in the `SHELL-CMDS` folder. +Before you'll run `compile.bat` script, you'll have to [create an Environment Variable](https://docs.oracle.com/en/database/oracle/machine-learning/oml4r/1.5.1/oread/creating-and-modifying-environment-variables-on-windows.html#GUID-DD6F9982-60D5-48F6-8270-A27EC53807D0) called `PROG8C` with its value being `"Drive:\path\to\your\prog8compiler.jar"`. If you don't want to do that, I guess you can just replace the `%PROG8C%` inside the `compile.bat` script with the path to your compiler. Then you can just run `compile.bat`. The outputted binary's going to be located in the `SHELL-FILES/commands` folder. -**In all of those cases remember to also include the filename of the compiler at the end of the path** (if it wasn't obvious)**!** +**In all of those cases, remember to also include the filename of the compiler at the end of the path** (if it wasn't obvious)**!** ## Usage -In order to use the program, you'll need to create the `SHELL-CMDS` folder inside your CX16 SD card or Emulator's working directory. Then copy your binary to that folder. It's recommended to remove the suffix from your binary file's name (if it has it), so that you don't have to type it. -Now you can run your [`SHELL.PRG`](https://github.com/irmen/cx16shell). Then you can simply execute the neofetch by typing `neofetch` in your shell – just like you'd do on any linux system. +In order to use the program, you'll need to create the `SHELL-FILES/commands` folder inside your CX16 SD card or Emulator's working directory. Then copy your binary to that folder. It's recommended to remove the suffix from your binary file's name (if it has it), so that you don't have to type it. +Now you can run your [`SHELL.PRG`](https://github.com/irmen/cx16shell). Then you can simply execute the neofetch by typing `neofetch` in your shell – just like you'd do on any Linux system. Note: you cannot run the program from the BASIC interpreter. This is probably going to result in your device crashing. -## Bonus – displaying neofetch when starting SHELL.PRG *(DEPRECATED)* -Since SHELL.PRG doesn't allow to autorun commands on boot, I've made a soft-fork of cx16shell, that contains the cx16-neofetch's code inside the SHELL.PRG, and executes it while shell's starting. You can get it [here](https://github.com/adiee5/cx16shell-with-neofetch)! \ No newline at end of file +Since `9cbb957`, Neofetch adjusts itself to the current screen resolution so that you can enjoy it in every resolution. You can also force neofetch to use a specific layout by providing a layout ID as an argument, for example you can type `neofetch 1` to display the former default layout no matter what screen resolution you have. Layout IDs correspond to numbers used by basic `SCREEN` and SHELL.PRG's `mode` commands. There are also additional layouts, which can be accessed by typing numbers larger than 11. + +## Bonus - How to make a neofetch run when starting shell +Starting with Shell v1.3, users can set up the starting routine of cx16shell by editing `/SHELL-FILES/config.sh` file. This file is a simple shell script, that contains commands you want to execute before shell gives you the ability to type commands. You just need to add command, that is `neofetch`. You can even select the neofetch layout just like you'd do in the command prompt. Before saving the file, make sure, that the file ends with an empty line. Now, when you start the shell, you are going to be greeted by the neofetch! :D diff --git a/compile.bat b/compile.bat index eecc2aa..91fcb28 100644 --- a/compile.bat +++ b/compile.bat @@ -1,6 +1,6 @@ -if exist ".\SHELL-CMDS\" ( -if exist ".\SHELL-CMDS\neofetch" del .\SHELL-CMDS\neofetch +if exist ".\SHELL-FILES\commands\" ( +if exist ".\SHELL-FILES\commands\neofetch" del .\SHELL-FILES\commands\neofetch ) -else md SHELL-CMDS +else md SHELL-FILES\commands java -jar %PROG8C% neofetch.p8 -target cx16 -move neofetch.prg .\SHELL-CMDS\neofetch +move neofetch.prg .\SHELL-FILES\commands\neofetch diff --git a/manpage.txt b/manpage.txt new file mode 100644 index 0000000..6cceb87 --- /dev/null +++ b/manpage.txt @@ -0,0 +1,23 @@ +@; this is intended to be read via man command +@hneofetch@n displays information about the system in an aesthetic manner. + +@eSYNTAX:@n + +@p$@n neofetch @p[layout] + +layout@n is an integer value, that corresponds to layout id. Layouts 0-11 correspond to the defaults used by screen modes 0-11. Numbers larger than that are additional layouts. +If no layout id is provided, the default layout of a the current screen mode is displayed + +@eEXAMPLES: + +@p$@n neofetch + @hDisplays a usual neofetch output + +@p$@n neofetch 4 + @hDisplays only a text system info - no logo + +@p$@n neofetch 12 + @hDisplays a small neofetch logo next to the text + + +@pneofetch cx16 edition created by Adiee5. licensed under MIT@n \ No newline at end of file diff --git a/neofetch.p8 b/neofetch.p8 index 32215be..eac963a 100644 --- a/neofetch.p8 +++ b/neofetch.p8 @@ -1,49 +1,92 @@ %launcher none %option no_sysinit -%zeropage basicsafe +%zeropage dontuse %import shellroutines +%import conv ;sadly, i really needed to import this this time 3-( +%import string ;for some reason it asks me to import it, I've never had to + ;implicitly import this lib up to this point %encoding iso %address $4000 main $4000 { - %option force_output + %option force_output sub start(){ - - uword shellcolors=shell.get_text_colors() - color(4) - shell.print("\r o o ") + shellcolors=$bf00 ;ahh yes, repurposing vars as much as we can B-) + ubyte resx=0 + ubyte resy=0 + %asm {{ + jsr cx16.get_screen_mode + sta p8b_logo.p8v_id + stx p8v_resx + sty p8v_resy + }} + cx16.rambank(0) + if string.length(shellcolors)>0{ + while string.isspace(shellcolors[0]){ + shellcolors++ + } + j=conv.str2ubyte(shellcolors) + if cx16.r15==0{ + void shell.err_set("Command argument wasn't readable") + } + else if j>=len(logo.list){ + void shell.err_set("We don't have that many layout variants...") + } + else{ + logo.id=j + } + } + if logo.id==7{ + logo.m7_remove_padding() + } + tmp_ctrl=logo.listb[logo.id] + logo.load() + if tmp_ctrl&logo.type.above!=0{ + logo.printall() + logo.id=4 + logo.load() + } + if tmp_ctrl&1!=0{ + sys.exit(0) + } + + uword shellcolors=shell.get_text_colors() + uword JDspeed=hertz_check() + + logo.print() + color(shellcolors[2]) shell.print("OS") color(shellcolors[0]) - shell.print(": Commander X16 KERNAL ROM ") + shell.print(": Commander X16 KERNAL ") cx16.rombank(0) byte ver = @($ff80) as byte if ver == -1 shell.print("unstable") else{ + if ver < 0 { + ver *= -1 + shell.print("pre-") + } shell.chrout('R') - if ver < 0 ver *= -1 shell.print_ub(ver as ubyte) } - color(4) - shell.print("\r M@\\ /@M ") + logo.print() color(shellcolors[2]) shell.print("Host") color(shellcolors[0]) shell.print(": Commander X16 ") if (@($9FBE)==$31) and (@($9FBF) == $36) - shell.print("Official Emulator") + shell.print("Emulator") else shell.print("gen1 board") ; TODO add functionality to distinguish gen2 and gen3 if it's going to be possible. - ; Additionally add support for distinguishing Box16 - color(14) - shell.print("\r M@@@\\ /@@@M ") + logo.print() color(shellcolors[2]) shell.print("Shell") @@ -51,26 +94,17 @@ main $4000 { shell.print(": SHELL.PRG ") ;are version numbers even a thing there? shell.print(shell.version()) ;yes, there are now! - color(14) - shell.print("\r :@@@@@\\ /@@@@@: ") + logo.print() color(shellcolors[2]) shell.print("Resolution") color(shellcolors[0]) - ubyte resx=0 - ubyte resy=0 - %asm {{ - jsr cx16.get_screen_mode - stx p8v_resx - sty p8v_resy - }} shell.print(": ") shell.print_uw((resx as uword)*8) shell.chrout('x') shell.print_uw((resy as uword)*8) - color(3) - shell.print("\r \\@@@@@@\\ /@@@@@@/ ") + logo.print() color(shellcolors[2]) shell.print("CPU") @@ -79,10 +113,16 @@ main $4000 { if cputype() shell.print("65c816") else shell.print("65c02") - shell.print(" (1) @ 8MHz") + shell.print(" (1) @ ") + ;shell.print_uwhex(JDspeed,true) + ;shell.chrout(' ') + if(JDspeed>=$2600)shell.chrout('>') + if(JDspeed>=$2000)shell.chrout('8') + else if(JDspeed>=$1000)shell.chrout('4') + else shell.chrout('2') + shell.print("MHz") - color(5) - shell.print("\r \'\'\"\"**N N**\"\"\'\' ") + logo.print() color(shellcolors[2]) shell.print("GPU") @@ -100,8 +140,7 @@ main $4000 { } cx16.VERA_CTRL = tmp_ctrl - color(7) - shell.print("\r N N ") + logo.print() color(shellcolors[2]) shell.print("Memory") @@ -109,11 +148,10 @@ main $4000 { shell.print(": ") shell.print_uw((sys.progend()-737) / 1024) ; 735 bytes of free golden ram + 2 bank registers = 737 shell.print("KiB / ") - shell.print_uw((cbm.MEMTOP(0, true)-2) / 1024) + shell.print_uw((MEMTOP()-2) / 1024) shell.print("KiB") - color(7) - shell.print("\r ..-*N N*-.. ") + logo.print() color(shellcolors[2]) shell.print("Hi-Memory") @@ -124,10 +162,8 @@ main $4000 { shell.print_uw(cx16.numbanks()) shell.print(" banks)") - color(8) - shell.print("\r :@@@@@/ \\@@@@@: ") - color(2) - shell.print("\r M@@@/ \\@@@M ") + logo.print() + logo.print() ubyte j for j in 0 to 15{ @@ -135,18 +171,21 @@ main $4000 { shell.print("\xad#") } - color(2) - shell.print("\r M@/ \\@M ") + logo.printall() + color(shellcolors[0]) shell.chrout('\r') sys.exit(0) } - sub color (ubyte txtcol) { - ubyte[16] color_to_charcode = [$90,$05,$1c,$9f,$9c,$1e,$1f,$9e,$81,$95,$96,$97,$98,$99,$9a,$9b] - txtcol &= 15 - cbm.CHROUT(color_to_charcode[txtcol]) + asmsub color(ubyte txtcol @X) clobbers(A){ + %asm{{ + lda color_to_charcode,x + jmp cbm.CHROUT + color_to_charcode .byte $90, $05, $1c, $9f, $9c, $1e, $1f, $9e, $81, $95, $96, $97, $98, $99, $9a, $9b + }} } + asmsub cputype() ->bool @A{ %asm {{ php @@ -156,9 +195,232 @@ main $4000 { lda #1 plp rts -+ lda #0 + + lda #0 plp rts }} } + + ; function, that checks how fast is the cpu (bigger number = faster cpu) + ; created bt JimmyDansbo. Og code here: https://gist.github.com/JimmyDansbo/bbbf8d9da8916d995af689248a266d9a + asmsub hertz_check() -> uword @R0{ + %asm{{ + stz cx16.r0 ; Ensure our cx16.r0 variable is zero + stz cx16.r0+1 + stz P8ZP_SCRATCH_REG ; Ensure trigger variable is zero + + ; Save original interrupt vector address + lda cbm.CINV + sta P8ZP_SCRATCH_W1 + lda cbm.CINV+1 + sta P8ZP_SCRATCH_W1+1 + + ; Install new interrupt handler + sei + lda #vera_tick + sta cbm.CINV+1 + cli + + ; Wait for an interrupt to ensure that we start the timing at + ; the beginning of an interrupt + firstwait + wai + lda P8ZP_SCRATCH_REG + beq firstwait + stz P8ZP_SCRATCH_REG + + ; Now we do as many counts as we can until next interrupt + timing + inc cx16.r0 + bne + + inc cx16.r0+1 + + lda P8ZP_SCRATCH_REG + beq timing + + ; Uninstall interrupt handler + sei ; Disable interrupts + lda P8ZP_SCRATCH_W1 + sta cbm.CINV + lda P8ZP_SCRATCH_W1+1 + sta cbm.CINV+1 + cli ; Enable interrupts + + ; High byte of the r0 have the following values on all systems + ; that I have tested (Emulator, CX16 PR board, OtterX & Community Board) + ; @ 2 MHz - $08 + ; @ 4 MHz - $11 + ; @ 8 MHz - $24 + + rts + + ; Ensure P8ZP_SCRATCH_REG is non-zero when irq happens + vera_tick + lda cx16.VERA_ISR + and #1 ; Is this VSYNC? + beq + ; if not, end + sta P8ZP_SCRATCH_REG + + jmp (P8ZP_SCRATCH_W1) + }} + } + inline asmsub MEMTOP() -> uword @ XY{ + %asm{{ + sec + jsr cbm.MEMTOP + }} + } +} +logo{ + uword[] list=[ + &square, ;0 + &original, ;1 + &square, ;2 + &original, ;3 + &empty, ;4 + &smallsq, ;5 + &smallsq, ;6 + &square, ;7 + &square, ;8 + &original, ;9 + &square, ;10 + &original, ;11 + &smallsq, ;12 + &smallsq, ;13 + &original ;14 + ] + ubyte[] listh=[ + len(square), ;0 + len(original), ;1 + len(square), ;2 + len(original), ;3 + len(empty), ;4 + len(smallsq), ;5 + len(smallsq), ;6 + len(square), ;7 + len(square), ;8 + len(original), ;9 + len(square), ;10 + len(original), ;11 + len(smallsq), ;12 + len(smallsq), ;13 + len(original) ;14 + ] + ubyte[] listb=[ + logo.type.normal, ;0 + logo.type.normal, ;1 + logo.type.above, ;2 + logo.type.above, ;3 + logo.type.normal, ;4 + logo.type.onlylogo, ;5 + logo.type.onlylogo, ;6 + logo.type.onlylogo, ;7 + logo.type.normal, ;8 + logo.type.normal, ;9 + logo.type.above, ;10 + logo.type.above, ;11 + logo.type.normal, ;12 + logo.type.above, ;13 + logo.type.onlylogo ;14 + ] + sub type(){ + const ubyte normal=0 + const ubyte onlylogo=3 + const ubyte above=2 + } + str[] original=[ + "\r\x9c o o ", + "\r\x9c M@\\ /@M ", + "\r\x9a M@@@\\ /@@@M ", + "\r\x9a :@@@@@\\ /@@@@@: ", + "\r\x9f \\@@@@@@\\ /@@@@@@/ ", + "\r\x1e \'\'\"\"**N N**\"\"\'\' ", + "\r\x9e N N ", + "\r\x9e ..-*N N*-.. ", + "\r\x81 :@@@@@/ \\@@@@@: ", + "\r\x1c M@@@/ \\@@@M ", + "\r\x1c M@/ \\@M " + ] + str[] empty=[ + "\r","\r","\r","\r","\r","\r","\r","\r","\r","\r","" + ] + str[] square=[ + "\r\x9c o o ", + "\r\x9c M\\ /M ", + "\r\x9c M@\\ /@M ", + "\r\x9c M@@\\ /@@M ", + "\r\x9a M@@@\\ /@@@M ", + "\r\x9a M@@@@\\ /@@@@M ", + "\r\x9a [@@@@@\\ /@@@@@] ", + "\r\x9f :@@@@@@\\ /@@@@@@: ", + "\r\x9f [@@@@@@\\ /@@@@@@] ", + "\r\x9f \\@@@@@@@\\ /@@@@@@@/ ", + "\r\x1e \"\"@@@@N N@@@@\"\" ", + "\r\x1e --N N-- ", + "\r\x1e N N ", + "\r\x9e N N ", + "\r\x9e .-N N-. ", + "\r\x9e ..--@@N N@@--.. ", + "\r\x81 :@@@@@@/ \\@@@@@@: ", + "\r\x81 [@@@@@/ \\@@@@@] ", + "\r\x1c M@@@@/ \\@@@@M ", + "\r\x1c M@@@/ \\@@@M ", + "\r\x1c M@@/ \\@@M ", + "\r\x1c M@/ \\@M " + ] + str[] smallsq=[ + "\r\x9c o o ", + "\r\x9c M\\ /M ", + "\r\x9a M@\\ /@M ", + "\r\x9a :@@\\ /@@: ", + "\r\x9f \\@@\\ /@@/ ", + "\r\x1e \'\"*N N*\"\' ", + "\r\x9e N N ", + "\r\x9e .-*N N*-. ", + "\r\x81 :@@/ \\@@: ", + "\r\x1c M@/ \\@M ", + "\r\x1c M/ \\M " + ] + + ubyte id + ubyte i=0 + uword current + sub load(){ + current = list[id] + i=0 + } + sub print(){ + cx16.r0L=current[i] + cx16.r0H=current[i+1] + shell.print(cx16.r0) + ;shell.print_ub(string.length(cx16.r0)) + ;shell.chrout('\r') + i+=2 + } + sub printall(){ + while i<= (listh[logo.id]-1)*2{ + print() + } + } + sub m7_remove_padding(){ + ubyte n + for n in 0 to 7{ + @(square[n]+25)=0 + } + @(square[8]+24)=0 + @(square[9]+24)=0 + @(square[10]+22)=0 + @(square[11]+18)=0 + @(square[12]+16)=0 + @(square[13]+16)=0 + @(square[14]+18)=0 + @(square[15]+22)=0 + for n in 16 to len(square)-1{ + @(square[n]+23)=0 + } + for n in 0 to len(square)-1{ + void string.copy(square[n]+4,square[n]+2) + } + } + } \ No newline at end of file