diff --git a/gr-sim/gr-sim.c b/gr-sim/gr-sim.c index 3b1798ee..7b0d9a61 100644 --- a/gr-sim/gr-sim.c +++ b/gr-sim/gr-sim.c @@ -886,7 +886,7 @@ int gr_copy_to_current(short source) { for(i=0;i<8;i++) { source_addr=gr_addr_lookup[i]+(source-0x400); - dest_addr=gr_addr_lookup[i]+(0x400*ram[DRAW_PAGE]); + dest_addr=gr_addr_lookup[i]+(ram[DRAW_PAGE]<<8); if (i<4) l=120; else l=80; @@ -1207,8 +1207,7 @@ void basic_normal(void) { static unsigned short hlin_addr; static unsigned short hlin_hi; -static unsigned short vlin_addr; -static unsigned short vlin_hi; + int hlin_continue(int width) { @@ -1243,28 +1242,44 @@ int hlin(int page, int x1, int x2, int at) { return 0; } -int vlin(int page, int y1, int y2, int at) { +static unsigned short vlin_hi; - int i; +/* TODO: optimize */ +/* Could make twice as fast if draw neighboring two in one write */ +/* instead of two */ - for(i=y1;i>8)&0xff; + + ram[OUTH]+=ram[DRAW_PAGE]; + + vlin_hi=x&1; + + y=ram[TEMPY]; // y=at; if (vlin_hi) { - ram[vlin_addr]=ram[vlin_addr]&0x0f; - ram[vlin_addr]|=ram[COLOR]&0xf0; + ram[y_indirect(OUTL,y)]=ram[y_indirect(OUTL,y)]&0x0f; + ram[y_indirect(OUTL,y)]|=ram[COLOR]&0xf0; } else { - ram[vlin_addr]=ram[vlin_addr]&0xf0; - ram[vlin_addr]|=ram[COLOR]&0x0f; + ram[y_indirect(OUTL,y)]=ram[y_indirect(OUTL,y)]&0xf0; + ram[y_indirect(OUTL,y)]|=ram[COLOR]&0x0f; } - } + x++; + if (x>8; diff --git a/gr-sim/gr-sim.h b/gr-sim/gr-sim.h index a3b8b13d..8b59e0a2 100644 --- a/gr-sim/gr-sim.h +++ b/gr-sim/gr-sim.h @@ -28,7 +28,7 @@ int hlin_double_continue(int width); int hlin_double(int page, int x1, int x2, int at); void soft_switch(unsigned short address); int soft_switch_read(unsigned short address); -int vlin(int page, int y1, int y2, int at); +int vlin(int y1, int y2, int at); int collision(int xx, int yy, int ground_color); void clear_top(int page); void clear_bottom(int page); diff --git a/gr-sim/tfv_opener.c b/gr-sim/tfv_opener.c index c0fe0b90..be0797b6 100644 --- a/gr-sim/tfv_opener.c +++ b/gr-sim/tfv_opener.c @@ -14,10 +14,10 @@ static void draw_segment(void) { ram[YY]=ram[YY]+ram[YADD]; if (ram[XX]==ram[MATCH]) color_equals(ram[COLOR1]*3); else color_equals(ram[COLOR1]); - vlin(ram[DRAW_PAGE],10,ram[YY],9+ram[XX]); + vlin(10,ram[YY],9+ram[XX]); if (ram[XX]==ram[MATCH]) color_equals(ram[COLOR2]*3); else color_equals(ram[COLOR2]); - if (ram[YY]!=34) vlin(ram[DRAW_PAGE],ram[YY],34,9+ram[XX]); + if (ram[YY]!=34) vlin(ram[YY],34,9+ram[XX]); ram[XX]++; } ram[YADD]=-ram[YADD]; diff --git a/gr-sim/tfv_utils.c b/gr-sim/tfv_utils.c index 07c41967..ec73e2fa 100644 --- a/gr-sim/tfv_utils.c +++ b/gr-sim/tfv_utils.c @@ -92,12 +92,12 @@ void page_flip(void) { if (ram[DISP_PAGE]==0) { soft_switch(HISCR); ram[DISP_PAGE]=1; - ram[DRAW_PAGE]=0; + ram[DRAW_PAGE]=0x0; } else { soft_switch(LOWSCR); ram[DISP_PAGE]=0; - ram[DRAW_PAGE]=1; + ram[DRAW_PAGE]=0x4; } grsim_update(); diff --git a/gr-sim/tfv_zp.h b/gr-sim/tfv_zp.h index 88f028e7..6e8d7a60 100644 --- a/gr-sim/tfv_zp.h +++ b/gr-sim/tfv_zp.h @@ -11,6 +11,9 @@ #define MEMPTRH 0x08 #define DISP_PAGE 0x09 #define DRAW_PAGE 0x0a +#define TEMPY 0xfb +#define OUTL 0xfe +#define OUTH 0xff /* stats */ extern unsigned char level; diff --git a/tfv/Makefile b/tfv/Makefile index 283f416b..c7911a77 100644 --- a/tfv/Makefile +++ b/tfv/Makefile @@ -48,7 +48,7 @@ backgrounds.inc: $(PNG2RLE) \ TFV: tfv.o ld65 -o TFV tfv.o -C ./apple2_1000.inc -tfv.o: tfv.s backgrounds.inc +tfv.o: tfv.s opener.s utils.s backgrounds.inc zp.inc ca65 -o tfv.o tfv.s -l tfv.lst diff --git a/tfv/opener.s b/tfv/opener.s new file mode 100644 index 00000000..8955ee33 --- /dev/null +++ b/tfv/opener.s @@ -0,0 +1,155 @@ + ;============================= + ; show VMW splash screen + ;============================= +opening: + lda #100 + sta MATCH + jsr draw_logo + jsr page_flip + + ; Draw the shining band + + lda #0 + sta MATCH +shine_loop: + + jsr draw_logo + jsr page_flip + + inc MATCH + lda MATCH + cmp #30 + bne shine_loop + + lda #8 + sta CH ; HTAB 9 + + lda #20 + jsr TABV ; VTAB 21 + + + lda #>(vmwsw_string) + sta OUTH + lda #<(vmwsw_string) + sta OUTL + + jsr print_string ; print("A VMW SOFTWARE PRODUCTION"); + + + jsr wait_until_keypressed + + + ;================= + ; display part of logo + ;================= + ; +draw_segment: + lda #0 + sta LOOP + +segment_loop: + lda YADD + clc + adc YY + sta YY ; yy=yy+yadd + + lda COLOR1 + sta COLOR ; color=COLOR1 + + lda MATCH ; if (ram[XX]==ram[MATCH]) + cmp XX + bne nocolmatch1 + + lda COLOR ; color_equals(ram[COLOR1]*3); + clc + adc COLOR1 + adc COLOR1 + sta COLOR + +nocolmatch1: + lda YY + sta V2 + lda XX + clc + adc #9 + tay + lda #10 + tax + + jsr vlin ; X,V2 at Y vlin(10,ram[YY],9+ram[XX]); + + lda COLOR2 + sta COLOR ; color=COLOR2 + + lda MATCH ; if (ram[XX]==ram[MATCH]) + cmp XX + bne nocolmatch2 + + lda COLOR ; color_equals(ram[COLOR2]*3); + clc + adc COLOR2 + adc COLOR2 + sta COLOR + +nocolmatch2: + lda #34 + sta V2 + lda XX + clc + adc #9 + tay + lda YY + tax + cmp #34 + beq skip_bottom ; if (ram[YY]==34) skip + jsr vlin ; X,V2 at Y vlin(ram[YY],34,9+ram[XX]); + +skip_bottom: + + + inc XX ; ram[XX]++; + + inc LOOP + lda LOOP + cmp #4 + bne segment_loop + + lda YADD ; ram[YADD]=-ram[YADD]; + eor #$ff + clc + adc #1 + sta YADD + + rts + + ;================= + ; display VMW logo + ;================= + ; +draw_logo: + lda #0 + sta XX ; start of logo + lda #10 + sta YY ; draw at Y=10 + lda #6 + sta YADD ; step of 6 + + lda #$00 + sta COLOR2 + lda #$11 + sta COLOR1 ; first colors are red/black + jsr draw_segment + lda #$44 + sta COLOR2 ; now red/green + jsr draw_segment + lda #$22 + sta COLOR1 ; now green/blue + jsr draw_segment + jsr draw_segment + jsr draw_segment + lda #$00 + sta COLOR2 ; now blue/black + jsr draw_segment + + rts + diff --git a/tfv/tfv.s b/tfv/tfv.s index 3fd83e05..8538b812 100644 --- a/tfv/tfv.s +++ b/tfv/tfv.s @@ -1,134 +1,30 @@ -.define EQU = - -KEYPRESS EQU $C000 -KEYRESET EQU $C010 - -;; SOFT SWITCHES -SET_GR EQU $C050 -SET_TEXT EQU $C051 -FULLGR EQU $C052 -TEXTGR EQU $C053 -PAGE0 EQU $C054 -PAGE1 EQU $C055 -LORES EQU $C056 -HIRES EQU $C057 - -PADDLE_BUTTON0 EQU $C061 -PADDL0 EQU $C064 -PTRIG EQU $C070 - -;; BASIC ROUTINES - -NORMAL EQU $F273 - -;; MONITOR ROUTINES - -HLINE EQU $F819 ;; HLINE Y,$2C at A -VLINE EQU $F828 ;; VLINE A,$2D at Y -CLRSCR EQU $F832 ;; Clear low-res screen -CLRTOP EQU $F836 ;; clear only top of low-res screen -SETCOL EQU $F864 ;; COLOR=A -TEXT EQU $FB36 -TABV EQU $FB5B ;; VTAB to A -BASCALC EQU $FBC1 ;; -VTAB EQU $FC22 ;; VTAB to CV -HOME EQU $FC58 ;; Clear the text screen -WAIT EQU $FCA8 ;; delay 1/2(26+27A+5A^2) us -SETINV EQU $FE80 ;; INVERSE -SETNORM EQU $FE84 ;; NORMAL -COUT EQU $FDED ;; output A to screen -COUT1 EQU $FDF0 ;; output A to screen - -;; Zero page addresses -WNDLFT EQU $20 -WNDWDTH EQU $21 -WNDTOP EQU $22 -WNDBTM EQU $23 -CH EQU $24 -CV EQU $25 -GBASL EQU $26 -GBASH EQU $27 -BASL EQU $28 -BASH EQU $29 -H2 EQU $2C -V2 EQU $2D -MASK EQU $2E -COLOR EQU $30 -INVFLG EQU $32 - -; Our zero-page addresses -; we try not to conflict with anything DOS, MONITOR or BASIC related - -COLOR1 EQU $E0 -COLOR2 EQU $E1 -MATCH EQU $E2 -XX EQU $E3 -YY EQU $E4 -YADD EQU $E5 -LOOP EQU $E6 -MEMPTRL EQU $E7 -MEMPTRH EQU $E8 -NAMEL EQU $E9 -NAMEH EQU $EA -NAMEX EQU $EB -CHAR EQU $EC - -FIRST EQU $F0 -LASTKEY EQU $F1 -PADDLE_STATUS EQU $F2 -XPOS EQU $F3 -YPOS EQU $F4 -TEMP EQU $FA -RUN EQU $FA -TEMP2 EQU $FB -TEMPY EQU $FB -INL EQU $FC -INH EQU $FD -OUTL EQU $FE -OUTH EQU $FF - - ;============================= - ; set low-res graphics, page 0 - ;============================= - jsr HOME - jsr set_gr_page0 - - ;============================= - ; show VMW splash screen - ;============================= - jsr CLRTOP - - lda #100 - sta MATCH - jsr draw_logo - - lda #0 - sta MATCH -shine_loop: - - jsr draw_logo - - inc MATCH - lda MATCH - cmp #30 - bne shine_loop - - lda #8 - sta CH ; HTAB 9 - - lda #20 - jsr TABV ; VTAB 21 +.include "zp.inc" - lda #>(vmwsw_string) - sta OUTH - lda #<(vmwsw_string) - sta OUTL + jsr HOME + jsr set_gr_page0 + + ; memset() + ; clear top page0 + ; clear top page1 + ; clear_top(0); + + jsr CLRTOP + + ; clear_top(1); + ; clear bottom page0 + ; clear bottom page1 + ; clear_bottom(0); + ; clear_bottom(1); + + ;========================== + ; Do Opening + ;========================== + + jsr opening - jsr print_string ; print("A VMW SOFTWARE PRODUCTION"); - jsr wait_until_keypressed ;====================== ; show the title screen @@ -317,510 +213,17 @@ exit: ; Return to BASIC? rts -;===================================================================== -;= ROUTINES -;===================================================================== - ;====================== - ; memset - ;====================== - ; a=value - ; x=length - ; MEMPTRL/MEMPTRH is address -memset: - ldy #0 -memset_loop: - sta MEMPTRL,Y - iny - dex - bne memset_loop - rts +;=============================================== +; External modules +;=============================================== - ;================= - ; display part of logo - ;================= - ; -draw_segment: - lda #0 - sta LOOP +.include "opener.s" +.include "utils.s" -segment_loop: - lda YADD - clc - adc YY - sta YY ; yy=yy+yadd - - lda COLOR1 - sta COLOR ; color=COLOR1 - - lda MATCH ; if (ram[XX]==ram[MATCH]) - cmp XX - bne nocolmatch1 - - lda COLOR ; color_equals(ram[COLOR1]*3); - clc - adc COLOR1 - adc COLOR1 - sta COLOR - -nocolmatch1: - lda YY - sta V2 - lda XX - clc - adc #9 - tay - lda #10 - - jsr VLINE ; A,V2 at Y vlin(10,ram[YY],9+ram[XX]); - - lda COLOR2 - sta COLOR ; color=COLOR2 - - lda MATCH ; if (ram[XX]==ram[MATCH]) - cmp XX - bne nocolmatch2 - - lda COLOR ; color_equals(ram[COLOR2]*3); - clc - adc COLOR2 - adc COLOR2 - sta COLOR - -nocolmatch2: - lda #34 - sta V2 - lda XX - clc - adc #9 - tay - lda YY - cmp #34 - beq skip_bottom ; if (ram[YY]==34) skip - jsr VLINE ; A,V2 at Y vlin(ram[YY],34,9+ram[XX]); - -skip_bottom: - - - inc XX ; ram[XX]++; - - inc LOOP - lda LOOP - cmp #4 - bne segment_loop - - lda YADD ; ram[YADD]=-ram[YADD]; - eor #$ff - clc - adc #1 - sta YADD - - rts - - ;================= - ; display VMW logo - ;================= - ; -draw_logo: - lda #0 - sta XX ; start of logo - lda #10 - sta YY ; draw at Y=10 - lda #6 - sta YADD ; step of 6 - - lda #$00 - sta COLOR2 - lda #$11 - sta COLOR1 ; first colors are red/black - jsr draw_segment - lda #$44 - sta COLOR2 ; now red/green - jsr draw_segment - lda #$22 - sta COLOR1 ; now green/blue - jsr draw_segment - jsr draw_segment - jsr draw_segment - lda #$00 - sta COLOR2 ; now blue/black - jsr draw_segment - - rts - - ;================= - ; load RLE image - ;================= - ; Output is BASH/BASL - ; Input is in GBASH/GBASL -load_rle_gr: - lda #$0 - tax - tay ; init X and Y to 0 - - sta CV ; ycoord=0 - - lda (GBASL),y ; load xsize - sta CH - iny ; (we should check if we had - ; bad luck and overflows page) - -rle_loop: - lda (GBASL),y ; load run value - cmp #$ff ; if 0xff - beq rle_done ; we are done - sta RUN - iny ; point to next value - bne rle_yskip1 ; if overflow, increment address - inc GBASH -rle_yskip1: - lda (GBASL),y ; load value to write - iny - bne rle_yskip2 - inc GBASH -rle_yskip2: - sty TEMP2 ; save y for later - pha - lda #$0 - tay - pla ; convoluted way to set y to 0 - -rle_run_loop: - sta (BASL),y ; write out the value - inc BASL ; increment the pointer - bne rle_skip3 ; if wrapped - inc BASH ; then increment the high value -rle_skip3: - inx ; increment the X value - cpx CH ; compare against the image width - bcc rle_not_eol ; if less then keep going - - pha ; save out value on stack - - lda BASL ; cheat to avoid a 16-bit add - cmp #$a7 ; we are adding 0x58 to get - bcc rle_add_skip ; to the next line - inc BASH -rle_add_skip: - clc - adc #$58 ; actually do the 0x58 add - sta BASL ; and store it back - - inc CV ; add 2 to ypos - inc CV ; each "line" is two high - - lda CV ; load value - cmp #15 ; if it's greater than 14 it wraps - bcc rle_no_wrap ; Thanks Woz - - lda #$0 ; we wrapped, so set to zero - sta CV - - ; when wrapping have to sub 0x3d8 - sec ; this is a 16-bit subtract routine - lda BASL - sbc #$d8 ; LSB - sta BASL - lda BASH ; MSB - sbc #$3 ; - sta BASH - -rle_no_wrap: - lda #$0 ; set X value back to zero - tax - pla ; restore value to write from stack - -rle_not_eol: - dec RUN ; decrement run value - bne rle_run_loop ; if not zero, keep looping - - ldy TEMP2 ; restore the input pointer - sec - bcs rle_loop ; and branch always - -rle_done: - lda #$15 ; move the cursor somewhere sane - sta CV - rts - - - ;========================================================== - ; set_text_page0 - ;========================================================== - ; -set_text_page0: - bit PAGE0 ; set page0 - bit TEXT ; set text mode - rts - - ;========================================================== - ; set_gr_page0 - ;========================================================== - ; -set_gr_page0: - ;lda #4 - ;sta GR_PAGE - bit PAGE0 ; set page 0 - bit LORES ; Lo-res graphics - bit TEXTGR ; mixed gr/text mode - bit SET_GR ; set graphics - rts - - ;========================================================= - ; gr_copy - ;========================================================= - ; for now copy 0xc00 to 0x400 - ; 2 + 8*38 + 4*80*23 + 4*120*26 + 13 = 20,159 = 20ms = 50Hz - ; -gr_copy: - ldx #0 ; set y to zero ; 2 - -gr_copy_loop: - stx TEMP ; save y ; 3 - txa ; move to A ; 2 - asl ; mult by 2 ; 2 - tay ; put into Y ; 2 - lda gr_offsets,Y ; lookup low byte for line addr ; 5 - sta OUTL ; out and in are the same ; 3 - sta INL ; 3 - lda gr_offsets+1,Y ; lookup high byte for line addr ; 5 - sta OUTH ; 3 - adc #$8 ; for now, fixed 0xc ; 2 - sta INH ; 3 - ldx TEMP ; restore y ; 3 - - ldy #0 ; set X counter to 0 ; 2 -gr_copy_line: - lda (INL),Y ; load a byte ; 5 - sta (OUTL),Y ; store a byte ; 6 - iny ; increment pointer ; 2 - - cpx #$4 ; don't want to copy bottom 4*40 ; 2 - bcs gr_copy_above4 ; 3 - -gr_copy_below4: - cpy #120 ; for early ones, copy 120 bytes ; 2 - bne gr_copy_line ; 3 - beq gr_copy_line_done ; 3 - -gr_copy_above4: ; for last four, just copy 80 bytes - cpy #80 ; 2 - bne gr_copy_line ; 3 - -gr_copy_line_done: - inx ; increment y value ; 2 - cpx #8 ; there are 8 of them ; 2 - bne gr_copy_loop ; if not, loop ; 3 - rts ; 6 - - ;========================================================== - ; Wait until keypressed - ;========================================================== - ; - -wait_until_keypressed: - lda KEYPRESS ; check if keypressed - bpl wait_until_keypressed ; if not, loop - jmp figure_out_key - - - ;========================================================== - ; Get Key - ;========================================================== - ; - -get_key: - -check_paddle_button: - - ; check for paddle button - - bit PADDLE_BUTTON0 - bpl no_button - lda #' '+128 - jmp save_key - -no_button: - lda KEYPRESS - bpl no_key - -figure_out_key: - cmp #' '+128 ; the mask destroys space - beq save_key ; so handle it specially - - and #$5f ; mask, to make upper-case -check_right_arrow: - cmp #$15 - bne check_left_arrow - lda #'K' -check_left_arrow: - cmp #$08 - bne check_up_arrow - lda #'J' -check_up_arrow: - cmp #$0B - bne check_down_arrow - lda #'I' -check_down_arrow: - cmp #$0A - bne check_escape - lda #'M' -check_escape: - cmp #$1B - bne save_key - lda #'Q' - jmp save_key - -no_key: - bit PADDLE_STATUS - bpl no_key_store - - ; check for paddle action - ; code from http://web.pdx.edu/~heiss/technotes/aiie/tn.aiie.06.html - - inc PADDLE_STATUS - lda PADDLE_STATUS - and #$03 - beq check_paddles - jmp no_key_store - -check_paddles: - lda PADDLE_STATUS - and #$80 - sta PADDLE_STATUS - - ldx #$0 - LDA PTRIG ;TRIGGER PADDLES - LDY #0 ;INIT COUNTER - NOP ;COMPENSATE FOR 1ST COUNT - NOP -PREAD2: LDA PADDL0,X ;COUNT EVERY 11 uSEC. - BPL RTS2D ;BRANCH WHEN TIMED OUT - INY ;INCREMENT COUNTER - BNE PREAD2 ;CONTINUE COUNTING - DEY ;COUNTER OVERFLOWED -RTS2D: ;RETURN W/VALUE 0-255 - - cpy #96 - bmi paddle_left - cpy #160 - bmi no_key_store - lda #'K' - jmp save_key -paddle_left: - lda #'J' - jmp save_key - -no_key_store: - lda #0 ; no key, so save a zero - -save_key: - sta LASTKEY ; save the key to our buffer - bit KEYRESET ; clear the keyboard buffer - rts - - ;============================================= - ; put_sprite - ;============================================= -put_sprite: - - lda #>tb1_sprite ; hardcoded for tb1 for now - sta INH - lda #tb1_sprite ; hardcoded for tb1 for now + sta INH + lda #