Import empty project

This commit is contained in:
hkz 2025-07-15 20:51:44 +02:00
commit 384d9b3fd1
15 changed files with 496 additions and 0 deletions

22
src/line_data.c Normal file
View file

@ -0,0 +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
};

9
src/line_data.h Normal file
View file

@ -0,0 +1,9 @@
#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 */

21
src/main.c Normal file
View file

@ -0,0 +1,21 @@
#include <stubs.h>
#include <stdint.h>
#include <string.h>
#include "utility.h"
#include "mem_registers.h"
#include "mem_map.h"
#include "monitor_subroutines.h"
__task int main () {
POKE(P3_PWRDUP, 0); // Dirty the value checked by the reset vector
PEEK(IO_ROMSEL); // Make sure the ROM is selected
while(1){
};
return 0;
}

11
src/mem_map.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef _MEMORY_MAP_HEADER_
#define _MEMORY_MAP_HEADER_
#define DISPLAY_PAGE_SIZE 0x2000
#define DISPLAY_PAGE_1 0x2000
#define DISPLAY_PAGE_2 0xA000
#define ROMRAM_BANK 0xC100
#endif /* _MEMORY_MAP_HEADER_ */

49
src/mem_registers.h Normal file
View file

@ -0,0 +1,49 @@
#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 (now 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
typedef struct {
uint8_t kb: 5; // 0:5
uint8_t prnt: 6;
uint8_t tapein: 7;
} datain;
#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_ */

19
src/monitor_subroutines.c Normal file
View file

@ -0,0 +1,19 @@
#include "monitor_subroutines.h"
void sbrt_prntax(uint8_t msb, uint8_t lsb) {
__asm(
" jsr 0xF941\n"
:
: "Ka" (msb), "Kx" (lsb)
:
);
}
void sbrt_prbl2(uint8_t count) {
__asm(
" jsr 0xF94A\n"
:
: "Kx" (count)
:
);
}

85
src/monitor_subroutines.h Normal file
View file

@ -0,0 +1,85 @@
#ifndef _MONITOR_SUBROUTINES_HEADER_
#define _MONITOR_SUBROUTINES_HEADER_
#include <stdint.h>
typedef struct {
uint8_t key;
uint8_t ch;
} rdkey_res;
inline void sbrt_crout(void);
inline void sbrt_crout1(void);
void sbrt_prntax(uint8_t a, uint8_t x);
inline void sbrt_prblnk(void);
void sbrt_prbl2(uint8_t count);
inline void sbrt_bell(void);
inline rdkey_res sbrt_rdkey(void);
/*** ***/
#define COUT(a) (((void (*)(char))(0xFDED))(a))
#define COUT1(a) (((void (*)(char))(0xFDF0))(a))
#define COUTZ(a) (((void (*)(char))(0xFDF6))(a))
#define PRBYTE(a) (((void (*)(uint8_t))(0xFDDA))(a))
#define PRHEX(a) (((void (*)(uint8_t))(0xFDE3))(a))
#define WAIT(a) (((void (*)(uint8_t))(0xFCA8))(a))
#define BELL1() (((void (*)(uint8_t))(0xFBD9))(0x87))
#define SETINV() (((void (*)(void))(0xFE80))())
#define SETNORM() (((void (*)(void))(0xFE84))())
inline void sbrt_crout(void) {
__asm volatile(
" jsr 0xFD8E\n"
:
:
:
);
}
inline void sbrt_crout1(void) {
__asm volatile(
" jsr 0xFD8B\n"
:
:
:
);
}
inline void sbrt_prblnk(void) {
__asm volatile(
" jsr 0xF948\n"
:
:
: "a", "x"
);
}
inline void sbrt_bell(void) {
__asm volatile(
" jsr 0xFF3A\n"
:
:
: "a"
);
}
inline rdkey_res sbrt_rdkey(void) {
rdkey_res res;
uint8_t key;
uint8_t ch;
__asm volatile(
" jsr 0xFD0C\n"
: "=Ka"(key), "=Ky"(ch)
:
: "a", "y"
);
res.key = key;
res.ch = ch;
return res;
}
#endif /* _MONITOR_SUBROUTINES_HEADER_ */

105
src/tk2k_startup.s Normal file
View file

@ -0,0 +1,105 @@
.rtmodel cstartup,"tk2k"
.rtmodel version, "1"
.rtmodel core, "*"
;; External declarations
.section cstack
.section heap
.section data_init_table
.section registers ; pseudo registers in zero page
.extern main, exit
.extern _Zp, _Vsp, _Vfp
.pubweak __program_root_section, __program_start
call: .macro dest
jsr \dest
.endm
.section programStart, root
__program_root_section:
.word nextLine
.byte 0x0a, 0x00 ; 10
.byte 0x8c, 0x32, 0x30, 0x36, 0x32, 0x00 ; CALL 2062
nextLine: .byte 0x00, 0x00 ; end of program
.section startup, root, noreorder
__program_start:
.section startup, noreorder
jsr __low_level_init
;;; Initialize data sections if needed.
.section startup, noroot, noreorder
.pubweak __data_initialization_needed
.extern __initialize_sections
__data_initialization_needed:
lda #.byte0 (.sectionStart data_init_table)
sta zp:_Zp
lda #.byte1 (.sectionStart data_init_table)
sta zp:_Zp+1
lda #.byte0 (.sectionEnd data_init_table)
sta zp:_Zp+2
lda #.byte1 (.sectionEnd data_init_table)
sta zp:_Zp+3
call __initialize_sections
.section startup, noroot, noreorder
.pubweak __call_initialize_global_streams
.extern __initialize_global_streams
__call_initialize_global_streams:
call __initialize_global_streams
;;; **** Initialize heap if needed.
.section startup, noroot, noreorder
.pubweak __call_heap_initialize
.extern __heap_initialize, __default_heap
__call_heap_initialize:
lda #.byte0 __default_heap
sta zp:_Zp+0
lda #.byte1 __default_heap
sta zp:_Zp+1
lda #.byte0 (.sectionStart heap)
sta zp:_Zp+2
lda #.byte1 (.sectionStart heap)
sta zp:_Zp+3
lda #.byte0 (.sectionSize heap)
sta zp:_Zp+4
lda #.byte1 (.sectionSize heap)
sta zp:_Zp+5
call __heap_initialize
.section startup, root, noreorder
tsx
stx _InitialStack ; for exit()
lda #0 ; argc = 0
sta zp:_Zp
sta zp:_Zp+1
jsr main
jmp exit
;;; ***************************************************************************
;;;
;;; __low_level_init - custom low level initialization
;;;
;;; This default routine just returns doing nothing. You can provide your own
;;; routine, either in C or assembly for doing custom low leve initialization.
;;;
;;; ***************************************************************************
.section code
.pubweak __low_level_init
__low_level_init:
rts
;;; ***************************************************************************
;;;
;;; Keep track of the initial stack pointer so that it can be restores to make
;;; a return back on exit().
;;;
;;; ***************************************************************************
.section zdata, bss
.pubweak _InitialStack
_InitialStack:
.space 1

87
src/utility.c Normal file
View file

@ -0,0 +1,87 @@
#include "utility.h"
#include "mem_registers.h"
#include "monitor_subroutines.h"
#include "line_data.h"
// 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;
}
// Note that the horizontal values here are in group of 7 pixels
void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y, uint8_t *disp_buf) {
for(uint8_t y = off_y; y < off_y + h; y++) {
uint16_t line_counter = line_offset_map[y];
for(uint8_t x = off_x; x < off_x + w; x++) {
disp_buf[line_counter + x] = 0;
}
}
}
void draw_pic(uint16_t w, uint8_t h, uint8_t off_x, uint8_t off_y, const uint8_t *data, uint8_t *disp_buf) {
uint8_t remainder = 0;
uint8_t remainder_size = 0;
uint8_t pic_width_bytes = w / 8 + ((w % 8) ? 1 : 0);
uint16_t counter;
for(uint8_t row = 0; row < h; row++) {
uint8_t screen_row = row + off_y;
counter = line_offset_map[screen_row] + (off_x/7);
remainder = 0;
remainder_size = 0;
// MSB is the color indicator
for(uint8_t column = 0; column < pic_width_bytes; column++) {
uint8_t pix_data = data[(pic_width_bytes * row) + column];
uint8_t conv_data = (pix_data << remainder_size) | remainder;
remainder_size++;
remainder = (pix_data >> (8 - remainder_size)) & 0x7F;
disp_buf[counter++] = conv_data & 0x7F;
if(remainder_size == 7) {
disp_buf[counter++] = remainder & 0x7F;
remainder = 0;
remainder_size = 0;
}
}
if(remainder_size != 0) {
uint8_t mask = ~((1 << remainder_size) - 1);
disp_buf[counter] = (disp_buf[counter] & mask) | (remainder & 0x7F);
counter++;
}
}
}
void print_line(const char* line, uint8_t off_x, uint8_t off_y) {
POKEZ(ZP_CV, off_y);
uint8_t cur_ch;
for(cur_ch = 0; line[cur_ch]; cur_ch++) {
SETNORM();
POKEZ(ZP_CH, cur_ch + off_x);
COUT1(line[cur_ch]|0x80);
SETINV();
COUT1(' '|0x80);
for(uint8_t snd_loop = 0x70; snd_loop; snd_loop--) PEEK(IO_SPEAKER);
WAIT(0xBE);
}
SETNORM();
POKEZ(ZP_CH, cur_ch + off_x);
COUT1(' '|0x80);
WAIT(0xFF);
}

26
src/utility.h Normal file
View file

@ -0,0 +1,26 @@
#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]))
uint8_t bit_count(uint8_t b);
void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y, uint8_t *disp_buf);
void draw_pic(uint16_t w, uint8_t h, uint8_t off_x, uint8_t off_y, const uint8_t *data, uint8_t *disp_buf);
void print_line(const char* line, uint8_t off_x, uint8_t off_y);
#endif /* _UTILITY_HEADER_ */