Permalink
Cannot retrieve contributors at this time
1269 lines (1189 sloc)
20.2 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; | |
| ; RHDE background rendering | |
| ; Copyright 2014 Damian Yerrick | |
| ; | |
| ; Copying and distribution of this file, with or without | |
| ; modification, are permitted in any medium without royalty provided | |
| ; the copyright notice and this notice are preserved in all source | |
| ; code copies. This file is offered as-is, without any warranty. | |
| ; | |
| .include "nes.inc" | |
| .include "global.inc" | |
| .include "mbyt.inc" | |
| .p02 | |
| .import INITIAL_CASH | |
| .segment "ZEROPAGE" | |
| ; Current row of fielddata | |
| fieldlo: .res 1 | |
| fieldhi: .res 1 | |
| player_grass_color: .res 2 | |
| ; PLAYFIELD INIT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| .segment "CODE" | |
| ; Playfield init | |
| .proc init_playfield | |
| ; Clear inventory quantities to 0 | |
| lda #0 | |
| ldx #NUM_FURNIS * 2 - 1 | |
| clearinvloop: | |
| sta player_inv,x | |
| dex | |
| bpl clearinvloop | |
| ; Set up players' | |
| ldx #1 | |
| initplayerloop: | |
| lda #<INITIAL_CASH | |
| sta cash_lo,x | |
| lda #>INITIAL_CASH | |
| sta cash_hi,x | |
| lda #COLOR_GOODGRASS | |
| sta player_grass_color,x | |
| ; 2013-12-28: Give one missile silo for free | |
| lda #1 | |
| sta player_inv+30,x | |
| dex | |
| bpl initplayerloop | |
| inx | |
| stx fullht_min_col | |
| ldy #30 | |
| sty fullht_max_col | |
| txa | |
| clc | |
| grassloop: | |
| ora #TILE_GRASS | |
| sta fielddata,x | |
| sta fielddata+256,x | |
| sta fielddata+512,x | |
| adc #1 | |
| and #$03 | |
| dey | |
| bne :+ | |
| inx | |
| inx | |
| ldy #30 | |
| : | |
| inx | |
| bne grassloop | |
| ; Add borders | |
| ldx #FIELD_HT | |
| lda #<fielddata | |
| sta 0 | |
| lda #>fielddata | |
| sta 1 | |
| borderloop: | |
| ldy #0 | |
| lda #TILE_LBORDER | |
| sta (0),y | |
| ldy #29 | |
| lda #TILE_RBORDER | |
| sta (0),y | |
| lda #32 | |
| clc | |
| adc 0 | |
| sta 0 | |
| bcc :+ | |
| inc 1 | |
| : | |
| dex | |
| bne borderloop | |
| lda #$4C | |
| sta bgup_jmp | |
| lda #<bgup_nop | |
| sta bgup_action | |
| lda #>bgup_nop | |
| sta bgup_action+1 | |
| rts | |
| .endproc | |
| .proc make_road | |
| dst = $00 | |
| dsthi = $01 | |
| road_map_type = $04 | |
| y1 = $05 | |
| y2 = $06 | |
| stamp_rows = $07 | |
| sta road_map_type | |
| ldx #ROAD_HT - 1 | |
| init_xmax: | |
| lda #7 | |
| sta xmax_1p,x | |
| lda #8 | |
| sta xmin_2p,x | |
| dex | |
| bpl init_xmax | |
| lda road_map_type | |
| and #$02 | |
| clc | |
| adc #2 | |
| sta y1 | |
| eor #$FF | |
| adc #ROAD_HT - 2 + 1 | |
| sta y2 | |
| lda road_map_type | |
| lsr a | |
| bcs adjust_xbounds_backslash | |
| ; Slash | |
| ldx #0 | |
| : | |
| inc xmax_1p,x | |
| inc xmin_2p,x | |
| inx | |
| cpx y1 | |
| bcc :- | |
| inc xmin_2p,x | |
| inc xmin_2p+1,x | |
| ldx y2 | |
| dec xmax_1p,x | |
| inx | |
| dec xmax_1p,x | |
| inx | |
| : | |
| dec xmax_1p,x | |
| dec xmin_2p,x | |
| inx | |
| cpx #ROAD_HT | |
| bcc :- | |
| bcs have_xbounds | |
| adjust_xbounds_backslash: | |
| ldx #0 | |
| : | |
| dec xmax_1p,x | |
| dec xmin_2p,x | |
| inx | |
| cpx y1 | |
| bcc :- | |
| dec xmax_1p,x | |
| dec xmax_1p+1,x | |
| ldx y2 | |
| inc xmin_2p,x | |
| inx | |
| inc xmin_2p,x | |
| inx | |
| : | |
| inc xmax_1p,x | |
| inc xmin_2p,x | |
| inx | |
| cpx #ROAD_HT | |
| bcc :- | |
| have_xbounds: | |
| ; Now place the road tiles in the playfield | |
| ldx #0 | |
| lda #<fielddata | |
| sta dst | |
| lda #>fielddata | |
| sta dsthi | |
| roadpieceloop: | |
| ldy xmin_2p,x | |
| dey | |
| tya | |
| cmp xmax_1p,x | |
| bne not_single_road | |
| asl a | |
| tay | |
| lda #TILE_ROADS | |
| sta (dst),y | |
| iny | |
| lda #TILE_ROADS|$01 | |
| sta (dst),y | |
| tya | |
| eor #$21 | |
| tay | |
| lda #TILE_ROADS|$10 | |
| sta (dst),y | |
| iny | |
| lda #TILE_ROADS|$11 | |
| sta (dst),y | |
| not_single_road: | |
| lda #64 | |
| clc | |
| adc dst | |
| sta dst | |
| bcc :+ | |
| inc dsthi | |
| : | |
| inx | |
| cpx #ROAD_HT | |
| bcc roadpieceloop | |
| ldy y1 | |
| jsr place_one_road_stamp | |
| ldy y2 | |
| ; fall through | |
| place_one_road_stamp: | |
| lda #4 | |
| sta stamp_rows | |
| lda #0 | |
| sta dst | |
| tya | |
| lsr a | |
| ror dst | |
| lsr a | |
| ror dst | |
| adc #>fielddata | |
| sta dsthi | |
| lda xmax_1p,y | |
| asl a | |
| ora dst | |
| sta dst | |
| lda road_map_type ; bit 0 false: slash; true: backslash | |
| lsr a | |
| ldx #0 | |
| bcc :+ | |
| ldx #16 | |
| : | |
| @rowloop: | |
| ldy #0 | |
| @tileloop: | |
| lda road_stamps,x | |
| sta (dst),y | |
| inx | |
| iny | |
| cpy #4 | |
| bcc @tileloop | |
| lda dst | |
| clc | |
| adc #32 | |
| sta dst | |
| bcc :+ | |
| inc dst+1 | |
| : | |
| dec stamp_rows | |
| bne @rowloop | |
| rts | |
| .pushseg | |
| .segment "RODATA" | |
| road_stamps: | |
| mbyt "002D2E2F" ; slash | |
| mbyt "003D3E3F" | |
| mbyt "2D2E2F00" | |
| mbyt "3D3E3F00" | |
| mbyt "2A2B2C00" ; backslash | |
| mbyt "3A3B3C00" | |
| mbyt "002A2B2C" | |
| mbyt "003A3B3C" | |
| .popseg | |
| .endproc | |
| .proc place_initial_houses | |
| lda xmax_1p+11 | |
| asl a | |
| adc #<-6 | |
| tay | |
| ldx #3 | |
| jsr place_one_house | |
| lda xmin_2p+0 | |
| asl a | |
| adc #<-8 | |
| tay | |
| ldx #19 | |
| jsr place_one_house | |
| rts | |
| place_one_house: | |
| jsr seek_fielddata_row_y | |
| txa | |
| ora fieldlo | |
| sta fieldlo | |
| ldy #0 | |
| lda #TILE_OV_STRAY_BLOCK | |
| @toploop: | |
| sta (fieldlo),y | |
| iny | |
| cpy #8 | |
| bcc @toploop | |
| ldy #224 | |
| @bottomloop: | |
| sta (fieldlo),y | |
| iny | |
| cpy #232 | |
| bcc @bottomloop | |
| ldy #32 | |
| clc | |
| ldx #0 | |
| @sidesloop: | |
| lda house_side_walls,x | |
| sta (fieldlo),y | |
| tya | |
| clc | |
| adc #7 | |
| tay | |
| inx | |
| lda house_side_walls,x | |
| sta (fieldlo),y | |
| tya | |
| adc #32-7 | |
| tay | |
| cpy #224 | |
| bcc @sidesloop | |
| ; Place one bed | |
| ldy #161 | |
| lda fieldlo | |
| and #$1F | |
| cmp #$0E | |
| bcc :+ | |
| ldy #165 | |
| : | |
| lda #TILE_BED | |
| sta (fieldlo),y | |
| iny | |
| lda #TILE_BED+1 | |
| sta (fieldlo),y | |
| tya | |
| clc | |
| adc #31 | |
| tay | |
| lda #TILE_BED+16 | |
| sta (fieldlo),y | |
| iny | |
| lda #TILE_BED+17 | |
| sta (fieldlo),y | |
| rts | |
| .pushseg | |
| .segment "RODATA" | |
| house_side_walls: | |
| .byte TILE_OV_STRAY_BLOCK, TILE_OV_STRAY_BLOCK | |
| .byte TILE_OV_STRAY_BLOCK, TILE_OV_DOOR_NS, TILE_OV_STRAY_BLOCK | |
| .byte TILE_OV_STRAY_BLOCK, TILE_OV_STRAY_BLOCK | |
| .popseg | |
| .endproc | |
| FIELD_DST_TOP = $2040 | |
| FIELD_BORDER_TOP = ::FIELD_DST_TOP - $20 | |
| SHOP_FRAME_TOP = FIELD_DST_TOP + (FIELD_HT - SHOP_FRAME_HT) * 32 | |
| FIELD_BORDER_BOTTOM = ::FIELD_DST_TOP + ::FIELD_HT * 32 | |
| .proc make_road_border | |
| attrblk = $07 | |
| attrbuf = $08 | |
| ; Make the attributes for the road tiles | |
| lda #VBLANK_NMI | |
| sta PPUCTRL | |
| lda #$23 | |
| sta PPUADDR | |
| lda #$C0 | |
| sta PPUADDR | |
| ldy #0 | |
| jsr get_one_attribute_row | |
| attrloop: | |
| jsr get_one_attribute_row | |
| jsr copy_attribute_row | |
| iny | |
| jsr get_one_attribute_row | |
| iny | |
| cpy #ROAD_HT | |
| bcc attrloop | |
| dey | |
| jsr get_one_attribute_row | |
| jsr copy_attribute_row | |
| jsr copy_attribute_row | |
| ; Now draw top and bottom borders of playfield including this road | |
| lda #>FIELD_BORDER_TOP | |
| sta PPUADDR | |
| .if <::FIELD_BORDER_TOP <> >::FIELD_BORDER_TOP | |
| lda #<::FIELD_BORDER_TOP | |
| .endif | |
| sta PPUADDR | |
| lda #TILE_TLBORDER | |
| sta PPUDATA | |
| ldx xmax_1p+0 | |
| dex | |
| lda #TILE_TBORDER | |
| : | |
| sta PPUDATA | |
| sta PPUDATA | |
| dex | |
| bne :- | |
| lda #TILE_TLINLET | |
| sta PPUDATA | |
| lda #TILE_ROADS|$10 | |
| sta PPUDATA | |
| lda #TILE_ROADS|$11 | |
| sta PPUDATA | |
| lda #TILE_TRINLET | |
| sta PPUDATA | |
| ldx xmin_2p+0 | |
| lda #TILE_TBORDER | |
| : | |
| sta PPUDATA | |
| sta PPUDATA | |
| inx | |
| cpx #14 | |
| bcc :- | |
| lda #TILE_TRBORDER | |
| sta PPUDATA | |
| lda #>FIELD_BORDER_BOTTOM | |
| sta PPUADDR | |
| lda #<FIELD_BORDER_BOTTOM | |
| sta PPUADDR | |
| lda #TILE_BLBORDER | |
| sta PPUDATA | |
| ldx xmax_1p+11 | |
| dex | |
| lda #TILE_BBORDER | |
| : | |
| sta PPUDATA | |
| sta PPUDATA | |
| dex | |
| bne :- | |
| lda #TILE_BLINLET | |
| sta PPUDATA | |
| lda #TILE_ROADS|$00 | |
| sta PPUDATA | |
| lda #TILE_ROADS|$01 | |
| sta PPUDATA | |
| lda #TILE_BRINLET | |
| sta PPUDATA | |
| ldx xmin_2p+11 | |
| lda #TILE_BBORDER | |
| : | |
| sta PPUDATA | |
| sta PPUDATA | |
| inx | |
| cpx #14 | |
| bcc :- | |
| lda #TILE_BRBORDER | |
| sta PPUDATA | |
| rts | |
| get_one_attribute_row: | |
| ldx #0 | |
| stx attrblk | |
| @loop: | |
| lsr attrbuf,x | |
| lsr attrbuf,x | |
| lda attrblk | |
| cmp xmin_2p,y | |
| bcc @notpast2 | |
| lda #$40 | |
| bne @have_orvalue | |
| @notpast2: | |
| cmp xmax_1p,y | |
| bcc @notpast1 | |
| lda #$80 | |
| @have_orvalue: | |
| ora attrbuf,x | |
| sta attrbuf,x | |
| @notpast1: | |
| inc attrblk | |
| lda attrblk | |
| lsr a | |
| tax | |
| cpx #8 | |
| bcc @loop | |
| rts | |
| copy_attribute_row: | |
| ldx #0 | |
| : | |
| lda attrbuf,x | |
| sta PPUDATA | |
| inx | |
| cpx #8 | |
| bcc :- | |
| rts | |
| .endproc | |
| ;; | |
| ; Loads fieldlo and fieldhi with the start address of row Y | |
| ; and clears C. | |
| .proc seek_fielddata_row_y | |
| tya | |
| .endproc | |
| .proc seek_fielddata_row_a | |
| lsr a | |
| ror a | |
| ror a | |
| sta fieldhi | |
| and #%11000000 | |
| ror a | |
| sta fieldlo | |
| lda fieldhi | |
| and #%00000011 | |
| adc #>fielddata | |
| sta fieldhi | |
| rts | |
| .endproc | |
| ;; | |
| ; Determines whether tile coordinates are within the playfield and | |
| ; gets the address of a tile point if so. | |
| ; @param 0,1 X,Y coordinates in tiles | |
| ; @return Address of tile row in fieldlo-fieldhi, Y = x coord; | |
| ; carry set if out of bounds | |
| .proc tile_to_addr | |
| pt_x = 0 | |
| pt_y = 1 | |
| ldy pt_x | |
| beq is_offscreen | |
| cpy #29 | |
| bcs is_offscreen | |
| lda pt_y | |
| cmp #FIELD_HT | |
| bcs is_offscreen | |
| jmp seek_fielddata_row_a | |
| is_offscreen: | |
| sec | |
| rts | |
| .endproc | |
| ; BACKGROUND UPDATE SCHEDULER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;; | |
| ; Updates the 3 columns around the cursor. If an update is already | |
| ; in progress, it instead schedules an update for the whole side. | |
| ; Assumes the cursor is on the same side as the player. | |
| ; | |
| ; Updating 3 columns takes one frame; updating a whole side takes 3. | |
| ; @param X player (0 or 1) | |
| .proc update_around_cursor | |
| ldy cursor_x,x | |
| ; fall through | |
| .endproc | |
| ;; Updates the three columns around column Y (1=left, 28=right). | |
| ; @param Y column to update | |
| ; @param X player (0 or 1) to update if fallback | |
| .proc update_around_column_y | |
| lda copy_region_width | |
| beq no_copy_in_progress | |
| lda #DIRTY_SIDE | |
| ora side_dirty,x | |
| sta side_dirty,x | |
| rts | |
| no_copy_in_progress: | |
| dey | |
| sty copy_region_left | |
| lda #3 | |
| sta copy_region_width | |
| rts | |
| .endproc | |
| ;; | |
| ; Begins or continues a playfield update job. | |
| .proc build_choose_redraw | |
| lda copy_region_width | |
| bne continue_current_job | |
| lda side_dirty | |
| and #DIRTY_SIDE | |
| beq not_redraw_left | |
| and side_dirty+1 | |
| beq redraw_only_left | |
| eor side_dirty | |
| sta side_dirty | |
| lda side_dirty+1 | |
| and #<~DIRTY_SIDE | |
| sta side_dirty+1 | |
| lda #0 | |
| sta copy_region_left | |
| lda #30 | |
| bne have_region_width | |
| redraw_only_left: | |
| lda side_dirty | |
| and #<~DIRTY_SIDE | |
| sta side_dirty | |
| lda #0 | |
| beq redraw_aplus16 | |
| not_redraw_left: | |
| lda side_dirty+1 | |
| and #DIRTY_SIDE | |
| beq no_redraw_just_yet | |
| eor side_dirty+1 | |
| sta side_dirty+1 | |
| lda #14 | |
| redraw_aplus16: | |
| sta copy_region_left | |
| lda #16 | |
| have_region_width: | |
| sta copy_region_width | |
| continue_current_job: | |
| lda #<bgup_field | |
| sta bgup_action | |
| no_redraw_just_yet: | |
| rts | |
| .endproc | |
| SHOPDRAW_DONE = 0 | |
| SHOPDRAW_FRAME1 = 2 | |
| SHOPDRAW_FRAME2 = 4 | |
| SHOPDRAW_FRAME3 = 6 | |
| SHOPDRAW_FRAME4 = 8 | |
| SHOPDRAW_LINE34 = 10 | |
| SHOPDRAW_LINECASH = 12 | |
| STOCKDRAW_LINE34 = 14 | |
| STOCKDRAW_LINE56 = 16 | |
| STOCKDRAW_LINE78 = 18 | |
| STOCKDRAW_COUNTS = 20 | |
| ;; | |
| ; More complicated update scheduler for furnish phase. | |
| .proc shop_choose_redraw | |
| ; If a map update is in progress, let it finish. Or if one is | |
| ; required, start it. Map lag is more noticeable than form lag. | |
| jsr build_choose_redraw | |
| lda copy_region_width | |
| beq no_map_update | |
| rts | |
| no_map_update: | |
| ; If the view type has changed, begin a view change. | |
| ; This interrupts updating the view contents. | |
| ldx enclose_turn | |
| lda form_desired_view,x | |
| cmp form_cur_view,x | |
| beq no_view_change | |
| ; Unless switching to no view, a blank view (just the frame) is | |
| ; acceptable as a temporary substitute because it signals a | |
| ; transition in progress. | |
| cmp #FRAME_NONE | |
| bne not_changing_to_none | |
| sta form_cur_view,x | |
| lda #DIRTY_SIDE | |
| ora side_dirty,x | |
| sta side_dirty,x | |
| force_shophide: | |
| lda #<bgup_shophide | |
| sta bgup_action | |
| rts | |
| not_changing_to_none: | |
| lda form_cur_view,x | |
| cmp #FRAME_BLANK | |
| beq no_view_change | |
| need_view_change: | |
| lda #FRAME_BLANK | |
| sta form_cur_view,x | |
| lda #<bgup_shopframe | |
| sta bgup_action | |
| lda #SHOPDRAW_FRAME1 | |
| sta enclose_state | |
| rts | |
| no_view_change: | |
| ; If an update is still in progress, continue it | |
| ldx enclose_state | |
| beq update_not_in_progress | |
| lda shop_updaters-1,x | |
| pha | |
| lda shop_updaters-2,x | |
| pha | |
| rts | |
| update_not_in_progress: | |
| ; If an update is requested for this player, begin the update. | |
| ldx enclose_turn | |
| lda #DIRTY_FORM|DIRTY_FORMEND | |
| and side_dirty,x | |
| bne begin_player_x_update | |
| ; If an update is requested for other player, begin the update. | |
| txa | |
| eor #$01 | |
| tax | |
| lda #DIRTY_FORM|DIRTY_FORMEND | |
| and side_dirty,x | |
| bne begin_player_x_update | |
| ; If no update is in progress or requested, make absolutely | |
| ; sure the correct view is showing. | |
| ldx enclose_turn | |
| lda form_desired_view,x | |
| cmp form_cur_view,x | |
| beq no_fill_frame | |
| fill_frame: | |
| ; Request full update of form contents | |
| ldx enclose_turn | |
| lda #DIRTY_FORM | |
| ora side_dirty,x | |
| sta side_dirty,x | |
| ; And load the nametable | |
| lda #SHOPDRAW_DONE | |
| sta enclose_state | |
| lda #<bgup_shopnt | |
| sta bgup_action | |
| lda form_desired_view,x | |
| sta form_cur_view,x | |
| lsr a | |
| lda #>stock_nt | |
| ldy #<stock_nt | |
| bcs nt_is_stock | |
| lda #>shop_nt | |
| ldy #<shop_nt | |
| nt_is_stock: | |
| jmp shop_load_nt | |
| no_fill_frame: | |
| lda enclose_turn | |
| eor #$01 | |
| and #$01 | |
| sta enclose_turn | |
| rts | |
| begin_player_x_update: | |
| stx enclose_turn | |
| and #DIRTY_FORM | |
| beq only_formend | |
| ; acknowledge | |
| eor side_dirty,x | |
| sta side_dirty,x | |
| lda form_cur_view,x | |
| lsr a | |
| bcs start_stock_update | |
| lda #SHOPDRAW_LINE34-2 | |
| sta enclose_state | |
| jmp shop_12 | |
| start_stock_update: | |
| lda #STOCKDRAW_LINE34-2 | |
| sta enclose_state | |
| jmp stock_12 | |
| only_formend: | |
| ; acknowledge | |
| lda #<~DIRTY_FORMEND | |
| and side_dirty,x | |
| sta side_dirty,x | |
| jmp shopfurni | |
| .pushseg | |
| .segment "RODATA" | |
| shop_updaters: | |
| .addr erase_80-1, erase_90-1, erase_A0-1, fill_frame-1 | |
| .addr shop_34-1, shopcash-1 | |
| .addr stock_34-1, stock_56-1, stock_78-1, stock_counts-1 | |
| .popseg | |
| erase_80: | |
| lda #$08 | |
| bne shop_choose_erase_A | |
| erase_90: | |
| lda #$09 | |
| bne shop_choose_erase_A | |
| erase_A0: | |
| lda #$0A | |
| shop_choose_erase_A: | |
| ldx enclose_turn | |
| beq not_player_2 | |
| ora #$04 | |
| not_player_2: | |
| sta bgup_arg | |
| lda #<bgup_clear2 | |
| sta bgup_action | |
| inc enclose_state | |
| inc enclose_state | |
| rts | |
| shop_12: | |
| ldy #0 | |
| beq shop_2lines | |
| shop_34: | |
| ldy #2 | |
| shop_2lines: | |
| inc enclose_state | |
| inc enclose_state | |
| tya | |
| lsr a | |
| ora #$08 | |
| ldx enclose_turn | |
| beq :+ | |
| ora #$04 | |
| : | |
| sta bgup_arg | |
| lda #<bgup_vwf | |
| sta bgup_action | |
| tya | |
| jmp draw_two_shopitems | |
| stock_12: | |
| ldy #0 | |
| beq stock_2lines | |
| stock_34: | |
| ldy #2 | |
| bne stock_2lines | |
| stock_56: | |
| ldy #4 | |
| bne stock_2lines | |
| stock_78: | |
| ldy #6 | |
| stock_2lines: | |
| inc enclose_state | |
| inc enclose_state | |
| tya | |
| lsr a | |
| lsr a | |
| bcc :+ | |
| ora #$80 | |
| : | |
| ora #$08 | |
| ldx enclose_turn | |
| beq :+ | |
| ora #$04 | |
| : | |
| sta bgup_arg | |
| lda #<bgup_8tiles | |
| sta bgup_action | |
| tya | |
| jmp draw_two_stockitems | |
| stock_counts: | |
| lda #0 | |
| sta enclose_state | |
| lda #<bgup_vwf | |
| sta bgup_action | |
| ; Draw counts to tiles A0-AF ($0A00) for 1P or E0-EF ($0E00) for 2P | |
| lda #$0A | |
| ldx enclose_turn | |
| beq :+ | |
| ora #$04 | |
| : | |
| sta bgup_arg | |
| ; 2014-03-01: Stock has no form-end handler; it redraws entirely | |
| ; (when changing pages) or not at all (when moving the cursor). | |
| ; Make sure shop's form-end (which draws the picture of the | |
| ; selected item at the lower left corner) isn't drawn. | |
| lda #<~DIRTY_FORMEND | |
| and side_dirty,x | |
| sta side_dirty,x | |
| jmp stock_draw_counts | |
| shopcash: | |
| lda #0 | |
| sta enclose_state | |
| lda #$0A ; $0A00 or $0E00 | |
| ldx enclose_turn | |
| beq :+ | |
| ora #$04 | |
| : | |
| sta bgup_arg | |
| lda #<bgup_vwf | |
| sta bgup_action | |
| lda #DIRTY_FORMEND | |
| ora side_dirty,x | |
| sta side_dirty,x | |
| jmp shop_draw_cash | |
| shopfurni: | |
| jsr clear_8_tiles | |
| lda #$0A ; $0A00 or $0E00 | |
| ldx enclose_turn | |
| beq :+ | |
| ora #$04 | |
| : | |
| sta bgup_arg | |
| lda #<bgup_8tiles | |
| sta bgup_action | |
| ldx enclose_turn | |
| lda form_pageitem,x | |
| cmp form_pagelen,x | |
| bcc :+ | |
| rts | |
| : | |
| asl a | |
| ora enclose_turn | |
| tax | |
| lda form_pageitems,x | |
| pha | |
| ; Draw how many the player owns | |
| asl a | |
| ora enclose_turn | |
| tax | |
| lda player_inv,x | |
| beq not_owned | |
| jsr bcd8bit | |
| pha | |
| lda $00 ; high digit | |
| beq noHighDigits | |
| ora #$30 | |
| ldx #75 | |
| jsr vwfPutTile | |
| noHighDigits: | |
| pla | |
| ora #$30 | |
| ldx #88 | |
| jsr vwfPutTile | |
| not_owned: | |
| pla | |
| ldx #0 ; 0: tiles B0-B3, 64: tiles B4-B7, only using B0-B3 | |
| jmp load_menu_furni | |
| .endproc | |
| .proc bottom_row_choose_redraw | |
| lda #0 | |
| sta form_cur_view+0 | |
| sta form_cur_view+1 | |
| jmp shop_choose_redraw::force_shophide | |
| .endproc | |
| ; BACKGROUND UPDATE EXECUTION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| .segment "ZEROPAGE" | |
| bgup_jmp: .res 1 | |
| bgup_action: .res 2 | |
| bgup_arg: .res 1 | |
| ; Playfield region to update over the next frames | |
| copy_region_left: .res 1 | |
| copy_region_width: .res 1 | |
| ; Columns that are safe for full height updates | |
| ; Use this when drawing furnish phase UI | |
| fullht_min_col: .res 1 | |
| fullht_max_col: .res 1 | |
| .segment "CODE" | |
| .align 32 | |
| bgup_nop: rts | |
| bgup_shopframe: jmp shop_draw_frame | |
| bgup_clear2: jmp clear_vwf_rows_bgup_arg | |
| bgup_shopnt: jmp shop_copy_nt | |
| bgup_shophide: jmp shop_erase_frame_bottom | |
| bgup_field: jmp copy_field_cols | |
| bgup_vwf: jmp copyLineImg_bgup_arg | |
| bgup_8tiles: jmp copy_8_tiles_bgup_arg | |
| ;; | |
| ; Waits for vertical blanking, copies the display list to OAM, | |
| ; copies data to video memory, and resets the scroll position. | |
| .proc bgup_vsync | |
| lda nmis | |
| : | |
| cmp nmis | |
| beq :- | |
| lda #0 | |
| sta OAMADDR | |
| sta PPUMASK | |
| lda #>OAM | |
| sta OAM_DMA | |
| jsr bgup_jmp | |
| lda #<bgup_nop | |
| sta bgup_action | |
| ; fall through | |
| .endproc | |
| .proc screen_back_on | |
| ; Turn the screen on | |
| ldx #248 | |
| ldy #236 | |
| lda #VBLANK_NMI|BG_0000|OBJ_1000|3 | |
| sec | |
| jmp ppu_screen_on | |
| .endproc | |
| .proc copy_field_cols | |
| maxwidth = 0 | |
| ldx copy_region_left | |
| lda #VBLANK_NMI|VRAM_DOWN | |
| sta PPUCTRL | |
| ; Find out how much we can copy per frame | |
| ; Copy 15 columns on PAL NES and 6 on NTSC NES | |
| ; Use NTSC NES value for Dendy because extending vblank on Dendy | |
| ; requires ending rendering early, and we don't do that yet | |
| ldy #6 | |
| lda tvSystem | |
| lsr a | |
| bcc :+ | |
| ldy #15 | |
| : | |
| cpy copy_region_width | |
| bcc copy_loop | |
| ldy copy_region_width | |
| bne copy_loop | |
| jmp copy_done | |
| copy_loop: | |
| lda #>FIELD_DST_TOP | |
| sta PPUADDR | |
| txa | |
| ora #<FIELD_DST_TOP | |
| sta PPUADDR | |
| .repeat ::FIELD_HT - ::SHOP_FRAME_HT, I | |
| lda fielddata+32*I,x | |
| sta PPUDATA | |
| .endrepeat | |
| cpx fullht_min_col | |
| bcc skip_bottom | |
| cpx fullht_max_col | |
| bcs skip_bottom | |
| .repeat ::SHOP_FRAME_HT, I | |
| lda fielddata+32*(::FIELD_HT - ::SHOP_FRAME_HT + I),x | |
| sta PPUDATA | |
| .endrepeat | |
| skip_bottom: | |
| inx | |
| dey | |
| beq copy_done | |
| jmp copy_loop | |
| copy_done: | |
| ; new width = old width + old x - new x | |
| txa | |
| eor #$FF | |
| sec | |
| adc copy_region_left | |
| clc | |
| adc copy_region_width | |
| sta copy_region_width | |
| stx copy_region_left | |
| rts | |
| .endproc | |
| .segment "RODATA" | |
| shop_frame_left: | |
| .byte 0, 18 | |
| .segment "CODE" | |
| .proc clear_vwf_rows_bgup_arg | |
| ldx bgup_arg | |
| ldy #16 | |
| .endproc | |
| ;; | |
| ; Fills 512 bytes (32 tiles) of pattern table starting at | |
| ; PPU $XX00 (tile $XX0) with blank tiles of color 1. | |
| ; Usually X=$08, $0A, $0C, or $0E. | |
| .proc clear_vwf_rows | |
| lda #VBLANK_NMI | |
| sta PPUCTRL | |
| asl a | |
| sta PPUMASK | |
| stx PPUADDR | |
| sta PPUADDR | |
| ldx #$FF | |
| rowloop: | |
| .repeat 8 | |
| stx PPUDATA | |
| .endrepeat | |
| .repeat 8 | |
| sta PPUDATA | |
| .endrepeat | |
| dey | |
| bne rowloop | |
| rts | |
| .endproc | |
| .proc copyLineImg_bgup_arg | |
| lda bgup_arg | |
| ldy #0 | |
| jmp copyLineImg | |
| .endproc | |
| ;; | |
| ; @param enclose_turn player (0 or 1) | |
| .proc shop_draw_frame | |
| dstlo = $00 | |
| dsthi = $01 | |
| ldx enclose_turn | |
| ; Write the top border | |
| lda #>SHOP_FRAME_TOP | |
| sta dsthi | |
| sta PPUADDR | |
| lda shop_frame_left,x | |
| ora #<SHOP_FRAME_TOP | |
| sta dstlo | |
| sta PPUADDR | |
| bit PPUDATA | |
| lda #TILE_BLACK | |
| jsr wr10 | |
| ; Write the body | |
| ldx #SHOP_FRAME_HT - 1 | |
| toploop: | |
| lda dsthi | |
| sta PPUADDR | |
| lda dstlo | |
| sta PPUADDR | |
| lda #TILE_FRAME_LEFT | |
| sta PPUDATA | |
| lda #TILE_WHITE | |
| jsr wr10 | |
| lda #TILE_FRAME_RIGHT | |
| sta PPUDATA | |
| dex | |
| bne toploop | |
| ; Don't overwrite the columns | |
| ldx enclose_turn | |
| bne is_player2 | |
| lda #12 | |
| sta fullht_min_col | |
| bne setframe_done | |
| is_player2: | |
| lda #18 | |
| sta fullht_max_col | |
| setframe_done: | |
| ; Write the bottom border | |
| lda dsthi | |
| sta PPUADDR | |
| lda dstlo | |
| sta PPUADDR | |
| bit PPUDATA | |
| lda #TILE_FRAME_BOTTOM | |
| wr10: | |
| ldy #(::SHOP_FRAME_WID - 2) / 2 | |
| : | |
| .repeat 2 | |
| sta PPUDATA | |
| .endrepeat | |
| dey | |
| bne :- | |
| clc | |
| lda dstlo | |
| adc #32 | |
| sta dstlo | |
| bcc :+ | |
| inc dsthi | |
| : | |
| rts | |
| .endproc | |
| .proc shop_erase_frame_bottom | |
| lda form_cur_view+0 | |
| bne left_view_showing | |
| ;lda #0 | |
| sta fullht_min_col | |
| lda #<FIELD_BORDER_BOTTOM + 1 | |
| jsr oneside | |
| left_view_showing: | |
| lda form_cur_view+1 | |
| bne right_view_showing | |
| lda #30 | |
| sta fullht_max_col | |
| lda #<FIELD_BORDER_BOTTOM + 19 | |
| oneside: | |
| ldy #>FIELD_BORDER_BOTTOM | |
| sty PPUADDR | |
| sta PPUADDR | |
| lda #TILE_BBORDER | |
| ldy #10 | |
| : | |
| sta PPUDATA | |
| dey | |
| bne :- | |
| right_view_showing: | |
| rts | |
| .endproc | |
| ;; | |
| ; Clears 8 tiles in transfer buffer to color 1. | |
| .proc clear_8_tiles | |
| lda #$FF | |
| ldy #0 | |
| planeloop: | |
| ldx #8 | |
| byteloop: | |
| sta lineImgBuf,y | |
| iny | |
| dex | |
| bne byteloop | |
| eor #$FF | |
| cpy #$80 | |
| bcc planeloop | |
| rts | |
| .endproc | |
| .proc copy_8_tiles_bgup_arg | |
| ldy #0 | |
| lda bgup_arg | |
| bpl copy_8_tiles | |
| ldy #$80 | |
| .endproc | |
| .proc copy_8_tiles | |
| sta PPUADDR | |
| sty PPUADDR | |
| lda #VBLANK_NMI | |
| sta PPUCTRL | |
| asl a ; A = 0 | |
| loop: | |
| tax | |
| .repeat 8, I | |
| ldy lineImgBuf+I,x | |
| sty PPUDATA | |
| .endrepeat | |
| clc | |
| adc #8 | |
| bpl loop | |
| rts | |
| .endproc | |
| ;; | |
| ; Copies a 70-byte nametable segment to the top border and interior | |
| ; of a shop frame. | |
| ; @param enclose_turn 0: player 1; 1: player 2 | |
| .proc shop_copy_nt | |
| dstlo = 0 | |
| dsthi = 1 | |
| ldx enclose_turn | |
| lda #>SHOP_FRAME_TOP | |
| sta dsthi | |
| lda #<SHOP_FRAME_TOP | |
| sec ; Skip the left border tile, which is never included | |
| adc shop_frame_left,x | |
| sta dstlo | |
| ldy #0 | |
| rowloop: | |
| lda dsthi | |
| sta PPUADDR | |
| lda dstlo | |
| sta PPUADDR | |
| clc | |
| adc #32 | |
| sta dstlo | |
| bcc :+ | |
| inc dsthi | |
| : | |
| ldx #(SHOP_FRAME_WID - 2)/2 | |
| byteloop: | |
| .repeat 2 | |
| lda lineImgBuf,y | |
| sta PPUDATA | |
| iny | |
| .endrepeat | |
| dex | |
| bne byteloop | |
| cpy #(SHOP_FRAME_WID - 2)*SHOP_FRAME_HT | |
| bcc rowloop | |
| rts | |
| .endproc | |