TK2048/src/master_main.c
hkz c1060fb449 Squashed commit of the following:
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
2025-10-07 09:02:18 +02:00

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;
}