From 2333b797f2637d81f9cd84da8b0c24c112be0edd Mon Sep 17 00:00:00 2001 From: Michaelangel007 Date: Mon, 17 Jul 2017 00:52:37 -0700 Subject: [PATCH] Add all files --- Makefile | 21 +++ README.md | 35 +++++ ascii2hgr2bit.c | 42 ++++- linuxlogo.s | 401 ++++++++++++++++++++++++++++++++++++++++++++++++ ll_6502.dsk | Bin 0 -> 143360 bytes 5 files changed, 492 insertions(+), 7 deletions(-) create mode 100644 Makefile create mode 100644 README.md create mode 100644 linuxlogo.s create mode 100644 ll_6502.dsk diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ee8c201 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +all: ascii2hgr2bit packedlogo.s linuxlogo dsk +.PHONY: clean + +clean: + rm -f ascii2hgr2bit packedlogo.s linuxlogo + +packedlogo.s: ascii2hgr2bit + ascii2hgr2bit > packedlogo.s + +# https://www.brutaldeluxe.fr/products/crossdevtools/merlin/index.html +linuxlogo: linuxlogo.s + merlin32 $< + +# a2tools +dsk: linuxlogo + -a2rm ll_6502.dsk LINUXLOGO > /dev/null 2>&1 + a2in B.0900 ll_6502.dsk LINUXLOGO linuxlogo + +ascii2hgr2bit: ascii2hgr2bit.c + gcc -Wall -Wextra $< -o $@ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..de07e11 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ + +# 6502 Linux Logo + +Linux Logo in 6502 assembly language. + +Size: 703 ($2BF) bytes + +Features: + +* Detects Apple \]\[, \]\[+, //e, //e+, //c, //c+ +* Detects 48K/64K/128K +* Cleaned up fugly Linux Logo + * Made logo 70 chars for integer multiple of 280 HGR width + * Logo takes up 210 bytes (2 bits/char) compared to 80*12 = 960 byte + +``` +__________________________________________________________@@@@@_______ +_________________________________________________________@@@@@@@______ +______________A__________________________________________@@_@_@@______ +@@@@@@_______AA@_________________________________________@BBBBB@______ +__@@__________@________________________________________@@__BBB__@@____ +__@@_______AAA__@@@_@@@@___@@@____@@@__@@@@@_@@@@@____@__________@@___ +__@@______A__A@__@@@____@@__@@_____@@____@@___@@_____@____________@@__ +__@@_____A___A@__@@_____@@__@@_____@@_____@@_@@______@____________@@@_ +__@@________AA@__@@_____@@__@@_____@@______@@@______BB@___________@@B_ +__@@_____@_AA@___@@_____@@__@@_____@@_____@@_@@____BBBBB@_______@BBBBB +__@@____@@_AA@_@_@@_____@@__@@@___@@@____@@___@@___BBBBBB@_____@BBBBBB +@@@@@@@@@@__@@@_@@@@___@@@@___@@@@_@@@_@@@@@_@@@@@__BBBBB@@@@@@@BBBBB_ +``` + +See: [ascii2hgr2bit](ascii2hgr2bit.c) for packing ASCII to 2 bits/4 pixels. + +Inspirited from non-optimized version. Size: 1,573 ($625) bytes +* https://github.com/deater/linux_logo + diff --git a/ascii2hgr2bit.c b/ascii2hgr2bit.c index f3b4201..49884c9 100644 --- a/ascii2hgr2bit.c +++ b/ascii2hgr2bit.c @@ -1,6 +1,9 @@ /* -Michaelangel007 6502 Linux Logo +Michaelangel007 +https://github.com/Michaelangel007/6502_linux_logo + +gcc -Wall -Wextra ascii2hgr2bit.c -o ascii2hgr2bit */ #include @@ -18,7 +21,7 @@ Michaelangel007 https://github.com/deater/linux_logo/blob/master/logos/banner.logo */ -int gbOutputHgr = 0; +int gbOutputHgr = 0; // 0 = 2bits/2pixel, 1=HGR bytes unsigned char gaLogoBits[ 280 / 2 * 192 / 8 ]; // packed bits const char* gaLogo70 = @@ -56,13 +59,34 @@ Bitpacked 2-bits/2 pixels "__@@____@@_AA@_@_@@_____@@__@@@___@@@____@@___@@___BBBBBB@_____@BBBBBB" "@@@@@@@@@@__@@@_@@@@___@@@@___@@@@_@@@_@@@@@_@@@@@__BBBBB@@@@@@@BBBBB_" #else + // _@_@_@_@_@_@_@ = PACK: $33,$33,$33,$33 -> HGR: $33,$66,$4C,$19 (MSB=0) -// = HGR: $B3,$E6,$CC,$99 (MSB=1) +// 1100110011001100110011001100 $B3,$E6,$CC,$99 (MSB=1) //"_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@" -// @_@_@_@_@_@_@_ = HGR: $4C,$19,$33,$66 (MSB=0) -// = PACK: $CC,$CC,$CC,$CC -> HGR: $CC,$99,$B3,$E6 (MSB=1) -//"@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_" + +/* +Bit Packing 2 bits / 1 pixels + + <--CC--> <--CC--> <--CC--> <--CC--> Packed Bytes +|11001100|11001100|11001100|11001100| Packed Bits +|hgfedcba|ponmlkji|xwvutsrq|FEDCBAzy| +| | | | | +|76543210|76543210|76543210|76543210| Bit Position +| 0 | 1 | 2 | 3 | Byte +| | | | | +|1gfedcba|1nmlkjih|1utsrqpo|1BAzyxwv| +|11001100|10011001|10110011|11100110| + <--CC--> <--99--> <--B3--> <--E6--> HGR Bytes + + @_@_@_@_@_@_@_ = 00110011001100110011001100 + = 11001100110011001100110011 (reverse bits) + = PACK: $CC,$CC,$CC,$CC + -> HGR: $CC,$99,$B3,$E6 (MSB=1) + HGR: $4C,$19,$33,$66 (MSB=0) +*/ +"@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_@_" + #endif ; @@ -105,11 +129,15 @@ if( gbOutputHgr ) } len = (unsigned int)(dst - gaLogoBits); + printf( "PackedLen\n" ); printf( " dfb $%02X\n", len ); + printf( "PackedBits\n"); + printf( " ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 byte\n" ); + printf( " ; 0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 256 272 8 24 40 56 72 88 104 120 136 152 168 184 200 216 232 248 264 px\n" ); for( i = 0; i < len; i++ ) { - if( (i % (70 / 2)) == 0 ) + if( (i % (35)) == 0 ) { if( i > 0 ) printf( "\n" ); diff --git a/linuxlogo.s b/linuxlogo.s new file mode 100644 index 0000000..dd62909 --- /dev/null +++ b/linuxlogo.s @@ -0,0 +1,401 @@ +; 6502 Linux Logo +; Michaelangel007 +; https://github.com/Michaelangel007/6502_linux_logo + +; Zero Page ROM vars +zCursorX = $24 ; CH +zCursorY = $25 ; CH +zHgrPtr = $26 ; GBASL = Dst +zTxtPtr = $28 ; BASL = Dst + +zSaveX = $F9 +zSaveY = $FA +zMask = $FB ; 16-bit but Acc has low +zSrcShift = $FC ; i mod 8 +zDstShift = $FD ; i mod 7 +zUnpackBits = $FE ; 16-bit unpack + +; ROM +HOME = $FC58 +IB_HGR = $D000 ; Integer BASIC ][ only +AS_HGR = $F3E2 ; Applesoft BASIC ][+ or newer +BASCALC = $FBC1 ; A=Row, Calculate BASL,BASH text address + +;Bank Addr -- Addr Bank Read --- Write ------- +; 2 $C080 == $C088 1 Read RAM Write protect +; 2 $C081 == $C089 1 Read ROM Write enabled +; 2 $C082 == $C08A 1 Read ROM Write protect +; 2 $C083 == $C08B 1 Read RAM Write enabled +RAMIN = $C080 +ROMIN = $C081 + +MACHINEID1 = $FBB3 +MACHINEID2 = $FBC0 +MACHINEID3 = $FBBF ; //c version + +; Config +UnpackAddr = $200 ; $28 bytes at Keyboard buffer +CONFIG_PROBE_CPUINFO = 1 +CONFIG_PRINT_CPUINFO = 1 + +; ======================================================================== + + ORG $900 +Main + jsr HOME + +; ------------------------------------------------------------------------ + DO CONFIG_PROBE_CPUINFO +DetectCPU + +; Apple II Technical Note #7 +; https://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20II/Documentation/Misc%20%23007%20Apple%20II%20Family%20ID.pdf +; +; Machine $FBB3 $FBC0 $FBBE +; Apple ][ $38 +; Apple ][+ $EA +; Apple /// $EA +; Apple //e $06 $EA +; Apple //e+ $06 $E0 +; Apple //e Option Card $06 $E0 +; Apple //c $06 $00 $FF +; Apple //c 3.5 $06 $00 $00 +; Apple //c Org Mem XP $06 $00 $03 +; Apple //c Rev Mem XP $06 $00 $04 +; Apple //c+ $06 $00 $05 +; Apple IIgs +detect_ram + lda MACHINEID1 ; FBB3: $38 = ][, $EA = ][+, $06 = //e //c IIgs + pha + cmp #$38 ; + bne apple_iiplus + +apple_ii + pla + jsr IB_HGR ; HGR on ][, ends with BNE $D01B + beq apple_ii_normal + +apple_iiplus + jsr AS_HGR ; ][ = $D000, Only on Apple ][+ + + pla + cmp #$EA ; apple ][+? + bne apple_iie ; if so keep going + + lda #"+" + bne set_apple_ii + +; if we get here we're a ii+ or iii in emulation mode +apple_ii_normal + lda #" " ; $A0 +set_apple_ii + sta ModType ; erase last 'e' in 'Apple IIe' + + sta CpuType ; '_6502' + lda #"6" + sta CpuType+1 + lda #"5" + sta CpuType+2 + +detect_langcard + sta RAMIN ; Detect 16K RAM / Language Card + sta RAMIN ; Read RAM + + lda $D000 + eor #$FF + sta $D000 + cmp $D000 + bne apple_ii_48K + eor #$FF + sta $D000 + +RAM_64K + ldx #"6" + ldy #"4" + bne RAM_size +apple_ii_48K + ldx #"4" + ldy #"8" +RAM_size + lda #" " + sta RamSize ; erase '1' in '128' + stx RamSize+1 + sty RamSize+2 + bne done_detecting + +; Detect //e //e+ //c +apple_iie + lda MACHINEID2 ; FBC0: $00 = //c, $EA = //e, E0 = //e+ + beq apple_iic ; check for apple //c + cmp #$E0 ; if we're an Apple IIe (original) + bne RAM_64K ; then use 64K and finish + beq apple_iie_enhanced +apple_iic + lda #"c" + sta CpuType+1 + lda MACHINEID3 + cmp #$05 ; //c+ + bne done_detecting +apple_iie_enhanced ; //c+ + ldx #1 ; //e+ + jsr ModelPlus ; ^ +done_detecting + sta ROMIN ; Turn off Language Card + sta ROMIN ; if it was probed + FIN + +; ------------------------------------------------------------------------ +; Unpack 2 bits/color -> $28 bytes/scanline +; +; Unpack one line to $200 +; Copy to 8 scanlines +Unpack + + DO 1-CONFIG_PROBE_CPUINFO + jsr AS_HGR ; *** DEBUG *** + FIN + + lda #8 ; $0428 (Text) + $1C00 => $2028 (HGR) + sta zCursorY ; Start Row=8 +DrawRow + jsr GetDestAddr + + lda #0 + tay + tax ; DstOffset within page + sta zDstShift + + lda PackedBits + sta zUnpackBits+0 + +NextSrcShift + lda #0 + sta zSrcShift + lda PackedBits+1,Y + sta zUnpackBits+1 +GetBit + jsr Unpack2Bits ; hhggffee C=? ddccbbaa + bcs UnpackDone + lsr zUnpackBits+1 ; 0hhggffe C=e ddccbbaa + ror zUnpackBits+0 ; 0hhggffe C=e eddccbba + lsr zUnpackBits+1 ; 00hhggff C=e eddccbba + ror zUnpackBits+0 ; 00hhggff c=e eeddccbb + inc zSrcShift ; + inc zSrcShift +CheckFetch + lda zSrcShift + cmp #8 ; have 8 input bits? + bne GetBit + iny ; src++ + cpy PackedLen + bcc NextSrcShift ; C=0 -> STZ zSrcShift +UnpackDone + + +; ------------------------------------------------------------------------ + + DO CONFIG_PRINT_CPUINFO + + ldx #0 +PrintText + jsr BASCALC ; + ldy #0 +CopyTextLine + lda TextLine,X + sta (zTxtPtr),Y + inx ; 3*40 = 120 chars max + iny + cpy #40 + bne CopyTextLine + + inc zCursorY + lda zCursorY + cmp #$17 ; Rows $14..$16 (inclusive) + bne PrintText + + dec zCursorY + +; End of String offse for Model +; IN: X = 0 II+ +; ^ +; 1 //e+ +; ^ +ModelPlus + lda #"+" + sta ModType,x + FIN + + rts + +; ------------------------------------------------------------------------ +; Expand 1 pixel (2 bits) via +; Output 2 pixels (4 bits) +Unpack2Bits + +; DoublePixel + stx zSaveX + lda zUnpackBits + and #3 ; A=000000ba + pha + asl ; A=00000ba0 + asl ; A=0000ba00 + sta zMask + pla + ora zMask ; A=0000baba + + ldx #0 + stx zMask + + ldx zDstShift + beq NoShiftSherlock +MakeShiftMask + asl + rol zMask + dex + bne MakeShiftMask +NoShiftSherlock + + cmp #$80 ; msb of byte0 set? + rol zMask ; shift in to lsb of byte1 + + ldx zDstShift ; x={0,1,2} + 4 < 7 + cpx #3 ; all bits fit into dest byte? + + ldx zSaveX + ora #$80 + ora UnpackAddr,X ; do all bits that fit + sta UnpackAddr,X + bcc UpdateDestOffset + +; Update partial next byte of dest + inx + stx zSaveX + cpx #$28 ; C = x < 28 + + lda zMask + ora #$80 + ora UnpackAddr,X + sta UnpackAddr,X + + ; x = x + 4 - 7 + ; x = x - 3 + ldx zDstShift + dex + dex + dex + + bcc LineNotDone ; C = x < 28 + +; ------------------------------------------------------------------------ +; Copy Buffer to HGR + + sty zSaveY + + ldx #7 ; Repeat each scanline 8 times +Draw8Rows + ldy #0 +CopyScanLine + lda UnpackAddr,Y + sta (zHgrPtr),Y + iny + cpy #40 + bne CopyScanLine + + clc ; y = y+1 + lda zHgrPtr+1 ; addr_y+1 = addr_y + $0400 + adc #$04 + sta zHgrPtr+1 + dex + bpl Draw8Rows + + ldy zSaveY + + inc zCursorY + jsr GetDestAddr + lda zCursorY + cmp #$14 ; Y=$40 .. $A0, Rows $8..$13 (inclusive) + bcs OuputDone + + ldx #0 + stx zSaveX + beq LineNotDone ; Next Scan Line, start at dst bit 0 + +UpdateDestOffset + ldx zDstShift + inx + inx + inx + inx +LineNotDone + stx zDstShift + clc + ldx zSaveX +OuputDone + rts + +; ------------------------------------------------------------------------ +; Udpate the Text Address +; Update the HGR scanline Address +; Clear the Text buffer +GetDestAddr + lda zCursorY + jsr BASCALC + + lda zTxtPtr+0 ; every 8 HGR scanline address + sta zHgrPtr+0 ; is exactly same as Text low byte + + lda zTxtPtr+1 + clc ; every 8 HGR scanline address + adc #$1c ; is Text Page $04 + $1C = HGR Page $20 + sta zHgrPtr+1 + + lda #0 + ldx #40-1 +ClearBuffer + sta UnpackAddr,X + dex + bpl ClearBuffer + + rts + +; ------------------------------------------------------------------------ + +CpuType = * + 13 + 40 +RamSize = * + 30 + 40 +ModType = * + 24 + 40*2 + +; Uppercase in case of Apple II without lowercase support + ; 1 2 3 +TextLine ;0123456789012345678901234567890123456789 + ASC " LINUX VERSION 2.6.22.6, COMPILED 2007 " ; Row $14 + ASC " ONE 1.02MHZ 65C02 PROCESSOR, 128KB RAM " ; Row $15 + ASC " APPLE IIe " ; Row $16 +; ^ ^ ^ + +; ------------------------------------------------------------------------ + +;"__________________________________________________________@@@@@_______" +;"_________________________________________________________@@@@@@@______" +;"______________A__________________________________________@@_@_@@______" +;"@@@@@@_______AA@_________________________________________@BBBBB@______" +;"__@@__________@________________________________________@@__BBB__@@____" +;"__@@_______AAA__@@@_@@@@___@@@____@@@__@@@@@_@@@@@____@__________@@___" +;"__@@______A__A@__@@@____@@__@@_____@@____@@___@@_____@____________@@__" +;"__@@_____A___A@__@@_____@@__@@_____@@_____@@_@@______@____________@@@_" +;"__@@________AA@__@@_____@@__@@_____@@______@@@______BB@___________@@B_" +;"__@@_____@_AA@___@@_____@@__@@_____@@_____@@_@@____BBBBB@_______@BBBBB" +;"__@@____@@_AA@_@_@@_____@@__@@@___@@@____@@___@@___BBBBBB@_____@BBBBBB" +;"@@@@@@@@@@__@@@_@@@@___@@@@___@@@@_@@@_@@@@@_@@@@@__BBBBB@@@@@@@BBBBB_" +; Char &3 Color +; @ 00 Black +; A 01 Blue +; B 10 Orange +; _ 11 White + +; NOTE: Generated by ascii2hgr2bit +; ASCII: 70*12 = 840 chars +; Packed 2bits/2pixel: 70 chars * 2 bits/char / 8 bits/byte = 140 bits / 8 = 17.5 bytes +; 840 chars * 2 bits/color / 8 bits/byte = 210 bytes + + PUT packedlogo.s + diff --git a/ll_6502.dsk b/ll_6502.dsk new file mode 100644 index 0000000000000000000000000000000000000000..dc93c27e1be4a1290addcce9907cb3843ec70e81 GIT binary patch literal 143360 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