Merged dii_refactoring, modularize code for 2.0

This commit is contained in:
hkz 2025-08-30 10:01:49 +02:00
commit cfc455f1ca
37 changed files with 2101 additions and 249 deletions

185
src/master_main.c Normal file
View file

@ -0,0 +1,185 @@
#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 5
#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)
};
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,
};
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);
static uint8_t calculate_crc8(uint8_t* data, uint8_t len);
// 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":::);
}
#define CRC8RDALLAS_POLY 0x31
static 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;
}
__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;
}