From 2cf26ac28dcf965795f0dc9da33f6721b9ba0c9d Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sat, 9 Mar 2024 13:36:33 -0500 Subject: [PATCH] keen: initial checkin --- games/duke/Makefile | 4 +- games/duke/empty.dsk | Bin 143360 -> 0 bytes games/keen/gr_copy.s | 161 ++++++ games/keen/gr_fast_clear.s | 201 +++++++ games/keen/graphics/Makefile | 32 ++ games/keen/graphics/keen1_title.png | Bin 0 -> 7006 bytes games/keen/init_vars.s | 32 ++ games/keen/keen_title.s | 277 +++++++++ games/keen/loader.s | 709 ++++++++++++++++++++++++ games/keen/print_help.s | 40 ++ games/keen/text_print.s | 191 +++++++ games/keen/zp.inc | 209 +++++++ games/keen/zx02_optim.s | 163 ++++++ games/sb/rat_graphics/Makefile | 2 +- graphics/gr/bubble_universe/Makefile | 32 ++ graphics/gr/bubble_universe/bubble_gr.s | 304 ++++++++++ graphics/gr/bubble_universe/hello.bas | 13 + 17 files changed, 2367 insertions(+), 3 deletions(-) delete mode 100644 games/duke/empty.dsk create mode 100644 games/keen/gr_copy.s create mode 100644 games/keen/gr_fast_clear.s create mode 100644 games/keen/graphics/Makefile create mode 100644 games/keen/graphics/keen1_title.png create mode 100644 games/keen/init_vars.s create mode 100644 games/keen/keen_title.s create mode 100644 games/keen/loader.s create mode 100644 games/keen/print_help.s create mode 100644 games/keen/text_print.s create mode 100644 games/keen/zp.inc create mode 100644 games/keen/zx02_optim.s create mode 100644 graphics/gr/bubble_universe/Makefile create mode 100644 graphics/gr/bubble_universe/bubble_gr.s create mode 100644 graphics/gr/bubble_universe/hello.bas diff --git a/games/duke/Makefile b/games/duke/Makefile index 99d28cad..8104cc2c 100644 --- a/games/duke/Makefile +++ b/games/duke/Makefile @@ -6,12 +6,12 @@ B2D = ../../utils/bmp2dhr/b2d PNG2GR = ../../utils/gr-utils/png2gr LZSA = ~/research/lzsa/lzsa/lzsa TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft - +EMPTY_DISK = ../../empty_disk/empty.dsk all: duke.dsk duke.dsk: HELLO LOADER DUKE_TITLE DUKE_LEVEL1 DUKE_LEVEL2 - cp empty.dsk duke.dsk + cp $(EMPTY_DISK) duke.dsk $(DOS33) -y duke.dsk SAVE A HELLO $(DOS33) -y duke.dsk BSAVE -a 0x1000 LOADER $(DOS33) -y duke.dsk BSAVE -a 0x4000 DUKE_TITLE diff --git a/games/duke/empty.dsk b/games/duke/empty.dsk deleted file mode 100644 index b34eb5199d4f28583c3ea48dbade142d2d16eefb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143360 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�)_rN2Z}tpyZ20mwR_% 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 z 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 disk_sprites.inc + +#### + +keen1_title.hgr.zx02: keen1_title.hgr + $(ZX02) keen1_title.hgr keen1_title.hgr.zx02 + +keen1_title.hgr: keen1_title.png + $(PNG_TO_HGR) keen1_title.png > keen1_title.hgr + +#### + +clean: + rm -f *~ *.o *.lst *.zx02 *.hgr + diff --git a/games/keen/graphics/keen1_title.png b/games/keen/graphics/keen1_title.png new file mode 100644 index 0000000000000000000000000000000000000000..b90b079e95f4d5dd23dcde8b523d244ecbd00f83 GIT binary patch literal 7006 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 Mojsk39Vkiv18Gw}=l}o! literal 0 HcmV?d00001 diff --git a/games/keen/init_vars.s b/games/keen/init_vars.s new file mode 100644 index 00000000..538b9b1d --- /dev/null +++ b/games/keen/init_vars.s @@ -0,0 +1,32 @@ + + ;===================== + ; init vars + ;===================== +init_vars: + lda #0 + sta ANIMATE_FRAME + sta FRAMEL + sta FRAMEH + sta DISP_PAGE + sta JOYSTICK_ENABLED + sta DUKE_WALKING + sta DUKE_JUMPING + sta LEVEL_OVER + sta LASER_OUT + sta DUKE_XL + sta SCORE0 + sta SCORE1 + sta SCORE2 + sta DUKE_FALLING + sta DUKE_SHOOTING + sta KICK_UP_DUST + sta DOOR_ACTIVATED + sta INVENTORY + + lda #1 + sta FIREPOWER + + lda #7 + sta HEALTH + + rts diff --git a/games/keen/keen_title.s b/games/keen/keen_title.s new file mode 100644 index 00000000..262e51e6 --- /dev/null +++ b/games/keen/keen_title.s @@ -0,0 +1,277 @@ +; Keen1 Title + +; loads a HGR version of the title + +; by deater (Vince Weaver) + +; Zero Page + .include "zp.inc" + .include "hardware.inc" + .include "common_defines.inc" + +keen_title_start: + ;=================== + ; init screen + ;=================== + + jsr TEXT + jsr HOME + bit KEYRESET + + bit SET_GR + bit PAGE0 + bit HIRES + bit FULLGR + + ;=================== + ; machine workarounds + ;=================== + ; mostly IIgs + ;=================== + ; thanks to 4am who provided this code from Total Replay + + lda ROM_MACHINEID + cmp #$06 + bne not_a_iigs + sec + jsr $FE1F ; check for IIgs + bcs not_a_iigs + + ; gr/text page2 handling broken on early IIgs models + ; this enables the workaround + + jsr ROM_TEXT2COPY ; set alternate display mode on IIgs + cli ; enable VBL interrupts + + ; also set background color to black instead of blue + lda NEWVIDEO + and #%00011111 ; bit 7 = 0 -> IIgs Apple II-compat video modes + ; bit 6 = 0 -> IIgs 128K memory map same as IIe + ; bit 5 = 0 -> IIgs DHGR is color, not mono + ; bits 0-4 unchanged + sta NEWVIDEO + lda #$F0 + sta TBCOLOR ; white text on black background + lda #$00 + sta CLOCKCTL ; black border + sta CLOCKCTL ; set twice for VidHD + +not_a_iigs: + + ;=================== + ; Load hires graphics + ;=================== +reload_everything: + + lda #new_title + sta ZX0_src+1 + + lda #$20 ; decompress to hgr page1 + + jsr full_decomp + + ;=================================== + ; detect if we have a language card + ; and load sound into it if possible + ;=================================== + +; lda #0 +; sta SOUND_STATUS ; clear out, sound enabled + +; jsr detect_language_card +; bcs no_language_card + + ; update sound status +; lda SOUND_STATUS +; ora #SOUND_IN_LC +; sta SOUND_STATUS + + ; load sounds into LC + + ; read ram, write ram, use $d000 bank1 +; bit $C08B +; bit $C08B + +; lda #linking_noise_compressed +; sta getsrc_smc+2 + +; lda #$D0 ; decompress to $D000 + +; jsr decompress_lzsa2_fast + +;blah: + + ; read rom, nowrite, use $d000 bank1 +; bit $C08A + +no_language_card: + + ;=================================== + ; Setup Mockingboard + ;=================================== +; lda #0 +; sta DONE_PLAYING +; sta LOOP + + ; detect mockingboard +; jsr mockingboard_detect + +; bcc mockingboard_notfound + +mockingboard_found: +;; jsr mockingboard_patch ; patch to work in slots other than 4? + +; lda SOUND_STATUS +; ora #SOUND_MOCKINGBOARD +; sta SOUND_STATUS + + ;======================= + ; Set up 50Hz interrupt + ;======================== + +; jsr mockingboard_init +; jsr mockingboard_setup_interrupt + + ;============================ + ; Init the Mockingboard + ;============================ + +; jsr reset_ay_both +; jsr clear_ay_both + + ;================== + ; init song + ;================== + +; jsr pt3_init_song + +; jmp done_setup_sound + + +mockingboard_notfound: + + +done_setup_sound: + + + + ;=================================== + ; Do Intro Sequence + ;=================================== + + ; wait a bit at LOAD screen + + lda #100 + jsr wait_a_bit + + +done_intro: + + ; restore to full screen (no text) + + bit FULLGR + bit LORES + + ;============================ + ; init vars + + jsr init_vars + + + + ;============================ + ; set up initial location + + lda #LOAD_DUKE1 + sta WHICH_LOAD ; start at first level + + rts + + + ;========================== + ; includes + ;========================== + + .include "gr_pageflip.s" + .include "gr_copy.s" +; .include "wait_a_bit.s" + .include "gr_offsets.s" + .include "zx02_optim.s" + + .include "print_help.s" + .include "gr_fast_clear.s" + .include "text_print.s" + + .include "init_vars.s" +; .include "graphics_title/title_graphics.inc" +; .include "lc_detect.s" + + + ; pt3 player +; .include "pt3_lib_core.s" +; .include "pt3_lib_init.s" +; .include "interrupt_handler.s" +; .include "pt3_lib_mockingboard_detect.s" +; .include "pt3_lib_mockingboard_setup.s" + +new_title: +.incbin "graphics/keen1_title.hgr.zx02" + + + + ;==================================== + ; wait for keypress or a few seconds + ;==================================== + +wait_a_bit: + + bit KEYRESET + tax + +keyloop: + lda #200 ; delay a bit + jsr WAIT + + lda KEYPRESS + bmi done_keyloop + +; bmi keypress_exit + + dex + bne keyloop + +done_keyloop: + bit KEYRESET + + cmp #'H'|$80 + bne really_done_keyloop + + bit SET_TEXT + jsr print_help + bit SET_GR + bit PAGE0 + + ldx #100 + + jmp keyloop + +really_done_keyloop: + + + rts + + + + + + +;PT3_LOC = theme_music + +;.align $100 +;theme_music: +;.incbin "audio/theme.pt3" + diff --git a/games/keen/loader.s b/games/keen/loader.s new file mode 100644 index 00000000..add1bc68 --- /dev/null +++ b/games/keen/loader.s @@ -0,0 +1,709 @@ +; Loader for DUKE + +.include "zp.inc" +.include "hardware.inc" +.include "common_defines.inc" + +nibtbl = $300 ; nothing uses the bottom 128 bytes of $300, do they? +bit2tbl = $380 ; bit2tbl: .res 86 ; = nibtbl+128 +filbuf = $3D6 ; filbuf: .res 4 ; = bit2tbl+86 + +; read any file slot 6 version +; based on FASTLD6 and RTS copyright (c) Peter Ferrie 2011-2013,2018 + +; modified to assembled with ca65 -- vmw +; added code to patch it to run from current disk slot -- vmw + +; WHICH_LOAD = $7E ; thing to load +; adrlo = $26 ; constant from boot prom +; adrhi = $27 ; constant from boot prom +; tmpsec = $3c ; constant from boot prom +; reqsec = $3d ; constant from boot prom +; sizelo = $44 +; sizehi = $45 +; secsize = $46 +; namlo = $f8 +; namhi = $f9 +; TEMPY = $fa +; step = $fd ; state for stepper motor +; tmptrk = $fe ; temporary copy of current track +; phase = $ff ; current phase for /seek +; OUTL = $fe ; for picking filename +; OUTH = $ff + + dirbuf = $c00 + ; note, don't put this immediately below + ; the value being read as destaddr-4 + ; is temporarily overwritten during read + ; process + + + FILENAME = $280 + + ;=================================================== + ;=================================================== + ; START / INIT + ;=================================================== + ;=================================================== + +loader_start: + + lda #LOAD_TITLE + sta WHICH_LOAD + + jsr init ; unhook DOS, init nibble table + + + ;=================================================== + ;=================================================== + ; SETUP THE FILENAME + ;=================================================== + ;=================================================== + +which_load_loop: + + + + ; update the which-file error message +; lda WHICH_LOAD +; tay +; lda which_disk,Y +; sta error_string+19 + + lda WHICH_LOAD + asl + + tay + lda filenames,Y + sta OUTL + lda filenames+1,Y + sta OUTH + + lda WHICH_LOAD + bne load_other + +load_intro: + lda #<$4000 + sta entry_smc+1 + lda #>$4000 + sta entry_smc+2 + jmp actual_load + +load_other: + lda #<$2000 + sta entry_smc+1 + lda #>$2000 + sta entry_smc+2 + +actual_load: + + ;=================================================== + ;=================================================== + ; SET UP DOS3.3 FILENAME + ;=================================================== + ;=================================================== + +load_file_and_execute: + + jsr opendir_filename + +entry_smc: + jsr $1000 ; jump to common entry point + + ; hope they updated the WHICH_LOAD value + + jmp which_load_loop + + + ;============================== + ; setup filename then open/load + +opendir_filename: + + ; clear out the filename with $A0 (space) + + lda #FILENAME + sta namhi + + ldy #29 +wipe_filename_loop: + lda #$A0 + sta (namlo),Y + dey + bpl wipe_filename_loop + + ldy #0 +copy_filename_loop: + lda (OUTL),Y + beq copy_filename_done + ora #$80 + sta (namlo),Y + iny + bne copy_filename_loop + +copy_filename_done: + jsr opendir ; open and read entire file into memory + + rts + +filenames: + .word title_filename + .word keen1_filename + .word keen2_filename + +title_filename: + .byte "KEEN_TITLE",0 +keen1_filename: + .byte "KEEN_LEVEL1",0 +keen2_filename: + .byte "KEEN_LEVEL2",0 + + + ;=================================================== + ;=================================================== + ; INIT (build nibble table) + ;=================================================== + ;=================================================== + + ;unhook DOS and build nibble table + +init: + ; patch to use current drive + + ; locate input paramater list + jsr $3E3 + ; result is in A:Y + sta $FF + sty $FE + ldy #1 + lda ($FE),y + + ; list+1 should have slot<<8 + + + ora #$80 ; add in $80 + + ; c0e0 + sta mlsmc06+1 + + ; c0e8 + clc + adc #8 + sta mlsmc02+1 + sta mlsmc07+1 + + ; c0e9 + clc + adc #1 + sta mlsmc01+1 + + ; c0ec + clc + adc #3 + sta mlsmc03+1 + sta mlsmc04+1 + sta mlsmc05+1 + + jsr $fe93 ; clear COUT + jsr $fe89 ; clear KEYIN + + ;======================== + ; Create nibble table + ; Note: the table starts 16 bytes in, and is sparse + ; so it doesn't entirely look like the DOS33 table at + + ldy #0 + ldx #3 +L1: stx $3c ; store tempx (3?) + txa ; a=x (a=3) + asl ; a*=2 (a=6) + bit $3c ; a&tempx, set N/V (a=6) + beq L3 ; if 0, skip to L3 + ora $3c ; a|=tempx (a=7) + eor #$ff ; a=~a (a=f8) + and #$7e ; a&=0x7e 0111 1110 (a=78) +L2: bcs L3 ; this set way back at asl?? + lsr ; a>>1 a=3c c=0 + ; a=1e c=0 + ; a=0f c=0 + ; a=07 c=1 + bne L2 ; if a!=0 goto l2 + tya ; if a==0, a=y + sta nibtbl, x ; write out to table + iny ; increment y +L3: inx ; increment x x=4, a=0f + bpl L1 ; loop while high bit not set + + rts + + + ;=================================================== + ;=================================================== + ; file not found + ;=================================================== + ;=================================================== + +file_not_found: + +mlsmc07:lda $c0e8 ; turn off drive motor? + + jsr TEXT + jsr HOME + + ldy #0 + + lda #error_string + sta OUTH + +quick_print: + lda (OUTL),Y + beq quick_print_done + jsr COUT1 + iny + jmp quick_print + +quick_print_done: +; rts + +; jsr quick_print + +fnf_keypress: + lda KEYPRESS + bpl fnf_keypress + bit KEYRESET + + jmp which_load_loop + +; offset for disk number is 19 +error_string: +.byte "PLEASE INSERT DISK 1, PRESS RETURN",0 + + + + + + ;=================================================== + ;=================================================== + ; OPENDIR: actually load the file + ;=================================================== + ;=================================================== + + ; turn on drive and read volume table of contents +opendir: +mlsmc01:lda $c0e9 ; turn slot#6 drive on + ldx #0 + stx adrlo ; zero out adrlo + stx secsize ; zero out secsize + lda #$11 ; a=$11 (VTOC) + jsr readdirsec +firstent: + + lda dirbuf+1 + + ; lock if entry not found +entry_not_found: + beq file_not_found + + ; read directory sector + + ldx dirbuf+2 + jsr seekread1 + ldy #7 ;number of directory entries in a sector + ldx #$2b ;offset of filename in directory entry +nextent: + tya + pha ; was **phy** + txa + pha ; was **phx** + ldy #$1d + + ; match name backwards (slower but smaller) + +L4: + lda (namlo), y + cmp dirbuf, x + beq foundname + pla + + ; move to next directory in this block, if possible + + clc + adc #$23 + tax + pla + tay ; was **ply** + dey + bne nextent + beq firstent ; was **bra** + +foundname: + dex + dey + bpl L4 + pla + tay ; was **ply** + pla + + ; read track/sector list + + lda dirbuf-32, y + ldx dirbuf-31, y + jsr seekread1 + + ; read load offset and length info only, initially + + lda #filbuf + jsr seekread + + ; reduce load offset by 4, to account for offset and length + + sec + lda filbuf + sbc #4 + sta adrlo + + lda filbuf+1 + sbc #0 + sta adrhi + + ; save on stack bytes that will be overwritten by extra read + + ldy #3 +L5: + lda (adrlo), y + pha + dey + bpl L5 + + lda adrhi + pha + lda adrlo + pha + + ; increase load size by 4, to account for offst and length + + lda filbuf+2 + adc #3 + sta sizelo + sta secsize + + lda filbuf+3 + adc #0 + sta sizehi + beq readfirst + lda #0 ; was **stz secsize** + sta secsize + +readfirst: + ldy #$0c + + ; read a file sector + +readnext: + tya + pha + lda dirbuf, y ; A = track + ldx dirbuf+1, y ; x = sector + jsr seekread1 + pla + tay + + ; if low count is non-zero then we are done + ; (can happen only for partial last block) + + lda secsize + bne readdone + + ; continue if more than $100 bytes left + + dec sizehi + bne L6 + + ; set read size to min(length, $100) + + lda sizelo + beq readdone + sta secsize +L6: + inc adrhi + iny + iny + bne readnext + + ; save current address for after t/s read + + lda adrhi + pha + lda adrlo + pha + lda #0 + sta adrlo ; was **stz adrlo** + + ; read next track/sector sector + + lda dirbuf+1 + ldx dirbuf+2 + jsr readdirsec + clc + + ; restore current address +readdone: + pla + sta adrlo ; code originally had this backwards + pla + sta adrhi + bcc readfirst + +mlsmc02:lda $c0e8 + + ; restore from stack bytes that were overwritten by extra read + + ldx #3 + ldy #0 +L7: + pla + sta (adrlo), y + iny + dex + bpl L7 + rts + + + ;====================== + ; readdirsec + ;====================== + ; a = track? + ; x = sector? +readdirsec: + ldy #>dirbuf +seekread: + sty adrhi +seekread1: + sta phase + lda sectbl, x + sta reqsec + jsr readadr + + ; if track does not match, then seek + + cpx phase + beq checksec + jsr seek + + + ;========================================= + ; re merge in with qkumba's recent changes + ; to fix seek problem? + ;========================================= + + ; [re-]read sector + +re_read_addr: + jsr readadr +checksec: + cmp reqsec + bne re_read_addr + + ;========================= + ; read sector data + ;========================= + +readdata: + jsr readd5aa + eor #$ad ; zero A if match + bne re_read_addr + +L12: +mlsmc03:ldx $c0ec ; read until valid data (high bit set) + bpl L12 + eor nibtbl-$80, x + sta bit2tbl-$aa, y + iny + bne L12 +L13: +mlsmc04:ldx $c0ec ; read until valid data (high bit set) + bpl L13 + eor nibtbl-$80, x + sta (adrlo), y ; the real address + iny + cpy secsize + bne L13 + ldy #0 +L14: + ldx #$a9 +L15: + inx + beq L14 + lda (adrlo), y + lsr bit2tbl-$aa, x + rol + lsr bit2tbl-$aa, x + rol + sta (adrlo), y + iny + cpy secsize + bne L15 + rts + + ; no tricks here, just the regular stuff + + ;======================= + ; readaddr -- read the address field + ;======================= + ; Find address field, put track in cutrk, sector in tmpsec + +readadr: + jsr readd5aa + cmp #$96 + bne readadr + ldy #3 ; three? + ; first read volume/volume + ; then track/track + ; then sector/sector? +adr_read_two_bytes: + tax + jsr readnib + rol + sta tmpsec + jsr readnib + and tmpsec + dey + bne adr_read_two_bytes + rts + + ;======================== + ; make sure we see the $D5 $AA pattern + +readd5aa: +L16: + jsr readnib +L17: + cmp #$d5 + bne L16 + jsr readnib + cmp #$aa + bne L17 + tay ; we need Y=#$AA later + +readnib: +mlsmc05:lda $c0ec ; read until valid (high bit set) + bpl readnib + +seekret: + rts + + ;===================== + ; SEEK + ;===================== + ; current track in X? + ; desired track in phase + +seek: + ldy #0 + sty step + asl phase ; multiply by two + txa ; current track? + asl ; mul by two +copy_cur: + tax + sta tmptrk + sec + sbc phase + beq L22 + bcs L18 + eor #$ff + inx + bcc L19 +L18: + sbc #1 + dex +L19: + cmp step + bcc L20 + lda step +L20: + cmp #8 + bcs L21 + tay + sec +L21: + txa + pha + ldx step1, y +L22: + php + bne L24 +L23: + clc + lda tmptrk + ldx step2, y +L24: + stx tmpsec + and #3 + rol + tax + lsr +mlsmc06:lda $c0e0, x +L25: + ldx #$12 +L26: + dex + bpl L26 + dec tmpsec + bne L25 + bcs L23 + plp + beq seekret + pla + inc step + bne copy_cur + + + +step1: .byte $01, $30, $28, $24, $20, $1e, $1d, $1c +step2: .byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c + +sectbl: .byte $00,$0d,$0b,$09,$07,$05,$03,$01,$0e,$0c,$0a,$08,$06,$04,$02,$0f + + +; From $BA96 of DOS33 +;nibtbl: .res 128 ; = * +; .byte $00,$01,$98,$99,$02,$03,$9C,$04 ; $BA96 ; 00 +; .byte $05,$06,$A0,$A1,$A2,$A4,$A4,$A5 ; $BA9E ; 08 +; .byte $07,$08,$A8,$A9,$AA,$09,$0A,$0B ; $BAA6 ; 10 +; .byte $0C,$0D,$B0,$B1,$0E,$0F,$10,$11 ; $BAAE ; 18 +; .byte $12,$13,$B8,$14,$15,$16,$17,$18 ; $BAB6 ; 20 +; .byte $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5 ; $BABE ; 28 +; .byte $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C ; $BAC6 ; 30 +; .byte $1D,$1E,$D0,$D1,$D2,$1E,$D4,$D5 ; $BACE ; 38 +; .byte $20,$21,$D8,$22,$23,$24,$25,$26 ; $BAD6 ; 40 +; .byte $27,$28,$E0,$E1,$E2,$E3,$E4,$29 ; $BADE ; 48 +; .byte $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30 ; $BAE6 ; 50 +; .byte $31,$32,$F0,$F1,$33,$34,$35,$36 ; $BAEE ; 58 +; .byte $37,$38,$F8,$39,$3A,$3B,$3C,$3D ; $BAF6 ; 60 +; .byte $3E,$3F,$13,$00,$01,$02,$01,$00 ; $BAFE ; 68 +; .byte $00,$00,$00,$00,$00,$00,$00,$00 +; .byte $00,$00,$00,$00,$00,$00,$00,$00 + + +;bit2tbl: .res 86 ; = nibtbl+128 +;filbuf: .res 4 ; = bit2tbl+86 + + + ;dataend = filbuf+4 + + .include "init_vars.s" + +loader_end: + +.assert (16, error, "loader too big" diff --git a/games/keen/print_help.s b/games/keen/print_help.s new file mode 100644 index 00000000..35113863 --- /dev/null +++ b/games/keen/print_help.s @@ -0,0 +1,40 @@ +; For Help press ^H + +print_help: + bit KEYRESET ; clear keyboard + bit SET_TEXT + + jsr normal_text + + lda #' '|$80 + sta clear_all_color+1 + jsr clear_all + + lda #help_text + sta OUTH + jsr move_and_print_list + + jsr page_flip + +wait_for_keypress: + lda KEYPRESS + bpl wait_for_keypress + bit KEYRESET + + + bit SET_GR + rts + +help_text: +.byte 0, 5,"CONTROLS:",0 +.byte 3, 6, "A OR <- : MOVE LEFT",0 +.byte 3, 7, "D OR -> : MOVE RIGHT",0 +.byte 3, 8, "W OR UP : ACTION, ENTER DOOR",0 +.byte 3, 9, "SPACEBAR : JUMP",0 +.byte 3,10, "RETURN : SHOOT LASER",0 +.byte 3,12, "ESC : QUITS",0 +.byte 3,13, "CONTROL-T : TOGGLE SOUND",0 +.byte 3,14, "J : ENABLE JOYSTICK",0 +.byte 255 diff --git a/games/keen/text_print.s b/games/keen/text_print.s new file mode 100644 index 00000000..dada5ca0 --- /dev/null +++ b/games/keen/text_print.s @@ -0,0 +1,191 @@ + ;============================= + ; normal_text + ;============================= + ; modify so print normal text +normal_text: + + ; want ora #$80 + lda #$09 + sta ps_smc1 + + lda #$80 + sta ps_smc1+1 + + rts + + ;============================= + ; inverse_text + ;============================= + ; modify so print inverse text +inverse_text: + + ; want and #$3f + lda #$29 + sta ps_smc1 + + lda #$3f + sta ps_smc1+1 + + rts + + + ;============================= + ; raw text + ;============================= + ; modify so print raw string +raw_text: + + ; want nop nop + lda #$EA + sta ps_smc1 + + lda #$EA + sta ps_smc1+1 + + rts + + + + ;================================ + ; move_and_print + ;================================ + ; get X,Y from OUTL/OUTH + ; then print following string to that address + ; stop at NUL + ; convert to APPLE ASCII (or with 0x80) + ; leave OUTL/OUTH pointing to next string + +move_and_print: + ldy #0 + lda (OUTL),Y + sta CH + iny + lda (OUTL),Y + asl + tay + lda gr_offsets,Y ; lookup low-res memory address + clc + adc CH ; add in xpos + sta BASL ; store out low byte of addy + + lda gr_offsets+1,Y ; look up high byte + adc DRAW_PAGE ; + sta BASH ; and store it out + ; BASH:BASL now points at right place + + clc + lda OUTL + adc #2 + sta OUTL + lda OUTH + adc #0 + sta OUTH + + ;================================ + ; print_string + ;================================ + +print_string: + ldy #0 +print_string_loop: + lda (OUTL),Y + beq done_print_string +ps_smc1: + and #$3f ; make sure we are inverse + sta (BASL),Y + iny + bne print_string_loop +done_print_string: + iny + clc + tya + adc OUTL + sta OUTL + lda OUTH + adc #0 + sta OUTH + + rts + + + ;================================ + ; move and print a list of lines + ;================================ +move_and_print_list: + jsr move_and_print + ldy #0 + lda (OUTL),Y + bpl move_and_print_list + + rts + + +.if 0 + ;================================ + ; move and print a list of lines + ;================================ +move_and_print_list_both_pages: + lda DRAW_PAGE + pha + + lda OUTL + pha + lda OUTH + pha + + lda #0 + sta DRAW_PAGE + + jsr move_and_print_list + + pla + sta OUTH + pla + sta OUTL + + lda #4 + sta DRAW_PAGE + + jsr move_and_print_list + + pla + sta DRAW_PAGE + + + rts + + + + ;======================= + ; print to both pages + ;======================= +print_both_pages: + lda DRAW_PAGE + pha + + lda OUTL + pha + lda OUTH + pha + + lda #0 + sta DRAW_PAGE + + jsr move_and_print + + pla + sta OUTH + pla + sta OUTL + + lda #4 + sta DRAW_PAGE + + jsr move_and_print + + pla + sta DRAW_PAGE + + + rts +.endif diff --git a/games/keen/zp.inc b/games/keen/zp.inc new file mode 100644 index 00000000..25419a34 --- /dev/null +++ b/games/keen/zp.inc @@ -0,0 +1,209 @@ +;; Zero Page + +;; ZX02 addresses + +ZP=$00 + +offset = ZP+0 +ZX0_src = ZP+2 +ZX0_dst = ZP+4 +bitr = ZP+6 +pntr = ZP+7 + + + +;; Zero page monitor routines addresses + +WNDLFT = $20 +WNDWDTH = $21 +WNDTOP = $22 +WNDBTM = $23 +CH = $24 +CV = $25 +GBASL = $26 +GBASH = $27 +BASL = $28 +BASH = $29 +H2 = $2C +X_LEFT = $2C +V2 = $2D +MASK = $2E +COLOR_MASK = $2F +COLOR = $30 + +SEEDL = $4e +SEEDH = $4f +XMAX = $50 + + + +; MIST zero page addresses + +FRAMEL = $60 +FRAMEH = $61 +;CURSOR_X = $62 +;CURSOR_Y = $63 +XPOS = $64 +YPOS = $65 +LOCATION_STRUCT_L = $66 +LOCATION_STRUCT_H = $67 +IN_SPECIAL = $68 +CURSOR_VISIBLE = $69 +IN_LEFT = $6A +IN_RIGHT = $6B +BTC_L = $6C +BTC_H = $6D + +; pt3 player registers +REGISTER_DUMP = $70 +AY_REGISTERS = $70 +A_FINE_TONE = $70 +A_COARSE_TONE = $71 +B_FINE_TONE = $72 +B_COARSE_TONE = $73 +C_FINE_TONE = $74 +C_COARSE_TONE = $75 +NOISE = $76 +ENABLE = $77 +PT3_MIXER_VAL = $77 +A_VOLUME = $78 +B_VOLUME = $79 +C_VOLUME = $7A +ENVELOPE_FINE = $7B +ENVELOPE_COARSE = $7C +ENVELOPE_SHAPE = $7D +COPY_OFFSET = $7E +DECODER_STATE = $7F + +PATTERN_L = $7E +PATTERN_H = $7F + + +; note 70-7f also used by disk code + +; note: rest are up at $f0 + +; We have to save/restore the following values +; when loading/storing from disk + +WHICH_LOAD = $80 ; which file to load + +DUKE_XL = $81 +DUKE_X = $82 ; location of protagonist +DUKE_Y = $83 +DUKE_DIRECTION = $84 +DUKE_WALKING = $85 +DUKE_JUMPING = $86 + +LASER_OUT = $87 +LASER_X = $88 +LASER_Y = $89 +LASER_DIRECTION = $8A +TILEMAP_X = $8B +TILEMAP_Y = $8C + +DUKE_FOOT_OFFSET = $8D + +FIREPOWER = $8E +INVENTORY = $8F + INV_RED_KEY = $80 + INV_BLUE_KEY = $20 + INV_SHOE = $08 + INV_GRIP = $02 +HEALTH = $90 +SCORE0 = $91 +SCORE1 = $92 +SCORE2 = $93 +UPDATE_STATUS = $94 + +DUKE_FALLING = $95 +DUKE_SHOOTING = $96 +KICK_UP_DUST = $97 +SUPPRESS_WALK = $98 +ENEMY_DATAL = $99 +ENEMY_DATAH = $9A +DOOR_ACTIVATED = $9B +LASER_TILE = $9C +TILE_TEMP = $9D + +; done game puzzle state + + +WHICH_SLOT = $DA +JS_BUTTON_STATE = $DB +CURRENT_DISK = $DC +JOYSTICK_ENABLED= $DD +SOUND_STATUS = $DE + SOUND_DISABLED = $80 + SOUND_IN_LC = $01 ; $01 sound effects in language card + SOUND_MOCKINGBOARD = $02 ; mockingboard detected + +GRID_PAGE = $DF +ANIMATE_FRAME = $E0 +LEVEL_OVER = $E1 + GAME_OVER = $FF + NEXT_LEVEL = $01 +LOCATIONS_L = $E2 +LOCATIONS_H = $E3 + +; temp var per-world define +LONG_FRAME = $E4 ; nibel +CURRENT_DISPLAY = $E4 ; selena +LAST_PLAYED = $E4 ; selena + +DISP_PAGE = $ED ; ALL +DRAW_PAGE = $EE ; ALL + +; rest of pt3_player +MB_DETECTED = $EF +WHICH_CHUNK = $F0 +MB_CHUNK_OFFSET = $F1 +LOOP = $F4 +MB_VALUE = $F5 +MB_ADDR_L = $F6 +MB_ADDR_H = $F7 +DONE_PLAYING = $F8 +DONE_SONG = $F9 + +; rest of pt3_player +PT3_TEMP = $EF +ORNAMENT_L = $F0 +ORNAMENT_H = $F1 +SAMPLE_L = $F2 +SAMPLE_H = $F3 + + + + + + +TEMP = $FA +TEMPY = $FB +INL = $FC +INH = $FD +OUTL = $FE +OUTH = $FF + +; read any file slot 6 version +; based on FASTLD6 and RTS copyright (c) Peter Ferrie 2011-2013,2018 + +; modified to assemble with ca65 -- vmw +; added code to patch it to run from current disk slot -- vmw + + + adrlo = $26 ; constant from boot prom + adrhi = $27 ; constant from boot prom + tmpsec = $3c ; constant from boot prom + reqsec = $3d ; constant from boot prom + sizelo = $44 + sizehi = $45 + secsize = $46 + + ldsizel = $70 + ldsizeh = $71 + namlo = $7b + namhi = $7c + step = $7d ; state for stepper motor + tmptrk = $7e ; temporary copy of current track + phase = $7f ; current phase for /seek + diff --git a/games/keen/zx02_optim.s b/games/keen/zx02_optim.s new file mode 100644 index 00000000..8b88caf8 --- /dev/null +++ b/games/keen/zx02_optim.s @@ -0,0 +1,163 @@ +; De-compressor for ZX02 files +; ---------------------------- +; +; Decompress ZX02 data (6502 optimized format), optimized for speed and size +; 138 bytes code, 58.0 cycles/byte in test file. +; +; Compress with: +; zx02 input.bin output.zx0 +; +; (c) 2022 DMSC +; Code under MIT license, see LICENSE file. + + +;ZP=$80 + +;offset = ZP+0 +;ZX0_src = ZP+2 +;ZX0_dst = ZP+4 +;bitr = ZP+6 +;pntr = ZP+7 + + ; Initial values for offset, source, destination and bitr +;zx0_ini_block: +; .byte $00, $00 ; offset +;comp_data: +; .byte $0, $0 ; zx0_src +;out_addr: +; .byte $0, $0 ; zx0_dst +; .byte $80 ; bitr + +;-------------------------------------------------- +; Decompress ZX0 data (6502 optimized format) + + ; destination page in A +full_decomp: + sta ZX0_dst+1 + + ldy #$80 + sty bitr + + ldy #0 ; always on page boundary + sty ZX0_dst + + sty offset + sty offset+1 + + ; Y needs to be 0 here + + ; Get initialization block +; ldy #7 + +;copy_init: lda zx0_ini_block-1, y + ; sta offset-1, y + ; dey + ; bne copy_init + +; Decode literal: Ccopy next N bytes from compressed file +; Elias(length) byte[1] byte[2] ... byte[N] +decode_literal: + jsr get_elias + +cop0: lda (ZX0_src), y + inc ZX0_src + bne plus1 + inc ZX0_src+1 +plus1: sta (ZX0_dst),y + inc ZX0_dst + bne plus2 + inc ZX0_dst+1 +plus2: dex + bne cop0 + + asl bitr + bcs dzx0s_new_offset + +; Copy from last offset (repeat N bytes from last offset) +; Elias(length) + jsr get_elias +dzx0s_copy: + lda ZX0_dst + sbc offset ; C=0 from get_elias + sta pntr + lda ZX0_dst+1 + sbc offset+1 + sta pntr+1 + +cop1: + lda (pntr), y + inc pntr + bne plus3 + inc pntr+1 +plus3: sta (ZX0_dst),y + inc ZX0_dst + bne plus4 + inc ZX0_dst+1 +plus4: dex + bne cop1 + + asl bitr + bcc decode_literal + +; Copy from new offset (repeat N bytes from new offset) +; Elias(MSB(offset)) LSB(offset) Elias(length-1) +dzx0s_new_offset: + ; Read elias code for high part of offset + jsr get_elias + beq exit ; Read a 0, signals the end + ; Decrease and divide by 2 + dex + txa + lsr ; @ + sta offset+1 + + ; Get low part of offset, a literal 7 bits + lda (ZX0_src), y + inc ZX0_src + bne plus5 + inc ZX0_src+1 +plus5: + ; Divide by 2 + ror ; @ + sta offset + + ; And get the copy length. + ; Start elias reading with the bit already in carry: + ldx #1 + jsr elias_skip1 + + inx + bcc dzx0s_copy + +; Read an elias-gamma interlaced code. +; ------------------------------------ +get_elias: + ; Initialize return value to #1 + ldx #1 + bne elias_start + +elias_get: ; Read next data bit to result + asl bitr + rol ; @ + tax + +elias_start: + ; Get one bit + asl bitr + bne elias_skip1 + + ; Read new bit from stream + lda (ZX0_src), y + inc ZX0_src + bne plus6 + inc ZX0_src+1 +plus6: ;sec ; not needed, C=1 guaranteed from last bit + rol ;@ + sta bitr + +elias_skip1: + txa + bcs elias_get + ; Got ending bit, stop reading +exit: + rts diff --git a/games/sb/rat_graphics/Makefile b/games/sb/rat_graphics/Makefile index 6b71962b..ab2e0774 100644 --- a/games/sb/rat_graphics/Makefile +++ b/games/sb/rat_graphics/Makefile @@ -96,5 +96,5 @@ a2_fortnight_rat2.hgr: a2_fortnight_rat2.png #### clean: - rm -f *~ *.o *.lst disk_sprintes.inc *.zx02 *.hgr + rm -f *~ *.o *.lst disk_sprites.inc *.zx02 *.hgr diff --git a/graphics/gr/bubble_universe/Makefile b/graphics/gr/bubble_universe/Makefile new file mode 100644 index 00000000..6b0ef91d --- /dev/null +++ b/graphics/gr/bubble_universe/Makefile @@ -0,0 +1,32 @@ +include ../../../Makefile.inc + +DOS33 = ../../../utils/dos33fs-utils/dos33 +TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft +LINKER_SCRIPTS = ../../../linker_scripts +EMPTY_DISK = ../../../empty_disk + +all: bubble_gr.dsk + +bubble_gr.dsk: HELLO BUBBLE_GR + cp $(EMPTY_DISK)/empty.dsk bubble_gr.dsk + $(DOS33) -y bubble_gr.dsk SAVE A HELLO + $(DOS33) -y bubble_gr.dsk BSAVE -a 0x2000 BUBBLE_GR + +### + +HELLO: hello.bas + $(TOKENIZE) < hello.bas > HELLO + +### + +BUBBLE_GR: bubble_gr.o + ld65 -o BUBBLE_GR bubble_gr.o -C $(LINKER_SCRIPTS)/apple2_2000.inc + +bubble_gr.o: bubble_gr.s + ca65 -o bubble_gr.o bubble_gr.s -l bubble_gr.lst + +### + +clean: + rm -f *~ *.o *.lst HELLO BUBBLE_GR + diff --git a/graphics/gr/bubble_universe/bubble_gr.s b/graphics/gr/bubble_universe/bubble_gr.s new file mode 100644 index 00000000..046a05c8 --- /dev/null +++ b/graphics/gr/bubble_universe/bubble_gr.s @@ -0,0 +1,304 @@ +; bubble universe -- Apple II Hires + +; size optimized version, using ROM (slower) + +; by Vince `deater` Weaver + +; this version based on fast c64 code by serato_fig +; as posted to the sizecoding discord +; based on his TIC-80 variant + +; originally was working off the BASIC code posted on the pouet forum +; original effect by yuruyrau on twitter + +; 534 bytes -- tiny version +; 250 bytes -- strip out fast clear and hplot code and use ROM + +; 76d03 cycles = 486659 cycles = 2fps + +; soft-switches + +KEYPRESS = $C000 +KEYRESET = $C010 +PAGE1 = $C054 +PAGE2 = $C055 + +; ROM routines + +BKGND0 = $F3F4 ; clear current page to A +HGR2 = $F3D8 ; set hires page2 and clear $4000-$5fff +HGR = $F3E2 ; set hires page1 and clear $2000-$3fff +HPLOT0 = $F457 ; plot at (Y,X), (A) +HCOLOR1 = $F6F0 ; set HGR_COLOR to value in X +;COLORTBL = $F6F6 +;WAIT = $FCA8 ; delay 1/2(26+27A+5A^2) us + +; zero page + +GBASL = $26 +GBASH = $27 + + +HPLOTYL = $92 + +I = $D0 +J = $D1 +T = $D7 +U = $D8 +V = $D9 + +HGR_PAGE = $E6 + +INL = $FC +INH = $FD +OUTL = $FE +OUTH = $FF + +; const + +;NUM = 32 +;NUM = 24 + +bubble: + + ;======================== + ; setup lookup tables + +; jsr hgr_make_tables + +; jsr hgr_clear_codegen + + jsr setup_sine_table + + ;======================= + ; init graphics + + jsr HGR + jsr HGR2 + + ;======================= + ; init variables + + ; HGR leaves A at 0 + +; lda #0 + sta U + sta V + sta T + + ldx #7 + jsr HCOLOR1 + + ;========================= + ;========================= + ; main loop + ;========================= + ;========================= + +next_frame: + + ; reset I*T + + lda T + sta it1_smc+1 + sta it2_smc+1 + + ; reset I*S + + lda #0 + sta is1_smc+1 + sta is2_smc+1 + +num1_smc: + lda #24 ; 40 + sta I + +i_loop: +num2_smc: + lda #24 ; 200 + + sta J +j_loop: + ldx U + ldy V + + + ; where S=41 (approximately 1/6.28) + + clc ; 2 + + + + ; calc: b=i+t+u; + ; u=cosines[a]+cosines[b]; +is2_smc: + lda cosines,Y ; 4+ +it2_smc: + adc cosines,X ; 4+ + sta V + + ; calc: a=i*s+v; + ; u=sines[a]+sines[b]; +is1_smc: + lda sines,Y ; 4+ +it1_smc: + adc sines,X ; 4+ + sta U ; 3 + + ;=========================================================== + ; HPLOT U+44,V+96 + ; U is centered at 96, to get to center of 280 screen add 44 + + ; U already in A + + adc #44 ; 2 + tax ; 2 + + ; calculate Ypos + lda V + +;HPLOT0 = $F457 ; plot at (Y,X), (A) + + ldy #0 + + jsr HPLOT0 + + + dec J + bne j_loop + +done_j: + + lda is1_smc+1 + clc + adc #41 ; 1/6.28 = 0.16 = 0 0 1 0 1 0 0 0 = 0x28 + sta is1_smc+1 + sta is2_smc+1 + dec I + bne i_loop +done_i: + +; sty V + inc T + +end: + +.if 0 + lda KEYPRESS + bpl flip_pages + bit KEYRESET + ; 0110 -> 0100 + and #$5f ; to handle lowercase too... + + cmp #'A' + bne check_z + inc num1_smc+1 + jmp done_keys +check_z: + cmp #'Z' + bne check_j + dec num1_smc+1 + jmp done_keys +check_j: + cmp #'J' + bne check_m + inc num2_smc+1 + jmp done_keys +check_m: + cmp #'M' + bne done_keys + dec num2_smc+1 +.endif +done_keys: + +flip_pages: + ; flip pages + + ; if $20 (draw PAGE1) draw PAGE2, SHOW page1 + ; if $40 (draw PAGE2) draw PAGE1, SHOW page2 + + lda HGR_PAGE + eor #$60 + sta HGR_PAGE + + cmp #$40 + bne flip2 +flip1: + bit PAGE1 + lda #0 + jsr BKGND0 +; jsr hgr_page2_clearscreen + jmp next_frame +flip2: + bit PAGE2 + lda #0 + jsr BKGND0 +; jsr hgr_page1_clearscreen + jmp next_frame + + +; floor(s*sin((x-96)*PI*2/256.0)+48.5); + +; note: min=7, around 32 +; max=89 ($59), around 160 +; subtract 7, so 0...82? halfway = 41 = $29 + 7 = $30 +; halfway= 6*16 = 96 + +sines = $6c00 +sines2 = $6d00 +cosines = $6e00 +cosines2= $6f00 + + ;=================================== + ; + ; + ; final_sine[i]=quarter_sine[i]; // 0..64 + ; final_sine[128-i]=quarter_sine[i]; // 64..128 + ; final_sine[128+i]=0x60-quarter_sine[i]; // 128..192 + ; final_sine[256-i]=0x60-quarter_sine[i]; // 192..256 + +setup_sine_table: + + ldy #64 + ldx #64 +setup_sine_loop: + + lda sines_base,Y + sta sines,Y + sta sines2,Y + sta sines,X + sta sines2,X + + lda #$60 + sec + sbc sines_base,Y + + sta sines+128,Y + sta sines2+128,Y + sta sines+128,X + sta sines2+128,X + + inx + dey + bpl setup_sine_loop + + + ldy #0 +cosine_loop: + lda sines+192,Y + sta cosines,Y + sta cosines2,Y + iny + bne cosine_loop + + rts + +sines_base: + .byte $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F + .byte $40,$41,$42,$42,$43,$44,$45,$46,$47,$48,$48,$49,$4A,$4B,$4C,$4C + .byte $4D,$4E,$4E,$4F,$50,$50,$51,$52,$52,$53,$53,$54,$54,$55,$55,$55 + .byte $56,$56,$57,$57,$57,$58,$58,$58,$58,$58,$59,$59,$59,$59,$59,$59 + .byte $59 + +; floor(s*cos((x-96)*PI*2/256.0)+48.5); + diff --git a/graphics/gr/bubble_universe/hello.bas b/graphics/gr/bubble_universe/hello.bas new file mode 100644 index 00000000..af786417 --- /dev/null +++ b/graphics/gr/bubble_universe/hello.bas @@ -0,0 +1,13 @@ +5 HOME +10 PRINT " BUBBLE GR" +15 PRINT " BY DEATER / FAST CODE BY SERATO_FIG" +20 PRINT +25 PRINT "THIS VERSION YOU CAN CHANGE" +27 PRINT "PARAMETERS ON THE FLY" +28 PRINT "+ TRY PRESSING A/Z TO INC/DEC I" +29 PRINT "+ TRY PRESSING J/M TO INC/DEC J" +30 PRINT:PRINT "PRESS ANY KEY TO START" +40 GET A$ +50 IF A$="Q" THEN END +60 PRINT:PRINT CHR$(4)"BRUN BUBBLE_GR" +