mirror of
https://codeberg.org/hkzlab/TK2048.git
synced 2025-12-25 18:12:15 +11:00
commit b29f27ab8d852ff575840060b9af7b62c1b69f68
Author: hkz <tabaglio@posteo.net>
Date: Tue Oct 7 09:01:06 2025 +0200
Removed unused loading_screen.c, Updated CHANGELOG, updated loading
screen
commit 2855ba5209
Author: hkz <tabaglio@posteo.net>
Date: Thu Sep 11 15:42:46 2025 +0200
Restore correct offsets for disk writing
commit e1216fa616
Author: hkz <tabaglio@posteo.net>
Date: Sat Sep 6 10:30:43 2025 +0200
Update the version number
commit 8a4559d4f9
Author: hkz <tabaglio@posteo.net>
Date: Sat Sep 6 09:58:24 2025 +0200
implement a demo mode
commit 22790bdc44
Author: hkz <tabaglio@posteo.net>
Date: Sat Sep 6 08:31:11 2025 +0200
Initial creation of demo module
166 lines
5.9 KiB
C
166 lines
5.9 KiB
C
#include <stubs.h>
|
|
|
|
#include <calypsi/intrinsics6502.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "shared_page.h"
|
|
#include "state_page.h"
|
|
#include "monitor_subroutines.h"
|
|
#include "utility.h"
|
|
#include "mem_map.h"
|
|
#include "mem_registers.h"
|
|
#include "disk2.h"
|
|
#include "dos_floppy.h"
|
|
|
|
// External initialization requirements
|
|
#pragma require __data_initialization_needed
|
|
|
|
// Require the exported function table to be present
|
|
//#pragma require __exported_func_table
|
|
|
|
#define DEFAULT_DRIVE_CONTROLLER_OFFSET 0x10
|
|
|
|
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 FNAME_LEN 6
|
|
#define STATE_FILE_IDX 1
|
|
|
|
#define AUTOLOAD_FILES 3 // Autoload the first 3 files
|
|
|
|
// We'll limit ourselves to files with a name of max 5 chars, to save some memory
|
|
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 | '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)
|
|
};
|
|
|
|
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.
|
|
static uint16_t file_load_address[FILE_LIST_LEN] = { // This will hold the load address for the files
|
|
DISPLAY_PAGE_1,
|
|
STATE_PAGE,
|
|
MODULE_PAGE,
|
|
MODULE_PAGE,
|
|
MODULE_PAGE,
|
|
MODULE_PAGE,
|
|
};
|
|
|
|
static void init(void);
|
|
static void init_floppy_data(uint8_t *cur_trk, uint8_t *cur_file);
|
|
static uint8_t fill_trksec_list(uint8_t* cur_trk);
|
|
|
|
// Low level initialization
|
|
static void init(void) {
|
|
POKE(P3_PWRDUP, 0); // Dirty the value checked by the reset vector
|
|
PEEK(IO_ROMSEL); // Make sure the ROM is selected
|
|
PEEK(DISPLAY_PAGE_1); // Select display page 1
|
|
PEEK(IO_DISPLAY_BW); // Disable colors
|
|
|
|
// Generate the decoding table
|
|
dii_generate_6bit_decoding_mapping_table((uint8_t*)DECODING_MAPPING_TABLE_DEFAULT_ADDRESS);
|
|
// Generate the encoding table
|
|
dii_generate_6bit_encoding_mapping_table((uint8_t*)ENCODING_MAPPING_TABLE_DEFAULT_ADDRESS);
|
|
}
|
|
|
|
static uint8_t fill_trksec_list(uint8_t* cur_trk) {
|
|
uint8_t file_counter = 0;
|
|
|
|
for(uint8_t file_idx = 0; file_idx < FILE_LIST_LEN; file_idx++) {
|
|
FDE* f_desc = df_search_file(DEFAULT_DRIVE_CONTROLLER_OFFSET, file_table[file_idx], cur_trk);
|
|
if(f_desc) {
|
|
file_trksec[file_idx][0] = f_desc->tsl_trk;
|
|
file_trksec[file_idx][1] = f_desc->tsl_sec;
|
|
|
|
file_counter++;
|
|
} else {
|
|
file_trksec[file_idx][0] = 0;
|
|
file_trksec[file_idx][1] = 0;
|
|
}
|
|
}
|
|
|
|
return file_counter;
|
|
}
|
|
|
|
// Load the info we need from floppy
|
|
static void init_floppy_data(uint8_t *cur_trk, uint8_t *cur_file) {
|
|
uint8_t initialized_correctly = 0;
|
|
|
|
// Power on the drive and reset the head
|
|
dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 0);
|
|
dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, 96, 0); // Head bang back to track 0!
|
|
|
|
|
|
// Build a table that maps every file we're interested in to the track/sector of the first T/S list entry.
|
|
initialized_correctly = fill_trksec_list(cur_trk) == FILE_LIST_LEN;
|
|
|
|
// Load the first files to autoload
|
|
for(uint8_t file_num = 0; file_num < AUTOLOAD_FILES && initialized_correctly; file_num++) {
|
|
initialized_correctly = df_read_file(DEFAULT_DRIVE_CONTROLLER_OFFSET, file_trksec[file_num][0], file_trksec[file_num][1], (uint8_t*)file_load_address[file_num], cur_trk) && initialized_correctly;
|
|
*cur_file = file_num;
|
|
shared_page->next_module_idx = file_num;
|
|
}
|
|
|
|
// Power off
|
|
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
|
|
|
|
// Check the CRC for the state page
|
|
uint8_t crc = calculate_crc8((uint8_t*)file_load_address[STATE_FILE_IDX], sizeof(state_page_data) - 1);
|
|
if(((state_page_data*)file_load_address[STATE_FILE_IDX])->crc != crc) {
|
|
memset(((void*)file_load_address[STATE_FILE_IDX]), 0, sizeof(state_page_data));
|
|
}
|
|
|
|
// If something went wrong, trigger a break
|
|
if (!initialized_correctly) __asm volatile(" brk\n":::);
|
|
}
|
|
|
|
__task int main(void) {
|
|
uint8_t cur_trk = 0;
|
|
uint8_t cur_file = 0;
|
|
uint8_t keep_going = 1;
|
|
|
|
__disable_interrupts();
|
|
|
|
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
|
|
if(cur_file != shared_page->next_module_idx) {
|
|
cur_file = shared_page->next_module_idx;
|
|
// Read the next module
|
|
keep_going = df_read_file(DEFAULT_DRIVE_CONTROLLER_OFFSET, file_trksec[cur_file][0], file_trksec[cur_file][1], (uint8_t*)file_load_address[cur_file], &cur_trk);
|
|
}
|
|
|
|
// Check if we need to save the state page
|
|
if (shared_page->master_command == MASTER_COMMAND_SAVE) {
|
|
uint8_t crc = calculate_crc8((uint8_t*)file_load_address[STATE_FILE_IDX], sizeof(state_page_data) - 1);
|
|
((state_page_data*)file_load_address[STATE_FILE_IDX])->crc = crc;
|
|
keep_going = keep_going && df_overwrite_file(DEFAULT_DRIVE_CONTROLLER_OFFSET, file_trksec[STATE_FILE_IDX][0], file_trksec[STATE_FILE_IDX][1], (uint8_t*)file_load_address[STATE_FILE_IDX], &cur_trk);
|
|
}
|
|
|
|
dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET);
|
|
__enable_interrupts();
|
|
}
|
|
|
|
shared_page->master_command = MASTER_COMMAND_NONE;
|
|
|
|
// Execute the module
|
|
(((void (*)(void))(MODULE_PAGE))());
|
|
} while(keep_going);
|
|
|
|
__asm volatile(" brk\n":::);
|
|
|
|
return 0;
|
|
}
|