Initial code import

This commit is contained in:
Kyle J Cardoza 2024-07-07 11:37:04 -04:00
commit e562ef8dab
30 changed files with 24426 additions and 0 deletions

36
Makefile Normal file
View File

@ -0,0 +1,36 @@
include config/config.mk
TARGET := sentinel-65x-512K
.PHONY: all
all: build/$(TARGET).bin
include config/boot.mk
include config/bios.mk
build/$(TARGET).bin: build/boot.bin build/bios.bin
#Create an empty .bin file.
@dd if=/dev/zero of=$@ bs=1024 count=512
# Add the boot module at offset 0x008000
@dd if=build/boot.bin of=$@ bs=1024 seek=32 conv=notrunc
# Add the bios module at offset 0x008300
@dd if=build/bios.bin of=$@ bs=1 seek=33536 conv=notrunc
.PHONY: clean
clean:
@find build -type f \( \
-name '*.pgz' -o \
-name '*.bin' -o \
-name '*.elf' -o \
-name '*.a' -o \
-name '*.lst' \
\) -delete
@find src -type f \( \
-name '*.o' \
\) -delete
.PHONY: flash
flash: $(TARGET).bin
$(MP) $(MPFLAGS) -w $<

12
config/bios.mk Normal file
View File

@ -0,0 +1,12 @@
BIOS_ASM_SRC := $(wildcard src/bios/*.s)
BIOS_C_SRC := $(wildcard src/bios/*.c)
BIOS_OBJ := $(BIOS_ASM_SRC:.s=.o)
BIOS_OBJ += $(BIOS_C_SRC:.c=.o)
BIOS_LDFLAGS := --list-file build/bios.lst
build/bios.bin: $(BIOS_OBJ)
echo "Linking $@..."
$(LD) -o $@ config/bios.scm $(LDFLAGS) $(BIOS_LDFLAGS) $^
mv build/bios.raw $@

41
config/bios.scm Normal file
View File

@ -0,0 +1,41 @@
(define memories '(
(memory RAM
(address (#x000200 . #x001FFF))
(section zhuge)
(section znear)
(section zdata)
(section heap)
)
(memory ROM
(address (#xC08300 . #xC0FFFF))
(section code)
(section farcode)
(section cdata)
(section switch)
(section near)
(section data)
(section (irq_trampolines #xC0F000))
(section (irq_vectors #xC0FF80))
)
(memory Stack
(address (#x000100 . #x0001FF))
(section (stack #x00100))
)
(memory DirectPage
(address (#x000000 . #x0000FF))
(section
(registers #x000004)
(ztiny)
)
)
(block stack (size #x100)) ; machine stack size
(base-address _DirectPageStart DirectPage 0)
(base-address _NearBaseAddress ROM 0)
))

10
config/boot.mk Normal file
View File

@ -0,0 +1,10 @@
BOOT_SRC := $(wildcard src/boot/*.s)
BOOT_OBJ := $(BOOT_SRC:.s=.o)
BOOT_LDFLAGS := --list-file build/boot.lst
build/boot.bin: $(BOOT_OBJ)
@echo "Linking $@..."
@$(LD) -o $@ config/boot.scm $(LDFLAGS) $(BOOT_LDFLAGS) $^
@mv build/boot.raw $@

36
config/boot.scm Normal file
View File

@ -0,0 +1,36 @@
(define memories '(
(memory Code
(address (#x008000 . #x0080FF))
(section code)
(section cdata)
(section switch)
)
(memory Data
(address (#x008100 . #x0081FF))
(section near)
(section data)
(section znear)
(section zdata)
)
(memory Stack
(address (#x000100 . #x0001FF))
(section (stack #x00100))
)
(memory DirectPage
(address (#x000000 . #x0000FF))
(section
(registers #x000004)
(ztiny)
)
)
(block stack (size #x100)) ; machine stack size
(base-address _DirectPageStart DirectPage 0)
(base-address _NearBaseAddress Data 0)
))

61
config/config.mk Normal file
View File

@ -0,0 +1,61 @@
SHELL := bash
CC := cc65816
AS := as65816
AR := nlib
LD := ln65816
MP := minipro
.SUFFIXES:
.SUFFIXES: .c .s .o .a
CFLAGS := -I include \
--code-model=large \
--data-model=huge \
--64bit-doubles \
--strong-inline \
--force-switch jump-table
ASFLAGS := -I include \
--code-model=large \
--data-model=huge
MPFLAGS := -p SST39LF040@PLCC32
ifeq ($(RELEASE), "true")
CFLAGS += -DNDEBUG \
-O2 \
--speed
else
CFLAGS += --debug \
-Wall \
-Wextra \
-Wpedantic \
-Werror \
-Wno-c11-extensions \
-Wno-gnu-binary-literal \
-Wno-gnu-conditional-omitted-operand \
-Wno-gnu-case-range \
-Wimplicit-fallthrough \
-Wno-gnu-folding-constant
ASFLAGS += --debug
endif
LDFLAGS := --no-data-init-table-section \
--rtattr cstartup=sentinel65x \
--verbose \
--output-format raw
ifeq ($(ENABLE_RELEASE_BUILD), "true")
CFLAGS += -DRELEASE_BUILD
CFLAGS += -DNDEBUG
else
CFLAGS += -DDEBUG
endif
%.o: %.c
@echo "Compiling $@..."
@$(CC) -c $(CFLAGS) -o $@ $<
%.o: %.s
@echo "Assembling $@..."
@$(AS) $(ASFLAGS) -o $@ $<

22
doc/shells.md Normal file
View File

@ -0,0 +1,22 @@
# Shells
Turaco-DOS reserves a portion of main memory for a "shell", a
program which exists to load and run other programs, and handle
their return values. This shell might be a command line, or some
other program that manages other programs, such as a batch file
interpreter.
The active shell has a "resident" portion of memory, which stays
in memory as long as the shell is active, and a "transient" portion
of memory which is only used while the shell is not running an
external program.
When the shell runs a program, and that program exits, its main
function returns a two-byte value; this value is stored in a
specific memory address, and used by the shell as the "status"
code for the program's exit. Like Unix, a zero value is considered
a normal exit, with any positive value being some type of error.
Additionaly, when running a program, the shell can provide the
program with a sequence of arguments, which populate the two
arguments to the main() function.

BIN
include/.DS_Store vendored Normal file

Binary file not shown.

67
include/bios/macros.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef __MACROS_H
#define __MACROS_H
#ifdef __CALYPSI_ASSEMBLER__
#ifdef __CALYPSI_CODE_MODEL_SMALL__
#define libcode code
call .macro dest
jsr \dest
.endm
return .macro
rts
.endm
jump .macro dest
jmp \dest
.endm
#else
#define libcode farcode
call .macro dest
jsl \dest
.endm
return .macro
rtl
.endm
jump .macro dest
jmp long:\dest
.endm
// ----------------------------------------------------------------------
//
// Define code and data model used. This is to add a bit of safety in
// case the way a file is assembled is combined with the wrong run-time.
//
// ----------------------------------------------------------------------
#if defined(__CALYPSI_DATA_MODEL_SMALL__)
.rtmodel dataModel,"small"
#elif defined (__CALYPSI_DATA_MODEL_MEDIUM__)
.rtmodel dataModel,"medium"
#elif defined(__CALYPSI_DATA_MODEL_LARGE__)
.rtmodel dataModel,"large"
#elif defined(__CALYPSI_DATA_MODEL_HUGE__)
.rtmodel dataModel,"huge"
#else
#pragma GCC error "unexpected data model"
#endif
#if defined(__CALYPSI_CODE_MODEL_SMALL__)
.rtmodel codeModel,"small"
#elif defined(__CALYPSI_CODE_MODEL_LARGE__)
.rtmodel codeModel,"large"
#else
#pragma GCC error "unexpected code model"
#endif
#endif // __CALYPSI_CODE_MODEL_SMALL__
#endif // __CALYPSI_ASSEMBLER__
#endif // __MACROS_H

38
include/boot/65c816.h Normal file
View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
//
// boot/w65c816s.h
// Assembly defines for the 65C816 architecture
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#define native_mode \
clc \
xce
#define long_a rep #0x20
#define short_a sep #0x20
#define long_i rep #0x10
#define short_i sep #0x10
#define save_registers \
php \
long_a \
long_i \
pha \
phx \
phy \
short_a \
long_i
#define restore_registers \
long_a \
long_i \
ply \
plx \
pla \
plp \
short_a \
long_i

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
//
// boot/sentinel65x.h
// Toplevel header for Sentinel 65X ROM firmware boot module
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#define CPU_SPEED_HZ 8000000
#define UART3_BAUD_RATE 9600
#define UART3_TIMER_VALUE (CPU_SPEED_HZ / (16 * UART3_BAUD_RATE) - 1)
#include "65c816.h"
#include "w65c265s.h"
#include "vera.h"

124
include/boot/vera.h Normal file
View File

@ -0,0 +1,124 @@
// SPDX-License-Identifier: MIT
//
// boot/vera.h
// Assembly language defines for the VERA chip
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#define AUTO_NONE 0x000000
#define AUTO_INC_1 0x100000
#define AUTO_INC_2 0x200000
#define AUTO_INC_4 0x300000
#define AUTO_INC_8 0x400000
#define AUTO_INC_16 0x500000
#define AUTO_INC_32 0x600000
#define AUTO_INC_64 0x700000
#define AUTO_INC_128 0x800000
#define AUTO_INC_256 0x900000
#define AUTO_INC_512 0xA00000
#define AUTO_INC_40 0xB00000
#define AUTO_INC_80 0xC00000
#define AUTO_INC_160 0xD00000
#define AUTO_INC_320 0xE00000
#define AUTO_INC_640 0xF00000
#define DISABLED 0
#define ENABLED 1
#define VERA_L_BPP1 0b00000000
#define VERA_L_BPP2 0b00000001
#define VERA_L_BPP4 0b00000010
#define VERA_L_BPP8 0b00000011
#define VERA_L_BITMAP 0b00000100
#define VERA_L_T256C 0b00001000
#define VERA_L_32W 0b00000000
#define VERA_L_64W 0b00010000
#define VERA_L_128W 0b00100000
#define VERA_L_256W 0b00110000
#define VERA_L_32H 0b00000000
#define VERA_L_64H 0b01000000
#define VERA_L_128H 0b10000000
#define VERA_L_256H 0b11000000
#define VERA_TILESIZE8x8 0b00000000
#define VERA_TILESIZE16x8 0b00000001
#define VERA_TILESIZE8x16 0b00000010
#define VERA_TILESIZE16x16 0b00000011
// The base address of the VERA chip
#define VERA_BASE 0x00DF00
// Offsets (relative to VERA_BASE) for each VERA register
#define VERA_ADDRx_L VERA_BASE + 00
#define VERA_ADDRx_M VERA_BASE + 01
#define VERA_ADDRx_H VERA_BASE + 02
// Accssible with ADDRSEL 0
#define VERA_ADDR0_L VERA_BASE + 00
#define VERA_ADDR0_M VERA_BASE + 01
#define VERA_ADDR0_H VERA_BASE + 02
// Accssible with ADDRSEL 1
#define VERA_ADDR1_L VERA_BASE + 00
#define VERA_ADDR1_M VERA_BASE + 01
#define VERA_ADDR1_H VERA_BASE + 02
#define VERA_DATA_0 VERA_BASE + 0x03
#define VERA_DATA_1 VERA_BASE + 0x04
#define VERA_CTRL VERA_BASE + 0x05
#define VERA_IEN VERA_BASE + 0x06
#define VERA_ISR VERA_BASE + 0x07
#define VERA_IRQLINE_L VERA_BASE + 0x08
#define VERA_SCANLINE_L VERA_BASE + 0x08
// Accssible with DCSEL 0
#define VERA_DC_VIDEO VERA_BASE + 0x09
#define VERA_DC_HSCALE VERA_BASE + 0x0A
#define VERA_DC_VSCALE VERA_BASE + 0x0B
#define VERA_DC_BORDER VERA_BASE + 0x0C
// Accssible with DCSEL 1
#define VERA_DC_HSTART VERA_BASE + 0x09
#define VERA_DC_HSTOP VERA_BASE + 0x0A
#define VERA_DC_VSTART VERA_BASE + 0x0B
#define VERA_DC_VSTOP VERA_BASE + 0x0C
// Layer 0
#define VERA_L0_CONFIG VERA_BASE + 0x0D
#define VERA_L0_MAPBASE VERA_BASE + 0x0E
#define VERA_L0_TILEBASE VERA_BASE + 0x0F
#define VERA_L0_HSCROLL_L VERA_BASE + 0x10
#define VERA_L0_HSCROLL_H VERA_BASE + 0x11
#define VERA_L0_VSCROLL_L VERA_BASE + 0x12
#define VERA_L0_VSCROLL_H VERA_BASE + 0x13
// Layer 1
#define VERA_L1_CONFIG VERA_BASE + 0x14
#define VERA_L1_MAPBASE VERA_BASE + 0x15
#define VERA_L1_TILEBASE VERA_BASE + 0x16
#define VERA_L1_HSCROLL_L VERA_BASE + 0x17
#define VERA_L1_HSCROLL_H VERA_BASE + 0x18
#define VERA_L1_VSCROLL_L VERA_BASE + 0x19
#define VERA_L1_VSCROLL_H VERA_BASE + 0x1A
// Audio
#define VERA_AUDIO_CTRL VERA_BASE + 0x1B
#define VERA_AUDIO_RATE VERA_BASE + 0x1C
#define VERA_AUDIO_DATA VERA_BASE + 0x1D
// SPI (Unused in prototype four!)
#define VERA_SPI_DATA VERA_BASE + 0x1E
#define VERA_SPI_CTRL VERA_BASE + 0x1F
// VRAM layout
#define TEXT_CONSOLE_TILES 0x000800
#define TEXT_CONSOLE0_VRAM 0x001800 // Runs up to 0x5800
#define TEXT_CONSOLE_SPRITE_BITMAPS 0x005800
#define VERA_PSG_BASE 0x01F9C0
#define VERA_PALETTE_BASE 0x01FA00
#define VERA_SPRITE_ATTR_BASE 0x01FC00

129
include/boot/w65c265s.h Normal file
View File

@ -0,0 +1,129 @@
// SPDX-License-Identifier: MIT
//
// boot/w65c265s.h
// Assembly defines for the W65C265S chip
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#define PD0 0x00DF00
#define PD1 0x00DF01
#define PD2 0x00DF02
#define PD3 0x00DF03
#define PD4 0x00DF20
#define PD5 0x00DF21
#define PD6 0x00DF22
#define PD7 0x00DF23
#define PDD0 0x00DF04
#define PDD1 0x00DF05
#define PDD2 0x00DF06
#define PDD3 0x00DF07
#define PDD4 0x00DF24
#define PDD5 0x00DF25
#define PDD6 0x00DF26
#define PCS7 0x00DF27
#define BCR 0x00DF40
#define SSCR 0x00DF41
#define TCR 0x00DF42
#define TER 0x00DF43
#define TIFR 0x00DF44
#define EIFR 0x00DF45
#define TIER 0x00DF46
#define EIER 0x00DF47
#define UIFR 0x00DF48
#define UIER 0x00DF49
#define T0LL 0x00DF50
#define T0LH 0x00DF51
#define T1LL 0x00DF52
#define T1LH 0x00DF53
#define T2LL 0x00DF54
#define T2LH 0x00DF55
#define T3LL 0x00DF56
#define T3LH 0x00DF57
#define T4LL 0x00DF58
#define T4LH 0x00DF59
#define T5LL 0x00DF5A
#define T5LH 0x00DF5B
#define T6LL 0x00DF5C
#define T6LH 0x00DF5D
#define T7LL 0x00DF5E
#define T7LH 0x00DF5F
#define T0CL 0x00DF60
#define T0CH 0x00DF61
#define T1CL 0x00DF62
#define T1CH 0x00DF63
#define T2CL 0x00DF64
#define T2CH 0x00DF65
#define T3CL 0x00DF66
#define T3CH 0x00DF67
#define T4CL 0x00DF68
#define T4CH 0x00DF69
#define T5CL 0x00DF6A
#define T5CH 0x00DF6B
#define T6CL 0x00DF6C
#define T6CH 0x00DF6D
#define T7CL 0x00DF6E
#define T7CH 0x00DF6F
#define ACSR0 0x00DF70
#define ARTD0 0x00DF71
#define ACSR1 0x00DF72
#define ARTD1 0x00DF73
#define ACSR2 0x00DF74
#define ARTD2 0x00DF75
#define ACSR3 0x00DF76
#define ARTD3 0x00DF77
#define PIBFR 0x00DF78
#define PIBER 0x00DF79
#define PIR2 0x00DF7A
#define PIR3 0x00DF7B
#define PIR4 0x00DF7C
#define PIR5 0x00DF7D
#define PIR6 0x00DF7E
#define PIR7 0x00DF7F
; Enable the 512 bytes of on-CPU SRAM from 0x000000-0001FF
w65c265s_sram_on .macro
lda #0b00000100
trb SSCR
.endm
w65c265s_sram_off .macro
lda #0b00000100
tsb SSCR
.endm
; Disable the on-CPU ROM
w65c265s_rom_off .macro
lda #1 << 7
tsb BCR
.endm
; Enable the on-CPU ROM
w65c265s_rom_on .macro
lda #1 << 7
trb BCR
.endm
; Start FCLK
fclk_start .macro
lda #0b00000001
tsb SSCR
.endm
; Stop FCLK
fclk_stop .macro
lda #0b00000001
trb SSCR
.endm
; Select FCLK as the clock source
fclk_select .macro
lda #0b11111010
tsb SSCR
.endm

9
include/config.h Normal file
View File

@ -0,0 +1,9 @@
//*****************************************************************************
// 65X-DOS
//
// include/config.h
//*****************************************************************************
#pragma once

7
license.md Normal file
View File

@ -0,0 +1,7 @@
Copyright © 2024 Kyle J Cardoza
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

15
readme.md Normal file
View File

@ -0,0 +1,15 @@
# Sentinel 65X ROM Firmware
This source tree builds the 512KB .bin file used to burn the system ROM
for Sentinel 65X. It consists of several modules:
- boot: initial boot code
- irq: interrupt handler vectors and trampolines
- bios: essential hardware driver code and IRQ handler implementations
- bdos: core operating system
In future, more modules are planned:
- A 65816 macro assembler
- A text editor
- Your idea here!

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

BIN
src/bdos/.DS_Store vendored Normal file

Binary file not shown.

35
src/bdos/fs/LICENSE.txt Normal file
View File

@ -0,0 +1,35 @@
FatFs License
FatFs has being developped as a personal project of the author, ChaN. It is
free from the code anyone else wrote at current release. Following code block
shows a copy of the FatFs license document that heading the source files.
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module Rx.xx /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
Therefore FatFs license is one of the BSD-style licenses, but there is a
significant feature. FatFs is mainly intended for embedded systems. In order to
extend the usability for commercial products, the redistributions of FatFs in
binary form, such as embedded code, binary library and any forms without source
code, do not need to include about FatFs in the documentations. This is
equivalent to the 1-clause BSD license. Of course FatFs is compatible with
the most of open source software licenses include GNU GPL. When you
redistribute the FatFs source code with changes or create a fork, the license
can also be changed to GNU GPL, BSD-style license or any open source software
license that not conflict with FatFs license.

470
src/bdos/fs/diskio.c Normal file
View File

@ -0,0 +1,470 @@
/*------------------------------------------------------------------------/
/ Foolproof MMCv3/SDv1/SDv2 (in SPI mode) control module
/-------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/
/ * This software is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-------------------------------------------------------------------------/
Features and Limitations:
* No Media Change Detection
Application program needs to perform a f_mount() after media change.
/-------------------------------------------------------------------------*/
#include "kernel/drivers/fatfs/ff.h" /* Obtains integer types for FatFs */
#include "kernel/drivers/fatfs/diskio.h" /* Common include file for FatFs and disk I/O layer */
/*-------------------------------------------------------------------------*/
/* Platform dependent macros and functions needed to be modified */
/*-------------------------------------------------------------------------*/
/*---------------------------------------------------------*/
/* User Provided RTC Function for FatFs module */
/*---------------------------------------------------------*/
/* This is a real time clock service to be called from */
/* FatFs module. Any valid time must be returned even if */
/* the system does not support an RTC. */
/* This function is not required in read-only cfg. */
// FIXME: Make this use the system RTC.
DWORD get_fattime (void)
{
return 0;
}
// FIXME: Make this delay using a system timer.
static void
dly_us (int n)
{
(void) n;
}
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
/* MMC/SD command (SPI mode) */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND */
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define CMD13 (13) /* SEND_STATUS */
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT */
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD32 (32) /* ERASE_ER_BLK_START */
#define CMD33 (33) /* ERASE_ER_BLK_END */
#define CMD38 (38) /* ERASE */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
static
DSTATUS Stat = STA_NOINIT; /* Disk status */
static
BYTE CardType; /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */
/*-----------------------------------------------------------------------*/
/* Transmit bytes to the card */
/*-----------------------------------------------------------------------*/
// FIXME: Make this use VERA.
static
void xmit_mmc (const BYTE* buff, UINT count)
{
(void) buff;
(void) count;
}
/*-----------------------------------------------------------------------*/
/* Receive bytes from the card */
/*-----------------------------------------------------------------------*/
// FIXME: Make this use VERA.
static
void rcvr_mmc (BYTE *buff, UINT count)
{
(void) buff;
(void) count;
}
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
static
int wait_ready (void) /* 1:OK, 0:Timeout */
{
BYTE d;
UINT tmr;
for (tmr = 5000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */
rcvr_mmc(&d, 1);
if (d == 0xFF) break;
dly_us(100);
}
return tmr ? 1 : 0;
}
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
/*-----------------------------------------------------------------------*/
// FIXME: Make this use VERA.
static
void deselect (void)
{
}
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready */
/*-----------------------------------------------------------------------*/
// FIXME: Make this use VERA.
static
int select (void) /* 1:OK, 0:Timeout */
{
return 0; /* Failed */
}
/*-----------------------------------------------------------------------*/
/* Receive a data packet from the card */
/*-----------------------------------------------------------------------*/
static
int rcvr_datablock ( /* 1:OK, 0:Failed */
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count */
)
{
BYTE d[2];
UINT tmr;
for (tmr = 1000; tmr; tmr--) { /* Wait for data packet in timeout of 100ms */
rcvr_mmc(d, 1);
if (d[0] != 0xFF) break;
dly_us(100);
}
if (d[0] != 0xFE) return 0; /* If not valid data token, return with error */
rcvr_mmc(buff, btr); /* Receive the data block into buffer */
rcvr_mmc(d, 2); /* Discard CRC */
return 1; /* Return with success */
}
/*-----------------------------------------------------------------------*/
/* Send a data packet to the card */
/*-----------------------------------------------------------------------*/
static
int xmit_datablock ( /* 1:OK, 0:Failed */
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
BYTE d[2];
if (!wait_ready()) return 0;
d[0] = token;
xmit_mmc(d, 1); /* Xmit a token */
if (token != 0xFD) { /* Is it data token? */
xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */
rcvr_mmc(d, 2); /* Xmit dummy CRC (0xFF,0xFF) */
rcvr_mmc(d, 1); /* Receive data response */
if ((d[0] & 0x1F) != 0x05) /* If not accepted, return with error */
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------*/
/* Send a command packet to the card */
/*-----------------------------------------------------------------------*/
static
BYTE send_cmd ( /* Returns command response (bit7==1:Send failed)*/
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
BYTE n, d, buf[6];
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
n = send_cmd(CMD55, 0);
if (n > 1) return n;
}
/* Select the card and wait for ready except to stop multiple block read */
if (cmd != CMD12) {
deselect();
if (!select()) return 0xFF;
}
/* Send a command packet */
buf[0] = 0x40 | cmd; /* Start + Command index */
buf[1] = (BYTE)(arg >> 24); /* Argument[31..24] */
buf[2] = (BYTE)(arg >> 16); /* Argument[23..16] */
buf[3] = (BYTE)(arg >> 8); /* Argument[15..8] */
buf[4] = (BYTE)arg; /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* (valid CRC for CMD0(0)) */
if (cmd == CMD8) n = 0x87; /* (valid CRC for CMD8(0x1AA)) */
buf[5] = n;
xmit_mmc(buf, 6);
/* Receive command response */
if (cmd == CMD12) rcvr_mmc(&d, 1); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
rcvr_mmc(&d, 1);
while ((d & 0x80) && --n);
return d; /* Return with the response value */
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Drive number (always 0) */
)
{
if (drv) return STA_NOINIT;
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0) */
)
{
BYTE n, ty, cmd, buf[4];
UINT tmr;
DSTATUS s;
if (drv) return RES_NOTRDY;
dly_us(10000); /* 10ms */
for (n = 10; n; n--) rcvr_mmc(buf, 1); /* Apply 80 dummy clocks and the card gets ready to receive command */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */
if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */
if (send_cmd(ACMD41, 1UL << 30) == 0) break;
dly_us(1000);
}
if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
rcvr_mmc(buf, 4);
ty = (buf[0] & 0x40) ? CT_SDC2 | CT_BLOCK : CT_SDC2; /* SDv2+ */
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SDC2; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC3; cmd = CMD1; /* MMCv3 */
}
for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */
if (send_cmd(cmd, 0) == 0) break;
dly_us(1000);
}
if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
ty = 0;
}
}
CardType = ty;
s = ty ? 0 : STA_NOINIT;
Stat = s;
deselect();
return s;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
LBA_t sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..128) */
)
{
BYTE cmd;
DWORD sect = (DWORD)sector;
if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;
if (!(CardType & CT_BLOCK)) sect *= 512; /* Convert LBA to byte address if needed */
cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
if (send_cmd(cmd, sect) == 0) {
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
LBA_t sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..128) */
)
{
DWORD sect = (DWORD)sector;
if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;
//if (!(CardType & CT_BLOCK)) sect *= 512; /* Convert LBA to byte address if needed */
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sect) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & CT_SDC) send_cmd(ACMD23, count);
if (send_cmd(CMD25, sect) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
BYTE n, csd[16];
DWORD cs;
if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY; /* Check if card is in the socket */
res = RES_ERROR;
switch (ctrl) {
case CTRL_SYNC : /* Make sure that no pending write process */
if (select()) res = RES_OK;
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
cs = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
*(LBA_t*)buff = cs << 10;
} else { /* SDC ver 1.XX or MMC */
n = (BYTE)((csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2);
cs = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(LBA_t*)buff = cs << (n - 9);
}
res = RES_OK;
}
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
*(DWORD*)buff = 128;
res = RES_OK;
break;
default:
res = RES_PARERR;
}
deselect();
return res;
}

7083
src/bdos/fs/ff.c Normal file

File diff suppressed because it is too large Load Diff

207
src/bdos/fs/ffsystem.c Normal file
View File

@ -0,0 +1,207 @@
/*------------------------------------------------------------------------*/
/* A Sample Code of User Provided OS Dependent Functions for FatFs */
/*------------------------------------------------------------------------*/
#include "kernel/drivers/fatfs/ff.h"
#if FF_USE_LFN == 3 /* Use dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate/Free a Memory Block */
/*------------------------------------------------------------------------*/
#include "stdlib.h" /* with POSIX API */
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc((size_t)msize); /* Allocate a new memory block */
}
void ff_memfree (
void* mblock /* Pointer to the memory block to free (no effect if null) */
)
{
free(mblock); /* Free the memory block */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Definitions of Mutex */
/*------------------------------------------------------------------------*/
#define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */
#if OS_TYPE == 0 /* Win32 */
#include <windows.h>
static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
#elif OS_TYPE == 1 /* uITRON */
#include "itron.h"
#include "kernel.h"
static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#elif OS_TYPE == 2 /* uc/OS-II */
#include "includes.h"
static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */
#elif OS_TYPE == 3 /* FreeRTOS */
#include "FreeRTOS.h"
#include "semphr.h"
static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
#elif OS_TYPE == 4 /* CMSIS-RTOS */
#include "cmsis_os.h"
static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#endif
/*------------------------------------------------------------------------*/
/* Create a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to create a new mutex
/ or semaphore for the volume. When a 0 is returned, the f_mount function
/ fails with FR_INT_ERR.
*/
int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
Mutex[vol] = CreateMutex(NULL, FALSE, NULL);
return (int)(Mutex[vol] != INVALID_HANDLE_VALUE);
#elif OS_TYPE == 1 /* uITRON */
T_CMTX cmtx = {TA_TPRI,1};
Mutex[vol] = acre_mtx(&cmtx);
return (int)(Mutex[vol] > 0);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
Mutex[vol] = OSMutexCreate(0, &err);
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
Mutex[vol] = xSemaphoreCreateMutex();
return (int)(Mutex[vol] != NULL);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDef(cmsis_os_mutex);
Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex));
return (int)(Mutex[vol] != NULL);
#endif
}
/*------------------------------------------------------------------------*/
/* Delete a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to delete a mutex or
/ semaphore of the volume created with ff_mutex_create function.
*/
void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
CloseHandle(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
del_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err);
#elif OS_TYPE == 3 /* FreeRTOS */
vSemaphoreDelete(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDelete(Mutex[vol]);
#endif
}
/*------------------------------------------------------------------------*/
/* Request a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on enter file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0);
#elif OS_TYPE == 1 /* uITRON */
return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err));
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Release a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leave file functions to unlock the volume.
*/
void ff_mutex_give (
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
ReleaseMutex(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
unl_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OSMutexPost(Mutex[vol]);
#elif OS_TYPE == 3 /* FreeRTOS */
xSemaphoreGive(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexRelease(Mutex[vol]);
#endif
}
#endif /* FF_FS_REENTRANT */

15592
src/bdos/fs/ffunicode.c Normal file

File diff suppressed because it is too large Load Diff

13
src/bdos/main.c Normal file
View File

@ -0,0 +1,13 @@
//*****************************************************************************
// 65X-DOS
//
// src/bdos/main.c
//*****************************************************************************
#include "config.h"
void
main(void)
{
for (;;) {}
}

10
src/bios/bios.c Normal file
View File

@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
//
// bios/main.c
// Sentinel 65X BIOS: main() function
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
void main(void) {
for (;;) {}
}

69
src/bios/cstartup.s Normal file
View File

@ -0,0 +1,69 @@
;;; Startup variant, change attribute value if you make your own
.rtmodel cstartup,"sentinel65x"
.rtmodel version, "1"
.rtmodel core, "*"
.section stack
.section cstack
.section heap
.extern main, exit
.extern _Dp, _Vfp
.extern _DirectPageStart
#ifndef __CALYPSI_DATA_MODEL_SMALL__
.extern _NearBaseAddress
#endif
#include "bios/macros.h"
;;; ***************************************************************************
;;;
;;; __program_start - actual start point of the program
;;;
;;; Set up CPU stack, initialize sections and call main().
;;; You can override this with your own routine, or tailor it as needed.
;;; The easiest way to make custom initialization is to provide your own
;;; __low_level_init which gets called after stacks have been initialized.
;;;
;;; ***************************************************************************
.section code, noreorder
.pubweak __program_root_section
__program_root_section:
clc
xce ; native 16-bit mode
rep #0x38 ; 16-bit registers, no decimal mode
ldx ##.sectionEnd stack
txs ; set stack
lda ##_DirectPageStart
tcd ; set direct page
lda ##.word2 _NearBaseAddress
stz dp:.tiny(_Vfp+2)
xba ; A upper half = data bank
pha
plb ; pop 8 dummy
plb ; set data bank
;;; **** Initialize heap if needed.
.section code, noroot, noreorder
.pubweak __call_heap_initialize
.extern __heap_initialize, __default_heap
__call_heap_initialize:
lda ##.word2 (.sectionStart heap)
sta dp:.tiny(_Dp+6)
lda ##.word0 (.sectionStart heap)
sta dp:.tiny(_Dp+4)
lda ##.word2 __default_heap
sta dp:.tiny(_Dp+2)
lda ##.word0 __default_heap
sta dp:.tiny(_Dp+0)
ldx ##.word2 (.sectionSize heap)
lda ##.word0 (.sectionSize heap)
call __heap_initialize
.section code, root, noreorder
lda ##0 ; argc = 0
call main
jump exit

7
src/bios/irq.c Normal file
View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
//
// bios/stubs.c
// Stub functions for Calypsi's C library
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>

171
src/bios/irq_trampoline.s Normal file
View File

@ -0,0 +1,171 @@
//; SPDX-License-Identifier: MIT
//;
//; bios/irq_trampoline.s
//; IRQ trampoline code for Sentinel 65X
//;
//; The two sections below are visible in ROM when the CPU's
//; on-chip ROM is disabled. They must be copied to RAM if
//; on-board ROM is to be disabled.
//;
//;
//; Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
; This section gets copied to 0x00F000
.section irq_trampolines
reserved_irq:
rti
timer0_irq:
rti
timer1_irq:
rti
timer2_irq:
rti
timer3_irq:
rti
timer4_irq:
rti
timer5_irq:
rti
timer6_irq:
rti
timer7_irq:
rti
pe56_irq:
rti
ne57_irq:
rti
pe60_irq:
rti
pe62_irq:
rti
ne64_irq:
rti
ne66_irq:
rti
pib_irq:
rti
level_irq:
rti
uart_0_rx_irq:
rti
uart_0_tx_irq:
rti
uart_1_rx_irq:
rti
uart_1_tx_irq:
rti
uart_2_rx_irq:
rti
uart_2_tx_irq:
rti
uart_3_rx_irq:
rti
uart_3_tx_irq:
rti
cop_irq:
rti
brk_irq:
rti
abort_irq:
rti
nmi_irq:
rti
; This section gets copied to 0x00FF80
.section irq_vectors
; Native mode IRQ vectors
.word .word0(timer0_irq)
.word .word0(timer1_irq)
.word .word0(timer2_irq)
.word .word0(timer3_irq)
.word .word0(timer4_irq)
.word .word0(timer5_irq)
.word .word0(timer6_irq)
.word .word0(timer7_irq)
.word .word0(pe56_irq)
.word .word0(ne57_irq)
.word .word0(pe60_irq)
.word .word0(pe62_irq)
.word .word0(ne64_irq)
.word .word0(ne66_irq)
.word .word0(pib_irq)
.word .word0(level_irq)
.word .word0(uart_0_rx_irq)
.word .word0(uart_0_tx_irq)
.word .word0(uart_1_rx_irq)
.word .word0(uart_1_tx_irq)
.word .word0(uart_2_rx_irq)
.word .word0(uart_2_tx_irq)
.word .word0(uart_3_rx_irq)
.word .word0(uart_3_tx_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(cop_irq)
.word .word0(brk_irq)
.word .word0(abort_irq)
.word .word0(nmi_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
; Emulation mode is not supported right now.
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)
.word .word0(reserved_irq)

95
src/bios/stubs.c Normal file
View File

@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT
//
// bios/stubs.c
// Stub functions for Calypsi's C library
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include "calypsi/stubs.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
int _Stub_putchar(int ch)
{
return -1;
}
int _Stub_puts(const char *str)
{
return -1;
}
int _Stub_raise(int signo)
{
return -1;
}
int _Stub_open(const char *path, int oflag, ...)
{
return -1;
}
int _Stub_close(int fd)
{
return -1;
}
int _Stub_fcntl(int fd, int command, ...)
{
return -1;
}
int _Stub_access(const char *path, int mode)
{
return -1;
}
long _Stub_lseek(int fd, long offset, int whence)
{
return -1;
}
int _Stub_fsetpos(int fd, const fpos_t *pos)
{
return -1;
}
size_t _Stub_read(int fd, void *buf, size_t count)
{
return 0;
}
size_t _Stub_write(int fd, const void *buf, size_t count)
{
return 0;
}
int _Stub_rename(const char *oldpath, const char *newpath)
{
return -1;
}
int _Stub_remove(const char *path)
{
return -1;
}
__noreturn_function
void _Stub_exit(int exitCode)
{
return;
}
char** _Stub_environ(void)
{
return NULL;
}
__noreturn_function
void _Stub_assert()
{
return;
}
#pragma clang diagnostic pop

53
src/boot/boot.s Normal file
View File

@ -0,0 +1,53 @@
//; SPDX-License-Identifier: MIT
//;
//; boot/boot.s
//; Boot code for Sentinel 65X
//;
//; Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include "boot/sentinel65x.h"
.section code, noreorder
.pubweak __program_root_section
__program_root_section:
.asciz "WDC"
w65c265s_init:
// Disable interrupts
sei
stz UIER
stz TIER
stz EIER
short_a
long_i
// We reset the VERA at boot. So P4.2 is an output, held
// low until later in the boot sequence.
lda #1 << 2
trb PD4
tsb PDD4
// Now we delay a while.
ldy ##0x0FFF
delay_y
dey
bne delay_y
// Set stack to $001FF
ldx ##0x01FF
txs
// Set data bank to 0
lda #0
pha
plb
// Set direct page to $0000
pea #0x0000
pld
// Enable all the in-use chip select lines.
lda #0b11110011
sta PCS7
// And we are booted enough to jump to high ROM.
jmp 0xC00000