diff --git a/games/sb/Makefile b/games/sb/Makefile index ea4e5664..91121910 100644 --- a/games/sb/Makefile +++ b/games/sb/Makefile @@ -34,11 +34,13 @@ sb.o: sb.s zx02_optim.s \ FN: fn.o ld65 -o FN fn.o -C $(LINKER_SCRIPTS)/apple2_6000.inc -fn.o: fn.s zx02_optim.s \ +fn.o: fn.s zx02_optim.s duet.s hgr_sprite_mask.s hgr_tables.s \ zp.inc hardware.inc \ + fn_sound/fortnight.ed \ fn_graphics/a2_fortnight.hgr.zx02 \ fn_graphics/a2_fortnight_rat1.hgr.zx02 \ - fn_graphics/a2_fortnight_rat2.hgr.zx02 + fn_graphics/a2_fortnight_rat2.hgr.zx02 \ + fn_graphics/disk_sprites.inc ca65 -o fn.o fn.s -l fn.lst diff --git a/games/sb/duet.s b/games/sb/duet.s index af7e745d..982c63c6 100644 --- a/games/sb/duet.s +++ b/games/sb/duet.s @@ -1,3 +1,5 @@ +; hacked up to switch pages + ; *************************************************************************** ; * Copyright (C) 1979-2015 by Paul Lutus * ; * http://arachnoid.com/administration * @@ -33,9 +35,11 @@ MADDRL = $1E MADDRH = $1F LOC4E = $4E COUNT256 = $4F +WHICH_PAGE = $50 play_ed: LDA #$01 ; 900: A9 01 ; 2 *!* + sta WHICH_PAGE STA INSTRUMENT1 ; 902: 85 09 ; 3 set default STA INSTRUMENT2 ; 904: 85 1D ; 3 instruments PHA ; 906: 48 ; 3 1 on stack @@ -44,13 +48,24 @@ play_ed: BNE load_triplet ; 909: D0 15 ; 4 *!* start decoding change_instrmnt: + INY ; 90B: C8 ; 2 LDA (MADDRL),Y ; 90C: B1 1E ; 5 *!* load next byte + bmi switch_page STA INSTRUMENT1 ; 90E: 85 09 ; 3 save instrument INY ; 910: C8 ; 2 LDA (MADDRL),Y ; 911: B1 1E ; 5 *!* load next byte STA INSTRUMENT2 ; 913: 85 1D ; 3 save instrument + jmp triplet_loop +switch_page: + lda WHICH_PAGE + eor #$1 + sta WHICH_PAGE + tax + lda PAGE1,X + + triplet_loop: LDA MADDRL ; 915: A5 1E ; 3 *!* increment pointer CLC ; 917: 18 ; 2 by three @@ -130,8 +145,10 @@ label7: BIT $C030 ; 96C: 2C 30C0 ; 4 SPEAKER label9: STA LOC4E ; 96F: 85 4E ; 3 + BIT $C000 ; 971: 2C 00C0 ; 4 KEYBOARD DATA BMI exit_player ; 974: 30 C0 ; 4 *!* if keypress, exit + DEY ; 976: 88 ; 2 BNE selfmodify2 ; 977: D0 02 ; 4 *!* BEQ label11 ; 979: F0 06 ; 4 *!* diff --git a/games/sb/fn.s b/games/sb/fn.s index 271fd42e..16767d68 100644 --- a/games/sb/fn.s +++ b/games/sb/fn.s @@ -10,6 +10,11 @@ fortnight_start: + lda #$20 + sta HGR_PAGE + + jsr hgr_make_tables + ;=================== ; set graphics mode ;=================== @@ -37,6 +42,23 @@ floppy_animation: jsr full_decomp + + lda #10 + sta CURSOR_X + lda #10 + sta CURSOR_Y + lda #disk_sprite0 + sta INH + lda #disk_mask0 + sta MASKH + + jsr hgr_draw_sprite + + jsr wait_until_keypress @@ -60,15 +82,30 @@ load_rats: jsr full_decomp + ;============================= + ; play music and animate rat + ;============================= +play_music: + lda #music + sta MADDRH + + jsr play_ed + rat_loop: - bit PAGE1 - jsr wait_until_keypress - bit PAGE2 +; bit PAGE1 +; jsr wait_until_keypress + + + +; bit PAGE2 jsr wait_until_keypress - jmp rat_loop +; jmp rat_loop + jmp fortnight_start wait_until_keypress: @@ -79,6 +116,14 @@ wait_until_keypress: .include "zx02_optim.s" + .include "hgr_sprite_mask.s" + .include "hgr_tables.s" + +.align $100 + .include "duet.s" + +music: + .incbin "fn_sound/fortnight.ed" fn_image: .incbin "fn_graphics/a2_fortnight.hgr.zx02" @@ -87,3 +132,4 @@ rat1_image: rat2_image: .incbin "fn_graphics/a2_fortnight_rat2.hgr.zx02" + .include "fn_graphics/disk_sprites.inc" diff --git a/games/sb/fn_graphics/Makefile b/games/sb/fn_graphics/Makefile index ecac474a..a0e058f8 100644 --- a/games/sb/fn_graphics/Makefile +++ b/games/sb/fn_graphics/Makefile @@ -8,10 +8,35 @@ 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: a2_fortnight.hgr.zx02 \ a2_fortnight_rat1.hgr.zx02 \ - a2_fortnight_rat2.hgr.zx02 + a2_fortnight_rat2.hgr.zx02 \ + disk_sprites.inc + + +#### + +disk_sprites.inc: a2_fortnight_sprites.png + $(HGR_SPRITE) -s -l disk_sprite0 a2_fortnight_sprites.png 14 7 41 34 > disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite1 a2_fortnight_sprites.png 14 42 41 69 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite2 a2_fortnight_sprites.png 14 77 41 104 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite3 a2_fortnight_sprites.png 14 112 41 139 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask0 a2_fortnight_sprites.png 56 7 83 34 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask1 a2_fortnight_sprites.png 56 42 83 69 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask2 a2_fortnight_sprites.png 56 77 83 104 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask3 a2_fortnight_sprites.png 56 112 83 139 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite4 a2_fortnight_sprites.png 98 7 125 34 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite5 a2_fortnight_sprites.png 98 42 125 69 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite6 a2_fortnight_sprites.png 98 77 125 104 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_sprite7 a2_fortnight_sprites.png 98 112 125 139 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask4 a2_fortnight_sprites.png 140 7 167 34 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask5 a2_fortnight_sprites.png 140 42 167 69 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask6 a2_fortnight_sprites.png 140 77 167 104 >> disk_sprites.inc + $(HGR_SPRITE) -s -l disk_mask7 a2_fortnight_sprites.png 140 112 167 139 >> disk_sprites.inc + + #### @@ -42,5 +67,5 @@ a2_fortnight_rat2.hgr: a2_fortnight_rat2.png #### clean: - rm -f *~ *.o *.lst + rm -f *~ *.o *.lst disk_sprintes.inc *.zx02 *.hgr diff --git a/games/sb/fn_graphics/a2_fortnight.png b/games/sb/fn_graphics/a2_fortnight.png index 1902b038..f7f840e9 100644 Binary files a/games/sb/fn_graphics/a2_fortnight.png and b/games/sb/fn_graphics/a2_fortnight.png differ diff --git a/games/sb/fn_graphics/a2_fortnight_sprites.png b/games/sb/fn_graphics/a2_fortnight_sprites.png new file mode 100644 index 00000000..0130ae98 Binary files /dev/null and b/games/sb/fn_graphics/a2_fortnight_sprites.png differ diff --git a/games/sb/hgr_sprite_mask.s b/games/sb/hgr_sprite_mask.s new file mode 100644 index 00000000..d3004946 --- /dev/null +++ b/games/sb/hgr_sprite_mask.s @@ -0,0 +1,86 @@ + ;=========================================== + ; hgr draw sprite (only at 7-bit boundaries) + ;=========================================== + ; SPRITE in INL/INH + ; Location at CURSOR_X CURSOR_Y + + ; xsize, ysize in first two bytes + + ; sprite AT INL/INH + +hgr_draw_sprite: + + ldy #0 + lda (INL),Y ; load xsize + clc + adc CURSOR_X + sta sprite_width_end_smc+1 ; self modify for end of line + + iny ; load ysize + lda (INL),Y + sta sprite_ysize_smc+1 ; self modify + + ; skip the xsize/ysize and point to sprite + clc + lda INL ; 16-bit add + adc #2 + sta sprite_smc1+1 + lda INH + adc #0 + sta sprite_smc1+2 + + ldx #0 ; X is pointer offset + + stx MASK ; actual row + +hgr_sprite_yloop: + + lda MASK ; row + + clc + adc CURSOR_Y ; add in cursor_y + + ; calc GBASL/GBASH + + tay ; get output ROW into GBASL/H + lda hposn_low,Y + sta GBASL + lda hposn_high,Y + + ; eor #$00 draws on page2 + ; eor #$60 draws on page1 +hgr_sprite_page_smc: + eor #$00 + sta GBASH + + ldy CURSOR_X + +sprite_inner_loop: + +sprite_smc1: + lda $d000 ; get sprite pattern + sta (GBASL),Y ; store out + + inx + iny + + + inc sprite_smc1+1 + bne sprite_noflo + inc sprite_smc1+2 +sprite_noflo: + +sprite_width_end_smc: + cpy #6 + bne sprite_inner_loop + + + inc MASK ; row + lda MASK ; row + +sprite_ysize_smc: + cmp #31 + bne hgr_sprite_yloop + + rts + diff --git a/games/sb/hgr_tables.s b/games/sb/hgr_tables.s new file mode 100644 index 00000000..7de885dc --- /dev/null +++ b/games/sb/hgr_tables.s @@ -0,0 +1,141 @@ +div7_table = $1000 +mod7_table = $1100 +hposn_high = $1200 +hposn_low = $1300 + + + + ;===================== + ; make /7 %7 tables + ;===================== + +hgr_make_tables: + + ldy #0 + lda #0 + ldx #0 +div7_loop: + sta div7_table,Y + + inx + cpx #7 + bne div7_not7 + + clc + adc #1 + ldx #0 +div7_not7: + iny + bne div7_loop + + + ldy #0 + lda #0 +mod7_loop: + sta mod7_table,Y + clc + adc #1 + cmp #7 + bne mod7_not7 + lda #0 +mod7_not7: + iny + bne mod7_loop + + + ; Hposn table + + lda #0 +hposn_loop: + ldy #0 + ldx #0 + pha + jsr hposn ; (Y,X),(A) + pla + tax + + lda GBASL + sta hposn_low,X + + lda GBASH + sta hposn_high,X + + inx + txa + + cmp #192 + bne hposn_loop + + rts + + ; left masks + ; in memory on screen + ; x111 1111 1111111 start at 0 + ; x111 1110 0111111 start at 1 + ; x111 1100 0011111 start at 2 + ; ... + ; x100 0000 0000001 start at 6 + +left_masks: + .byte $FF,$FE,$FC,$F8, $F0,$E0,$C0 + + ; right masks + ; in memory on screen + ; x000 0001 1000000 end at 0 + ; x000 0011 1100000 end at 1 + ; x000 0111 1110000 end at 2 + ; ... + ; x011 1111 1111110 end at 5 + ; x111 1111 1111111 end at 6 +right_masks: + .byte $81,$83,$87, $8F,$9F,$BF,$FF + + + + + ; from the Apple II firmware +hposn: +; sta HGR_Y ; save Y and X positions +; stx HGR_X +; sty HGR_X+1 + + pha ; Y pos on stack + + and #$C0 ; calc base addr for Y-pos + + sta GBASL + lsr + lsr + ora GBASL + sta GBASL + pla + + sta GBASH + asl + asl + asl + rol GBASH + asl + rol GBASH + asl + ror GBASL + lda GBASH + + and #$1F + + ora HGR_PAGE ; default is $40 in this game + sta GBASH + +; txa +; cpy #0 +; beq xpos_lessthan_256 +; ldy #35 +; adc #4 +;label_1: +; iny +;xpos_lessthan_256: +; sbc #7 +; bcs label_1 + + rts + diff --git a/games/sb/title.s b/games/sb/title.s index 3610da80..99d27777 100644 --- a/games/sb/title.s +++ b/games/sb/title.s @@ -66,4 +66,4 @@ which_ok: comp_data: - .incbin "graphics/strongbad_sample.hgr.zx02" + .incbin "graphics/czmg4ap_title.hgr.zx02" diff --git a/games/sb/zp.inc b/games/sb/zp.inc index 25ea1e12..d063da7a 100644 --- a/games/sb/zp.inc +++ b/games/sb/zp.inc @@ -161,6 +161,9 @@ DRAW_PAGE = $EF XPOS = $F0 YPOS = $F1 XMAX = $F2 +CURSOR_X = $F3 +CURSOR_Y = $F4 +HGR_PAGE = $F5 TEMP = $F8 TEMPY = $F9 diff --git a/music/electric_duet/Makefile b/music/electric_duet/Makefile index ae33a242..6a8d3055 100644 --- a/music/electric_duet/Makefile +++ b/music/electric_duet/Makefile @@ -2,7 +2,7 @@ include ../../Makefile.inc TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft DOS33 = ../../utils/dos33fs-utils/dos33 -TEXT_TO_ED = ./text_to_ed +TEXT_TO_ED = ../../utils/music/text_to_ed EMPTY_DISK = ../../empty_disk/empty.dsk all: eduet.dsk @@ -81,17 +81,6 @@ korobeiniki.ed: $(TEXT_TO_ED) korobeiniki.txt ### -text_to_ed: text_to_ed.o notes.o - $(CC) -o text_to_ed text_to_ed.o notes.o $(LFLAGS) -lm - -text_to_ed.o: text_to_ed.c notes.h - $(CC) $(CFLAGS) -c text_to_ed.c - -notes.o: notes.c notes.h - $(CC) $(CFLAGS) -c notes.c - -### - clean: - rm -f *~ *.o *.lst ED text_to_ed + rm -f *~ *.o *.lst ED diff --git a/utils/music/text_to_ed.c b/utils/music/text_to_ed.c index e4249ac6..08957a57 100644 --- a/utils/music/text_to_ed.c +++ b/utils/music/text_to_ed.c @@ -26,6 +26,7 @@ /* byte1 = voice1 instrument */ /* byte2 = voice2 instrument */ /* Varies, bigger than 8 seem to make no difference */ +/* custom hack, negative means do action */ /* Otherwise, byte0 = duration (20=quarter, 40=half) */ /* byte1 = voice1 note */ @@ -101,7 +102,6 @@ static int get_note(char *string, int sp, struct note_type *n, int line) { int freq; int ch; -// fprintf(stderr,"VMW: Entering, sp=%d\n",sp); /* Skip white space */ while((string[sp]==' ' || string[sp]=='\t')) sp++; @@ -111,8 +111,6 @@ static int get_note(char *string, int sp, struct note_type *n, int line) { /* return early if no change */ ch=string[sp]; -// fprintf(stderr,"VMW: %d %d\n",ch,sp); - if (ch=='-') { if (header_version==0) return sp+6; else { @@ -198,6 +196,12 @@ static int get_string(char *string, char *key, char *output, int strip_linefeed) } +static void update_voice(FILE *ed_file,int voice1,int voice2) { + + fprintf(ed_file,"%c%c%c",1,voice1,voice2); + +} + static void print_help(int just_version, char *exec_name) { printf("\ntext_to_ed version %s by Vince Weaver \n\n",VERSION); @@ -206,13 +210,14 @@ static void print_help(int just_version, char *exec_name) { printf("This created Electric Duet files\n\n"); printf("Usage:\n"); - printf("\t%s [-h] [-v] [-d] [-o X] [-i X] textfile outbase\n\n", + printf("\t%s [-h] [-v] [-d] [-o X] [-i X] [-l] textfile outbase\n\n", exec_name); printf("\t-h: this help message\n"); printf("\t-v: version info\n"); printf("\t-d: print debug messages\n"); printf("\t-o: Offset octave by X\n"); printf("\t-i: set second instrument to X\n"); + printf("\t-l: generate lyrics file\n"); exit(0); } @@ -224,15 +229,17 @@ int main(int argc, char **argv) { char *result; char ed_filename[BUFSIZ],lyrics_filename[BUFSIZ],*in_filename; char temp[BUFSIZ]; - FILE *ed_file,*lyrics_file,*in_file=NULL; + FILE *ed_file,*lyrics_file=NULL,*in_file=NULL; //int attributes=0; int loop=0,i; int sp,external_frequency,irq; struct note_type a,b,c; int copt; + int generate_lyrics=0; // Instruments 0=square int voice1=0,voice2=0; + int newvoice1,newvoice2; char song_name[BUFSIZ]; char author_name[BUFSIZ]; @@ -265,6 +272,10 @@ int main(int argc, char **argv) { /* instrument to use */ voice1=atoi(optarg); break; + case 'l': + /* generate lyrics */ + generate_lyrics=1; + break; default: print_help(0,argv[0]); break; @@ -303,13 +314,14 @@ int main(int argc, char **argv) { return -1; } - lyrics_file=fopen(lyrics_filename,"w"); - if (lyrics_file==NULL) { - fprintf(stderr,"Couldn't open %s\n",lyrics_filename); - return -1; + if (generate_lyrics) { + lyrics_file=fopen(lyrics_filename,"w"); + if (lyrics_file==NULL) { + fprintf(stderr,"Couldn't open %s\n",lyrics_filename); + return -1; + } } - /* Get the info for the header */ while(1) { @@ -392,7 +404,7 @@ int main(int argc, char **argv) { int frame=0,lyric=0; int lyric_line=1; - fprintf(ed_file,"%c%c%c",1,voice1,voice2); + update_voice(ed_file,voice1,voice2); offset+=3; while(1) { @@ -410,6 +422,38 @@ int main(int argc, char **argv) { if (string[0]=='-') continue; if (string[0]=='*') continue; + if (string[0]=='@') { + sscanf(string,"@%d %d",&newvoice1,&newvoice2); + /* special case */ + if (newvoice1>128) { + update_voice(ed_file,0xff,0xff); + } + else { + voice1=newvoice1; + voice2=newvoice2; + update_voice(ed_file,voice1,voice2); + } + + offset+=3; + + + /* Avoid changing instrument by accident */ + /* Also keep lyrics in sync */ + if (same_count<2) { + same_count=2; + } + + fprintf(ed_file,"%c%c%c",same_count,a_last,b_last); + offset+=3; + if (debug) { + printf("%04X: %x %x %x\n",offset,same_count,a_last,b_last); + } + same_count=0; + + + continue; + } + sp=0; /* Skip line number */ @@ -420,60 +464,59 @@ int main(int argc, char **argv) { if (sp!=-1) sp=get_note(string,sp,&c,line); /* handle lyrics */ - if ((sp!=-1) && (string[sp]!='\n') && (string[sp]!=0)) { - fprintf(lyrics_file,"; %d: %s",frame,&string[sp]); - while((string[sp]==' ' || string[sp]=='\t')) sp++; - if (string[sp]!='\n') { - fprintf(lyrics_file,".byte\t$%02X",lyric_line&0xff); + if (generate_lyrics) { + if ((sp!=-1) && (string[sp]!='\n') && (string[sp]!=0)) { + fprintf(lyrics_file,"; %d: %s",frame,&string[sp]); + while((string[sp]==' ' || string[sp]=='\t')) sp++; + if (string[sp]!='\n') { + fprintf(lyrics_file,".byte\t$%02X",lyric_line&0xff); - /* get to first quote */ - while(string[sp]!='\"') sp++; - sp++; - - /* stop at second quote */ - while(string[sp]!='\"') { - if (string[sp]=='\\') { - sp++; - /* Ignore if we have LED panel */ - if (string[sp]=='i') { - //printf(",$%02X",10); - } - /* form feed */ - else if (string[sp]=='f') { - fprintf(lyrics_file,",$%02X",12); - } - /* Vertical tab */ - else if (string[sp]=='v') { - fprintf(lyrics_file,",$%02X",11); - } - else if (string[sp]=='n') { - fprintf(lyrics_file,",$%02X",13|0x80); - } - else if ((string[sp]>='0') && - (string[sp]<=':')) { - fprintf(lyrics_file,",$%02X",string[sp]-'0'); - } - else { - printf("UNKNOWN ESCAPE %d\n",string[sp]); - } + /* get to first quote */ + while(string[sp]!='\"') sp++; + sp++; + + /* stop at second quote */ + while(string[sp]!='\"') { + if (string[sp]=='\\') { + sp++; + /* Ignore if we have LED panel */ + if (string[sp]=='i') { + //printf(",$%02X",10); + } + /* form feed */ + else if (string[sp]=='f') { + fprintf(lyrics_file,",$%02X",12); + } + /* Vertical tab */ + else if (string[sp]=='v') { + fprintf(lyrics_file,",$%02X",11); + } + else if (string[sp]=='n') { + fprintf(lyrics_file,",$%02X",13|0x80); + } + else if ((string[sp]>='0') && + (string[sp]<=':')) { + fprintf(lyrics_file,",$%02X",string[sp]-'0'); + } + else { + printf("UNKNOWN ESCAPE %d\n",string[sp]); + } + sp++; + continue; + } + fprintf(lyrics_file,",$%02X",string[sp]|0x80); sp++; - continue; } - fprintf(lyrics_file,",$%02X",string[sp]|0x80); - sp++; + fprintf(lyrics_file,",$00\n"); + +// fprintf(lyrics_file," %s",&string[sp]); +// printf("%s",&string[sp]); + } + lyric=1; + } - fprintf(lyrics_file,",$00\n"); - - - -// fprintf(lyrics_file," %s",&string[sp]); -// printf("%s",&string[sp]); - } - lyric=1; - } - if ((a.ed_freq!=0)||(b.ed_freq!=0)) { if (debug) { printf("%d: ",frame); @@ -564,7 +607,10 @@ int main(int argc, char **argv) { fprintf(ed_file,"%c%c%c",0,0,0); // EOF? fclose(ed_file); - fclose(lyrics_file); + + if (generate_lyrics) { + fclose(lyrics_file); + } (void) irq; (void) loop;