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 b34eb519..00000000 Binary files a/games/duke/empty.dsk and /dev/null differ diff --git a/games/keen/gr_copy.s b/games/keen/gr_copy.s new file mode 100644 index 00000000..a657400b --- /dev/null +++ b/games/keen/gr_copy.s @@ -0,0 +1,161 @@ + ;========================================================= + ; gr_copy_to_current, 40x48 version + ;========================================================= + ; copy 0xc00 to DRAW_PAGE + ; + ; 45 + 2 + 120*(8*9 + 5) -1 + 6 = 9292 +;.align $100 +gr_copy_to_current: + + lda DRAW_PAGE ; 3 + clc ; 2 + adc #$4 ; 2 + sta gr_copy_line+5 ; 4 + sta gr_copy_line+11 ; 4 + adc #$1 ; 2 + sta gr_copy_line+17 ; 4 + sta gr_copy_line+23 ; 4 + adc #$1 ; 2 + sta gr_copy_line+29 ; 4 + sta gr_copy_line+35 ; 4 + adc #$1 ; 2 + sta gr_copy_line+41 ; 4 + sta gr_copy_line+47 ; 4 + ;=========== + ; 45 + + ldy #119 ; for early ones, copy 120 bytes ; 2 + +gr_copy_line: + lda $C00,Y ; load a byte (self modified) ; 4 + sta $400,Y ; store a byte (self modified) ; 5 + + lda $C80,Y ; load a byte (self modified) ; 4 + sta $480,Y ; store a byte (self modified) ; 5 + + lda $D00,Y ; load a byte (self modified) ; 4 + sta $500,Y ; store a byte (self modified) ; 5 + + lda $D80,Y ; load a byte (self modified) ; 4 + sta $580,Y ; store a byte (self modified) ; 5 + + lda $E00,Y ; load a byte (self modified) ; 4 + sta $600,Y ; store a byte (self modified) ; 5 + + lda $E80,Y ; load a byte (self modified) ; 4 + sta $680,Y ; store a byte (self modified) ; 5 + + lda $F00,Y ; load a byte (self modified) ; 4 + sta $700,Y ; store a byte (self modified) ; 5 + + lda $F80,Y ; load a byte (self modified) ; 4 + sta $780,Y ; store a byte (self modified) ; 5 + + dey ; decrement pointer ; 2 + bpl gr_copy_line ; ; 2nt/3 + + rts ; 6 + + + + ;========================================================= + ; gr_copy_to_current, 40x48 version + ;========================================================= + ; copy 0x1000 to DRAW_PAGE + +gr_copy_to_current_1000: + + lda DRAW_PAGE ; 3 + clc ; 2 + adc #$4 ; 2 + sta gr_copy_line_40+5 ; 4 + sta gr_copy_line_40+11 ; 4 + adc #$1 ; 2 + sta gr_copy_line_40+17 ; 4 + sta gr_copy_line_40+23 ; 4 + adc #$1 ; 2 + sta gr_copy_line_40+29 ; 4 + sta gr_copy_line_40+35 ; 4 + adc #$1 ; 2 + sta gr_copy_line_40+41 ; 4 + sta gr_copy_line_40+47 ; 4 + ;=========== + ; 45 + + ldy #119 ; for early ones, copy 120 bytes ; 2 + +gr_copy_line_40: + lda $1000,Y ; load a byte (self modified) ; 4 + sta $400,Y ; store a byte (self modified) ; 5 + + lda $1080,Y ; load a byte (self modified) ; 4 + sta $480,Y ; store a byte (self modified) ; 5 + + lda $1100,Y ; load a byte (self modified) ; 4 + sta $500,Y ; store a byte (self modified) ; 5 + + lda $1180,Y ; load a byte (self modified) ; 4 + sta $580,Y ; store a byte (self modified) ; 5 + + lda $1200,Y ; load a byte (self modified) ; 4 + sta $600,Y ; store a byte (self modified) ; 5 + + lda $1280,Y ; load a byte (self modified) ; 4 + sta $680,Y ; store a byte (self modified) ; 5 + + lda $1300,Y ; load a byte (self modified) ; 4 + sta $700,Y ; store a byte (self modified) ; 5 + + lda $1380,Y ; load a byte (self modified) ; 4 + sta $780,Y ; store a byte (self modified) ; 5 + + dey ; decrement pointer ; 2 + bpl gr_copy_line_40 ; ; 2nt/3 + + rts ; 6 + + + + ;========================================================= + ; gr_copy_to_current_40x40 + ;========================================================= + ; Take image in 0xc00 + ; Copy to DRAW_PAGE + ; Actually copy lines 0..39 + ; Don't over-write bottom 4 lines of text +gr_copy_to_current_40x40: + + ldx #0 +gc_40x40_loop: + lda gr_offsets,x + sta OUTL + sta INL + lda gr_offsets+1,x + clc + adc DRAW_PAGE + sta OUTH + + lda gr_offsets+1,x + clc + adc #$8 + sta INH + + ldy #39 +gc_40x40_inner: + lda (INL),Y + sta (OUTL),Y + + dey + bpl gc_40x40_inner + + inx + inx + + cpx #40 + bne gc_40x40_loop + + rts ; 6 + + + + diff --git a/games/keen/gr_fast_clear.s b/games/keen/gr_fast_clear.s new file mode 100644 index 00000000..76035a21 --- /dev/null +++ b/games/keen/gr_fast_clear.s @@ -0,0 +1,201 @@ +;clear_screens: +; ;=================================== +; ; Clear top/bottom of page 0 +; ;=================================== +; +; lda #$0 +; sta DRAW_PAGE +; jsr clear_top +; jsr clear_bottom + +; ;=================================== +; ; Clear top/bottom of page 1 +; ;=================================== +; +; lda #$4 +; sta DRAW_PAGE +; jsr clear_top +; jsr clear_bottom +; +; rts + + + + + ;========================================================= + ; clear_top + ;========================================================= + ; clear DRAW_PAGE + ; original = 14,558 cycles(?) 15ms, 70Hz + ; OPTIMIZED MAX (page0,48rows): 45*120+4+6 = 5410 = 5.4ms 185Hz + ; (pageX,40rows): 50*120+4+6 = 6010 = 6.0ms 166Hz + ; 50*120+4+6+37 = 6055 = 6.0ms 166Hz +clear_top: + lda #0 ; 2 +clear_top_a: + sta COLOR ; 3 + clc ; 2 + lda DRAW_PAGE ; 3 + + adc #4 ; 2 + sta __ctf+2 ; 3 + sta __ctf+5 ; 3 + adc #1 ; 2 + sta __ctf+8 ; 3 + sta __ctf+11 ; 3 + adc #1 ; 2 + sta __ctf2+2 ; 3 + sta __ctf2+5 ; 3 + adc #1 ; 2 + sta __ctf2+8 ; 3 + sta __ctf2+11 ; 3 + + + ldy #120 ; 2 + lda COLOR ; 3 +clear_top_fast_loop: +__ctf: + sta $400,Y ; 5 + sta $480,Y ; 5 + sta $500,Y ; 5 + sta $580,Y ; 5 + + cpy #80 ; 2 + bpl no_draw_bottom ; 2nt/3 +__ctf2: + sta $600,Y ; 5 + sta $680,Y ; 5 + sta $700,Y ; 5 + sta $780,Y ; 5 +no_draw_bottom: + + dey ; 2 + bpl clear_top_fast_loop ; 2nt/3 + + rts ; 6 + + + + + ;========================================================= + ; clear_bottom + ;========================================================= + ; clear bottom of draw page + +clear_bottom: + clc ; 2 + lda DRAW_PAGE ; 3 + + adc #6 ; 2 + sta __cbf2+2 ; 3 + sta __cbf2+5 ; 3 + adc #1 ; 2 + sta __cbf2+8 ; 3 + sta __cbf2+11 ; 3 + + + ldy #120 ; 2 + lda #$a0 ; Normal Space ; 2 +clear_bottom_fast_loop: +__cbf2: + sta $600,Y ; 5 + sta $680,Y ; 5 + sta $700,Y ; 5 + sta $780,Y ; 5 + + dey ; 2 + cpy #80 ; 2 + bpl clear_bottom_fast_loop ; 2nt/3 + + rts ; 6 + + +;clear_screens_notext: + ;=================================== + ; Clear top/bottom of page 0 + ;=================================== + +; lda #$0 +; sta DRAW_PAGE +; jsr clear_all + + ;=================================== + ; Clear top/bottom of page 1 + ;=================================== + +; lda #$4 +; sta DRAW_PAGE +; jsr clear_all + +; rts + + +clear_bottoms: + + lda DRAW_PAGE + pha + + ;=================================== + ; Clear bottom of page 0 + ;=================================== + + lda #$0 + sta DRAW_PAGE + jsr clear_bottom + + ;=================================== + ; Clear bottom of page 1 + ;=================================== + + lda #$4 + sta DRAW_PAGE + jsr clear_bottom + + pla + sta DRAW_PAGE + + rts + + + ;========================================================= + ; clear_all + ;========================================================= + ; clear 48 rows + +clear_all: + clc ; 2 + lda DRAW_PAGE ; 3 + + adc #4 ; 2 + sta __caf+2 ; 3 + sta __caf+5 ; 3 + adc #1 ; 2 + sta __caf+8 ; 3 + sta __caf+11 ; 3 + adc #1 ; 2 + sta __caf2+2 ; 3 + sta __caf2+5 ; 3 + adc #1 ; 2 + sta __caf2+8 ; 3 + sta __caf2+11 ; 3 + + + ldy #120 ; 2 +clear_all_color: + lda #' '|$80 ; 2 +clear_all_fast_loop: +__caf: + sta $400,Y ; 5 + sta $480,Y ; 5 + sta $500,Y ; 5 + sta $580,Y ; 5 +__caf2: + sta $600,Y ; 5 + sta $680,Y ; 5 + sta $700,Y ; 5 + sta $780,Y ; 5 + + dey ; 2 + bpl clear_all_fast_loop ; 2nt/3 + + rts ; 6 diff --git a/games/keen/graphics/Makefile b/games/keen/graphics/Makefile new file mode 100644 index 00000000..8edb44e5 --- /dev/null +++ b/games/keen/graphics/Makefile @@ -0,0 +1,32 @@ +include ../../../Makefile.inc + +ZX02 = ~/research/6502_compression/zx02.git/build/zx02 -f +PNG_TO_HGR = ../../../utils/hgr-utils/png2hgr +LINKER_SCRIPTS = ../../../linker_scripts +DOS33 = ../../../utils/dos33fs-utils/dos33 +EMPTY_DISK = ../../../empty_disk/empty.dsk +TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft +PNG2GR = ../../../utils/gr-utils/png2gr +PNG2SPRITES = ../../../utils/gr-utils/png2sprites +HGR_SPRITE = ../../../utils/hgr-utils/hgr_make_sprite + +all: keen1_title.hgr.zx02 + +#### + +#disk_sprites.inc: a2_fortnight_sprites.png +# $(HGR_SPRITE) -s -l disk_sprite0 a2_fortnight_sprites.png 14 7 41 34 > 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 00000000..b90b079e Binary files /dev/null and b/games/keen/graphics/keen1_title.png differ 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" +