; Copyright (C) 2019 Christophe Meneboeuf ; ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . .include "world.inc" .include "memory.inc" .include "math.inc" .include "monitor.inc" .include "io/gr.inc" ; inits display of map .export Display_Map_Init ; displays the map and reacts to keyboard input .export Map_Loop ; displays the map .export Display_Map_Show .define DBG_DISP_WIDTH 40 .define DBG_DISP_HEIGHT 48 .BSS Map_x: .byte 1 Map_y: .byte 1 .define MAX_Y HEIGHT_WORLD - DBG_DISP_HEIGHT .define MAX_X WIDTH_WORLD - DBG_DISP_WIDTH .CODE .define KEY_UP $C9 .define KEY_LEFT $CA .define KEY_DOWN $CB .define KEY_RIGHT $CC .define TAB $89 ; ##################### MAP ################## ; Buffer to save the 4 bottom line of gr1 SAVED_GR_L36: .res 40 SAVED_GR_L37: .res 40 SAVED_GR_L38: .res 40 SAVED_GR_L39: .res 40 ; The 4 bottom lines of GR1 .define SRC_GR1_L36 $650 .define SRC_GR1_L37 $6D0 .define SRC_GR1_L38 $750 .define SRC_GR1_L39 $7D0 ; @brief Displays the map and wait for action: move the view or exit Map_Loop: ; save the 4 last lines of GR1 ldx #39 loop_save_gr: lda SRC_GR1_L36, X sta SAVED_GR_L36, X lda SRC_GR1_L37, X sta SAVED_GR_L37, X lda SRC_GR1_L38, X sta SAVED_GR_L38, X lda SRC_GR1_L39, X sta SAVED_GR_L39, X dex bne loop_save_gr lda SRC_GR1_L36, X sta SAVED_GR_L36, X lda SRC_GR1_L37, X sta SAVED_GR_L37, X lda SRC_GR1_L38, X sta SAVED_GR_L38, X lda SRC_GR1_L39, X sta SAVED_GR_L39, X disp: ; display map ;sta $C051 ; full screen sta $C054 ; page 1 sta $C056 ; lores sta $C050 ; gfx sta $C052 ; mixed mode off ldx Map_x ldy Map_y ; capping X and Y min_x: cpx #$FF bne max_x ldx #0 bvc min_y max_x: cpx #MAX_X bcc min_y ldx #MAX_X min_y: cpy #$FF bne max_y ldy #0 bvc disp_map max_y: cpy #MAX_Y bcc disp_map ldy #MAX_Y disp_map: stx Map_x sty Map_y jsr Display_Map_Show ; waiting for a key to be pressed kbd_loop: lda KEYBD bpl kbd_loop ; bit #8 is set when a character is present (thus A < 0) sta KEYBD_STROBE cmp #KEY_UP beq move_up cmp #KEY_RIGHT beq move_right cmp #KEY_DOWN beq move_down cmp #KEY_LEFT beq move_left cmp #TAB beq quit jmp kbd_loop move_up: dec Map_y jmp disp move_right: inc Map_x jmp disp move_down: inc Map_y jmp disp move_left: dec Map_x jmp disp quit: ; restore player's view ;sta $C054 ; page 1 sta $C057 ; hires sta $C053 ; mixed mode on ; restore the 4 last lines of GR1 ldx #39 loop_restore_gr: lda SAVED_GR_L36, X sta SRC_GR1_L36, X lda SAVED_GR_L37, X sta SRC_GR1_L37, X lda SAVED_GR_L38, X sta SRC_GR1_L38, X lda SAVED_GR_L39, X sta SRC_GR1_L39, X dex bne loop_restore_gr lda SAVED_GR_L36, X sta SRC_GR1_L36, X lda SAVED_GR_L37, X sta SRC_GR1_L37, X lda SAVED_GR_L38, X sta SRC_GR1_L38, X lda SAVED_GR_L39, X sta SRC_GR1_L39, X rts Display_Map_Init: ; Init coords to view map lda #0 sta Map_x sta Map_y jsr Clear_Gr1 ; display GR1 sta $C051 ; full screen sta $C054 ; page 1 sta $C056 ; lores sta $C050 ; gfx sta $C052 ; mixed mode off rts .import World .define SRC_LINE_UP ZERO_7_1 .define SRC_LINE_DOWN ZERO_8_1 .define SRC_OFFSET ZERO_5_5 .define DST_GR1 ZERO_5_5 .define CPT_FILL ZERO_5_4 Addr_GR1: ; 3 address blocks to fill GR1 (address -1), stored in reversed endianess. .word $4F04, $2704, $FF03 ; @brief Displays the map in GR1 screen ; @param X top-left x coordinate ; @param Y top-left y coordinate ; X, Y capped by WITH_WOLRD - GR_WIDTH, HEIGHT_WORLD - GR_HEIGHT ; The code in "copy_8x2_lines" copies 16 lines from World ; It is called 3 times to fill the entire screen. Each line ; is two tile heigh. Display_Map_Show: ; display GR1 sta $C051 ; full screen sta $C054 ; page 1 sta $C056 ; lores sta $C050 ; gfx sta $C052 ; mixed mode off ld_src: ; compute offset stx ZERO_5_4 sty FAC1 lda #WIDTH_WORLD sta FAC2 jsr mul8 sta SRC_OFFSET+1 txa clc adc ZERO_5_4 sta SRC_OFFSET lda SRC_OFFSET+1 adc #0 sta SRC_OFFSET+1 ; source address in World lda #<(World-1) clc adc SRC_OFFSET sta SRC_LINE_UP lda #>(World-1) adc SRC_OFFSET+1 sta SRC_LINE_UP+1 lda SRC_LINE_UP clc adc #WIDTH_WORLD sta SRC_LINE_DOWN lda SRC_LINE_UP+1 adc #0 sta SRC_LINE_DOWN+1 ldx #5 stx CPT_FILL ; destination adress in GR1. lda Addr_GR1,X sta DST_GR1 dex lda Addr_GR1,X sta DST_GR1+1 dex stx CPT_FILL fill: ldx #8 copy_8x2_lines: ; call 3 times to fill the screen ldy #DBG_DISP_WIDTH copy_2_lines: lda (SRC_LINE_DOWN),Y asl asl asl asl ora (SRC_LINE_UP),Y sta (DST_GR1), Y dey bne copy_2_lines ; update source lda SRC_LINE_UP clc adc #(2*WIDTH_WORLD) sta SRC_LINE_UP lda SRC_LINE_UP+1 adc #0 sta SRC_LINE_UP+1 lda SRC_LINE_DOWN clc adc #(2*WIDTH_WORLD) sta SRC_LINE_DOWN lda SRC_LINE_DOWN+1 adc #0 sta SRC_LINE_DOWN+1 ; update destination clc lda DST_GR1 adc #$80 sta DST_GR1 lda DST_GR1+1 adc #0 sta DST_GR1+1 dex bne copy_8x2_lines ; destination adress in GR1. ldx CPT_FILL lda Addr_GR1,X sta DST_GR1 dex lda Addr_GR1,X sta DST_GR1+1 dex stx CPT_FILL cpx #$FD bne fill rts