diff --git a/BADAPPLE.s b/BADAPPLE.s new file mode 100644 index 0000000..650e3d9 --- /dev/null +++ b/BADAPPLE.s @@ -0,0 +1,615 @@ + DSK GREENSCALE + +************************************************** +* Autoplaying version for Bad Apple demo +************************************************** +* Variables +************************************************** + +ROW EQU $FA ; row in pixels - 1-48 (#00-#2F) +COLUMN EQU $FB ; col in pixels - 1-40 (#00-#27) + +COLOR EQU $FC ; index color of pixel to plot - #00-#0F +PLOTCOLOR EQU $21 ; color to plot - #00-#0F from COLORTABLE +CHAR EQU $FD ; byte at PLOTROW,PLOTCOLUMN + +PLOTROW EQU $FE ; row in text page = ROW/2, remainder = nibble +PLOTCOLUMN EQU $FF ; col in text page == COLUMN + +IMGLO EQU $CD ; image data addres, LO +IMGHI EQU $CE ; image data addres, HI + +SEEDADDRLO EQU $CB ; db TABLESEED + +FRAMENUM EQU $1D ; which frame of the anim +FRAMES EQU $1E ; total frames + +DELAY EQU $1F ; interframe delay amount. + ; FF=3FPS $80=10FPS $40=24FPS $20=37FPS $10=43FPS $00=46FPS +PAUSED EQU $20 ; paused state - stop animation + +COLORMODE EQU $22 ; which color mode are we in? which table to draw from +TABLEOFFSET EQU $23 + +AUTOPLAYTIMER EQU $EB ; how many loops has the animation played? +AUTOPLAY EQU $EC ; Autoplay mode or not + +************************************************** +* Apple Standard Memory Locations +************************************************** +CLRLORES EQU $F832 +LORES EQU $C050 +TXTSET EQU $C051 +MIXCLR EQU $C052 +MIXSET EQU $C053 +TXTPAGE1 EQU $C054 +TXTPAGE2 EQU $C055 +KEY EQU $C000 +C80STOREOF EQU $C000 +C80STOREON EQU $C001 +STROBE EQU $C010 +SPEAKER EQU $C030 +VBL EQU $C02E +RDVBLBAR EQU $C019 ;not VBL (VBL signal low +WAIT EQU $FCA8 +RAMWRTAUX EQU $C005 +RAMWRTMAIN EQU $C004 +SETAN3 EQU $C05E ;Set annunciator-3 output to 0 +SET80VID EQU $C00D ;enable 80-column display mode (WR-only) +CLR80VID EQU $C00C +HOME EQU $FC58 ; clear the text screen +CH EQU $24 ; cursor Horiz +CV EQU $25 ; cursor Vert +VTAB EQU $FC22 ; Sets the cursor vertical position (from CV) +COUT EQU $FDED ; Calls the output routine whose address is stored in CSW, + ; normally COUTI +STROUT EQU $DB3A ;Y=String ptr high, A=String ptr low + +ALTTEXT EQU $C055 +ALTTEXTOFF EQU $C054 + +ROMINIT EQU $FB2F +ROMSETKBD EQU $FE89 +ROMSETVID EQU $FE93 + +ALTCHAR EQU $C00F ; enables alternative character set - mousetext + +BLINK EQU $F3 +SPEED EQU $F1 + +BELL EQU $FF3A ; Monitor BELL routine +CROUT EQU $FD8E ; Monitor CROUT routine +PRBYTE EQU $FDDA ; Monitor PRBYTE routine +MLI EQU $BF00 ; ProDOS system call +OPENCMD EQU $C8 ; OPEN command index +READCMD EQU $CA ; READ command index +CLOSECMD EQU $CC ; CLOSE command index + + +************************************************** +* START - sets up various fiddly zero page bits +************************************************** + + ORG $0800 ; PROGRAM DATA STARTS AT $0C00 NOW + + JSR BLOAD ; BLOAD DATA + + JSR HOWMANYFRAMES ; how big is the animation data? + + JSR ROMSETVID ; Init char output hook at $36/$37 + JSR ROMSETKBD ; Init key input hook at $38/$39 + JSR ROMINIT ; GR/HGR off, Text page 1 + + LDA #$00 + STA BLINK ; blinking text? no thanks. + STA LORES ; low res graphics mode + STA MIXCLR ; For IIGS - bottom 4 lines to GR + + STA PAUSED ; start not paused + STA COLORMODE ; start in default, real hardware mode + STA AUTOPLAYTIMER ; reset timer for autoplay + STA AUTOPLAY ; autoplay off by default +DETECTGS + SEC ;Set carry bit (flag) + JSR $FE1F ;Call to the monitor + BCS NOTGS ;If carry is still set, then old machine + ;BCC ISGS ;If carry is clear, then new machine + +ISGS lda #$01 ; disable SHR for IIgs + sta $c029 ; re: John Brooks + ; need to skip this if on IIe card, otherwise goes to alt ROM + +NOTGS LDA #$30 + STA DELAY ; start with a modest 30FPS + + lda SETAN3 + sta CLR80VID ; turn 80 column off + + JSR CLRLORES ; clear screen + + JSR EMULATORCHECK ; check for Virtual II, MicroM8 + + LDY COLORMODE ; colormode set by EMULATORCHECK, or 00 + LDA SEEDSTABLELO,Y ; which "Seed" table to generate from + STA SEEDADDRLO + + LDA SEEDSTABLEHI,Y + STA SEEDADDRHI + + JSR GENERATETABLE ; create a 256byte table from 16bytes. Magic! + +************************************************** +* MAIN LOOP +************************************************** + +STARTANIMATION + LDA DATAHI ; image data starts at end of code. + STA IMGHI + LDA DATALO + STA IMGLO + LDA FRAMES + STA FRAMENUM ; frame #0 + +EACHFRAME JSR INTERFRAMEDELAY + LDX #$00 + STX PLOTROW + LDY #$27 ; Y IS PLOTCOLUMN + +EACHROW LDA LoLineTableL,X + STA $0 + LDA LoLineTableH,X + STA $1 ; now word/pointer at $0+$1 points to screen line + +EACHPIXEL LDA (IMGLO),Y ; load byte at IMGLO,IMGHI + COLUMN + TAX ; look up color from lookup table +WHICHTABLE LDA COLORTABLE,X + STA ($0),Y ; store byte at LINE + COLUMN + +DECCOLUMN DEY ; next column of 2 pixels + BPL EACHPIXEL ; Y IS PLOTCOLUMN + LDY #$27 ; reset to col 0 + +INCROW INC PLOTROW + LDA IMGLO + CLC + ADC #$28 + STA IMGLO + BCS INCHI + +CMPROW LDX PLOTROW + CPX #$18 + BNE EACHROW + +LOOPTY DEC FRAMENUM + BNE EACHFRAME ; next frame in sequence + + JSR NEXTFILE ; LOAD NEXT FILE IN SEQUENCE + JMP STARTANIMATION + +INCHI INC IMGHI + BCS CMPROW + +;/MAIN LOOP + +************************************************** +* By popular(?) demand - slows down framerate +* based on keyboard input +************************************************** +PAUSE STA PAUSED ; stores #$A0 at PAUSED. + STA STROBE + +INTERFRAMEDELAY + INC AUTOPLAYTIMER ; played a frame, increment autoplay timer + LDA KEY ; check for keydown + CMP PAUSED ; space bar = #$A0 + BEQ UNPAUSE + + LDA PAUSED ; check for paused state + BNE INTERFRAMEDELAY ; loop forever until space bar + + +CHECKDELAY LDA KEY ; check for keydown + + CMP #$A0 ; space bar, pause + BEQ PAUSE + + CMP #$AB ; plus + BEQ INCDELAY ; if EQ, slow down (INC DELAY) + CMP #$BD ; equals + BEQ INCDELAY ; if EQ, slow down (INC DELAY) + CMP #$AD ; minus + BEQ DECDELAY ; if EQ, speed up (DEC DELAY) + + CMP #$C3 ; c + BEQ SWITCHCOLOR ; if C switch color mode + CMP #$E3 ; C + BEQ SWITCHCOLOR ; if C switch color mode + + CMP #$CE ; N + BEQ SWITCHDATA ; go to next DATA0* file + CMP #$EE ; N + BEQ SWITCHDATA ; go to next DATA0* file + + + CMP #$C1 ; a + BEQ AUTOSWITCH ; if A turn on/off autoplay + CMP #$E1 ; A + BEQ AUTOSWITCH ; if A turn on/off autoplay + + LDA AUTOPLAY + BEQ XLOOP ; autoplay = 0, skip the auto switch + LDA AUTOPLAYTIMER ; reset timer for autoplay + BEQ SWITCHDATA ; auto switch after 256 frames displayed + + +XLOOP LDX DELAY ; typical delay loop + +DELAYLOOP LDY DELAY + +YLOOP DEY + BNE YLOOP + + DEX + BNE DELAYLOOP + + RTS +;/INTERFRAMEDELAY + +UNPAUSE LDA #$0 + STA PAUSED + STA STROBE + JMP CHECKDELAY + +INCDELAY STA STROBE + INC DELAY + JMP XLOOP + +DECDELAY STA STROBE + DEC DELAY + JMP XLOOP + +SWITCHCOLOR STA STROBE + JSR COLORSWAP + JMP XLOOP + +SWITCHDATA STA STROBE + JSR NEXTFILE + RTS + +AUTOSWITCH STA STROBE + LDA AUTOPLAY + BEQ AUTOPLAYON ; if it's 0, inc to 1 + DEC AUTOPLAY ; otherwise, dec to 0 + JMP AUTOPLAYSET +AUTOPLAYON INC AUTOPLAY +AUTOPLAYSET RTS + + +************************************************** +* Check to see if I'm running in Virtual II or +* real hardware (or a different emulator) +* CARRY SET == running in VII +************************************************** + +EMULATORCHECK + LDX #$00 ; reset X and Y + LDY #$00 + CLC ; CARRY=VII found + +CHKVII ; if C04F is and stays zero, INC X + INX ; if X rolls over to zero, it's VII + BEQ FOUNDVII + LDA $C04F + BEQ CHKVII ; 0, then may be VII + +CHKM8 INY ; now to check for MICROM8 + CPY #$FF + BEQ FOUNDM8 + CMP #$2E + BEQ CHKM8 ; it's #$2E. Does it stay that way? + + CLC ;set return value: no Virtual II or M8 + RTS +FOUNDVII + SEC ;set return value: found Virtual II + JSR COLORSWAP ; otherwise, swap the color table (#1 is VII) + RTS + +FOUNDM8 ADC #$80 ; add over 128 = set OVerflow + INC COLORMODE ; next color mode + JSR COLORSWAP ; otherwise, swap the color table (#2 is M8) + RTS + + +************************************************** +* Load "banana" into memory +* +************************************************** + + +BLOAD JSR OPEN ;open "DATA" + JSR READ + JSR CLOSE + RTS ;Otherwise done + +OPEN JSR MLI ;Perform call + DB OPENCMD ;CREATE command number + DW OPENLIST ;Pointer to parameter list + BNE ERROR ;If error, display it + LDA REFERENCE + STA READLIST+1 + STA CLOSELIST+1 + RTS + +READ JSR MLI + DB READCMD + DW READLIST + BNE ERROR + RTS + +CLOSE JSR MLI + DB CLOSECMD + DW CLOSELIST + BNE ERROR + RTS + +ERROR CMP #$46 ; file not found during OPEN? reset to "DATA00" + BNE PRINTERROR + LDA #$30 + STA ENDNAME-1 + STA ENDNAME-2 + STA ENDNAME-3 + JMP OPEN +PRINTERROR JSR PRBYTE ;Print error code + JSR BELL ;Ring the bell + JSR CROUT ;Print a carriage return + RTS + +OPENLIST DB $03 ; parameter list for OPEN command + DW FILENAME + DA MLI-$400 ; buffer snuggled up tight with PRODOS +REFERENCE DB $00 ; reference to opened file + +READLIST DB $04 + DB $00 ; REFERENCE written here after OPEN + DB BEGINDATA ; write to end of code + DB $FF,$FF ; read as much as $FFFF - should error out with EOF before that. +TRANSFERRED DB $00,$00 + +CLOSELIST DB $01 + DB $00 + +FILENAME DB ENDNAME-NAME ;Length of name +NAME ASC '/GREENSCALE/DATA/DATA000' ;followed by the name +ENDNAME EQU * + + +************************************************** +* How many frames have transferred? +* up to 32 ($20) based on TRANSFERRED+1 +************************************************** +HOWMANYFRAMES LDX #$00 ; X=0 + LDA TRANSFERRED+1 ; LDA TRANSFERRED amt hi byte +HOWMANYLOOP CMP FRAMESTABLE,X ; compare A to FRAMESTABLE,X + BEQ HOWMANYSET ; if equal, X frames loaded. + INX + CPX $30 ; out of memory around 41 frames. + BEQ HOWMANYSET ; max 32 frames + JMP HOWMANYLOOP ; otherwise, INX, Loop +HOWMANYSET INX + STX FRAMES + RTS + +************************************************** +* Swap the color table with one for real +* hardware/OpenEmulator +* This works because the color tables are $FF bytes long. +************************************************** + +COLORSWAP INC COLORMODE ; next mode to cycle through + + LDX COLORMODE ; load to X + CPX #$05 ; is it now the text mode? + BEQ TEXTSWAP + ; otherwise, be sure to be back in GR + STX LORES ; low res graphics mode + STX MIXCLR ; For IIGS - bottom 4 lines to GR + +NEWTABLE + LDA SEEDSTABLELO,X + STA SEEDADDRLO + + LDA SEEDSTABLEHI,X + STA SEEDADDRHI + + JSR GENERATETABLE ; create a 256byte table from 16bytes. Magic! + + LDA COLORTABLEHI ; grab table address for LUT + STA WHICHTABLE+2 ; put it in the code + RTS + +TEXTSWAP STA TXTSET ; set text mode +SWAPTABLE LDA TEXTTABLEHI ; grab table address for LUT + STA WHICHTABLE+2 ; put it in the code + LDX #$FF + STX COLORMODE + RTS + + + +************************************************** +* Increment the name of the file to be loaded +* then trigger the load again. +************************************************** +NEXTFILE LDY ENDNAME-1 ; last char in ascii filename "DATA000" = #$30 + INY + CPY #$3A ; roll over past "xx9"? + BNE SETFILE + LDY #$30 ; reset to "0" + LDX ENDNAME-2 + INX + CPX #$3A ; roll over past "x90"? + BNE SETFILE10 + LDX #$30 ; reset to "00" + INC ENDNAME-3 ; add 100 +SETFILE10 STX ENDNAME-2 +SETFILE STY ENDNAME-1 + JSR BLOAD + JSR HOWMANYFRAMES ; how big is the new animation data? + LDA #$01 + STA FRAMENUM ; start new anim at frame 0 + RTS + +************************************************** +* Data Tables +* +* I was looking up each nibble, then converting +* the two nibbles to a full byte, but it's +* considerably faster to lookup a full byte at +* a time, skipping manipulating nibbles. +* +************************************************** + +************************************************** +* Generates a 256 byte table, given a pattern of +* 16 bytes. With more color tables in the program, +* this saves me more than 1K of memory +************************************************** + +GENERATETABLE + ; start with address of "seed" + LDA #$FF ; TABLEOFFSET = FF + STA TABLEOFFSET ; where in the COLORTABLE I'm writing + + LDA #$0F ; for X F to 0 + STA $07 + +GENXLOOP LDA #$0F ; for Y F to 0 + STA $06 + +GENYLOOP +; STY $06 ; hang onto Y + LDY $07 + LDA (SEEDADDRLO),Y ; (A=0F) + ROL ; ROLx4 (A=20) + ROL + ROL + ROL + LDY $06 ; get Y back + ADC (SEEDADDRLO),Y ; (A=FF) +; STY $06 ; store Y at $06 for safekeeping + LDY TABLEOFFSET + STA COLORTABLE,Y + DEC TABLEOFFSET +; LDY $06 +; DEY + DEC $06 + BPL GENYLOOP ; if Y = FF, next X +GENDECX DEC $07 + BPL GENXLOOP ; if X=FF, done +GENRTS RTS +;/GENERATETABLE + + + +TABLESEED HEX 00,02,01,04,08,03,06,0C,09,05,0A,07,0B,0E,0D,0F +V2COLORTABLE HEX 00,02,06,01,04,05,08,03,0C,09,07,0A,0B,0E,0D,0F ; Low res colors from darkest to lightest for Virtual ][ +MICROM8 HEX 00,02,04,08,0C,01,09,05,06,0E,0D,03,0A,07,0B,0F +THREEGRAYSTABLE HEX 00,02,02,02,02,06,06,06,06,06,06,07,07,07,07,0F ; W/B and 3 grays/shades of blue +VIDHD HEX 00,02,01,04,08,03,09,05,0A,06,0C,07,0B,0E,0D,0F + +SEEDSTABLEHI db >TABLESEED,>V2COLORTABLE,>MICROM8,>THREEGRAYSTABLE,>VIDHD +SEEDSTABLELO db LJJ7499PP" + ASC ";;!/l)>CC66999RR" + ASC "ii/11)>CCOO999RR" + ASC "iil11UUZQGB988RR" + ASC "vv1]]EEZQGB888RR" + ASC "uu1]]WWZQGB888@@" + ASC "oo[[[}}}JJNNMM@@" + ASC "wwhhddbbkkKK##**" + ASC "mmhhddbbkkKK##&*" + +TEXTTABLEHI db >TEXTTABLE +COLORTABLEHI db >COLORTABLE + + +FRAMESTABLE HEX 03,07,0B,0F,12,16,1A,1E,21,25,29,2D,30,34,38,3C ; how many frames transferred? HI byte lookup table + HEX 3F,43,47,4B,4E,52,56,5A,5D,61,65,69,6C,70,74,78 + HEX 7B,7F,83,87,8A,8E,92,96,99,9D,A1,A5,A8,AC,B0,B4 + +************************************************** +* Lores/Text lines +* Thanks to Dagen Brock for this. +************************************************** +Lo01 equ $400 +Lo02 equ $480 +Lo03 equ $500 +Lo04 equ $580 +Lo05 equ $600 +Lo06 equ $680 +Lo07 equ $700 +Lo08 equ $780 +Lo09 equ $428 +Lo10 equ $4a8 +Lo11 equ $528 +Lo12 equ $5a8 +Lo13 equ $628 +Lo14 equ $6a8 +Lo15 equ $728 +Lo16 equ $7a8 +Lo17 equ $450 +Lo18 equ $4d0 +Lo19 equ $550 +Lo20 equ $5d0 +* the "plus four" lines +Lo21 equ $650 +Lo22 equ $6d0 +Lo23 equ $750 +Lo24 equ $7d0 + +LoLineTable da Lo01,Lo02,Lo03,Lo04 + da Lo05,Lo06,Lo07,Lo08 + da Lo09,Lo10,Lo11,Lo12 + da Lo13,Lo14,Lo15,Lo16 + da Lo17,Lo18,Lo19,Lo20 + da Lo21,Lo22,Lo23,Lo24 + + +** Here we split the table for an optimization +** We can directly get our line numbers now +** Without using ASL +LoLineTableH db >Lo01,>Lo02,>Lo03 + db >Lo04,>Lo05,>Lo06 + db >Lo07,>Lo08,>Lo09 + db >Lo10,>Lo11,>Lo12 + db >Lo13,>Lo14,>Lo15 + db >Lo16,>Lo17,>Lo18 + db >Lo19,>Lo20,>Lo21 + db >Lo22,>Lo23,>Lo24 +LoLineTableL db BEGINDATA + +BEGINDATA EQU *