commit 5f27aeb2fbc726981f825b363dc25fc33888ed92 Author: 4am Date: Tue Mar 13 21:27:30 2018 -0400 initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9955f60 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +/build/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5ccafcc --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +# +# DHRSLIDE.SYSTEM Makefile +# assembles source code, optionally builds a disk image and mounts it +# +# original by Quinn Dunki on 2014-08-15 +# One Girl, One Laptop Productions +# http://www.quinndunki.com/blondihacks +# +# adapted by 4am on 2018-01-08 +# + +# third-party tools required to build +# https://sourceforge.net/projects/acme-crossass/ +ACME=acme +# https://sourceforge.net/projects/applecommander/ +AC=bin/AppleCommander.jar + +BUILDDISK=build/dhrslide.po + +asm: + mkdir -p build + cd src && $(ACME) -r ../build/dhrslide.lst dhrslide.system.a + cp res/work.po $(BUILDDISK) + java -jar $(AC) -p $(BUILDDISK) "DHRSLIDE.SYSTEM" sys 0x2000 < "build/DHRSLIDE.SYSTEM#FF2000" + +clean: + rm -rf build/ + +mount: + osascript bin/V2Make.scpt "`pwd`" $(BUILDDISK) + +all: clean asm mount diff --git a/bin/AppleCommander.jar b/bin/AppleCommander.jar new file mode 100644 index 0000000..f74e7cb Binary files /dev/null and b/bin/AppleCommander.jar differ diff --git a/bin/V2Make.scpt b/bin/V2Make.scpt new file mode 100644 index 0000000..b17c861 Binary files /dev/null and b/bin/V2Make.scpt differ diff --git a/res/work.po b/res/work.po new file mode 100644 index 0000000..ed29af1 Binary files /dev/null and b/res/work.po differ diff --git a/src/dhrslide.system.a b/src/dhrslide.system.a new file mode 100644 index 0000000..5e75c44 --- /dev/null +++ b/src/dhrslide.system.a @@ -0,0 +1,414 @@ +!cpu 6502 +!to "../build/DHRSLIDE.SYSTEM#FF2000",plain +*=$2000 +; +; DHRSLIDE.SYSTEM +; (c) 2018 by 4am +; a small DHGR graphics slideshow +; loads first .a2fc file in current directory, +; displays it, +; waits, +; finds next .a2fc file in same directory, +; repeats endlessly until keypress, +; quits via MLI +; +; known bugs: +; - does not reconnect /RAM properly, not sure why +; + +; +; application-specific addresses +; +entry = $82 +aDirData = $1600 +aDirBuff = $1800 +aFileBuff = $1C00 +; +; application constants +; +TRUE = $00 +FALSE = $FF +; +; ProDOS addresses +; +MLI = $BF00 ; ProDOS MLI entry point +NODEV = $BF10 ; means 'no device connected' +RAM32 = $BF26 ; S3,D2 /RAM device +DEVCNT = $BF31 ; ProDOS device count +DEVLST = $BF32 ; ProDOS device list +MACHID = $BF98 ; machine identification byte +; +; ProDOS constants +; +kMLIGetPrefix = $C7 +kMLIGetPrefixCount = 1 +kMLIOpen = $C8 +kMLIOpenCount = 3 +kMLIRead = $CA +kMLIReadCount = 4 +kMLIClose = $CC +kMLICloseCount = 1 +kMLISetMark = $CE +kMLISetMarkCount = 2 +kMLIQuit = $65 +kMLIQuitCount = 4 +; +; ROM addresses +; +ROM80STOREOFF = $C000 +KEY = $C000 +WRITEMAINMEM = $C004 +WRITEAUXMEM = $C005 +; +; memory map +; +; 0800..0AFF relocated program code +; 0800..0AFF[aux] copy of program code +; 1600..17FF buffer for directory block +; 1800..1BFF ProDOS file buffer for reading directory +; 1C00..1FFF ProDOS file buffer for reading file +; 2000..3FFF graphics page 1 [shown] +; 2000..3FFF[aux] graphics page 1 [shown] +; 4000..5FFF offscreen buffer for next graphic file +; 4000..5FFF[aux] offscreen buffer for next graphic file +; + + jmp Start ; magic jump + !byte $EE,$EE ; magic bytes + !byte $40 ; length of inputbuffer +inputbuffer + !fill $40 +Start +!cpu 65816 + sep #2 ; set Z flag on 65816 only +!cpu 6502 + bne + ; skip GS-specific code on non-GS machines (required, will crash on //c, grr) + lda $C029 + and #$1F + sta $C029 ; set GS NEWVIDEO mode to turn off linearize ++ + lda RAM32 ; search for /RAM and disconnect if found + cmp NODEV + bne + + lda RAM32+1 + cmp NODEV+1 + beq noRAMdisk ++ ldy DEVCNT +- lda DEVLST, y + and #$F3 + cmp #$B3 + beq foundRAMdisk + dey + bpl - + bmi noRAMdisk +foundRAMdisk + lda DEVLST, y + sta saveRAMDiskUnit ; save RAM disk unit number +- lda DEVLST+1, y ; move other devices up in list + sta DEVLST, y + beq + ; device list is zero-terminated + iny + bne - ; always branches ++ lda RAM32 + sta saveRAMDiskDriver ; save RAM disk device address + lda RAM32+1 + sta saveRAMDiskDriver+1 + lda NODEV ; tell ProDOS there's no RAM disk anymore + sta RAM32 + lda NODEV+1 + sta RAM32+1 + dec DEVCNT ; reduce ProDOS device count +noRAMdisk + sta ROM80STOREOFF + ldx #$00 ; copy code to lower memory so we can load graphic at $2000 +- lda CodeStart, x + sta $0800, x + lda CodeStart+$100, x + sta $0900, x + lda CodeStart+$200, x + sta $0A00, x + sta WRITEAUXMEM + lda CodeStart, x ; also copy it to aux memory so fizzle fade can freely switch back and forth + sta $0800, x + lda CodeStart+$100, x + sta $0900, x + lda CodeStart+$200, x + sta $0A00, x + sta WRITEMAINMEM + inx + bne - + + jmp $0800 + +CodeStart +!pseudopc $800 { + jsr CheckFor128K ; does not return if we have less than 128K + lda #kMLIGetPrefix + ldy #kMLIGetPrefixCount + ldx #FALSE ; do not return to caller on error + jsr CallMLI ; get current prefix + + lda #kMLIOpen + ldy #kMLIOpenCount + ldx #FALSE ; do not return to caller on error + jsr CallMLI ; open directory as file + + lda mliparam+5 ; directory refnum + sta saveDirRefnum +ReadFirstDirectoryBlock + lda foundAtLeastOne ; if we've gone through the entire directory and ended up + beq + ; back here without ever finding a suitable file to display, + jmp CloseAll ; just quit ++ lda #FALSE + sta foundAtLeastOne + lda #$00 + sta entryLength + sta mliparam+2 ; position for MLI_SET_MARK + sta mliparam+3 + sta mliparam+4 + lda saveDirRefnum + sta mliparam+1 + lda #kMLISetMark + ldy #kMLISetMarkCount + ldx #FALSE ; do not return to caller on error + jsr CallMLI ; set mark of directory file back to the beginning (position 000000) +ReadNextDirectoryBlock + lda saveDirRefnum + sta mliparam+1 ; refnum for directory-as-file + lda #aDirData+1 + sta mliparam+3 ; store in (aDirData) + lda #$00 + sta mliparam+4 + lda #$02 ; read $0200 bytes (= 2 sectors, = 1 ProDOS block) + sta mliparam+5 + lda #kMLIRead + ldy #kMLIReadCount + ldx #TRUE ; always return to caller, even if there is an error + jsr CallMLI ; MLI_READ to read a directory block + bcc firstTimeSetup ; check error manually + cmp #$4C ; MLI error was EOF? + beq ReadFirstDirectoryBlock;yes, start over at the beginning of directory + bne CloseAll ; no, real error +firstTimeSetup + lda entryLength + bne skipFirstTime + lda aDirData+$23 + sta entryLength + lda aDirData+$24 + sta entriesPerBlock +skipFirstTime + lda #<(aDirData+4) + sta entry + lda #>(aDirData+4) + sta entry+1 + lda entriesPerBlock + sta entriesRemaining +GoToNextEntry + dec entriesRemaining + beq ReadNextDirectoryBlock + lda entry + clc + adc entryLength + sta entry + lda entry+1 + adc #$00 + sta entry+1 + ldy #$00 + lda (entry), y + and #$F0 + cmp #$00 + beq GoToNextEntry ; skip inactive entry + cmp #$D0 + beq GoToNextEntry ; skip subdirectory + ldy #$00 + lda (entry), y ; get filename length + and #$0F + sta (entry), y ; store actual length so we can use this as a length-prefixed string later + cmp #$06 + bcc GoToNextEntry ; filename not long enough, skip entry + tay + ldx #$04 +- lda (entry), y + cmp suffix, x ; match required suffix ('.A2FC') + bne GoToNextEntry ; no match, skip entry + dey + dex + bpl - + lda #TRUE + sta foundAtLeastOne + jsr DisplayFile + lda #$00 + ldy #$15 +.wait0 sec +.wait1 pha +.wait2 sbc #$01 + bne .wait2 + pla + ldx KEY + bmi CloseAll + sbc #$01 + bne .wait1 + dey + bpl .wait0 + bmi GoToNextEntry + +CloseAll + lda #$00 + sta mliparam+1 ; close all open files + lda #kMLIClose + ldy #kMLICloseCount + ldx #TRUE ; always return to caller, even on error (which we will ignore) + jsr CallMLI + ; execution falls through here + +Quit + lda saveRAMDiskUnit + beq noReconnect + ldy DEVCNT ; reconnect /RAM +- lda DEVLST + and #$F0 + cmp #$B0 + beq noReconnect + dey + bpl - + lda saveRAMDiskDriver ; restore /RAM driver + sta RAM32 + lda saveRAMDiskDriver+1 + sta RAM32+1 + inc DEVCNT ; insert /RAM unit into front of device list + ldy DEVCNT +- lda DEVLST-1, y + sta DEVLST + dey + bne - + lda #$03 ; format /RAM + sta $42 + lda saveRAMDiskUnit + sta DEVLST + and #$F0 + sta $43 + lda #aFileBuff + sta $45 + lda $C08B + lda $C08B + jsr CallRAMDriver + bit $C082 +noReconnect + bit $C010 ; reset keyboard strobe on the way out + lda #kMLIQuit + ldy #kMLIQuitCount + ; execution falls through here + +CallMLI + sta mlicmd + sty mliparam + jsr MLI +mlicmd !byte $00 + !word mliparam + bcc + ; no MLI error, so return + cpx #TRUE ; MLI error, so check if caller wants us to return or not + bne CloseAll ; caller said don't return on error, so close and quit ++ rts +mliparam + !byte 0 + !word inputbuffer + !word aDirBuff + !byte 0,0,0 ; extra space for MLI_READ (longest parameter block) + +CheckFor128K + lda MACHID + and #$30 + cmp #$30 + bne Quit + rts + + !source "fizzledhgr.a" + +DisplayFile + lda entry + sta mliparam+1 ; (entry) points to filename in aDirData + lda entry+1 + sta mliparam+2 + lda #aFileBuff + sta mliparam+4 + lda #kMLIOpen + ldy #kMLIOpenCount + ldx #FALSE + jsr CallMLI ; open .a2fc file + lda KEY + bpl + + rts ++ lda mliparam+5 + sta saveFileRefnum + sta mliparam+1 + lda #$00 + sta mliparam+2 + sta mliparam+4 + lda #$40 + sta mliparam+3 ; read into $4000 + sta copya+2 + sta copyb+2 + lda #$20 + sta mliparam+5 ; $2000 bytes + lda #kMLIRead + ldy #kMLIReadCount + ldx #FALSE + jsr CallMLI ; read first half of .a2fc file (will copy to auxmem) + lda KEY + bpl + + rts ++ sta ROM80STOREOFF + ldx #$20 ; copy $2000 bytes to auxmem + ldy #$00 +copyToAux + sta WRITEAUXMEM +copya lda $FF00, y ; self-modified address +copyb sta $FF00, y ; self-modified address + iny + bne copya + sta WRITEMAINMEM + inc copya+2 + inc copyb+2 + dex + bne copyToAux + lda #kMLIRead + ldy #kMLIReadCount + ldx #FALSE + jsr CallMLI ; read second half of .a2fc file (stays in main memory) + lda #kMLIClose + ldy #kMLICloseCount + ldx #FALSE + jsr CallMLI + jmp Fizzle ; fancy memory copy from page 2 to 1 + +CallRAMDriver + jmp (RAM32) +; +; global variables +; +saveRAMDiskUnit + !byte 0 +saveRAMDiskDriver + !word 0 +entryLength + !byte $00 +entriesPerBlock + !byte $00 +entriesRemaining + !byte $00 +foundAtLeastOne + !byte TRUE +saveDirRefnum + !byte $00 +saveFileRefnum + !byte $00 +suffix + !text ".A2FC" +} +CodeEnd diff --git a/src/fizzledhgr.a b/src/fizzledhgr.a new file mode 100644 index 0000000..1504867 --- /dev/null +++ b/src/fizzledhgr.a @@ -0,0 +1,83 @@ +;license:MIT +;(c) 2017-2018 by qkumba +; +; assumes this code is in an identical location in auxmem +; (currently taken care of in dhrslide.system.a) +; +Fizzle + ;graphics mode + + sta $c00d + sta $c057 + sta $c052 + sta $c050 + sta $c05e + + ;init RNG + + ldx #1 + stx rndval1+1 + dex + stx rndval2+1 + + ;iterate + +- ldy rndval1+1 + ldx rndval2+1 + lsr rndval2+1 + ror rndval1+1 + bcc + + + ;feedback polynomial forms #$2015 for period of 16383 + + lda rndval1+1 + eor #$15 + sta rndval1+1 + lda rndval2+1 + eor #$20 + sta rndval2+1 + + ;little hack to avoid missing offset zero + ;screen hole at $xxFF is missed instead + ++ tya + eor #$ff + sta $26 + sta $3c + txa + and #$1f + + ;target page 1 + + ora #$20 + sta $27 + eor #$60 + sta $3d + + ;copy pixel from other page to this page + + ldy #0 + cpx #$20 + bcc + + sta $c003 + sta $c005 ++ lda ($3c),y + sta ($26),y + sta $c002 + sta $c004 + + ;check for keypress + + lda $c000 + bmi fizzledone + + ;and exit condition + +rndval2 lda #0 + bne - +rndval1 lda #0 + cmp #1 + bne - + +fizzledone + rts