mirror of
https://codeberg.org/hkzlab/TK2048.git
synced 2025-12-25 10:52:15 +11:00
Squashed commit of the following:
commitce479dacb9Author: hkz <tabaglio@posteo.net> Date: Fri Oct 17 09:31:15 2025 +0200 Update README and CHANGELOG commit6840e57190Author: hkz <tabaglio@posteo.net> Date: Wed Oct 15 13:25:23 2025 +0200 Rework graphics commit0f0fe3ecb7Author: hkz <tabaglio@posteo.net> Date: Wed Oct 15 13:10:55 2025 +0200 Rework graphics commitf258d81f73Author: hkz <tabaglio@posteo.net> Date: Wed Oct 15 12:54:29 2025 +0200 Rework colors commit631097903bAuthor: hkz <tabaglio@posteo.net> Date: Wed Oct 15 09:24:59 2025 +0200 Centralize versioning commit3219687fd7Author: hkz <tabaglio@posteo.net> Date: Wed Oct 15 07:38:55 2025 +0200 move some definitions outside of utility.h commit07d054ea51Author: hkz <tabaglio@posteo.net> Date: Tue Oct 14 14:03:24 2025 +0200 Tweak some initialization code commitd920f68139Author: hkz <tabaglio@posteo.net> Date: Tue Oct 14 11:04:53 2025 +0200 Reworked wait time before making a move in demo mode commita3425993b1Author: hkz <tabaglio@posteo.net> Date: Tue Oct 14 08:57:48 2025 +0200 Tweak strings to indicate DEMO mode commit46f3662322Author: hkz <tabaglio@posteo.net> Date: Tue Oct 14 08:39:41 2025 +0200 Rewritten the irq handler commit2999c7c218Author: hkz <tabaglio@posteo.net> Date: Mon Oct 13 21:10:54 2025 +0200 fix saving commite7a5006a4aAuthor: hkz <tabaglio@posteo.net> Date: Mon Oct 13 21:00:29 2025 +0200 nitial working version for the VDP commit735513e5c8Author: hkz <tabaglio@posteo.net> Date: Mon Oct 13 19:36:20 2025 +0200 Fix game mode commit76fed16432Author: hkz <tabaglio@posteo.net> Date: Mon Oct 13 18:59:02 2025 +0200 Re-enable partial drawing commitf5cfc0f5daAuthor: hkz <tabaglio@posteo.net> Date: Mon Oct 13 18:46:08 2025 +0200 Use signed arithmetics for game logic commit5348adcd72Author: hkz <tabaglio@posteo.net> Date: Mon Oct 13 17:53:49 2025 +0200 Enable tiles redrawing commit31018463adAuthor: hkz <tabaglio@posteo.net> Date: Mon Oct 13 17:48:52 2025 +0200 Fix joystick code commit7c4385972dAuthor: hkz <tabaglio@posteo.net> Date: Mon Oct 13 17:24:13 2025 +0200 Begin fixing game code commit78604e6f7dAuthor: hkz <tabaglio@posteo.net> Date: Mon Oct 13 16:24:29 2025 +0200 Begin writing code to update the tiles commit26e94d2957Author: hkz <tabaglio@posteo.net> Date: Mon Oct 13 11:43:41 2025 +0200 Begin wiring in the VDP code in the game module commit28a1fbfc18Author: hkz <tabaglio@posteo.net> Date: Mon Oct 13 10:09:43 2025 +0200 Implement (untested) code to draw joystick commitd3d2207b4fAuthor: hkz <tabaglio@posteo.net> Date: Mon Oct 13 08:44:00 2025 +0200 Add dummy demo and game modules for VDP commit5deb0d802fAuthor: hkz <tabaglio@posteo.net> Date: Sun Oct 12 21:27:15 2025 +0200 Update the charset commitd2cd7356ecAuthor: hkz <tabaglio@posteo.net> Date: Sun Oct 12 21:19:43 2025 +0200 Tweak nametable for the dialog commitdd0e5ce53dAuthor: hkz <tabaglio@posteo.net> Date: Sun Oct 12 21:12:24 2025 +0200 Integrate the new dialog module for the VDP commitb4469d514cAuthor: hkz <tabaglio@posteo.net> Date: Sun Oct 12 15:25:31 2025 +0200 Add dummy module for VDP dialog commitd1dcdd1381Author: hkz <tabaglio@posteo.net> Date: Sun Oct 12 12:15:23 2025 +0200 Add initializer module for VDP commitfd84d3abbbAuthor: hkz <tabaglio@posteo.net> Date: Tue Oct 7 20:15:46 2025 +0200 Begin defining binaries commitbd650081fcAuthor: hkz <tabaglio@posteo.net> Date: Tue Oct 7 15:02:56 2025 +0200 Add resources for two screens of the VDP version commit58f7436c45Author: hkz <tabaglio@posteo.net> Date: Tue Oct 7 12:52:38 2025 +0200 Add a module list with defines commit969fe9deabAuthor: hkz <tabaglio@posteo.net> Date: Tue Oct 7 12:35:40 2025 +0200 Additional renaming commit83552c2ad8Author: hkz <tabaglio@posteo.net> Date: Tue Oct 7 12:14:27 2025 +0200 Rename other graphic files, remove unused imports commitdbc1bebf9fAuthor: hkz <tabaglio@posteo.net> Date: Tue Oct 7 11:59:16 2025 +0200 Begin renaming graphic files to mention they're for HGR
This commit is contained in:
parent
49232e5887
commit
4fd200b7b7
43 changed files with 2545 additions and 674 deletions
|
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## 3.0 - 2025-10-17
|
||||
|
||||
### Added
|
||||
|
||||
- Support for the TK2000 VDP board
|
||||
|
||||
|
||||
## 2.1 - 2025-10-07
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
60
Makefile
60
Makefile
|
|
@ -12,6 +12,10 @@ INTRO_PRG=intro
|
|||
DLOG_PRG=dlog
|
||||
GAME_PRG=game
|
||||
DEMO_PRG=demo
|
||||
VDPIN_PRG=vdpin
|
||||
VDDLG_PRG=vddlg
|
||||
VDGAM_PRG=vdgam
|
||||
VDDEM_PRG=vddem
|
||||
|
||||
# Libraries
|
||||
LIBS=clib-6502.a
|
||||
|
|
@ -19,17 +23,29 @@ LIBS=clib-6502.a
|
|||
MASTER_ASM_SRCS = tk2k_startup_master.s disk2.s master_func.s
|
||||
MASTER_C_SRCS = master_main.c dos_floppy.c utility.c
|
||||
|
||||
INTRO_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s
|
||||
INTRO_C_SRCS = intro_main.c utility.c
|
||||
INTRO_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s vdp.s vdp_utils.s
|
||||
INTRO_C_SRCS = intro_main.c utility.c input.c
|
||||
|
||||
DLOG_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s sound.s
|
||||
DLOG_C_SRCS = dlog_main.c input.c utility.c game_graphics.c line_data.c
|
||||
DLOG_C_SRCS = dlog_main.c input.c utility.c game_hgr_graphics.c hgr_line_data.c
|
||||
|
||||
GAME_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s
|
||||
GAME_C_SRCS = game_main.c input.c utility.c game_graphics.c line_data.c game_logic.c arrows_pic.c tiles.c graph_misc_data.c
|
||||
GAME_C_SRCS = game_main.c input.c utility.c game_hgr_graphics.c hgr_line_data.c game_logic.c arrows_pic.c tiles.c hgr_graph_misc_data.c
|
||||
|
||||
DEMO_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s
|
||||
DEMO_C_SRCS = demo_main.c input.c utility.c game_graphics_demo.c line_data.c game_logic.c arrows_pic.c tiles.c graph_misc_data.c
|
||||
DEMO_C_SRCS = demo_main.c input.c utility.c game_hgr_graphics_demo.c hgr_line_data.c game_logic.c arrows_pic.c tiles.c hgr_graph_misc_data.c
|
||||
|
||||
VDPIN_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s vdp.s vdp_utils.s vdp_init.s
|
||||
VDPIN_C_SRCS = vdpin_main.c utility.c
|
||||
|
||||
VDDLG_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s sound.s vdp.s vdp_utils.s game_vdp_graphics.s
|
||||
VDDLG_C_SRCS = vddlg_main.c input.c utility.c
|
||||
|
||||
VDGAM_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s vdp.s vdp_utils.s game_vdp_graphics.s
|
||||
VDGAM_C_SRCS = vdgam_main.c input.c utility.c game_logic.c
|
||||
|
||||
VDDEM_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s vdp.s vdp_utils.s game_vdp_graphics.s
|
||||
VDDEM_C_SRCS = vddem_main.c input.c utility.c game_logic.c
|
||||
|
||||
# Object files
|
||||
MASTER_OBJS = $(MASTER_ASM_SRCS:%.s=%.o) $(MASTER_C_SRCS:%.c=%.o)
|
||||
|
|
@ -37,6 +53,10 @@ INTRO_OBJS = $(INTRO_ASM_SRCS:%.s=%.o) $(INTRO_C_SRCS:%.c=%.o)
|
|||
DLOG_OBJS = $(DLOG_ASM_SRCS:%.s=%.o) $(DLOG_C_SRCS:%.c=%.o)
|
||||
GAME_OBJS = $(GAME_ASM_SRCS:%.s=%.o) $(GAME_C_SRCS:%.c=%.o)
|
||||
DEMO_OBJS = $(DEMO_ASM_SRCS:%.s=%.o) $(DEMO_C_SRCS:%.c=%.o)
|
||||
VDPIN_OBJS = $(VDPIN_ASM_SRCS:%.s=%.o) $(VDPIN_C_SRCS:%.c=%.o)
|
||||
VDDLG_OBJS = $(VDDLG_ASM_SRCS:%.s=%.o) $(VDDLG_C_SRCS:%.c=%.o)
|
||||
VDGAM_OBJS = $(VDGAM_ASM_SRCS:%.s=%.o) $(VDGAM_C_SRCS:%.c=%.o)
|
||||
VDDEM_OBJS = $(VDDEM_ASM_SRCS:%.s=%.o) $(VDDEM_C_SRCS:%.c=%.o)
|
||||
|
||||
all: $(SW_NAME).woz
|
||||
|
||||
|
|
@ -61,6 +81,18 @@ $(GAME_PRG).hex: $(GAME_OBJS)
|
|||
$(DEMO_PRG).hex: $(DEMO_OBJS)
|
||||
(cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code)
|
||||
|
||||
$(VDPIN_PRG).hex: $(VDPIN_OBJS)
|
||||
(cd obj ; ln6502 -g ../linker-files/vdpin_module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code)
|
||||
|
||||
$(VDDLG_PRG).hex: $(VDDLG_OBJS)
|
||||
(cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code)
|
||||
|
||||
$(VDGAM_PRG).hex: $(VDGAM_OBJS)
|
||||
(cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code)
|
||||
|
||||
$(VDDEM_PRG).hex: $(VDDEM_OBJS)
|
||||
(cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code)
|
||||
|
||||
$(MASTER_PRG).bin: $(MASTER_PRG).hex
|
||||
(cd out ; objcopy -I ihex -O binary $(MASTER_PRG).hex $(MASTER_PRG).bin)
|
||||
|
||||
|
|
@ -75,14 +107,30 @@ $(GAME_PRG).bin: $(GAME_PRG).hex
|
|||
|
||||
$(DEMO_PRG).bin: $(DEMO_PRG).hex
|
||||
(cd out ; objcopy -I ihex -O binary $(DEMO_PRG).hex $(DEMO_PRG).bin)
|
||||
|
||||
$(VDPIN_PRG).bin: $(VDPIN_PRG).hex
|
||||
(cd out ; objcopy -I ihex -O binary $(VDPIN_PRG).hex $(VDPIN_PRG).bin)
|
||||
|
||||
$(SW_NAME).dsk: $(MASTER_PRG).bin $(INTRO_PRG).bin $(DLOG_PRG).bin $(GAME_PRG).bin $(DEMO_PRG).bin
|
||||
$(VDDLG_PRG).bin: $(VDDLG_PRG).hex
|
||||
(cd out ; objcopy -I ihex -O binary $(VDDLG_PRG).hex $(VDDLG_PRG).bin)
|
||||
|
||||
$(VDGAM_PRG).bin: $(VDGAM_PRG).hex
|
||||
(cd out ; objcopy -I ihex -O binary $(VDGAM_PRG).hex $(VDGAM_PRG).bin)
|
||||
|
||||
$(VDDEM_PRG).bin: $(VDDEM_PRG).hex
|
||||
(cd out ; objcopy -I ihex -O binary $(VDDEM_PRG).hex $(VDDEM_PRG).bin)
|
||||
|
||||
$(SW_NAME).dsk: $(MASTER_PRG).bin $(INTRO_PRG).bin $(DLOG_PRG).bin $(GAME_PRG).bin $(DEMO_PRG).bin $(VDPIN_PRG).bin $(VDDLG_PRG).bin $(VDGAM_PRG).bin $(VDDEM_PRG).bin
|
||||
(cd out ; cp ../dsk/TK2048_AUTO_BRUN.dsk ./$(SW_NAME).dsk; \
|
||||
cat $(MASTER_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk HELLO B 0x800; \
|
||||
cat $(INTRO_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk INTRO b; \
|
||||
cat $(DLOG_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk DLOG b; \
|
||||
cat $(GAME_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk GAME b; \
|
||||
cat $(DEMO_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk DEMO b; \
|
||||
cat $(VDPIN_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDPIN b; \
|
||||
cat $(VDDLG_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDDLG b; \
|
||||
cat $(VDGAM_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDGAM b; \
|
||||
cat $(VDDEM_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDDEM b; \
|
||||
cat ../data/LOADS.bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk LOADS b; \
|
||||
cat ../data/STATE.bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk STATE b;)
|
||||
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -35,6 +35,7 @@ If you wish to support me in building new hardware and software for old machines
|
|||
The game is playable, and the following features have been implemented:
|
||||
|
||||
- B/W mode
|
||||
- VDP board support
|
||||
- Single graphical tileset
|
||||
- Simple sound effects
|
||||
- Control via keyboard
|
||||
|
|
@ -52,6 +53,17 @@ The game is playable, and the following features have been implemented:
|
|||
|
||||
The game ends once you reach a tile with a value of 2048.
|
||||
|
||||
### VDP support
|
||||
|
||||
The game supports the [TK2000 VDP board](https://codeberg.org/hkzlab/TK2000_VDPboard) configured at address `C0Cx`.
|
||||
|
||||

|
||||
|
||||
The card gets automatically detected and used: once the game completes the initial load, everything will be displayed on the screen
|
||||
connected to the VDP board, and the main screen connected to the TK2000 will be left blank.
|
||||
|
||||
If you want to override detection and force the use of the main screen, just keep a button pressed while the title screen image loads.
|
||||
|
||||
### Floppy version
|
||||
|
||||
Just put your floppy in the first drive and power on the TK2000. It will autoboot.
|
||||
|
|
|
|||
BIN
data/vdp_charset.bin
Normal file
BIN
data/vdp_charset.bin
Normal file
Binary file not shown.
BIN
data/vdp_colortable.bin
Normal file
BIN
data/vdp_colortable.bin
Normal file
Binary file not shown.
BIN
data/vdp_nt_board.bin
Normal file
BIN
data/vdp_nt_board.bin
Normal file
Binary file not shown.
BIN
data/vdp_nt_dialog.bin
Normal file
BIN
data/vdp_nt_dialog.bin
Normal file
Binary file not shown.
BIN
data/vdp_sprite_tiles.bin
Normal file
BIN
data/vdp_sprite_tiles.bin
Normal file
Binary file not shown.
|
|
@ -1,19 +1,19 @@
|
|||
(define memories
|
||||
'((memory zeroPage (address (#x56 . #xff)) (type ram)
|
||||
(section registers zpage zzpage))
|
||||
(memory firstPage (address (#x100 . #x1ff)) (section stack))
|
||||
(memory reserved (address (#x200 . #x1fff)) (type ram))
|
||||
(memory displayPage1 (address (#x2000 . #x3fff)) (type ram))
|
||||
(memory upperProg (address (#x4000 . #x93ff)) (type ram) (section (programStart #x4000) startup code switch idata cdata data_init_table))
|
||||
(memory upperData (address (#x9400 . #x99ff)) (type ram) (section cstack zdata data heap))
|
||||
(memory sharedMem (address (#x9a00 . #x9bff)) (type ram)) ;;; This memory page will be used to pass parameters and data between the master and the modules, and to save the game state
|
||||
(memory diskBuffer (address (#x9c00 . #x9eff)) (type ram))
|
||||
(memory zeroPageBackup (address (#x9f00 . #x9fff)) (type ram) (section (zpsave #x9f00)))
|
||||
(memory displayPage2 (address (#xa000 . #xbfff)) (type ram))
|
||||
(memory io (address (#xc000 . #xc0ff)) (type ram))
|
||||
(memory rombank (address (#xc100 . #xffff)) (type rom))
|
||||
|
||||
(block cstack (size #x400))
|
||||
(block heap (size #x020))
|
||||
(block stack (size #x100))
|
||||
(define memories
|
||||
'((memory zeroPage (address (#x56 . #xff)) (type ram)
|
||||
(section registers zpage zzpage))
|
||||
(memory firstPage (address (#x100 . #x1ff)) (section stack))
|
||||
(memory reserved (address (#x200 . #x1fff)) (type ram))
|
||||
(memory displayPage1 (address (#x2000 . #x3fff)) (type ram))
|
||||
(memory upperProg (address (#x4000 . #x935f)) (type ram) (section (programStart #x4000) startup code switch idata cdata data_init_table))
|
||||
(memory upperData (address (#x9360 . #x99ff)) (type ram) (section cstack zdata data heap intrzp))
|
||||
(memory sharedMem (address (#x9a00 . #x9bff)) (type ram)) ;;; This memory page will be used to pass parameters and data between the master and the modules, and to save the game state
|
||||
(memory diskBuffer (address (#x9c00 . #x9eff)) (type ram))
|
||||
(memory zeroPageBackup (address (#x9f00 . #x9fff)) (type ram) (section (zpsave #x9f00)))
|
||||
(memory displayPage2 (address (#xa000 . #xbfff)) (type ram))
|
||||
(memory io (address (#xc000 . #xc0ff)) (type ram))
|
||||
(memory rombank (address (#xc100 . #xffff)) (type rom))
|
||||
|
||||
(block cstack (size #x400))
|
||||
(block heap (size #x020))
|
||||
(block stack (size #x100))
|
||||
))
|
||||
19
linker-files/vdpin_module.scm
Normal file
19
linker-files/vdpin_module.scm
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(define memories
|
||||
'((memory zeroPage (address (#x56 . #xff)) (type ram)
|
||||
(section registers zpage zzpage))
|
||||
(memory firstPage (address (#x100 . #x1ff)) (section stack))
|
||||
(memory reserved (address (#x200 . #x1fff)) (type ram))
|
||||
(memory displayPage1 (address (#x2000 . #x3fff)) (type ram))
|
||||
(memory upperProg (address (#x4000 . #x7fff)) (type ram) (section (programStart #x4000) startup code switch idata cdata data_init_table))
|
||||
(memory upperData (address (#x8000 . #x99ff)) (type ram) (section cstack zdata data heap intrzp))
|
||||
(memory sharedMem (address (#x9a00 . #x9bff)) (type ram)) ;;; This memory page will be used to pass parameters and data between the master and the modules, and to save the game state
|
||||
(memory diskBuffer (address (#x9c00 . #x9eff)) (type ram))
|
||||
(memory zeroPageBackup (address (#x9f00 . #x9fff)) (type ram) (section (zpsave #x9f00)))
|
||||
(memory displayPage2 (address (#xa000 . #xbfff)) (type ram))
|
||||
(memory io (address (#xc000 . #xc0ff)) (type ram))
|
||||
(memory rombank (address (#xc100 . #xffff)) (type rom))
|
||||
|
||||
(block cstack (size #x400))
|
||||
(block heap (size #x020))
|
||||
(block stack (size #x100))
|
||||
))
|
||||
BIN
pics/vdp_mode.jpg
Normal file
BIN
pics/vdp_mode.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
|
|
@ -12,9 +12,10 @@
|
|||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "game_logic.h"
|
||||
#include "game_graphics.h"
|
||||
#include "game_hgr_graphics.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "sound.h"
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
|
|
@ -44,7 +45,7 @@ void main(void) {
|
|||
|
||||
// By default, once we return from this, return to the DLOG module and give the master no command to execute
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = 3; // Go to the DLOG module
|
||||
shared_page->next_module_idx = MODULE_DLOG; // Go to the DLOG module
|
||||
|
||||
dlog_data *dld = (dlog_data *)(shared_page->module_data);
|
||||
dlog_data *gad = (dlog_data *)(shared_page->module_data);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "game_graphics.h"
|
||||
#include "game_hgr_graphics.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "sound.h"
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
|
|
@ -54,7 +55,7 @@ void main(void) {
|
|||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
}
|
||||
|
||||
shared_page->next_module_idx = 4; // Go to the GAME module
|
||||
shared_page->next_module_idx = MODULE_GAME; // Go to the GAME module
|
||||
gad->mode = GAME_MODE_NORMAL; // Set the proper start mode for the game
|
||||
|
||||
while(!read_any_key() && (wait_counter != WAIT_COUNTER_END)) {
|
||||
|
|
@ -63,7 +64,7 @@ void main(void) {
|
|||
}
|
||||
|
||||
if (wait_counter == WAIT_COUNTER_END) {
|
||||
shared_page->next_module_idx = 5; // Actually go to the DEMO module
|
||||
shared_page->next_module_idx = MODULE_DEMO; // Actually go to the DEMO module
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
#ifndef _GAME_DATA_HEADER_
|
||||
#define _GAME_DATA_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GAME_MODE_NORMAL 0
|
||||
#define GAME_MODE_LOAD 1
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t mode;
|
||||
} game_data;
|
||||
|
||||
#endif /* _GAME_DATA_HEADER_ */
|
||||
#ifndef _GAME_DATA_HEADER_
|
||||
#define _GAME_DATA_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GAME_VER_CH0 '3'
|
||||
#define GAME_VER_CH1 '.'
|
||||
#define GAME_VER_CH2 '0'
|
||||
|
||||
|
||||
#define GAME_MODE_NORMAL 0
|
||||
#define GAME_MODE_LOAD 1
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t mode;
|
||||
} game_data;
|
||||
|
||||
#endif /* _GAME_DATA_HEADER_ */
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
#define _DEMO_MODE_ 1
|
||||
|
||||
#include "game_graphics.c"
|
||||
|
|
@ -1,16 +1,17 @@
|
|||
#include "game_graphics.h"
|
||||
#include "game_hgr_graphics.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "game_data.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "mem_registers.h"
|
||||
#include "line_data.h"
|
||||
#include "hgr_line_data.h"
|
||||
#include "game_logic.h"
|
||||
#include "tiles.h"
|
||||
#include "charset.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "graph_misc_data.h"
|
||||
#include "hgr_graph_misc_data.h"
|
||||
#include "arrows_pic.h"
|
||||
|
||||
#define SCREEN_WIDTH 280
|
||||
|
|
@ -78,7 +79,7 @@ static const uint8_t box_content_start[BOX_CONTENT_SIZE] = {
|
|||
0, 0, 0, 0, 0, 0, 0,203, 77, 0, 0, 77, 0, 0, 77,192, 77, 0, 77, 77,211, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 77, 77,211, 0, 0, 77, 0, 0, 77, 0, 77, 0, 77,198, 84, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 20, 11, 50, 48, 52, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 50, 46, 49, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 20, 11, 50, 48, 52, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, GAME_VER_CH0, GAME_VER_CH1, GAME_VER_CH2, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
|
@ -106,7 +107,7 @@ static const uint8_t instruction_box[INSTR_BOX_SIZE] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
18, 5, 1, 3, 8, 0, 0, 50, 48, 52, 56, 33,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
79, 0, 50, 48, 50, 53, 0, 50, 46, 49, 0, 79
|
||||
7, 15, 15, 4, 0, 12, 21, 3, 11, 33, 33, 33
|
||||
};
|
||||
|
||||
static const uint8_t demo_box[INSTR_BOX_SIZE] = {
|
||||
|
|
@ -117,7 +118,7 @@ static const uint8_t demo_box[INSTR_BOX_SIZE] = {
|
|||
4, 5, 0, 0, 4, 5, 13, 15, 0, 0, 13, 15,
|
||||
15, 4, 5, 0, 0, 4, 5, 13, 15, 0, 0, 13,
|
||||
13, 15, 4, 5, 0, 0, 4, 5, 13, 15, 0, 0,
|
||||
79, 0, 50, 48, 50, 53, 0, 50, 46, 49, 0, 79
|
||||
0, 13, 15, 4, 5, 0, 0, 4, 5, 13, 15, 0
|
||||
};
|
||||
|
||||
#ifdef _DEMO_MODE_
|
||||
|
|
@ -1,34 +1,34 @@
|
|||
#ifndef _GAME_GRAPHICS_HEADER_
|
||||
#define _GAME_GRAPHICS_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BRD_DOUBLING_UP(a) (a & 0x01)
|
||||
#define BRD_DOUBLING_DOWN(a) (a & 0x02)
|
||||
#define BRD_DOUBLING_LEFT(a) (a & 0x04)
|
||||
#define BRD_DOUBLING_RIGHT(a) (a & 0x08)
|
||||
|
||||
#define BRD_SKIP_UP(a) (a & 0x10)
|
||||
#define BRD_SKIP_DOWN(a) (a & 0x20)
|
||||
#define BRD_SKIP_LEFT(a) (a & 0x40)
|
||||
#define BRD_SKIP_RIGHT(a) (a & 0x80)
|
||||
|
||||
#define GRAPH_ARROW_UP 0
|
||||
#define GRAPH_ARROW_DOWN 1
|
||||
#define GRAPH_ARROW_LEFT 2
|
||||
#define GRAPH_ARROW_RIGHT 3
|
||||
|
||||
void initialize_display_buffers(void);
|
||||
void ddraw_field_borders_on_buffer(uint8_t brd);
|
||||
void draw_game_background(uint16_t hi_score);
|
||||
void draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y);
|
||||
void draw_tiles(void);
|
||||
void ddraw_single_tile(uint8_t offset);
|
||||
void swap_display_buffers(void);
|
||||
void clear_display_buffers(void);
|
||||
void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y, uint8_t *disp_buf);
|
||||
void ddraw_direction_arrows(uint8_t dir);
|
||||
void ddraw_endgame_box(int8_t done, uint16_t score, uint16_t hi_score);
|
||||
void sync_display1_buffer(void);
|
||||
|
||||
#endif /* _GAME_GRAPHICS_HEADER_ */
|
||||
#ifndef _GAME_HGR_GRAPHICS_HEADER_
|
||||
#define _GAME_HGR_GRAPHICS_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BRD_DOUBLING_UP(a) (a & 0x01)
|
||||
#define BRD_DOUBLING_DOWN(a) (a & 0x02)
|
||||
#define BRD_DOUBLING_LEFT(a) (a & 0x04)
|
||||
#define BRD_DOUBLING_RIGHT(a) (a & 0x08)
|
||||
|
||||
#define BRD_SKIP_UP(a) (a & 0x10)
|
||||
#define BRD_SKIP_DOWN(a) (a & 0x20)
|
||||
#define BRD_SKIP_LEFT(a) (a & 0x40)
|
||||
#define BRD_SKIP_RIGHT(a) (a & 0x80)
|
||||
|
||||
#define GRAPH_ARROW_UP 0
|
||||
#define GRAPH_ARROW_DOWN 1
|
||||
#define GRAPH_ARROW_LEFT 2
|
||||
#define GRAPH_ARROW_RIGHT 3
|
||||
|
||||
void initialize_display_buffers(void);
|
||||
void ddraw_field_borders_on_buffer(uint8_t brd);
|
||||
void draw_game_background(uint16_t hi_score);
|
||||
void draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y);
|
||||
void draw_tiles(void);
|
||||
void ddraw_single_tile(uint8_t offset);
|
||||
void swap_display_buffers(void);
|
||||
void clear_display_buffers(void);
|
||||
void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y, uint8_t *disp_buf);
|
||||
void ddraw_direction_arrows(uint8_t dir);
|
||||
void ddraw_endgame_box(int8_t done, uint16_t score, uint16_t hi_score);
|
||||
void sync_display1_buffer(void);
|
||||
|
||||
#endif /* _GAME_HGR_GRAPHICS_HEADER_ */
|
||||
3
src/game_hgr_graphics_demo.c
Normal file
3
src/game_hgr_graphics_demo.c
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#define _DEMO_MODE_ 1
|
||||
|
||||
#include "game_hgr_graphics.c"
|
||||
298
src/game_logic.c
298
src/game_logic.c
|
|
@ -1,149 +1,149 @@
|
|||
#include "game_logic.h"
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static uint8_t game_grid_alpha[GRID_SIDE * GRID_SIDE];
|
||||
static uint8_t game_grid_beta[GRID_SIDE * GRID_SIDE];
|
||||
|
||||
static uint8_t *front_grid = game_grid_alpha;
|
||||
static uint8_t *back_grid = game_grid_beta;
|
||||
|
||||
void swap_grids(void);
|
||||
|
||||
void swap_grids(void) {
|
||||
uint8_t *temp = front_grid;
|
||||
|
||||
front_grid = back_grid;
|
||||
back_grid = temp;
|
||||
}
|
||||
|
||||
uint8_t reset_game(void) {
|
||||
uint8_t score = 0;
|
||||
|
||||
// Clear the back and front grid
|
||||
memset(back_grid, 0, GRID_SIDE * GRID_SIDE);
|
||||
memset(front_grid, 0, GRID_SIDE * GRID_SIDE);
|
||||
|
||||
// Then add two random tiles
|
||||
score += (1 << front_grid[add_random_tile() - 1]);
|
||||
score += (1 << front_grid[add_random_tile() - 1]);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
uint8_t *get_front_grid(void) {
|
||||
return front_grid;
|
||||
}
|
||||
|
||||
uint8_t add_random_tile(void) {
|
||||
uint16_t rand = lfsr_update();
|
||||
uint8_t tile_val = (rand & 0x000F) > 0x0D ? 2 : 1; // ~90% chance of a tile of type 1 (a "2"), 10% of a type 2 (a "4")
|
||||
|
||||
uint8_t free_tiles = 0;
|
||||
uint8_t chosen_tile;
|
||||
|
||||
for (uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) {
|
||||
if (!front_grid[offset]) free_tiles++;
|
||||
}
|
||||
|
||||
if(!free_tiles) return 0;
|
||||
chosen_tile = (rand >> 8) % free_tiles;
|
||||
|
||||
for (uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) {
|
||||
if (!front_grid[offset] && !(chosen_tile--)) {
|
||||
front_grid[offset] = tile_val;
|
||||
return offset + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // Return 0 if we were not able to place the tile, else we return (offset + 1) to indicate where the tile was placed
|
||||
}
|
||||
|
||||
int8_t step_game(uint8_t dir) {
|
||||
int8_t done = 0;
|
||||
uint8_t start_offset;
|
||||
int8_t column_step;
|
||||
int8_t row_step;
|
||||
|
||||
/*
|
||||
* UP: scans TOP to BOTTOM, RIGHT to LEFT
|
||||
* DOWN: scans BOTTOM to TOP, RIGHT to LEFT
|
||||
* LEFT: scans LEFT to RIGHT, TOP to BOTTOM
|
||||
* RIGHT: scans RIGHT to LEFT, TOP to BOTTOM
|
||||
*/
|
||||
|
||||
switch(dir) {
|
||||
case GAME_STEP_UP:
|
||||
start_offset = GRID_SIDE - 1;
|
||||
column_step = GRID_SIDE;
|
||||
row_step = -1;
|
||||
break;
|
||||
case GAME_STEP_DOWN:
|
||||
start_offset = (GRID_SIDE * GRID_SIDE) - 1;
|
||||
column_step = -GRID_SIDE;
|
||||
row_step = -1;
|
||||
break;
|
||||
case GAME_STEP_LEFT:
|
||||
start_offset = 0;
|
||||
column_step = 1;
|
||||
row_step = GRID_SIDE;
|
||||
break;
|
||||
case GAME_STEP_RIGHT:
|
||||
start_offset = GRID_SIDE - 1;
|
||||
column_step = -1;
|
||||
row_step = GRID_SIDE;
|
||||
break;
|
||||
};
|
||||
|
||||
// Clear the back grid
|
||||
memset(back_grid, 0, GRID_SIDE * GRID_SIDE);
|
||||
|
||||
for (uint8_t row = 0; row < GRID_SIDE; row++) {
|
||||
for(uint8_t col = 0; col < GRID_SIDE; col++) {
|
||||
uint8_t current_offset = start_offset + (col * column_step) + (row * row_step);
|
||||
uint8_t sub_col;
|
||||
|
||||
// Search for the first non-zero value in the front grid and copy it in the current place of the back grid (zeroing it in the front)
|
||||
for(sub_col = col; sub_col < GRID_SIDE; sub_col++) {
|
||||
uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step);
|
||||
if(front_grid[sub_col_offset]) {
|
||||
back_grid[current_offset] = front_grid[sub_col_offset];
|
||||
front_grid[sub_col_offset] = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The value is still 0, we found nothing. On to the next row!
|
||||
if (!back_grid[current_offset]) break;
|
||||
|
||||
// Now search if there is an identical value following this one, so we can merge them
|
||||
for(; sub_col < GRID_SIDE; sub_col++) {
|
||||
uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step);
|
||||
if(front_grid[sub_col_offset] == back_grid[current_offset]) {
|
||||
back_grid[current_offset]++; // Merge them (by increasing the value of the current square and removing the merged one)
|
||||
front_grid[sub_col_offset] = 0;
|
||||
|
||||
done += back_grid[current_offset] == 11 ? 1 : 0;
|
||||
break;
|
||||
} else if (front_grid[sub_col_offset]) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
swap_grids();
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
uint16_t calculate_score(void) {
|
||||
uint16_t score = 0;
|
||||
|
||||
for(uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) {
|
||||
if(front_grid[offset]) score += ((uint16_t)1 << front_grid[offset]);
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
#include "game_logic.h"
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static uint8_t game_grid_alpha[GRID_SIDE * GRID_SIDE];
|
||||
static uint8_t game_grid_beta[GRID_SIDE * GRID_SIDE];
|
||||
|
||||
static uint8_t *front_grid = game_grid_alpha;
|
||||
static uint8_t *back_grid = game_grid_beta;
|
||||
|
||||
void swap_grids(void);
|
||||
|
||||
void swap_grids(void) {
|
||||
uint8_t *temp = front_grid;
|
||||
|
||||
front_grid = back_grid;
|
||||
back_grid = temp;
|
||||
}
|
||||
|
||||
uint8_t reset_game(void) {
|
||||
uint8_t score = 0;
|
||||
|
||||
// Clear the back and front grid
|
||||
memset(back_grid, 0, GRID_SIDE * GRID_SIDE);
|
||||
memset(front_grid, 0, GRID_SIDE * GRID_SIDE);
|
||||
|
||||
// Then add two random tiles
|
||||
score += (1 << front_grid[add_random_tile() - 1]);
|
||||
score += (1 << front_grid[add_random_tile() - 1]);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
uint8_t *get_front_grid(void) {
|
||||
return front_grid;
|
||||
}
|
||||
|
||||
uint8_t add_random_tile(void) {
|
||||
uint16_t rand = lfsr_update();
|
||||
uint8_t tile_val = (rand & 0x000F) > 0x0D ? 2 : 1; // ~90% chance of a tile of type 1 (a "2"), 10% of a type 2 (a "4")
|
||||
|
||||
uint8_t free_tiles = 0;
|
||||
uint8_t chosen_tile;
|
||||
|
||||
for (int8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) {
|
||||
if (!front_grid[offset]) free_tiles++;
|
||||
}
|
||||
|
||||
if(!free_tiles) return 0;
|
||||
chosen_tile = (rand >> 8) % free_tiles;
|
||||
|
||||
for (int8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) {
|
||||
if (!front_grid[offset] && !(chosen_tile--)) {
|
||||
front_grid[offset] = tile_val;
|
||||
return offset + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // Return 0 if we were not able to place the tile, else we return (offset + 1) to indicate where the tile was placed
|
||||
}
|
||||
|
||||
int8_t step_game(uint8_t dir) {
|
||||
int8_t done = 0;
|
||||
int8_t start_offset;
|
||||
int8_t column_step;
|
||||
int8_t row_step;
|
||||
|
||||
/*
|
||||
* UP: scans TOP to BOTTOM, RIGHT to LEFT
|
||||
* DOWN: scans BOTTOM to TOP, RIGHT to LEFT
|
||||
* LEFT: scans LEFT to RIGHT, TOP to BOTTOM
|
||||
* RIGHT: scans RIGHT to LEFT, TOP to BOTTOM
|
||||
*/
|
||||
|
||||
switch(dir) {
|
||||
case GAME_STEP_UP:
|
||||
start_offset = GRID_SIDE - 1;
|
||||
column_step = GRID_SIDE;
|
||||
row_step = -1;
|
||||
break;
|
||||
case GAME_STEP_DOWN:
|
||||
start_offset = (GRID_SIDE * GRID_SIDE) - 1;
|
||||
column_step = -GRID_SIDE;
|
||||
row_step = -1;
|
||||
break;
|
||||
case GAME_STEP_LEFT:
|
||||
start_offset = 0;
|
||||
column_step = 1;
|
||||
row_step = GRID_SIDE;
|
||||
break;
|
||||
case GAME_STEP_RIGHT:
|
||||
start_offset = GRID_SIDE - 1;
|
||||
column_step = -1;
|
||||
row_step = GRID_SIDE;
|
||||
break;
|
||||
};
|
||||
|
||||
// Clear the back grid
|
||||
memset(back_grid, 0, GRID_SIDE * GRID_SIDE);
|
||||
|
||||
for (int8_t row = 0; row < GRID_SIDE; row++) {
|
||||
for(int8_t col = 0; col < GRID_SIDE; col++) {
|
||||
uint8_t current_offset = start_offset + (col * column_step) + (row * row_step);
|
||||
uint8_t sub_col;
|
||||
|
||||
// Search for the first non-zero value in the front grid and copy it in the current place of the back grid (zeroing it in the front)
|
||||
for(sub_col = col; sub_col < GRID_SIDE; sub_col++) {
|
||||
uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step);
|
||||
if(front_grid[sub_col_offset]) {
|
||||
back_grid[current_offset] = front_grid[sub_col_offset];
|
||||
front_grid[sub_col_offset] = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The value is still 0, we found nothing. On to the next row!
|
||||
if (!back_grid[current_offset]) break;
|
||||
|
||||
// Now search if there is an identical value following this one, so we can merge them
|
||||
for(; sub_col < GRID_SIDE; sub_col++) {
|
||||
uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step);
|
||||
if(front_grid[sub_col_offset] == back_grid[current_offset]) {
|
||||
back_grid[current_offset]++; // Merge them (by increasing the value of the current square and removing the merged one)
|
||||
front_grid[sub_col_offset] = 0;
|
||||
|
||||
done += back_grid[current_offset] == 11 ? 1 : 0;
|
||||
break;
|
||||
} else if (front_grid[sub_col_offset]) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
swap_grids();
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
uint16_t calculate_score(void) {
|
||||
uint16_t score = 0;
|
||||
|
||||
for(uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) {
|
||||
if(front_grid[offset]) score += ((uint16_t)1 << front_grid[offset]);
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
|
|
|||
331
src/game_main.c
331
src/game_main.c
|
|
@ -1,165 +1,166 @@
|
|||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "shared_page.h"
|
||||
#include "state_page.h"
|
||||
#include "dlog_data.h"
|
||||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "game_logic.h"
|
||||
#include "game_graphics.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "sound.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
#define MOVES_TEXT_X 32
|
||||
#define MOVES_TEXT_Y 61
|
||||
#define MOVES_TEXT_WIDTH 5
|
||||
|
||||
#define SCORE_TEXT_X 32
|
||||
#define SCORE_TEXT_Y 29
|
||||
#define SCORE_TEXT_WIDTH 5
|
||||
|
||||
#define HIGH_TEXT_X 32
|
||||
#define HIGH_TEXT_Y 107
|
||||
|
||||
#define WIN_SCORE_BONUS 10000
|
||||
|
||||
static state_page_data* state_page = (state_page_data*)STATE_PAGE;
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
|
||||
void main(void) {
|
||||
uint16_t moves_count = 0;
|
||||
uint16_t score = 0;
|
||||
int8_t done = 0;
|
||||
|
||||
// By default, once we return from this, return to the DLOG module and give the master no command to execute
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = 3; // Go to the DLOG module
|
||||
|
||||
dlog_data *dld = (dlog_data *)(shared_page->module_data);
|
||||
dlog_data *gad = (dlog_data *)(shared_page->module_data);
|
||||
|
||||
// Make sure the buffers are pointing to the correct memory and are clear
|
||||
clear_display_buffers();
|
||||
|
||||
// Reset the game, calculate the initial score depending on which tiles we randomly get
|
||||
score = reset_game();
|
||||
|
||||
// Load the game
|
||||
if(gad->mode == GAME_MODE_LOAD) {
|
||||
gad->mode = GAME_MODE_NORMAL;
|
||||
|
||||
memcpy(get_front_grid(), (void*)(state_page->save_grid), GRID_SIDE * GRID_SIDE);
|
||||
moves_count = state_page->saved_moves_count;
|
||||
score = calculate_score();
|
||||
|
||||
// We loaded an empty save, just restart the game
|
||||
if (!score) score = reset_game();
|
||||
}
|
||||
|
||||
// Draw the initial state of the game
|
||||
draw_game_background(state_page->hi_score);
|
||||
draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y);
|
||||
draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y);
|
||||
draw_tiles();
|
||||
|
||||
// Swap graphical buffers
|
||||
swap_display_buffers();
|
||||
|
||||
while(1) { // Game loop
|
||||
lfsr_update();
|
||||
|
||||
switch(read_kb()) {
|
||||
case K_UP:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_UP);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_UP);
|
||||
break;
|
||||
case K_DOWN:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_DOWN);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_DOWN);
|
||||
break;
|
||||
case K_LEFT:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_LEFT);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_LEFT);
|
||||
break;
|
||||
case K_RIGHT:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_RIGHT);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_RIGHT);
|
||||
break;
|
||||
case K_CTRL_R:
|
||||
snd_mod_button();
|
||||
score = 0; // We'll reset the score
|
||||
done = -1;
|
||||
break;
|
||||
case K_CTRL_S: // The following two will return early
|
||||
snd_mod_button();
|
||||
memcpy((void*)(state_page->save_grid), get_front_grid(), GRID_SIDE * GRID_SIDE);
|
||||
state_page->saved_moves_count = moves_count;
|
||||
shared_page->master_command = MASTER_COMMAND_SAVE;
|
||||
case K_CTRL_L:
|
||||
snd_mod_button();
|
||||
sync_display1_buffer();
|
||||
shared_page->next_module_idx = 4;
|
||||
gad->mode = GAME_MODE_LOAD;
|
||||
return;
|
||||
default:
|
||||
continue; // Do nothing, loop again
|
||||
}
|
||||
|
||||
// Increase the count of moves we made (unless we lost or reset the game)
|
||||
if(done >= 0) moves_count++;
|
||||
|
||||
// Draw the number of moves
|
||||
draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y);
|
||||
|
||||
// Draw the moved tiles
|
||||
draw_tiles();
|
||||
|
||||
// If we have won, or we got a reset request, break out of this loop
|
||||
if(done) {
|
||||
score += (done > 0) ? WIN_SCORE_BONUS : 0;
|
||||
draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y);
|
||||
swap_display_buffers(); // Make sure we show the latest changes
|
||||
break;
|
||||
}
|
||||
|
||||
// Unable to add a tile: we ran out of space and lost!!!
|
||||
uint8_t random_tile_off = add_random_tile();
|
||||
if(!random_tile_off) {
|
||||
done = -1; // Lost the game
|
||||
break;
|
||||
}
|
||||
|
||||
score = calculate_score();
|
||||
|
||||
// Draw the score
|
||||
draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y);
|
||||
|
||||
swap_display_buffers();
|
||||
|
||||
// Draw the new tile directly on the front buffer, this way we make it appear with an "animation"
|
||||
ddraw_single_tile(random_tile_off - 1);
|
||||
}
|
||||
|
||||
// Sync the display buffers
|
||||
sync_display1_buffer();
|
||||
|
||||
dld->mode = (done > 0) ? DLOG_MODE_WIN : DLOG_MODE_LOSE;
|
||||
dld->score = score;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "shared_page.h"
|
||||
#include "state_page.h"
|
||||
#include "dlog_data.h"
|
||||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "game_logic.h"
|
||||
#include "game_hgr_graphics.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "sound.h"
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
#define MOVES_TEXT_X 32
|
||||
#define MOVES_TEXT_Y 61
|
||||
#define MOVES_TEXT_WIDTH 5
|
||||
|
||||
#define SCORE_TEXT_X 32
|
||||
#define SCORE_TEXT_Y 29
|
||||
#define SCORE_TEXT_WIDTH 5
|
||||
|
||||
#define HIGH_TEXT_X 32
|
||||
#define HIGH_TEXT_Y 107
|
||||
|
||||
#define WIN_SCORE_BONUS 10000
|
||||
|
||||
static state_page_data* state_page = (state_page_data*)STATE_PAGE;
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
|
||||
void main(void) {
|
||||
uint16_t moves_count = 0;
|
||||
uint16_t score = 0;
|
||||
int8_t done = 0;
|
||||
|
||||
// By default, once we return from this, return to the DLOG module and give the master no command to execute
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = MODULE_DLOG; // Go to the DLOG module
|
||||
|
||||
dlog_data *dld = (dlog_data *)(shared_page->module_data);
|
||||
dlog_data *gad = (dlog_data *)(shared_page->module_data);
|
||||
|
||||
// Make sure the buffers are pointing to the correct memory and are clear
|
||||
clear_display_buffers();
|
||||
|
||||
// Reset the game, calculate the initial score depending on which tiles we randomly get
|
||||
score = reset_game();
|
||||
|
||||
// Load the game
|
||||
if(gad->mode == GAME_MODE_LOAD) {
|
||||
gad->mode = GAME_MODE_NORMAL;
|
||||
|
||||
memcpy(get_front_grid(), (void*)(state_page->save_grid), GRID_SIDE * GRID_SIDE);
|
||||
moves_count = state_page->saved_moves_count;
|
||||
score = calculate_score();
|
||||
|
||||
// We loaded an empty save, just restart the game
|
||||
if (!score) score = reset_game();
|
||||
}
|
||||
|
||||
// Draw the initial state of the game
|
||||
draw_game_background(state_page->hi_score);
|
||||
draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y);
|
||||
draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y);
|
||||
draw_tiles();
|
||||
|
||||
// Swap graphical buffers
|
||||
swap_display_buffers();
|
||||
|
||||
while(1) { // Game loop
|
||||
lfsr_update();
|
||||
|
||||
switch(read_kb()) {
|
||||
case K_UP:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_UP);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_UP);
|
||||
break;
|
||||
case K_DOWN:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_DOWN);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_DOWN);
|
||||
break;
|
||||
case K_LEFT:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_LEFT);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_LEFT);
|
||||
break;
|
||||
case K_RIGHT:
|
||||
SND_TAP();
|
||||
done = step_game(GAME_STEP_RIGHT);
|
||||
ddraw_direction_arrows(GRAPH_ARROW_RIGHT);
|
||||
break;
|
||||
case K_CTRL_R:
|
||||
snd_mod_button();
|
||||
score = 0; // We'll reset the score
|
||||
done = -1;
|
||||
break;
|
||||
case K_CTRL_S: // The following two will return early
|
||||
snd_mod_button();
|
||||
memcpy((void*)(state_page->save_grid), get_front_grid(), GRID_SIDE * GRID_SIDE);
|
||||
state_page->saved_moves_count = moves_count;
|
||||
shared_page->master_command = MASTER_COMMAND_SAVE;
|
||||
case K_CTRL_L:
|
||||
snd_mod_button();
|
||||
sync_display1_buffer();
|
||||
shared_page->next_module_idx = MODULE_GAME;
|
||||
gad->mode = GAME_MODE_LOAD;
|
||||
return;
|
||||
default:
|
||||
continue; // Do nothing, loop again
|
||||
}
|
||||
|
||||
// Increase the count of moves we made (unless we lost or reset the game)
|
||||
if(done >= 0) moves_count++;
|
||||
|
||||
// Draw the number of moves
|
||||
draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y);
|
||||
|
||||
// Draw the moved tiles
|
||||
draw_tiles();
|
||||
|
||||
// If we have won, or we got a reset request, break out of this loop
|
||||
if(done) {
|
||||
score += (done > 0) ? WIN_SCORE_BONUS : 0;
|
||||
draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y);
|
||||
swap_display_buffers(); // Make sure we show the latest changes
|
||||
break;
|
||||
}
|
||||
|
||||
// Unable to add a tile: we ran out of space and lost!!!
|
||||
uint8_t random_tile_off = add_random_tile();
|
||||
if(!random_tile_off) {
|
||||
done = -1; // Lost the game
|
||||
break;
|
||||
}
|
||||
|
||||
score = calculate_score();
|
||||
|
||||
// Draw the score
|
||||
draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y);
|
||||
|
||||
swap_display_buffers();
|
||||
|
||||
// Draw the new tile directly on the front buffer, this way we make it appear with an "animation"
|
||||
ddraw_single_tile(random_tile_off - 1);
|
||||
}
|
||||
|
||||
// Sync the display buffers
|
||||
sync_display1_buffer();
|
||||
|
||||
dld->mode = (done > 0) ? DLOG_MODE_WIN : DLOG_MODE_LOSE;
|
||||
dld->score = score;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
19
src/game_vdp_graphics.h
Normal file
19
src/game_vdp_graphics.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _GAME_VDP_GRAPHICS_HEADER_
|
||||
#define _GAME_VDP_GRAPHICS_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define JS_POS_CENTER 0
|
||||
#define JS_POS_UP 1
|
||||
#define JS_POS_DOWN 2
|
||||
#define JS_POS_LEFT 3
|
||||
#define JS_POS_RIGHT 4
|
||||
|
||||
|
||||
void vdp_clear_gamegrid(void);
|
||||
void vdp_clear_dialog(void);
|
||||
uint8_t vdp_draw_numtile(uint8_t type, uint8_t x, uint8_t y);
|
||||
void vdp_redraw_tiles(uint8_t *grid);
|
||||
void vdp_draw_joystick(uint8_t position);
|
||||
|
||||
#endif /* _GAME_VDP_GRAPHICS_HEADER_ */
|
||||
323
src/game_vdp_graphics.s
Normal file
323
src/game_vdp_graphics.s
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
.rtmodel version,"1"
|
||||
.rtmodel core,"6502"
|
||||
|
||||
.extern _Zp
|
||||
.extern VDP_MEM, VDP_REG
|
||||
|
||||
.extern vdp_point_to_vram_xy, vdp_hide_sprite, vdp_show_sprite, vdp_set_sprite_tile
|
||||
|
||||
NUM_TILE_OFFSET: .equ 0x14
|
||||
|
||||
.section code,text
|
||||
|
||||
vdp_redraw_tiles:
|
||||
P_GRID_H$: .equ _Zp+9
|
||||
P_GRID_L$: .equ _Zp+8
|
||||
|
||||
lda zp:_Zp+0
|
||||
sta zp:P_GRID_L$
|
||||
lda zp:_Zp+1
|
||||
sta zp:P_GRID_H$
|
||||
|
||||
ldy #24
|
||||
SetSprtLoop$:
|
||||
lda (zp:P_GRID_L$),y
|
||||
bne SkipHide$
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
jsr vdp_hide_sprite
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
jmp SkipSprite$
|
||||
SkipHide$:
|
||||
sta zp:_Zp+0
|
||||
dec zp:_Zp+0
|
||||
tya
|
||||
pha
|
||||
jsr vdp_set_sprite_tile
|
||||
pla
|
||||
tay
|
||||
pha
|
||||
jsr vdp_show_sprite
|
||||
pla
|
||||
tay
|
||||
SkipSprite$:
|
||||
dey
|
||||
bpl SetSprtLoop$
|
||||
|
||||
ldy #24
|
||||
SetTileLoop$:
|
||||
tya
|
||||
pha
|
||||
lda TileNum_To_X_Map,y
|
||||
sta zp:_Zp+0
|
||||
lda TileNum_To_Y_Map,y
|
||||
sta zp:_Zp+1
|
||||
lda (zp:P_GRID_L$),y
|
||||
|
||||
jsr vdp_draw_numtile
|
||||
|
||||
pla
|
||||
tay
|
||||
dey
|
||||
bpl SetTileLoop$
|
||||
|
||||
rts
|
||||
|
||||
vdp_draw_joystick:
|
||||
T_NT_IDX$: .equ _Zp+4
|
||||
P_POS$: .equ _Zp+2
|
||||
T_Y$: .equ _Zp+1
|
||||
T_X$: .equ _Zp+0
|
||||
|
||||
pha
|
||||
|
||||
ldx #0
|
||||
stx zp:T_NT_IDX$
|
||||
|
||||
; Clear the table
|
||||
lda #29
|
||||
sta zp:T_X$
|
||||
lda #16
|
||||
sta zp:T_Y$
|
||||
jsr vdp_point_to_vram_xy
|
||||
lda #0
|
||||
sta VDP_MEM
|
||||
nop
|
||||
|
||||
lda #29
|
||||
sta zp:T_X$
|
||||
lda #18
|
||||
sta zp:T_Y$
|
||||
jsr vdp_point_to_vram_xy
|
||||
lda #0
|
||||
sta VDP_MEM
|
||||
nop
|
||||
|
||||
lda #28
|
||||
sta zp:T_X$
|
||||
lda #17
|
||||
sta zp:T_Y$
|
||||
jsr vdp_point_to_vram_xy
|
||||
lda #0
|
||||
sta VDP_MEM
|
||||
nop ; Slow down, we're using this while the IC is rendering
|
||||
nop
|
||||
sta VDP_MEM
|
||||
nop
|
||||
nop
|
||||
sta VDP_MEM
|
||||
nop
|
||||
nop
|
||||
|
||||
; Jump to the correct code to handle joystick drawing
|
||||
pla
|
||||
asl a
|
||||
tax
|
||||
lda _draw_joystick_jumptable$,x
|
||||
sta zp:_Zp+0
|
||||
lda _draw_joystick_jumptable$+1,x
|
||||
sta zp:_Zp+1
|
||||
sec
|
||||
jmp (_Zp+0)
|
||||
|
||||
J_Center$:
|
||||
ldx #29
|
||||
ldy #17
|
||||
bcs J_Done$
|
||||
J_Up$:
|
||||
ldx #29
|
||||
ldy #16
|
||||
bcs J_Done$
|
||||
J_Down$:
|
||||
ldx #29
|
||||
ldy #18
|
||||
bcs J_Done$
|
||||
J_Left$:
|
||||
ldx #28
|
||||
ldy #17
|
||||
bcs J_Done$
|
||||
J_Right$:
|
||||
ldx #30
|
||||
ldy #17
|
||||
J_Done$:
|
||||
stx zp:T_X$
|
||||
sty zp:T_Y$
|
||||
jsr vdp_point_to_vram_xy
|
||||
lda #120
|
||||
sta VDP_MEM
|
||||
nop
|
||||
nop
|
||||
|
||||
rts
|
||||
_draw_joystick_jumptable$:
|
||||
.word J_Center$
|
||||
.word J_Up$
|
||||
.word J_Down$
|
||||
.word J_Left$
|
||||
.word J_Right$
|
||||
|
||||
vdp_clear_gamegrid:
|
||||
T_NT_IDX$: .equ _Zp+4
|
||||
T_Y$: .equ _Zp+1
|
||||
T_X$: .equ _Zp+0
|
||||
|
||||
|
||||
lda #0x00
|
||||
sta zp:T_NT_IDX$
|
||||
lda #0x01
|
||||
sta zp:T_X$
|
||||
lda #19
|
||||
sta zp:T_Y$
|
||||
|
||||
ClearLine$:
|
||||
jsr vdp_point_to_vram_xy
|
||||
lda #0x00
|
||||
ldx #24
|
||||
ClearTile$:
|
||||
sta VDP_MEM
|
||||
dex
|
||||
bne ClearTile$
|
||||
|
||||
dec zp:T_Y$
|
||||
bne ClearLine$
|
||||
|
||||
rts
|
||||
|
||||
vdp_clear_dialog:
|
||||
T_NT_IDX$: .equ _Zp+4
|
||||
T_Y$: .equ _Zp+1
|
||||
T_X$: .equ _Zp+0
|
||||
|
||||
|
||||
lda #0x01
|
||||
sta zp:T_NT_IDX$
|
||||
lda #0x04
|
||||
sta zp:T_X$
|
||||
lda #15
|
||||
sta zp:T_Y$
|
||||
ldy #9
|
||||
|
||||
ClearLine$:
|
||||
jsr vdp_point_to_vram_xy
|
||||
lda #0x00
|
||||
ldx #24
|
||||
ClearTile$:
|
||||
sta VDP_MEM
|
||||
dex
|
||||
bne ClearTile$
|
||||
|
||||
dec zp:T_Y$
|
||||
dey
|
||||
bne ClearLine$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_draw_numtile:
|
||||
;;; Draws the 2048 tile at specified coordinates
|
||||
;;; Parameters:
|
||||
;;; - Type of tile [A]
|
||||
;;; - X in game grid [Zp[0]]
|
||||
;;; - Y in game grid [Zp[1]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 0, 1, 2, 3, 4, 5, 6, 7
|
||||
;;;
|
||||
vdp_draw_numtile:
|
||||
T_LINE_COUNT$:.equ _Zp+7
|
||||
T_NT_IDX$: .equ _Zp+4
|
||||
T_COUNTER$: .equ _Zp+3
|
||||
P_TYPE$: .equ _Zp+2
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
sta zp:P_TYPE$
|
||||
lda #0
|
||||
sta zp:T_NT_IDX$ ; the tiles here will be drawn only on game table
|
||||
sta zp:T_COUNTER$
|
||||
|
||||
lda #3
|
||||
sta zp:T_LINE_COUNT$
|
||||
|
||||
; Convert the coordinates
|
||||
ldx zp:P_X$
|
||||
lda X_To_TileNum_Map,x
|
||||
sta zp:P_X$
|
||||
|
||||
ldx zp:P_Y$
|
||||
lda Y_To_TileNum_Map,x
|
||||
sta zp:P_Y$
|
||||
|
||||
; Calculate the beginning of the tile section we're interested in
|
||||
clc
|
||||
lda #NUM_TILE_OFFSET
|
||||
adc zp:P_TYPE$
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
sta zp:P_TYPE$
|
||||
|
||||
; Draw the tile
|
||||
DrawNextLine$:
|
||||
jsr vdp_point_to_vram_xy
|
||||
ldx zp:T_COUNTER$
|
||||
|
||||
ldy #4
|
||||
SetTile$:
|
||||
clc
|
||||
lda TileNum_Offset_Map,x
|
||||
adc zp:P_TYPE$
|
||||
sta VDP_MEM
|
||||
nop
|
||||
inx
|
||||
dey
|
||||
bne SetTile$
|
||||
|
||||
stx zp:T_COUNTER$
|
||||
inc zp:P_Y$
|
||||
dec zp:T_LINE_COUNT$
|
||||
bne DrawNextLine$
|
||||
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;
|
||||
.section data,data
|
||||
|
||||
TileNum_Offset_Map: ; Offset from the beginning of the selected tilemap section, of the tiles composing the numeric-2048 tile
|
||||
.byte 0x00, 0x04, 0x04, 0x02 ; First line
|
||||
.byte 0x04, 0x04, 0x04, 0x04 ; Second
|
||||
.byte 0x01, 0x04, 0x04, 0x03 ; Third and last
|
||||
|
||||
; The following maps convert between X and Y in the game grid into the tile map grid
|
||||
X_To_TileNum_Map:
|
||||
.byte 0x01, 0x06, 0x0B, 0x10, 0x15
|
||||
Y_To_TileNum_Map:
|
||||
.byte 0x01, 0x05, 0x09, 0x0D, 0x11
|
||||
|
||||
; The following maps convert between the tile number and the corresponding X and Y coordinates
|
||||
TileNum_To_X_Map:
|
||||
.byte 0x00, 0x01, 0x02, 0x03, 0x04
|
||||
.byte 0x00, 0x01, 0x02, 0x03, 0x04
|
||||
.byte 0x00, 0x01, 0x02, 0x03, 0x04
|
||||
.byte 0x00, 0x01, 0x02, 0x03, 0x04
|
||||
.byte 0x00, 0x01, 0x02, 0x03, 0x04
|
||||
|
||||
TileNum_To_Y_Map:
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x01, 0x01, 0x01, 0x01, 0x01
|
||||
.byte 0x02, 0x02, 0x02, 0x02, 0x02
|
||||
.byte 0x03, 0x03, 0x03, 0x03, 0x03
|
||||
.byte 0x04, 0x04, 0x04, 0x04, 0x04
|
||||
|
||||
;;;;;;;;;;;;;;;;;;
|
||||
.public vdp_draw_numtile
|
||||
.public vdp_clear_gamegrid
|
||||
.public vdp_clear_dialog
|
||||
.public vdp_redraw_tiles
|
||||
.public vdp_draw_joystick
|
||||
|
||||
|
|
@ -1,31 +1,31 @@
|
|||
#include <stdint.h>
|
||||
|
||||
const uint8_t score_pic_data[] = {
|
||||
0x00, 0x2C, 0x40, 0x40, 0x03, 0x05, 0x30, 0x00, 0x00, 0x7B, 0x70, 0x63, 0x06, 0x7B, 0x70, 0x0F, 0x00, 0x0F,
|
||||
0x78, 0x57, 0x0B, 0x47, 0x39, 0x00, 0x40, 0x03, 0x3C, 0x2E, 0x4E, 0x63, 0x39, 0x00, 0x60, 0x00, 0x3C, 0x1B,
|
||||
0x2E, 0x61, 0x39, 0x00, 0x00, 0x07, 0x5E, 0x1F, 0x6E, 0x71, 0x18, 0x00, 0x40, 0x1D, 0x4E, 0x0C, 0x66, 0x1D,
|
||||
0x7E, 0x03, 0x00, 0x3A, 0x0E, 0x4E, 0x67, 0x07, 0x7C, 0x01, 0x00, 0x30, 0x07, 0x0E, 0x77, 0x02, 0x0C, 0x00,
|
||||
0x00, 0x3C, 0x07, 0x66, 0x33, 0x06, 0x06, 0x00, 0x40, 0x1B, 0x47, 0x46, 0x3B, 0x0D, 0x06, 0x00, 0x30, 0x0F,
|
||||
0x23, 0x6E, 0x19, 0x0E, 0x7F, 0x00, 0x78, 0x01, 0x3E, 0x78, 0x18, 0x1C, 0x3F, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t moves_pic_data[] = {
|
||||
0x00, 0x06, 0x00, 0x1C, 0x06, 0x30, 0x00, 0x0B, 0x00, 0x3E, 0x0C, 0x36, 0x0E, 0x72, 0x6F, 0x1E, 0x00, 0x7F,
|
||||
0x0A, 0x5D, 0x06, 0x3A, 0x60, 0x03, 0x00, 0x57, 0x4D, 0x72, 0x0E, 0x3F, 0x70, 0x00, 0x40, 0x6F, 0x46, 0x71,
|
||||
0x26, 0x39, 0x18, 0x00, 0x50, 0x33, 0x67, 0x71, 0x47, 0x1B, 0x60, 0x01, 0x60, 0x19, 0x67, 0x30, 0x67, 0x7F,
|
||||
0x33, 0x07, 0x60, 0x15, 0x73, 0x3C, 0x67, 0x7C, 0x41, 0x0E, 0x70, 0x4C, 0x73, 0x38, 0x37, 0x0C, 0x00, 0x0C,
|
||||
0x68, 0x5C, 0x33, 0x1E, 0x1F, 0x06, 0x00, 0x0F, 0x30, 0x4C, 0x31, 0x1C, 0x1F, 0x06, 0x70, 0x06, 0x38, 0x26,
|
||||
0x71, 0x0E, 0x0E, 0x7F, 0x6C, 0x03, 0x38, 0x66, 0x41, 0x07, 0x07, 0x3F, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x00
|
||||
};
|
||||
|
||||
const uint8_t high_pic_data[] = {
|
||||
0x00, 0x00, 0x06, 0x60, 0x21, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x78, 0x51, 0x20, 0x00, 0x00, 0x00,
|
||||
0x0E, 0x6E, 0x1D, 0x72, 0x70, 0x00, 0x00, 0x00, 0x06, 0x7E, 0x1E, 0x33, 0x30, 0x00, 0x00, 0x00, 0x0E, 0x33,
|
||||
0x0E, 0x71, 0x18, 0x00, 0x00, 0x00, 0x07, 0x7B, 0x05, 0x38, 0x18, 0x00, 0x00, 0x00, 0x5F, 0x1B, 0x07, 0x79,
|
||||
0x1D, 0x00, 0x00, 0x00, 0x7B, 0x59, 0x73, 0x59, 0x0F, 0x00, 0x00, 0x40, 0x27, 0x5D, 0x43, 0x3C, 0x0A, 0x00,
|
||||
0x00, 0x20, 0x51, 0x4C, 0x61, 0x0A, 0x05, 0x00, 0x00, 0x40, 0x71, 0x4C, 0x63, 0x0C, 0x07, 0x00, 0x00, 0x60,
|
||||
0x61, 0x06, 0x31, 0x0E, 0x06, 0x00, 0x00, 0x60, 0x30, 0x02, 0x3E, 0x06, 0x03, 0x00, 0x00, 0x20, 0x20, 0x00,
|
||||
0x00, 0x02, 0x02, 0x00
|
||||
};
|
||||
#include <stdint.h>
|
||||
|
||||
const uint8_t score_pic_data[] = {
|
||||
0x00, 0x2C, 0x40, 0x40, 0x03, 0x05, 0x30, 0x00, 0x00, 0x7B, 0x70, 0x63, 0x06, 0x7B, 0x70, 0x0F, 0x00, 0x0F,
|
||||
0x78, 0x57, 0x0B, 0x47, 0x39, 0x00, 0x40, 0x03, 0x3C, 0x2E, 0x4E, 0x63, 0x39, 0x00, 0x60, 0x00, 0x3C, 0x1B,
|
||||
0x2E, 0x61, 0x39, 0x00, 0x00, 0x07, 0x5E, 0x1F, 0x6E, 0x71, 0x18, 0x00, 0x40, 0x1D, 0x4E, 0x0C, 0x66, 0x1D,
|
||||
0x7E, 0x03, 0x00, 0x3A, 0x0E, 0x4E, 0x67, 0x07, 0x7C, 0x01, 0x00, 0x30, 0x07, 0x0E, 0x77, 0x02, 0x0C, 0x00,
|
||||
0x00, 0x3C, 0x07, 0x66, 0x33, 0x06, 0x06, 0x00, 0x40, 0x1B, 0x47, 0x46, 0x3B, 0x0D, 0x06, 0x00, 0x30, 0x0F,
|
||||
0x23, 0x6E, 0x19, 0x0E, 0x7F, 0x00, 0x78, 0x01, 0x3E, 0x78, 0x18, 0x1C, 0x3F, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t moves_pic_data[] = {
|
||||
0x00, 0x06, 0x00, 0x1C, 0x06, 0x30, 0x00, 0x0B, 0x00, 0x3E, 0x0C, 0x36, 0x0E, 0x72, 0x6F, 0x1E, 0x00, 0x7F,
|
||||
0x0A, 0x5D, 0x06, 0x3A, 0x60, 0x03, 0x00, 0x57, 0x4D, 0x72, 0x0E, 0x3F, 0x70, 0x00, 0x40, 0x6F, 0x46, 0x71,
|
||||
0x26, 0x39, 0x18, 0x00, 0x50, 0x33, 0x67, 0x71, 0x47, 0x1B, 0x60, 0x01, 0x60, 0x19, 0x67, 0x30, 0x67, 0x7F,
|
||||
0x33, 0x07, 0x60, 0x15, 0x73, 0x3C, 0x67, 0x7C, 0x41, 0x0E, 0x70, 0x4C, 0x73, 0x38, 0x37, 0x0C, 0x00, 0x0C,
|
||||
0x68, 0x5C, 0x33, 0x1E, 0x1F, 0x06, 0x00, 0x0F, 0x30, 0x4C, 0x31, 0x1C, 0x1F, 0x06, 0x70, 0x06, 0x38, 0x26,
|
||||
0x71, 0x0E, 0x0E, 0x7F, 0x6C, 0x03, 0x38, 0x66, 0x41, 0x07, 0x07, 0x3F, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x00
|
||||
};
|
||||
|
||||
const uint8_t high_pic_data[] = {
|
||||
0x00, 0x00, 0x06, 0x60, 0x21, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x78, 0x51, 0x20, 0x00, 0x00, 0x00,
|
||||
0x0E, 0x6E, 0x1D, 0x72, 0x70, 0x00, 0x00, 0x00, 0x06, 0x7E, 0x1E, 0x33, 0x30, 0x00, 0x00, 0x00, 0x0E, 0x33,
|
||||
0x0E, 0x71, 0x18, 0x00, 0x00, 0x00, 0x07, 0x7B, 0x05, 0x38, 0x18, 0x00, 0x00, 0x00, 0x5F, 0x1B, 0x07, 0x79,
|
||||
0x1D, 0x00, 0x00, 0x00, 0x7B, 0x59, 0x73, 0x59, 0x0F, 0x00, 0x00, 0x40, 0x27, 0x5D, 0x43, 0x3C, 0x0A, 0x00,
|
||||
0x00, 0x20, 0x51, 0x4C, 0x61, 0x0A, 0x05, 0x00, 0x00, 0x40, 0x71, 0x4C, 0x63, 0x0C, 0x07, 0x00, 0x00, 0x60,
|
||||
0x61, 0x06, 0x31, 0x0E, 0x06, 0x00, 0x00, 0x60, 0x30, 0x02, 0x3E, 0x06, 0x03, 0x00, 0x00, 0x20, 0x20, 0x00,
|
||||
0x00, 0x02, 0x02, 0x00
|
||||
};
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
#ifndef _GRAPH_MISC_DATA_HEADER_
|
||||
#define _GRAPH_MISC_DATA_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SCORE_PIC_WIDTH_BYTES 8
|
||||
#define SCORE_PIC_HEIGHT 14
|
||||
extern const uint8_t score_pic_data[];
|
||||
|
||||
#define MOVES_PIC_WIDTH_BYTES 8
|
||||
#define MOVES_PIC_HEIGHT 14
|
||||
extern const uint8_t moves_pic_data[];
|
||||
|
||||
#define HIGH_PIC_WIDTH_BYTES 8
|
||||
#define HIGH_PIC_HEIGHT 14
|
||||
extern const uint8_t high_pic_data[];
|
||||
|
||||
#endif /* _GRAPH_MISC_DATA_HEADER_ */
|
||||
#ifndef _HGR_GRAPH_MISC_DATA_HEADER_
|
||||
#define _HGR_GRAPH_MISC_DATA_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SCORE_PIC_WIDTH_BYTES 8
|
||||
#define SCORE_PIC_HEIGHT 14
|
||||
extern const uint8_t score_pic_data[];
|
||||
|
||||
#define MOVES_PIC_WIDTH_BYTES 8
|
||||
#define MOVES_PIC_HEIGHT 14
|
||||
extern const uint8_t moves_pic_data[];
|
||||
|
||||
#define HIGH_PIC_WIDTH_BYTES 8
|
||||
#define HIGH_PIC_HEIGHT 14
|
||||
extern const uint8_t high_pic_data[];
|
||||
|
||||
#endif /* _HGR_GRAPH_MISC_DATA_HEADER_ */
|
||||
8
src/hgr_graphics.h
Normal file
8
src/hgr_graphics.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _HGR_GRAPHICS_HEADER_
|
||||
#define _HGR_GRAPHICS_HEADER_
|
||||
|
||||
#define SCREEN_HEIGHT 192
|
||||
#define SCREEN_WIDTH_BYTES 128
|
||||
#define BYTES_PER_LINE 40
|
||||
|
||||
#endif /* _HGR_GRAPHICS_HEADER_ */
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
const uint16_t line_offset_map[SCREEN_HEIGHT] = {
|
||||
0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x0080, 0x0480, 0x0880, 0x0C80,
|
||||
0x1080, 0x1480, 0x1880, 0x1C80, 0x0100, 0x0500, 0x0900, 0x0D00, 0x1100, 0x1500, 0x1900, 0x1D00,
|
||||
0x0180, 0x0580, 0x0980, 0x0D80, 0x1180, 0x1580, 0x1980, 0x1D80, 0x0200, 0x0600, 0x0A00, 0x0E00,
|
||||
0x1200, 0x1600, 0x1A00, 0x1E00, 0x0280, 0x0680, 0x0A80, 0x0E80, 0x1280, 0x1680, 0x1A80, 0x1E80,
|
||||
0x0300, 0x0700, 0x0B00, 0x0F00, 0x1300, 0x1700, 0x1B00, 0x1F00, 0x0380, 0x0780, 0x0B80, 0x0F80,
|
||||
0x1380, 0x1780, 0x1B80, 0x1F80, 0x0028, 0x0428, 0x0828, 0x0C28, 0x1028, 0x1428, 0x1828, 0x1C28,
|
||||
0x00A8, 0x04A8, 0x08A8, 0x0CA8, 0x10A8, 0x14A8, 0x18A8, 0x1CA8, 0x0128, 0x0528, 0x0928, 0x0D28,
|
||||
0x1128, 0x1528, 0x1928, 0x1D28, 0x01A8, 0x05A8, 0x09A8, 0x0DA8, 0x11A8, 0x15A8, 0x19A8, 0x1DA8,
|
||||
0x0228, 0x0628, 0x0A28, 0x0E28, 0x1228, 0x1628, 0x1A28, 0x1E28, 0x02A8, 0x06A8, 0x0AA8, 0x0EA8,
|
||||
0x12A8, 0x16A8, 0x1AA8, 0x1EA8, 0x0328, 0x0728, 0x0B28, 0x0F28, 0x1328, 0x1728, 0x1B28, 0x1F28,
|
||||
0x03A8, 0x07A8, 0x0BA8, 0x0FA8, 0x13A8, 0x17A8, 0x1BA8, 0x1FA8, 0x0050, 0x0450, 0x0850, 0x0C50,
|
||||
0x1050, 0x1450, 0x1850, 0x1C50, 0x00D0, 0x04D0, 0x08D0, 0x0CD0, 0x10D0, 0x14D0, 0x18D0, 0x1CD0,
|
||||
0x0150, 0x0550, 0x0950, 0x0D50, 0x1150, 0x1550, 0x1950, 0x1D50, 0x01D0, 0x05D0, 0x09D0, 0x0DD0,
|
||||
0x11D0, 0x15D0, 0x19D0, 0x1DD0, 0x0250, 0x0650, 0x0A50, 0x0E50, 0x1250, 0x1650, 0x1A50, 0x1E50,
|
||||
0x02D0, 0x06D0, 0x0AD0, 0x0ED0, 0x12D0, 0x16D0, 0x1AD0, 0x1ED0, 0x0350, 0x0750, 0x0B50, 0x0F50,
|
||||
0x1350, 0x1750, 0x1B50, 0x1F50, 0x03D0, 0x07D0, 0x0BD0, 0x0FD0, 0x13D0, 0x17D0, 0x1BD0, 0x1FD0
|
||||
};
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hgr_graphics.h"
|
||||
|
||||
const uint16_t line_offset_map[SCREEN_HEIGHT] = {
|
||||
0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x0080, 0x0480, 0x0880, 0x0C80,
|
||||
0x1080, 0x1480, 0x1880, 0x1C80, 0x0100, 0x0500, 0x0900, 0x0D00, 0x1100, 0x1500, 0x1900, 0x1D00,
|
||||
0x0180, 0x0580, 0x0980, 0x0D80, 0x1180, 0x1580, 0x1980, 0x1D80, 0x0200, 0x0600, 0x0A00, 0x0E00,
|
||||
0x1200, 0x1600, 0x1A00, 0x1E00, 0x0280, 0x0680, 0x0A80, 0x0E80, 0x1280, 0x1680, 0x1A80, 0x1E80,
|
||||
0x0300, 0x0700, 0x0B00, 0x0F00, 0x1300, 0x1700, 0x1B00, 0x1F00, 0x0380, 0x0780, 0x0B80, 0x0F80,
|
||||
0x1380, 0x1780, 0x1B80, 0x1F80, 0x0028, 0x0428, 0x0828, 0x0C28, 0x1028, 0x1428, 0x1828, 0x1C28,
|
||||
0x00A8, 0x04A8, 0x08A8, 0x0CA8, 0x10A8, 0x14A8, 0x18A8, 0x1CA8, 0x0128, 0x0528, 0x0928, 0x0D28,
|
||||
0x1128, 0x1528, 0x1928, 0x1D28, 0x01A8, 0x05A8, 0x09A8, 0x0DA8, 0x11A8, 0x15A8, 0x19A8, 0x1DA8,
|
||||
0x0228, 0x0628, 0x0A28, 0x0E28, 0x1228, 0x1628, 0x1A28, 0x1E28, 0x02A8, 0x06A8, 0x0AA8, 0x0EA8,
|
||||
0x12A8, 0x16A8, 0x1AA8, 0x1EA8, 0x0328, 0x0728, 0x0B28, 0x0F28, 0x1328, 0x1728, 0x1B28, 0x1F28,
|
||||
0x03A8, 0x07A8, 0x0BA8, 0x0FA8, 0x13A8, 0x17A8, 0x1BA8, 0x1FA8, 0x0050, 0x0450, 0x0850, 0x0C50,
|
||||
0x1050, 0x1450, 0x1850, 0x1C50, 0x00D0, 0x04D0, 0x08D0, 0x0CD0, 0x10D0, 0x14D0, 0x18D0, 0x1CD0,
|
||||
0x0150, 0x0550, 0x0950, 0x0D50, 0x1150, 0x1550, 0x1950, 0x1D50, 0x01D0, 0x05D0, 0x09D0, 0x0DD0,
|
||||
0x11D0, 0x15D0, 0x19D0, 0x1DD0, 0x0250, 0x0650, 0x0A50, 0x0E50, 0x1250, 0x1650, 0x1A50, 0x1E50,
|
||||
0x02D0, 0x06D0, 0x0AD0, 0x0ED0, 0x12D0, 0x16D0, 0x1AD0, 0x1ED0, 0x0350, 0x0750, 0x0B50, 0x0F50,
|
||||
0x1350, 0x1750, 0x1B50, 0x1F50, 0x03D0, 0x07D0, 0x0BD0, 0x0FD0, 0x13D0, 0x17D0, 0x1BD0, 0x1FD0
|
||||
};
|
||||
10
src/hgr_line_data.h
Normal file
10
src/hgr_line_data.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef _HGR_LINE_DATA_HEADER_
|
||||
#define _HGR_LINE_DATA_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hgr_graphics.h"
|
||||
|
||||
extern const uint16_t line_offset_map[SCREEN_HEIGHT];
|
||||
|
||||
#endif /* _HGR_LINE_DATA_HEADER_ */
|
||||
|
|
@ -1,39 +1,46 @@
|
|||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "shared_page.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
|
||||
void main(void) {
|
||||
uint8_t wait_count = 0x40;
|
||||
|
||||
// Initialize the register for LFSR
|
||||
lfsr_init(0xF00D);
|
||||
|
||||
// Clear the memory used to pass parameters to the next module
|
||||
memset((void*)(shared_page->module_data), 0, MODULE_DATA_SIZE);
|
||||
|
||||
// TODO: Detect expansion hardware, and choose what to load according to that
|
||||
|
||||
// Delay a bit
|
||||
while(wait_count--) WAIT(0xFF);
|
||||
|
||||
// Clear the display memory
|
||||
memset((void*)DISPLAY_PAGE_2, 0, DISPLAY_PAGE_SIZE);
|
||||
memset((void*)DISPLAY_PAGE_1, 0, DISPLAY_PAGE_SIZE);
|
||||
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = 3; // DLOG module is next!
|
||||
|
||||
return;
|
||||
}
|
||||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "vdp_utils.h"
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "input.h"
|
||||
#include "mem_map.h"
|
||||
#include "shared_page.h"
|
||||
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
|
||||
void main(void) {
|
||||
uint8_t wait_count = 0x40;
|
||||
uint8_t vdp_detected;
|
||||
|
||||
// Initialize the register for LFSR
|
||||
lfsr_init(0xF00D);
|
||||
|
||||
// Clear the memory used to pass parameters to the next module
|
||||
memset((void*)(shared_page->module_data), 0, MODULE_DATA_SIZE);
|
||||
|
||||
// Detect expansion hardware, and choose what to load according to that
|
||||
vdp_detected = vdp_detect() && !read_any_key();
|
||||
|
||||
// Delay a bit
|
||||
while(wait_count--) WAIT(0xFF);
|
||||
|
||||
// Clear the display memory
|
||||
memset((void*)DISPLAY_PAGE_2, 0, DISPLAY_PAGE_SIZE);
|
||||
memset((void*)DISPLAY_PAGE_1, 0, DISPLAY_PAGE_SIZE);
|
||||
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = vdp_detected ? MODULE_INIT_VDP : MODULE_DLOG; // If VDP is detected, load the module to initialize it, otherwise DLOG module is next!
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef _LINE_DATA_HEADER_
|
||||
#define _LINE_DATA_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "utility.h"
|
||||
|
||||
extern const uint16_t line_offset_map[SCREEN_HEIGHT];
|
||||
|
||||
#endif /* _LINE_DATA_HEADER */
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
static uint8_t *module_page = (uint8_t*)MODULE_PAGE;
|
||||
static shared_page_data * shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
|
||||
#define FILE_LIST_LEN 6
|
||||
#define FILE_LIST_LEN 10
|
||||
#define FNAME_LEN 6
|
||||
#define STATE_FILE_IDX 1
|
||||
|
||||
|
|
@ -34,10 +34,14 @@ static shared_page_data * shared_page = (shared_page_data*)SHARED_PAGE;
|
|||
static const uint8_t file_table[FILE_LIST_LEN][FNAME_LEN] = {
|
||||
{ 0x80 | 'L', 0x80 | 'O', 0x80 | 'A', 0x80 | 'D', 0x80 | 'S', 0x00}, // LOADS (this is not an executable, but will be used to show the loading screen).
|
||||
{ 0x80 | 'S', 0x80 | 'T', 0x80 | 'A', 0x80 | 'T', 0x80 | 'E', 0x00}, // STATE (this is not an executable, but will be used to save/load the game and scores).
|
||||
{ 0x80 | 'I', 0x80 | 'N', 0x80 | 'T', 0x80 | 'R', 0x80 | 'O', 0x00}, // INTRO (this executable will show the initial presentation picture)
|
||||
{ 0x80 | 'I', 0x80 | 'N', 0x80 | 'T', 0x80 | 'R', 0x80 | 'O', 0x00}, // INTRO (this executable will detect hardware and load the appropriate followup module)
|
||||
{ 0x80 | 'D', 0x80 | 'L', 0x80 | 'O', 0x80 | 'G', 0xA0, 0x00}, // DLOG (startup, win, lose dialogs)
|
||||
{ 0x80 | 'G', 0x80 | 'A', 0x80 | 'M', 0x80 | 'E', 0xA0, 0x00}, // GAME (the actual game)
|
||||
{ 0x80 | 'D', 0x80 | 'E', 0x80 | 'M', 0x80 | 'O', 0xA0, 0x00}, // DEMO (automatic demo)
|
||||
{ 0x80 | 'D', 0x80 | 'E', 0x80 | 'M', 0x80 | 'O', 0xA0, 0x00}, // DEMO (automatic demo),
|
||||
{ 0x80 | 'V', 0x80 | 'D', 0x80 | 'P', 0x80 | 'I', 0x80 | 'N', 0x00}, // VDPIN (Loads VDP resources),
|
||||
{ 0x80 | 'V', 0x80 | 'D', 0x80 | 'D', 0x80 | 'L', 0x80 | 'G', 0x00}, // VDDLG (VDP startup, win, lose dialogs),
|
||||
{ 0x80 | 'V', 0x80 | 'D', 0x80 | 'G', 0x80 | 'A', 0x80 | 'M', 0x00}, // VDGAM (Game, VDP version),
|
||||
{ 0x80 | 'V', 0x80 | 'D', 0x80 | 'D', 0x80 | 'E', 0x80 | 'M', 0x00}, // VDDEM (Demo, VDP version),
|
||||
};
|
||||
|
||||
static uint8_t file_trksec[FILE_LIST_LEN][2]; // This will hold track/sector for initial ts list sector for every one of the listed files. Populated at startup.
|
||||
|
|
@ -48,6 +52,10 @@ static uint16_t file_load_address[FILE_LIST_LEN] = { // This will hold the load
|
|||
MODULE_PAGE,
|
||||
MODULE_PAGE,
|
||||
MODULE_PAGE,
|
||||
MODULE_PAGE,
|
||||
MODULE_PAGE,
|
||||
MODULE_PAGE,
|
||||
MODULE_PAGE,
|
||||
};
|
||||
|
||||
static void init(void);
|
||||
|
|
@ -123,17 +131,14 @@ __task int main(void) {
|
|||
uint8_t cur_file = 0;
|
||||
uint8_t keep_going = 1;
|
||||
|
||||
__disable_interrupts();
|
||||
__disable_interrupts(); // Keep the interrupts disabled in the master module
|
||||
|
||||
init();
|
||||
init_floppy_data(&cur_trk, &cur_file);
|
||||
|
||||
__enable_interrupts();
|
||||
|
||||
|
||||
do {
|
||||
if((cur_file != shared_page->next_module_idx) || (shared_page->master_command == MASTER_COMMAND_SAVE)) {
|
||||
__disable_interrupts();
|
||||
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 0);
|
||||
|
||||
// Check if we need to load another module
|
||||
|
|
@ -151,7 +156,6 @@ __task int main(void) {
|
|||
}
|
||||
|
||||
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
|
||||
__enable_interrupts();
|
||||
}
|
||||
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
|
|
|
|||
|
|
@ -1,48 +1,51 @@
|
|||
#ifndef _MEM_REGISTERS_HEADER_
|
||||
#define _MEM_REGISTERS_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ROM_MONITOR 0xFF61
|
||||
|
||||
#define ZP_WNDLFT 0x0020 // 0, left column of scroll window
|
||||
#define ZP_WNDWDTH 0x0021 // 40, width of scroll window
|
||||
#define ZP_WNDTOP 0x0022 // 0, top line of the scroll window
|
||||
#define ZP_WNDBTM 0x0023 // 24, bottom line of the scroll window
|
||||
|
||||
#define ZP_CH 0x0024 // Displacement from window left for the cursor
|
||||
#define ZP_CV 0x0025 // Displacement from top of screen (not window!) for the cursor
|
||||
|
||||
#define ZP_INVFLAG 0x0032 // Either 0x00 or 0x7F, set text color inversion
|
||||
#define ZP_PROMPT 0x0033 // Prompt character
|
||||
|
||||
#define ZP_RND 0x004E // Note that this is a 16bit register incremented by the RDKEY func
|
||||
|
||||
#define P3_PWRDUP_REF 0x03F3
|
||||
#define P3_PWRDUP 0x03F4 // Already-powered-up indicator. If it is set to the content of 0x03F3 XOR'd with 0xA5, the soft reset vector is considered valid
|
||||
|
||||
|
||||
#define DATAIN_KB_MASK 0x3F
|
||||
#define DATAIN_PRNT_MASK 0x40
|
||||
#define DATAIN_TAPEIN_MASK 0x80
|
||||
|
||||
#define IO_DATAOUT 0xC000 // (W) To keyboard and printer port
|
||||
#define IO_DATAIN 0xC010 // (R) Data input from keyboard (0:5), printer (6) and tape (7)
|
||||
#define IO_TAPEOUT 0xC020 // (R) Data output for tape, read from here to output bit on tape
|
||||
#define IO_SPEAKER 0xC030 // (R) Speaker toggle
|
||||
#define IO_DISPLAY_COLOR 0xC050 // (R / W) Access here to enable the colorburst
|
||||
#define IO_DISPLAY_BW 0xC051 // (R / W) Access here to disable the colorburst
|
||||
#define IO_MTA_OFF 0xC052 // (?)
|
||||
#define IO_MTA_ON 0xC053 // (?)
|
||||
#define IO_DISPLAY_PAGE1 0xC054 // (R / W) Access here to select the primary display page
|
||||
#define IO_DISPLAY_PAGE2 0xC055 // (R / W) Access here to select the secondary display page
|
||||
#define IO_MTB_OFF 0xC056 // (?)
|
||||
#define IO_MTB_ON 0xC057 // (?)
|
||||
#define IO_PRNT_STRB_LO 0xC058 // (R / W) Access LO/HI/LO or HI/LO/HI consecutively depending on the type of strobe pulse to create
|
||||
#define IO_PRNT_STRB_HI 0xC059 // (R / W)
|
||||
#define IO_ROMSEL 0xC05A // (R / W) Access here will make region C100-FFFF a ROM area
|
||||
#define IO_RAMSEL 0xC05B // (R / W) Access here will make region C100-FFFF a RAM area
|
||||
#define IO_KB_CTRL_LOW 0xC05E // (R / W) Set the CTRL line to 0, access is through DATAIN
|
||||
#define IO_KB_CTRL_HI 0xC05F // (R / W) Set the CTRL line to 1
|
||||
|
||||
#endif /* _MEM_REGISTERS_HEADER_ */
|
||||
#ifndef _MEM_REGISTERS_HEADER_
|
||||
#define _MEM_REGISTERS_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NMI_HANDLER_ADDRESS 0x03FB
|
||||
#define IRQ_HANDLER_ADDRESS 0x03FE
|
||||
|
||||
#define ROM_MONITOR 0xFF61
|
||||
|
||||
#define ZP_WNDLFT 0x0020 // 0, left column of scroll window
|
||||
#define ZP_WNDWDTH 0x0021 // 40, width of scroll window
|
||||
#define ZP_WNDTOP 0x0022 // 0, top line of the scroll window
|
||||
#define ZP_WNDBTM 0x0023 // 24, bottom line of the scroll window
|
||||
|
||||
#define ZP_CH 0x0024 // Displacement from window left for the cursor
|
||||
#define ZP_CV 0x0025 // Displacement from top of screen (not window!) for the cursor
|
||||
|
||||
#define ZP_INVFLAG 0x0032 // Either 0x00 or 0x7F, set text color inversion
|
||||
#define ZP_PROMPT 0x0033 // Prompt character
|
||||
|
||||
#define ZP_RND 0x004E // Note that this is a 16bit register incremented by the RDKEY func
|
||||
|
||||
#define P3_PWRDUP_REF 0x03F3
|
||||
#define P3_PWRDUP 0x03F4 // Already-powered-up indicator. If it is set to the content of 0x03F3 XOR'd with 0xA5, the soft reset vector is considered valid
|
||||
|
||||
|
||||
#define DATAIN_KB_MASK 0x3F
|
||||
#define DATAIN_PRNT_MASK 0x40
|
||||
#define DATAIN_TAPEIN_MASK 0x80
|
||||
|
||||
#define IO_DATAOUT 0xC000 // (W) To keyboard and printer port
|
||||
#define IO_DATAIN 0xC010 // (R) Data input from keyboard (0:5), printer (6) and tape (7)
|
||||
#define IO_TAPEOUT 0xC020 // (R) Data output for tape, read from here to output bit on tape
|
||||
#define IO_SPEAKER 0xC030 // (R) Speaker toggle
|
||||
#define IO_DISPLAY_COLOR 0xC050 // (R / W) Access here to enable the colorburst
|
||||
#define IO_DISPLAY_BW 0xC051 // (R / W) Access here to disable the colorburst
|
||||
#define IO_MTA_OFF 0xC052 // (?)
|
||||
#define IO_MTA_ON 0xC053 // (?)
|
||||
#define IO_DISPLAY_PAGE1 0xC054 // (R / W) Access here to select the primary display page
|
||||
#define IO_DISPLAY_PAGE2 0xC055 // (R / W) Access here to select the secondary display page
|
||||
#define IO_MTB_OFF 0xC056 // (?)
|
||||
#define IO_MTB_ON 0xC057 // (?)
|
||||
#define IO_PRNT_STRB_LO 0xC058 // (R / W) Access LO/HI/LO or HI/LO/HI consecutively depending on the type of strobe pulse to create
|
||||
#define IO_PRNT_STRB_HI 0xC059 // (R / W)
|
||||
#define IO_ROMSEL 0xC05A // (R / W) Access here will make region C100-FFFF a ROM area
|
||||
#define IO_RAMSEL 0xC05B // (R / W) Access here will make region C100-FFFF a RAM area
|
||||
#define IO_KB_CTRL_LOW 0xC05E // (R / W) Set the CTRL line to 0, access is through DATAIN
|
||||
#define IO_KB_CTRL_HI 0xC05F // (R / W) Set the CTRL line to 1
|
||||
|
||||
#endif /* _MEM_REGISTERS_HEADER_ */
|
||||
|
|
|
|||
13
src/module_list.h
Normal file
13
src/module_list.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _MODULE_LIST_HEADER_
|
||||
#define _MODULE_LIST_HEADER_
|
||||
|
||||
#define MODULE_DLOG 3
|
||||
#define MODULE_GAME 4
|
||||
#define MODULE_DEMO 5
|
||||
#define MODULE_INIT_VDP 6
|
||||
#define MODULE_DLOG_VDP 7
|
||||
#define MODULE_GAME_VDP 8
|
||||
#define MODULE_DEMO_VDP 9
|
||||
|
||||
|
||||
#endif /* _MODULE_LIST_HEADER_ */
|
||||
142
src/utility.c
142
src/utility.c
|
|
@ -1,65 +1,77 @@
|
|||
#include "utility.h"
|
||||
|
||||
#include "mem_registers.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "line_data.h"
|
||||
|
||||
void num_to_decbuf(uint16_t n, uint8_t len, uint8_t *buf) {
|
||||
|
||||
for(uint8_t idx = 0; idx < len; idx++) {
|
||||
buf[idx] = n % 10;
|
||||
n /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/2602823/in-c-c-whats-the-simplest-way-to-reverse-the-order-of-bits-in-a-byte
|
||||
uint8_t bit_reverse(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/14009765/fastest-way-to-count-bits
|
||||
uint8_t bit_count(uint8_t b) {
|
||||
b = (b & 0x55) + (b >> 1 & 0x55);
|
||||
b = (b & 0x33) + (b >> 2 & 0x33);
|
||||
b = (b & 0x0f) + (b >> 4 & 0x0f);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void lfsr_init(uint16_t reg) {
|
||||
*((uint16_t*)LFSR_REGISTER_ADDRESS) = 0xF00D;
|
||||
}
|
||||
|
||||
uint16_t lfsr_update(void) {
|
||||
uint16_t *lfsr = ((uint16_t*)LFSR_REGISTER_ADDRESS);
|
||||
|
||||
*lfsr ^= (*lfsr) >> 7;
|
||||
*lfsr ^= (*lfsr) << 9;
|
||||
*lfsr ^= (*lfsr) >> 13;
|
||||
|
||||
return *lfsr;
|
||||
}
|
||||
|
||||
#define CRC8RDALLAS_POLY 0x31
|
||||
uint8_t calculate_crc8(uint8_t* data, uint8_t len) {
|
||||
uint8_t crc = 0;
|
||||
|
||||
for(uint8_t data_idx = 0; data_idx < len; data_idx++) {
|
||||
uint8_t carry;
|
||||
uint8_t d = data[data_idx];
|
||||
|
||||
for (uint8_t i = 8; i > 0; i--) {
|
||||
carry = (crc & 0x80);
|
||||
crc <<= 1;
|
||||
if (d & 1) crc |= 1;
|
||||
d >>= 1;
|
||||
if (carry) crc ^= CRC8RDALLAS_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
#include "utility.h"
|
||||
|
||||
#include "mem_registers.h"
|
||||
#include "monitor_subroutines.h"
|
||||
|
||||
void decbuf_to_ascii(uint8_t len, uint8_t *buf) {
|
||||
for(uint8_t idx = 0; idx < len; idx++) {
|
||||
buf[idx] += 0x30;
|
||||
}
|
||||
|
||||
// Swap the order in the array
|
||||
uint8_t tmp;
|
||||
for(uint8_t idx = 0; idx < len/2; idx++) {
|
||||
tmp = buf[idx];
|
||||
buf[idx] = buf[(len - 1) - idx];
|
||||
buf[(len - 1) - idx] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void num_to_decbuf(uint16_t n, uint8_t len, uint8_t *buf) {
|
||||
for(uint8_t idx = 0; idx < len; idx++) {
|
||||
buf[idx] = n % 10;
|
||||
n /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/2602823/in-c-c-whats-the-simplest-way-to-reverse-the-order-of-bits-in-a-byte
|
||||
uint8_t bit_reverse(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/14009765/fastest-way-to-count-bits
|
||||
uint8_t bit_count(uint8_t b) {
|
||||
b = (b & 0x55) + (b >> 1 & 0x55);
|
||||
b = (b & 0x33) + (b >> 2 & 0x33);
|
||||
b = (b & 0x0f) + (b >> 4 & 0x0f);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void lfsr_init(uint16_t reg) {
|
||||
*((uint16_t*)LFSR_REGISTER_ADDRESS) = 0xF00D;
|
||||
}
|
||||
|
||||
uint16_t lfsr_update(void) {
|
||||
uint16_t *lfsr = ((uint16_t*)LFSR_REGISTER_ADDRESS);
|
||||
|
||||
*lfsr ^= (*lfsr) >> 7;
|
||||
*lfsr ^= (*lfsr) << 9;
|
||||
*lfsr ^= (*lfsr) >> 13;
|
||||
|
||||
return *lfsr;
|
||||
}
|
||||
|
||||
#define CRC8RDALLAS_POLY 0x31
|
||||
uint8_t calculate_crc8(uint8_t* data, uint8_t len) {
|
||||
uint8_t crc = 0;
|
||||
|
||||
for(uint8_t data_idx = 0; data_idx < len; data_idx++) {
|
||||
uint8_t carry;
|
||||
uint8_t d = data[data_idx];
|
||||
|
||||
for (uint8_t i = 8; i > 0; i--) {
|
||||
carry = (crc & 0x80);
|
||||
crc <<= 1;
|
||||
if (d & 1) crc |= 1;
|
||||
d >>= 1;
|
||||
if (carry) crc ^= CRC8RDALLAS_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,31 @@
|
|||
#ifndef _UTILITY_HEADER_
|
||||
#define _UTILITY_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SCREEN_HEIGHT 192
|
||||
#define SCREEN_WIDTH_BYTES 128
|
||||
#define BYTES_PER_LINE 40
|
||||
|
||||
#define PEEKZ(a) (*(volatile uint8_t* __attribute__((zpage)))(a))
|
||||
#define POKEZ(a, b) ((*(volatile uint8_t* __attribute__((zpage)))(a)) = b)
|
||||
|
||||
#define PEEK(a) (*(volatile uint8_t*)(a))
|
||||
#define POKE(a, b) ((*(volatile uint8_t*)(a)) = b)
|
||||
|
||||
#define PEEKW(a) (*(volatile uint16_t*)(a))
|
||||
#define POKEW(a, b) ((*(volatile uint16_t*)(a)) = b)
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
// 0x356 - 0x357 actually fall inside the
|
||||
// decoding table for DISK II sector reading,
|
||||
// but they're unused bytes! So we can use them
|
||||
// to store the lfsr_update
|
||||
#define LFSR_REGISTER_ADDRESS 0x0356
|
||||
|
||||
void num_to_decbuf(uint16_t n, uint8_t len, uint8_t *buf);
|
||||
uint8_t bit_reverse(uint8_t b);
|
||||
uint8_t bit_count(uint8_t b);
|
||||
void lfsr_init(uint16_t reg);
|
||||
uint16_t lfsr_update(void);
|
||||
uint8_t calculate_crc8(uint8_t* data, uint8_t len);
|
||||
|
||||
#endif /* _UTILITY_HEADER_ */
|
||||
#ifndef _UTILITY_HEADER_
|
||||
#define _UTILITY_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PEEKZ(a) (*(volatile uint8_t* __attribute__((zpage)))(a))
|
||||
#define POKEZ(a, b) ((*(volatile uint8_t* __attribute__((zpage)))(a)) = b)
|
||||
|
||||
#define PEEK(a) (*(volatile uint8_t*)(a))
|
||||
#define POKE(a, b) ((*(volatile uint8_t*)(a)) = b)
|
||||
|
||||
#define PEEKW(a) (*(volatile uint16_t*)(a))
|
||||
#define POKEW(a, b) ((*(volatile uint16_t*)(a)) = b)
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
// 0x356 - 0x357 actually fall inside the
|
||||
// decoding table for DISK II sector reading,
|
||||
// but they're unused bytes! So we can use them
|
||||
// to store the lfsr_update
|
||||
#define LFSR_REGISTER_ADDRESS 0x0356
|
||||
|
||||
void decbuf_to_ascii(uint8_t len, uint8_t *buf);
|
||||
void num_to_decbuf(uint16_t n, uint8_t len, uint8_t *buf);
|
||||
uint8_t bit_reverse(uint8_t b);
|
||||
uint8_t bit_count(uint8_t b);
|
||||
void lfsr_init(uint16_t reg);
|
||||
uint16_t lfsr_update(void);
|
||||
uint8_t calculate_crc8(uint8_t* data, uint8_t len);
|
||||
|
||||
#endif /* _UTILITY_HEADER_ */
|
||||
|
|
|
|||
197
src/vddem_main.c
Normal file
197
src/vddem_main.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "vdp_utils.h"
|
||||
#include "game_vdp_graphics.h"
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "mem_registers.h"
|
||||
#include "shared_page.h"
|
||||
#include "state_page.h"
|
||||
#include "dlog_data.h"
|
||||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "game_logic.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "sound.h"
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
#define HSCORE_TEXT_X 27
|
||||
#define HSCORE_TEXT_Y 13
|
||||
|
||||
#define SCORE_TEXT_X 27
|
||||
#define SCORE_TEXT_Y 4
|
||||
|
||||
#define MOVES_TEXT_X 27
|
||||
#define MOVES_TEXT_Y 8
|
||||
|
||||
#define BOTTOM_TEXT_X 1
|
||||
#define BOTTOM_TEXT_Y 23
|
||||
|
||||
#define MAX_DEMO_MOVES 30
|
||||
|
||||
#define RUNS_TO_SKIP 4000
|
||||
|
||||
static state_page_data* state_page = (state_page_data*)STATE_PAGE;
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
static uint8_t text_buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
static volatile uint8_t key_pressed = 0;
|
||||
|
||||
void main(void) {
|
||||
uint16_t moves_count = 0;
|
||||
uint16_t score = 0;
|
||||
int8_t done = 0;
|
||||
|
||||
__disable_interrupts(); // Make sure the interrupts are disabled
|
||||
|
||||
// By default, once we return from this, return to the DLOG module and give the master no command to execute
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = MODULE_DLOG_VDP; // Go to the DLOG module
|
||||
|
||||
dlog_data *dld = (dlog_data *)(shared_page->module_data);
|
||||
dlog_data *gad = (dlog_data *)(shared_page->module_data);
|
||||
|
||||
// Make sure the buffers are pointing to the correct memory and are clear
|
||||
vdp_hide_sprites();
|
||||
vdp_clear_gamegrid();
|
||||
vdp_switch_nt(0); // Make sure VDP shows the gamegrid
|
||||
|
||||
// Setup the IRQ handler
|
||||
POKEW(IRQ_HANDLER_ADDRESS, (uint16_t)vdp_irq_handler);
|
||||
|
||||
// Reset the game, calculate the initial score depending on which tiles we randomly get
|
||||
score = reset_game();
|
||||
|
||||
// Draw the initial state of the game
|
||||
vdp_print_string(0, BOTTOM_TEXT_X, BOTTOM_TEXT_Y, "DEMO MODE Press any key to exit");
|
||||
|
||||
num_to_decbuf(state_page->hi_score, 5, text_buf); // High score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, HSCORE_TEXT_X, HSCORE_TEXT_Y, (char*)text_buf);
|
||||
|
||||
num_to_decbuf(moves_count, 5, text_buf); // Moves count
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, MOVES_TEXT_X, MOVES_TEXT_Y, (char*)text_buf);
|
||||
|
||||
num_to_decbuf(score, 5, text_buf); // Score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
||||
|
||||
vdp_draw_joystick(JS_POS_CENTER); // Center the joystick
|
||||
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
|
||||
uint16_t lfsr;
|
||||
uint16_t current_run = 0;
|
||||
|
||||
__enable_interrupts();
|
||||
while(1) { // Game loop
|
||||
lfsr = lfsr_update();
|
||||
|
||||
// Any key will let us out of this, wait some time for a keypress
|
||||
__disable_interrupts();
|
||||
if(read_any_key()) {
|
||||
snd_mod_button();
|
||||
done = 1;
|
||||
}
|
||||
|
||||
if(!done && current_run <= RUNS_TO_SKIP) {
|
||||
current_run++;
|
||||
__enable_interrupts();
|
||||
continue;
|
||||
}
|
||||
|
||||
__disable_interrupts();
|
||||
current_run = 0;
|
||||
|
||||
if(!done) {
|
||||
switch((lfsr & 0x0003) + 1) {
|
||||
case K_UP:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_UP);
|
||||
done = step_game(GAME_STEP_UP);
|
||||
break;
|
||||
case K_DOWN:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_DOWN);
|
||||
done = step_game(GAME_STEP_DOWN);
|
||||
break;
|
||||
case K_LEFT:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_LEFT);
|
||||
done = step_game(GAME_STEP_LEFT);
|
||||
break;
|
||||
case K_RIGHT:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_RIGHT);
|
||||
done = step_game(GAME_STEP_RIGHT);
|
||||
break;
|
||||
default:
|
||||
__enable_interrupts();
|
||||
continue; // Do nothing, loop again
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Increase the count of moves we made (unless we lost or reset the game)
|
||||
if(done >= 0) {
|
||||
moves_count++;
|
||||
done = done || (moves_count >= MAX_DEMO_MOVES);
|
||||
}
|
||||
|
||||
// Draw the number of moves
|
||||
num_to_decbuf(moves_count, 5, text_buf);
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, MOVES_TEXT_X, MOVES_TEXT_Y, (char*)text_buf);
|
||||
|
||||
// Draw the moved tiles
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
|
||||
// If we have won, or we got a reset request, break out of this loop
|
||||
if(done) {
|
||||
num_to_decbuf(score, 5, text_buf); // Score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Unable to add a tile: we ran out of space and lost!!!
|
||||
uint8_t random_tile_off = add_random_tile();
|
||||
if(!random_tile_off) {
|
||||
done = -1; // Lost the game
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
score = calculate_score();
|
||||
|
||||
// Draw the score
|
||||
num_to_decbuf(score, 5, text_buf); // Score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
vdp_draw_joystick(JS_POS_CENTER);
|
||||
|
||||
__enable_interrupts();
|
||||
}
|
||||
|
||||
__disable_interrupts();
|
||||
|
||||
// Always go back to the start dialog
|
||||
dld->mode = DLOG_MODE_START;
|
||||
dld->score = 0;
|
||||
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
|
||||
return;
|
||||
}
|
||||
96
src/vddlg_main.c
Normal file
96
src/vddlg_main.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "vdp_utils.h"
|
||||
#include "game_vdp_graphics.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "shared_page.h"
|
||||
#include "state_page.h"
|
||||
#include "dlog_data.h"
|
||||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "sound.h"
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
static state_page_data* state_page = (state_page_data*)STATE_PAGE;
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
static uint8_t score_buf[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static char game_ver[5] = {'V', GAME_VER_CH0, GAME_VER_CH1, GAME_VER_CH2, '\0'};
|
||||
|
||||
#define WAIT_COUNTER_END 0xFFFF
|
||||
|
||||
void main(void) {
|
||||
uint16_t wait_counter = 0;
|
||||
dlog_data *dld = (dlog_data *)(shared_page->module_data);
|
||||
game_data *gad = (game_data *)(shared_page->module_data);
|
||||
|
||||
__disable_interrupts(); // Make sure the interrupts are disabled
|
||||
|
||||
num_to_decbuf(state_page->hi_score, 6, score_buf);
|
||||
decbuf_to_ascii(6, score_buf);
|
||||
|
||||
vdp_hide_sprites();
|
||||
vdp_clear_dialog();
|
||||
vdp_switch_nt(1); // Make sure VDP shows the correct dialog nametable
|
||||
|
||||
vdp_print_string(1, 6, 10, "Current High-Score :");
|
||||
vdp_print_string(1, 13, 12, (char*)score_buf);
|
||||
vdp_print_string(1, 5, 15, "Press any key to START");
|
||||
vdp_print_string(1, 1, 23, "hkz@social.chinwag.org");
|
||||
vdp_print_string(1, 28, 23, game_ver);
|
||||
|
||||
switch(dld->mode) {
|
||||
case DLOG_MODE_WIN:
|
||||
snd_festive();
|
||||
vdp_print_string(1, 11, 8, "YOU WIN!!!");
|
||||
break;
|
||||
case DLOG_MODE_LOSE:
|
||||
snd_sad_scale();
|
||||
vdp_print_string(1, 11, 8, "GAME OVER!");
|
||||
break;
|
||||
default:
|
||||
case DLOG_MODE_START:
|
||||
vdp_print_string(1, 7, 8, "WELCOME TO TK2048!");
|
||||
snd_start();
|
||||
break;
|
||||
};
|
||||
|
||||
if(dld->score > state_page->hi_score) { // New high-score. We need to save it.
|
||||
state_page->hi_score = dld->score;
|
||||
|
||||
// Update the score!
|
||||
num_to_decbuf(state_page->hi_score, 6, score_buf);
|
||||
decbuf_to_ascii(6, score_buf);
|
||||
vdp_print_string(1, 13, 12, (char*)score_buf);
|
||||
vdp_print_string(1, 8, 13, "!NEW HIGH SCORE!");
|
||||
|
||||
shared_page->master_command = MASTER_COMMAND_SAVE;
|
||||
} else {
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
}
|
||||
|
||||
shared_page->next_module_idx = MODULE_GAME_VDP; // Go to the GAME module
|
||||
gad->mode = GAME_MODE_NORMAL; // Set the proper start mode for the game
|
||||
|
||||
while(!read_any_key() && (wait_counter != WAIT_COUNTER_END)) {
|
||||
wait_counter++;
|
||||
lfsr_update();
|
||||
}
|
||||
|
||||
if (wait_counter == WAIT_COUNTER_END) {
|
||||
shared_page->next_module_idx = MODULE_DEMO_VDP; // Actually go to the DEMO module
|
||||
return;
|
||||
}
|
||||
|
||||
snd_mod_button();
|
||||
|
||||
return;
|
||||
}
|
||||
198
src/vdgam_main.c
Normal file
198
src/vdgam_main.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "vdp_utils.h"
|
||||
#include "game_vdp_graphics.h"
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "mem_registers.h"
|
||||
#include "shared_page.h"
|
||||
#include "state_page.h"
|
||||
#include "dlog_data.h"
|
||||
#include "game_data.h"
|
||||
#include "input.h"
|
||||
#include "game_logic.h"
|
||||
#include "monitor_subroutines.h"
|
||||
#include "sound.h"
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
#define HSCORE_TEXT_X 27
|
||||
#define HSCORE_TEXT_Y 13
|
||||
|
||||
#define SCORE_TEXT_X 27
|
||||
#define SCORE_TEXT_Y 4
|
||||
|
||||
#define MOVES_TEXT_X 27
|
||||
#define MOVES_TEXT_Y 8
|
||||
|
||||
#define BOTTOM_TEXT_X 1
|
||||
#define BOTTOM_TEXT_Y 23
|
||||
|
||||
#define WIN_SCORE_BONUS 10000
|
||||
|
||||
static state_page_data* state_page = (state_page_data*)STATE_PAGE;
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
static uint8_t text_buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
void main(void) {
|
||||
uint16_t moves_count = 0;
|
||||
uint16_t score = 0;
|
||||
int8_t done = 0;
|
||||
|
||||
__disable_interrupts(); // Make sure the interrupts are disabled
|
||||
|
||||
// By default, once we return from this, return to the DLOG module and give the master no command to execute
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = MODULE_DLOG_VDP; // Go to the dialog module
|
||||
|
||||
dlog_data *dld = (dlog_data *)(shared_page->module_data);
|
||||
dlog_data *gad = (dlog_data *)(shared_page->module_data);
|
||||
|
||||
// Make sure the buffers are pointing to the correct memory and are clear
|
||||
vdp_hide_sprites();
|
||||
vdp_clear_gamegrid();
|
||||
vdp_switch_nt(0); // Make sure VDP shows the gamegrid
|
||||
|
||||
// Setup the IRQ handler
|
||||
POKEW(IRQ_HANDLER_ADDRESS, (uint16_t)vdp_irq_handler);
|
||||
|
||||
// Reset the game, calculate the initial score depending on which tiles we randomly get
|
||||
score = reset_game();
|
||||
|
||||
// Load the game
|
||||
if(gad->mode == GAME_MODE_LOAD) {
|
||||
gad->mode = GAME_MODE_NORMAL;
|
||||
|
||||
memcpy(get_front_grid(), (void*)(state_page->save_grid), GRID_SIDE * GRID_SIDE);
|
||||
moves_count = state_page->saved_moves_count;
|
||||
score = calculate_score();
|
||||
|
||||
// We loaded an empty save, just restart the game
|
||||
if (!score) score = reset_game();
|
||||
}
|
||||
|
||||
// Draw the initial state of the game
|
||||
vdp_print_string(0, BOTTOM_TEXT_X, BOTTOM_TEXT_Y, "hkz@social.chinwag.org 2025");
|
||||
|
||||
num_to_decbuf(state_page->hi_score, 5, text_buf); // High score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, HSCORE_TEXT_X, HSCORE_TEXT_Y, (char*)text_buf);
|
||||
|
||||
num_to_decbuf(moves_count, 5, text_buf); // Moves count
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, MOVES_TEXT_X, MOVES_TEXT_Y, (char*)text_buf);
|
||||
|
||||
num_to_decbuf(score, 5, text_buf); // Score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
||||
|
||||
vdp_draw_joystick(JS_POS_CENTER); // Center the joystick
|
||||
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
|
||||
__enable_interrupts();
|
||||
|
||||
while(1) { // Game loop
|
||||
lfsr_update();
|
||||
|
||||
__disable_interrupts();
|
||||
switch(read_kb()) {
|
||||
case K_UP:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_UP);
|
||||
done = step_game(GAME_STEP_UP);
|
||||
break;
|
||||
case K_DOWN:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_DOWN);
|
||||
done = step_game(GAME_STEP_DOWN);
|
||||
break;
|
||||
case K_LEFT:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_LEFT);
|
||||
done = step_game(GAME_STEP_LEFT);
|
||||
break;
|
||||
case K_RIGHT:
|
||||
SND_TAP();
|
||||
vdp_draw_joystick(JS_POS_RIGHT);
|
||||
done = step_game(GAME_STEP_RIGHT);
|
||||
break;
|
||||
case K_CTRL_R:
|
||||
snd_mod_button();
|
||||
|
||||
score = 0; // We'll reset the score
|
||||
done = -1;
|
||||
break;
|
||||
case K_CTRL_S: // The following two will return early
|
||||
snd_mod_button();
|
||||
|
||||
memcpy((void*)(state_page->save_grid), get_front_grid(), GRID_SIDE * GRID_SIDE);
|
||||
state_page->saved_moves_count = moves_count;
|
||||
shared_page->master_command = MASTER_COMMAND_SAVE;
|
||||
case K_CTRL_L:
|
||||
snd_mod_button();
|
||||
|
||||
shared_page->next_module_idx = MODULE_GAME_VDP;
|
||||
gad->mode = GAME_MODE_LOAD;
|
||||
return;
|
||||
default:
|
||||
__enable_interrupts();
|
||||
continue; // Do nothing, loop again
|
||||
}
|
||||
|
||||
// Increase the count of moves we made (unless we lost or reset the game)
|
||||
if(done >= 0) moves_count++;
|
||||
|
||||
num_to_decbuf(moves_count, 5, text_buf); // Moves count
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, MOVES_TEXT_X, MOVES_TEXT_Y, (char*)text_buf);
|
||||
|
||||
// If we have won, or we got a reset request, break out of this loop
|
||||
if(done) {
|
||||
score += (done > 0) ? WIN_SCORE_BONUS : 0;
|
||||
|
||||
num_to_decbuf(score, 5, text_buf); // Score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Unable to add a tile: we ran out of space and lost!!!
|
||||
uint8_t random_tile_off = add_random_tile();
|
||||
if(!random_tile_off) {
|
||||
done = -1; // Lost the game
|
||||
break;
|
||||
}
|
||||
|
||||
score = calculate_score();
|
||||
|
||||
// Draw the score
|
||||
num_to_decbuf(score, 5, text_buf); // Score
|
||||
decbuf_to_ascii(5, text_buf);
|
||||
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
vdp_draw_joystick(JS_POS_CENTER);
|
||||
|
||||
__enable_interrupts();
|
||||
}
|
||||
|
||||
dld->mode = (done > 0) ? DLOG_MODE_WIN : DLOG_MODE_LOSE;
|
||||
dld->score = score;
|
||||
|
||||
vdp_redraw_tiles(get_front_grid());
|
||||
|
||||
WAIT(0xFF);
|
||||
|
||||
__disable_interrupts();
|
||||
|
||||
return;
|
||||
}
|
||||
10
src/vdp.s
Normal file
10
src/vdp.s
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
.rtmodel version,"1"
|
||||
.rtmodel core,"6502"
|
||||
|
||||
;;; IO Ports
|
||||
SLOT_OFFSET:.equ 0x40
|
||||
VDP_BASE: .equ 0xC080 + SLOT_OFFSET
|
||||
VDP_MEM: .equ VDP_BASE + 0x00
|
||||
VDP_REG: .equ VDP_BASE + 0x01
|
||||
|
||||
.public VDP_MEM, VDP_REG
|
||||
8
src/vdp_init.h
Normal file
8
src/vdp_init.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _VDP_INIT_HEADER_
|
||||
#define _VDP_INIT_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t vdp_init(void);
|
||||
|
||||
#endif /* _VDP_INIT_HEADER_ */
|
||||
161
src/vdp_init.s
Normal file
161
src/vdp_init.s
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
.rtmodel version,"1"
|
||||
.rtmodel core,"6502"
|
||||
|
||||
.extern _Zp
|
||||
.extern vdp_write_vram, vdp_write_registers
|
||||
.extern SpriteAttributeTable, NT_P0, NT_P1
|
||||
.extern VDP_MEM, VDP_REG
|
||||
|
||||
.section code,text
|
||||
|
||||
;;; vdp_init:
|
||||
;;; Initialize the VDP processor
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 1, 2, 3, 4, 5
|
||||
;;;
|
||||
vdp_init:
|
||||
T_SCRATCH_L$:.equ _Zp+0
|
||||
T_SCRATCH_H$:.equ _Zp+1
|
||||
|
||||
; Get the board ready to accept the rest of the commands
|
||||
lda #0x80 ; Disable interrupts and video, set 16K mode
|
||||
sta VDP_REG
|
||||
lda #0x81
|
||||
sta VDP_REG
|
||||
|
||||
; Load the pattern table int 0x0800
|
||||
lda #.byte0 PatternTable_Charset
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 PatternTable_Charset
|
||||
sta zp:_Zp+1
|
||||
lda #0x00
|
||||
sta zp:_Zp+2
|
||||
lda #0x08
|
||||
sta zp:_Zp+3
|
||||
lda #0x00
|
||||
sta zp:_Zp+4
|
||||
lda #0x08
|
||||
sta zp:_Zp+5
|
||||
jsr vdp_write_vram
|
||||
|
||||
; Load the Color Table into 0x0380
|
||||
lda #.byte0 ColorTable
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 ColorTable
|
||||
sta zp:_Zp+1
|
||||
lda #0x20
|
||||
sta zp:_Zp+2
|
||||
lda #0x00
|
||||
sta zp:_Zp+3
|
||||
lda #0x80
|
||||
sta zp:_Zp+4
|
||||
lda #0x03
|
||||
sta zp:_Zp+5
|
||||
jsr vdp_write_vram
|
||||
|
||||
; Load the Sprite attribute table at 0x0300
|
||||
lda #.byte0 SpriteAttributeTable
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 SpriteAttributeTable
|
||||
sta zp:_Zp+1
|
||||
lda #0x80
|
||||
sta zp:_Zp+2
|
||||
lda #0x00
|
||||
sta zp:_Zp+3
|
||||
lda #0x00
|
||||
sta zp:_Zp+4
|
||||
lda #0x03
|
||||
sta zp:_Zp+5
|
||||
jsr vdp_write_vram
|
||||
|
||||
; Load the Name Table for the Game Board at 0x0000
|
||||
lda #.byte0 NameTable_GameBoard
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 NameTable_GameBoard
|
||||
sta zp:_Zp+1
|
||||
lda #0x00
|
||||
sta zp:_Zp+2
|
||||
lda #0x03
|
||||
sta zp:_Zp+3
|
||||
lda #0x00
|
||||
sta zp:_Zp+4
|
||||
lda NT_P0
|
||||
sta zp:_Zp+5
|
||||
jsr vdp_write_vram
|
||||
|
||||
; Load the Name Table for the Dialog Screens at 0x1400
|
||||
lda #.byte0 NameTable_Dialog
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 NameTable_Dialog
|
||||
sta zp:_Zp+1
|
||||
lda #0x00
|
||||
sta zp:_Zp+2
|
||||
lda #0x03
|
||||
sta zp:_Zp+3
|
||||
lda #0x00
|
||||
sta zp:_Zp+4
|
||||
lda NT_P1
|
||||
sta zp:_Zp+5
|
||||
jsr vdp_write_vram
|
||||
|
||||
; Load the Sprite Pattern table at 0x1000
|
||||
lda #.byte0 SpritePatternTable
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 SpritePatternTable
|
||||
sta zp:_Zp+1
|
||||
lda #0x80
|
||||
sta zp:_Zp+2
|
||||
lda #0x01
|
||||
sta zp:_Zp+3
|
||||
lda #0x00
|
||||
sta zp:_Zp+4
|
||||
lda #0x10
|
||||
sta zp:_Zp+5
|
||||
jsr vdp_write_vram
|
||||
|
||||
; Write the register sequence
|
||||
lda #.byte0 VDPRegs_M0
|
||||
sta zp:_Zp+0
|
||||
lda #.byte1 VDPRegs_M0
|
||||
sta zp:_Zp+1
|
||||
jsr vdp_write_registers
|
||||
|
||||
rts
|
||||
|
||||
.section data,data
|
||||
|
||||
PatternTable_Charset:
|
||||
.incbin "..\\data\\vdp_charset.bin"
|
||||
|
||||
NameTable_GameBoard:
|
||||
.incbin "..\\data\\vdp_nt_board.bin"
|
||||
|
||||
NameTable_Dialog:
|
||||
.incbin "..\\data\\vdp_nt_dialog.bin"
|
||||
|
||||
SpritePatternTable:
|
||||
.incbin "..\\data\\vdp_sprite_tiles.bin"
|
||||
|
||||
ColorTable:
|
||||
.incbin "..\\data\\vdp_colortable.bin"
|
||||
|
||||
VDPRegs_M0:
|
||||
.byte 0x00, 0x80 ; Reg. 0, Disable external video, set M3 to 0 (we'll use mode 0/Graphics I)
|
||||
.byte 0xE3, 0x81 ; Reg. 1, Enable display and interrupts, 16x16 sprites and magnification
|
||||
.byte 0x05, 0x82 ; Reg. 2, Place Name Table at 0x1400 (Load the Dialog)
|
||||
.byte 0x0E, 0x83 ; Reg. 3, Place Color Table at 0x0380
|
||||
.byte 0x01, 0x84 ; Reg. 4, Place Pattern Table at 0x0800
|
||||
.byte 0x06, 0x85 ; Reg. 5, Place Sprite Attribute Table at 0x0300, the secondary will live at 0x1200
|
||||
.byte 0x02, 0x86 ; Reg. 6, Place Sprite Pattern Table at 0x1000
|
||||
.byte 0xF1, 0x87 ; Reg. 7, Set foreground and background color (white on black)
|
||||
|
||||
;;;
|
||||
;;;
|
||||
;;; Exported symbols
|
||||
.public vdp_init
|
||||
|
||||
20
src/vdp_utils.h
Normal file
20
src/vdp_utils.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef _VDP_UTILS_HEADER_
|
||||
#define _VDP_UTILS_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void vdp_write_vram(uint8_t *src, uint16_t len, uint16_t vram_dest);
|
||||
void vdp_fill_vram(uint8_t val, uint16_t len, uint16_t vram_dest);
|
||||
uint8_t vdp_detect(void);
|
||||
void vdp_init_registers(uint8_t *reg_array);
|
||||
void vdp_hide_sprites(void);
|
||||
void vdp_hide_sprite(uint8_t sprite_number);
|
||||
void vdp_show_sprite(uint8_t sprite_number);
|
||||
void vdp_set_sprite_tile(uint8_t sprite_number, uint8_t tile_idx);
|
||||
void vdp_switch_nt(uint8_t nt_idx);
|
||||
void vdp_print_string(uint8_t nt_idx, uint8_t x, uint8_t y, char *str);
|
||||
void vdp_set_tile(uint8_t nt_idx, uint8_t x, uint8_t y, uint8_t tile_idx);
|
||||
void vdp_write_interleaved_sat(void);
|
||||
void vdp_irq_handler(void);
|
||||
|
||||
#endif /* _VDP_UTILS_HEADER_ */
|
||||
665
src/vdp_utils.s
Normal file
665
src/vdp_utils.s
Normal file
|
|
@ -0,0 +1,665 @@
|
|||
.rtmodel version,"1"
|
||||
.rtmodel core,"6502"
|
||||
|
||||
.extern _Zp
|
||||
.extern VDP_MEM, VDP_REG
|
||||
|
||||
;;; Define a space
|
||||
.section intrzp, noinit, root ; root, as we always require it
|
||||
.space 0xA9
|
||||
|
||||
.section code,text
|
||||
|
||||
|
||||
;;; vdp_point_to_vram_xy:
|
||||
;;; Readies the VDP registers to write on a tile at XY
|
||||
;;; Parameters:
|
||||
;;; - nametable index in vram [_Zp[4]]
|
||||
;;; - X coordinate [_Zp[0]]
|
||||
;;; - Y coordinate [_Zp[1]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 5, 6
|
||||
;;;
|
||||
vdp_point_to_vram_xy:
|
||||
T_VADD_H$: .equ _Zp+6
|
||||
T_VADD_L$: .equ _Zp+5
|
||||
P_NT_IDX$: .equ _Zp+4
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
lda #0x00
|
||||
sta zp:T_VADD_H$
|
||||
lda zp:P_Y$
|
||||
sta zp:T_VADD_L$
|
||||
|
||||
;; Shift Y five times to the left to get the offset for the ROW in VRAM
|
||||
ldx #5
|
||||
ShiftOffset$:
|
||||
asl zp:T_VADD_L$
|
||||
rol zp:T_VADD_H$
|
||||
dex
|
||||
bne ShiftOffset$
|
||||
|
||||
clc
|
||||
|
||||
; Calculate the VRAM address
|
||||
lda zp:P_X$
|
||||
adc zp:T_VADD_L$
|
||||
sta zp:T_VADD_L$
|
||||
ldx zp:P_NT_IDX$
|
||||
lda NameTablesList,x
|
||||
adc zp:T_VADD_H$
|
||||
sta zp:T_VADD_H$
|
||||
|
||||
; Setup the VDP to write into VRAM
|
||||
lda zp:T_VADD_L$
|
||||
sta VDP_REG
|
||||
nop
|
||||
lda zp:T_VADD_H$
|
||||
ora #0x40
|
||||
sta VDP_REG
|
||||
nop
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_set_tile:
|
||||
;;; Prints the provided ASCII string at the specified coordinates
|
||||
;;; Parameters:
|
||||
;;; - nametable index in vram [A]
|
||||
;;; - X coordinate [_Zp[0]]
|
||||
;;; - Y coordinate [_Zp[1]]
|
||||
;;; - tile index [_Zp[2]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 5, 6
|
||||
;;;
|
||||
vdp_set_tile:
|
||||
T_VADD_H$: .equ _Zp+6
|
||||
T_VADD_L$: .equ _Zp+5
|
||||
P_NT_IDX$: .equ _Zp+4
|
||||
P_TILE$: .equ _Zp+2
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
sta zp:P_NT_IDX$
|
||||
|
||||
jsr vdp_point_to_vram_xy
|
||||
|
||||
lda zp:P_TILE$
|
||||
sta VDP_MEM
|
||||
nop
|
||||
|
||||
EOS$:
|
||||
rts
|
||||
|
||||
;;; vdp_print_string:
|
||||
;;; Prints the provided ASCII string at the specified coordinates (newlines and control chars are not supported)
|
||||
;;; Parameters:
|
||||
;;; - nametable index in vram [A]
|
||||
;;; - X coordinate [_Zp[0]]
|
||||
;;; - Y coordinate [_Zp[1]]
|
||||
;;; - string address [_Zp[2], _Zp[3]]: Address of the beginning of data to write
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 5, 6
|
||||
;;;
|
||||
vdp_print_string:
|
||||
T_VADD_H$: .equ _Zp+6
|
||||
T_VADD_L$: .equ _Zp+5
|
||||
P_NT_IDX$: .equ _Zp+4
|
||||
P_DATA_H$: .equ _Zp+3
|
||||
P_DATA_L$: .equ _Zp+2
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
sta zp:P_NT_IDX$
|
||||
|
||||
jsr vdp_point_to_vram_xy
|
||||
|
||||
ldy #0x00
|
||||
NextChar$:
|
||||
lda (zp:P_DATA_L$),y
|
||||
beq EOS$
|
||||
sec
|
||||
sbc #0x20
|
||||
sta VDP_MEM
|
||||
nop
|
||||
nop
|
||||
iny
|
||||
bne NextChar$
|
||||
|
||||
EOS$:
|
||||
rts
|
||||
|
||||
;;; vdp_write_vram:
|
||||
;;; Write the provided data into VRAM at specified address
|
||||
;;; Parameters:
|
||||
;;; - data address [_Zp[0], _Zp[1]]: Address of the beginning of data to write
|
||||
;;; - data length [_Zp[2], _Zp[3]]: Length of data to write
|
||||
;;; - VRAM address [_Zp[4], _Zp[5]]: Start address of data in VRAM
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 1, 2, 3
|
||||
;;;
|
||||
vdp_write_vram:
|
||||
P_VADD_H$: .equ _Zp+5
|
||||
P_VADD_L$: .equ _Zp+4
|
||||
P_DLEN_H$: .equ _Zp+3
|
||||
P_DLEN_L$: .equ _Zp+2
|
||||
P_DATA_H$: .equ _Zp+1
|
||||
P_DATA_L$: .equ _Zp+0
|
||||
|
||||
; Decrement length by one, so or the loop would do an off-by-one write
|
||||
sec
|
||||
lda zp:P_DLEN_L$
|
||||
sbc #1
|
||||
sta zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_H$
|
||||
sbc #0
|
||||
sta zp:P_DLEN_H$
|
||||
|
||||
; Setup the VDP to write into VRAM
|
||||
lda zp:P_VADD_L$
|
||||
sta VDP_REG
|
||||
lda zp:P_VADD_H$
|
||||
ora #0x40
|
||||
sta VDP_REG
|
||||
|
||||
; Actually write data into VRAM
|
||||
ldx zp:P_DLEN_H$
|
||||
ldy #0x00
|
||||
CopyLoop$:
|
||||
lda (zp:P_DATA_L$),y
|
||||
sta VDP_MEM
|
||||
nop
|
||||
iny
|
||||
bne SkipHIncr$ ; Check if we did overflow. In case, increment the high byte of the address
|
||||
inc zp:P_DATA_H$
|
||||
SkipHIncr$:
|
||||
dec zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_L$
|
||||
cmp #0xFF
|
||||
bne CopyLoop$
|
||||
dex
|
||||
bpl CopyLoop$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_fill_vram:
|
||||
;;; Fill VRAM with a specific byte
|
||||
;;; Parameters:
|
||||
;;; - fill value [A]
|
||||
;;; - data length [_Zp[0], _Zp[1]]: Length of data to write
|
||||
;;; - VRAM address [_Zp[2], _Zp[3]]: Start address of data in VRAM
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 0, 1, 2, 4
|
||||
;;;
|
||||
vdp_fill_vram:
|
||||
T_FILLVAL$: .equ _Zp+4
|
||||
P_VADD_H$: .equ _Zp+3
|
||||
P_VADD_L$: .equ _Zp+2
|
||||
P_DLEN_H$: .equ _Zp+1
|
||||
P_DLEN_L$: .equ _Zp+0
|
||||
|
||||
sta zp:T_FILLVAL$
|
||||
|
||||
; Decrement length by one, so or the loop would do an off-by-one write
|
||||
sec
|
||||
lda zp:P_DLEN_L$
|
||||
sbc #1
|
||||
sta zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_H$
|
||||
sbc #0
|
||||
sta zp:P_DLEN_H$
|
||||
|
||||
; Setup the VDP to write into VRAM
|
||||
lda zp:P_VADD_L$
|
||||
sta VDP_REG
|
||||
lda zp:P_VADD_H$
|
||||
ora #0x40
|
||||
sta VDP_REG
|
||||
|
||||
; Fill the VRAM
|
||||
ldx zp:P_DLEN_H$
|
||||
CopyLoop$:
|
||||
lda zp:T_FILLVAL$
|
||||
sta VDP_MEM
|
||||
nop
|
||||
|
||||
dec zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_L$
|
||||
cmp #0xFF
|
||||
bne CopyLoop$
|
||||
dex
|
||||
bpl CopyLoop$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_detect:
|
||||
;;; Check if a VDP is present
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: 0xFF in A if VDP is present, 0 otherwise
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A
|
||||
;;;
|
||||
vdp_detect:
|
||||
lda #0x00
|
||||
sta VDP_REG
|
||||
nop
|
||||
lda #0x40
|
||||
sta VDP_REG
|
||||
nop
|
||||
|
||||
lda #0x55
|
||||
sta VDP_MEM
|
||||
nop
|
||||
lda #0xAA
|
||||
sta VDP_MEM
|
||||
nop
|
||||
|
||||
lda #0x00
|
||||
sta VDP_REG
|
||||
nop
|
||||
sta VDP_REG
|
||||
nop
|
||||
|
||||
eor VDP_MEM
|
||||
nop
|
||||
eor VDP_MEM
|
||||
nop
|
||||
|
||||
cmp #0xFF
|
||||
beq VdpFound$
|
||||
lda #0x00
|
||||
VdpFound$:
|
||||
rts
|
||||
|
||||
;;; vdp_hide_sprites:
|
||||
;;; Marks all sprites as hidden
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 1, 2, 3, 4, 5, 6, 7
|
||||
;;;
|
||||
vdp_hide_sprites:
|
||||
ldy #0
|
||||
HideLoop$:
|
||||
tya
|
||||
|
||||
jsr vdp_hide_sprite
|
||||
|
||||
iny
|
||||
cpy #25
|
||||
bne HideLoop$
|
||||
|
||||
; Make sure the table gets updated in memory
|
||||
jsr vdp_write_interleaved_sat
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_hide_sprite:
|
||||
;;; Mark a single sprite as hidden
|
||||
;;; Parameters:
|
||||
;;; - sprite number [A]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_hide_sprite:
|
||||
tay
|
||||
ldx SAT_RowCol_Trans_Table,y
|
||||
lda #0xC0
|
||||
sta SpriteAttributeTable,x
|
||||
rts
|
||||
|
||||
;;; vdp_show_sprite:
|
||||
;;; Enable a single sprite in the game grid
|
||||
;;; Parameters:
|
||||
;;; - sprite number [A]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_show_sprite:
|
||||
tay
|
||||
ldx SAT_RowCol_Trans_Table,y
|
||||
lda SAT_Y_Map,y
|
||||
sta SpriteAttributeTable,x
|
||||
rts
|
||||
|
||||
;;; vdp_set_sprite_tile:
|
||||
;;; Set the current tile index for a specific sprite
|
||||
;;; Parameters:
|
||||
;;; - sprite number [A]
|
||||
;;; - tile index [_Zp [0]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_set_sprite_tile:
|
||||
P_TILE_IDX$:.equ _Zp+0
|
||||
asl zp:P_TILE_IDX$ ; We're using 2x2 tile sprites
|
||||
asl zp:P_TILE_IDX$
|
||||
|
||||
tay
|
||||
ldx SAT_RowCol_Trans_Table,y
|
||||
lda zp:P_TILE_IDX$
|
||||
sta SpriteAttributeTable+2,x
|
||||
rts
|
||||
|
||||
;;; vdp_switch_nt:
|
||||
;;; Switch shown nametable
|
||||
;;; Parameters:
|
||||
;;; - name table index [A]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, X
|
||||
;;;
|
||||
vdp_switch_nt:
|
||||
tax
|
||||
lda NameTablesList,x
|
||||
lsr a
|
||||
lsr a
|
||||
sta VDP_REG
|
||||
nop
|
||||
lda #0x82
|
||||
sta VDP_REG
|
||||
nop
|
||||
rts
|
||||
|
||||
;;; vdp_write_registers:
|
||||
;;; Initialize the registers of the VDP, using the provided byte array
|
||||
;;; Parameters:
|
||||
;;; - data address [_Zp[0], _Zp[1]]: Address of the beginning of initialization data, a 16 byte array
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y
|
||||
;;;
|
||||
vdp_write_registers:
|
||||
P_REG_H$: .equ _Zp+1
|
||||
P_REG_L$: .equ _Zp+0
|
||||
|
||||
; Write the register sequence
|
||||
ldy #0x00
|
||||
RegLoop$:
|
||||
lda (zp:P_REG_L$),y
|
||||
sta VDP_REG
|
||||
nop
|
||||
iny
|
||||
cpy #16
|
||||
bne RegLoop$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_write_interleaved_sat:
|
||||
;;; Updates SAT at 0x300 with sprite multiplexing
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 1, 2, 3, 4, 5, 6, 7
|
||||
;;;
|
||||
vdp_write_interleaved_sat:
|
||||
T_COUNT$: .equ _Zp+7
|
||||
T_SATB_IDX$: .equ _Zp+6
|
||||
T_DEST_H$: .equ _Zp+5
|
||||
T_DEST_L$: .equ _Zp+4
|
||||
T_DLEN_H$: .equ _Zp+3
|
||||
T_DLEN_L$: .equ _Zp+2
|
||||
T_DATA_H$: .equ _Zp+1
|
||||
T_DATA_L$: .equ _Zp+0
|
||||
|
||||
lda #0x00
|
||||
sta zp:T_DEST_L$
|
||||
lda #0x03
|
||||
sta zp:T_DEST_H$
|
||||
|
||||
lda CurrentByteTableOffset
|
||||
cmp #5
|
||||
bne NoOverflow$
|
||||
lda #0
|
||||
sta CurrentByteTableOffset
|
||||
NoOverflow$:
|
||||
asl a
|
||||
sta zp:T_SATB_IDX$
|
||||
|
||||
lda #4
|
||||
sta zp:T_COUNT$
|
||||
|
||||
WriteLoop$:
|
||||
lda #20
|
||||
sta zp:T_DLEN_L$
|
||||
lda #00
|
||||
sta zp:T_DLEN_H$
|
||||
|
||||
lda zp:T_SATB_IDX$
|
||||
tax
|
||||
|
||||
lda SAT_Block_Table,x
|
||||
sta zp:T_DATA_L$
|
||||
lda SAT_Block_Table+1,x
|
||||
sta zp:T_DATA_H$
|
||||
|
||||
jsr vdp_write_vram
|
||||
|
||||
clc
|
||||
lda zp:T_DEST_L$
|
||||
adc #20
|
||||
sta zp:T_DEST_L$
|
||||
|
||||
lda zp:T_SATB_IDX$
|
||||
adc #0x02
|
||||
sta zp:T_SATB_IDX$
|
||||
dec zp:T_COUNT$
|
||||
bpl WriteLoop$
|
||||
|
||||
inc CurrentByteTableOffset
|
||||
|
||||
rts
|
||||
|
||||
_irq_save_zp:
|
||||
ldx #0
|
||||
|
||||
SaveZp$:
|
||||
lda zp:_Zp,x
|
||||
sta .sectionStart intrzp,x
|
||||
inx
|
||||
;cpx #.sectionSize intrzp
|
||||
cpx #10 ; Save only part of the ZP, we're not using more
|
||||
bne SaveZp$
|
||||
|
||||
rts
|
||||
|
||||
_irq_restore_zp:
|
||||
ldx #0
|
||||
|
||||
RestoreZp$:
|
||||
lda .sectionStart intrzp,x
|
||||
sta zp:_Zp,x
|
||||
inx
|
||||
;cpx #.sectionSize intrzp
|
||||
cpx #10 ; Restpre only part of the ZP, we're not using more
|
||||
bne RestoreZp$
|
||||
|
||||
rts
|
||||
|
||||
vdp_irq_handler:
|
||||
; Save the registers
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
|
||||
;;; Save ZP
|
||||
jsr _irq_save_zp
|
||||
|
||||
jsr vdp_write_interleaved_sat
|
||||
|
||||
;;; Restore ZP
|
||||
jsr _irq_restore_zp
|
||||
|
||||
;;; Clear the IRQ
|
||||
lda VDP_REG
|
||||
|
||||
; Restore the registers
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
|
||||
rti
|
||||
|
||||
;;;;;;;;;;;;;;;;;;
|
||||
.section data,data
|
||||
|
||||
SpriteAttributeTable:
|
||||
; Organized in columns
|
||||
SAT_Col1:
|
||||
.byte 0xC0, 0x08, 0x30, 0x01 ; Col 1
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
SAT_Col2:
|
||||
.byte 0xC0, 0x30, 0x30, 0x01 ; Col 2
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
SAT_Col3:
|
||||
.byte 0xC0, 0x58, 0x30, 0x01 ; Col 3
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
SAT_Col4:
|
||||
.byte 0xC0, 0x80, 0x30, 0x01 ; Col 4
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
SAT_Col5:
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01 ; Col 5
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
; Unused
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
|
||||
SAT_RowCol_Trans_Table:
|
||||
.byte 0, 20, 40, 60, 80
|
||||
.byte 4, 24, 44, 64, 84
|
||||
.byte 8, 28, 48, 68, 88
|
||||
.byte 12, 32, 52, 72, 92
|
||||
.byte 16, 36, 56, 76, 96
|
||||
|
||||
SAT_Y_Map:
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
|
||||
SAT_Block_Table:
|
||||
.word SAT_Col1
|
||||
.word SAT_Col2
|
||||
.word SAT_Col3
|
||||
.word SAT_Col4
|
||||
.word SAT_Col5
|
||||
.word SAT_Col1
|
||||
.word SAT_Col2
|
||||
.word SAT_Col3
|
||||
.word SAT_Col4
|
||||
.word SAT_Col5
|
||||
|
||||
; Contains a list of VRAM addresses corresponding to every page
|
||||
NameTablesList:
|
||||
NT_P0: .byte 0x00
|
||||
NT_P1: .byte 0x14
|
||||
|
||||
|
||||
CurrentByteTableOffset:
|
||||
.byte 0x00
|
||||
|
||||
;;;
|
||||
;;;
|
||||
;;; Exported symbols
|
||||
.public vdp_write_vram
|
||||
.public vdp_detect
|
||||
.public vdp_write_registers
|
||||
.public vdp_hide_sprites
|
||||
.public vdp_hide_sprite
|
||||
.public vdp_show_sprite
|
||||
.public vdp_switch_nt
|
||||
.public vdp_set_sprite_tile
|
||||
.public vdp_print_string
|
||||
.public vdp_set_tile
|
||||
.public vdp_point_to_vram_xy
|
||||
.public vdp_write_interleaved_sat
|
||||
.public vdp_irq_handler
|
||||
|
||||
.public SpriteAttributeTable ; We'll need to set change visibility and values
|
||||
.public NT_P0, NT_P1
|
||||
34
src/vdpin_main.c
Normal file
34
src/vdpin_main.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include <stubs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <calypsi/intrinsics6502.h>
|
||||
|
||||
#include "vdp_init.h"
|
||||
#include "vdp_utils.h"
|
||||
|
||||
#include "monitor_subroutines.h"
|
||||
#include "utility.h"
|
||||
#include "mem_map.h"
|
||||
#include "shared_page.h"
|
||||
|
||||
#include "module_list.h"
|
||||
|
||||
// External initialization requirements
|
||||
#pragma require __preserve_zp
|
||||
#pragma require __data_initialization_needed
|
||||
|
||||
static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE;
|
||||
|
||||
void main(void) {
|
||||
|
||||
__disable_interrupts(); // Make sure the interrupts are disabled
|
||||
|
||||
vdp_init();
|
||||
|
||||
vdp_print_string(1, 6, 10, "Loading...");
|
||||
|
||||
shared_page->master_command = MASTER_COMMAND_NONE;
|
||||
shared_page->next_module_idx = MODULE_DLOG_VDP;
|
||||
|
||||
return;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue