mirror of
https://github.com/cc65/cc65.git
synced 2024-06-03 11:29:42 +00:00
commit
7e6399d439
97
asminc/rp6502.inc
Normal file
97
asminc/rp6502.inc
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
; Picocomputer 6502 general defines
|
||||||
|
|
||||||
|
; RIA UART
|
||||||
|
RIA_READY := $FFE0 ; TX=$80 RX=$40
|
||||||
|
RIA_TX := $FFE1
|
||||||
|
RIA_RX := $FFE2
|
||||||
|
|
||||||
|
; VSYNC from PIX VGA
|
||||||
|
RIA_VSYNC := $FFE3
|
||||||
|
|
||||||
|
; RIA XRAM portal 0
|
||||||
|
RIA_RW0 := $FFE4
|
||||||
|
RIA_STEP0 := $FFE5
|
||||||
|
RIA_ADDR0 := $FFE6
|
||||||
|
|
||||||
|
; RIA XRAM portal 1
|
||||||
|
RIA_RW1 := $FFE8
|
||||||
|
RIA_STEP1 := $FFE9
|
||||||
|
RIA_ADDR1 := $FFEA
|
||||||
|
|
||||||
|
; RIA OS fastcall
|
||||||
|
RIA_XSTACK := $FFEC
|
||||||
|
RIA_ERRNO := $FFED
|
||||||
|
RIA_OP := $FFEF
|
||||||
|
RIA_IRQ := $FFF0
|
||||||
|
RIA_SPIN := $FFF1
|
||||||
|
RIA_BUSY := $FFF2 ; Bit $80
|
||||||
|
RIA_A := $FFF4
|
||||||
|
RIA_X := $FFF6
|
||||||
|
RIA_SREG := $FFF8
|
||||||
|
|
||||||
|
; RIA OS operation numbers
|
||||||
|
RIA_OP_EXIT := $FF
|
||||||
|
RIA_OP_ZXSTACK := $00
|
||||||
|
RIA_OP_XREG := $01
|
||||||
|
RIA_OP_PHI2 := $02
|
||||||
|
RIA_OP_CODEPAGE := $03
|
||||||
|
RIA_OP_LRAND := $04
|
||||||
|
RIA_OP_STDIN_OPT := $05
|
||||||
|
RIA_OP_CLOCK_GETRES := $10
|
||||||
|
RIA_OP_CLOCK_GETTIME := $11
|
||||||
|
RIA_OP_CLOCK_SETTIME := $12
|
||||||
|
RIA_OP_CLOCK_GETTIMEZONE := $13
|
||||||
|
RIA_OP_OPEN := $14
|
||||||
|
RIA_OP_CLOSE := $15
|
||||||
|
RIA_OP_READ_XSTACK := $16
|
||||||
|
RIA_OP_READ_XRAM := $17
|
||||||
|
RIA_OP_WRITE_XSTACK := $18
|
||||||
|
RIA_OP_WRITE_XRAM := $19
|
||||||
|
RIA_OP_LSEEK := $1A
|
||||||
|
RIA_OP_UNLINK := $1B
|
||||||
|
RIA_OP_RENAME := $1C
|
||||||
|
|
||||||
|
; 6522 VIA
|
||||||
|
VIA := $FFD0 ; VIA base address
|
||||||
|
VIA_PB := VIA+$0 ; Port register B
|
||||||
|
VIA_PA1 := VIA+$1 ; Port register A
|
||||||
|
VIA_PRB := VIA+$0 ; *** Deprecated ***
|
||||||
|
VIA_PRA := VIA+$1 ; *** Deprecated ***
|
||||||
|
VIA_DDRB := VIA+$2 ; Data direction register B
|
||||||
|
VIA_DDRA := VIA+$3 ; Data direction register A
|
||||||
|
VIA_T1CL := VIA+$4 ; Timer 1, low byte
|
||||||
|
VIA_T1CH := VIA+$5 ; Timer 1, high byte
|
||||||
|
VIA_T1LL := VIA+$6 ; Timer 1 latch, low byte
|
||||||
|
VIA_T1LH := VIA+$7 ; Timer 1 latch, high byte
|
||||||
|
VIA_T2CL := VIA+$8 ; Timer 2, low byte
|
||||||
|
VIA_T2CH := VIA+$9 ; Timer 2, high byte
|
||||||
|
VIA_SR := VIA+$A ; Shift register
|
||||||
|
VIA_CR := VIA+$B ; Auxiliary control register
|
||||||
|
VIA_PCR := VIA+$C ; Peripheral control register
|
||||||
|
VIA_IFR := VIA+$D ; Interrupt flag register
|
||||||
|
VIA_IER := VIA+$E ; Interrupt enable register
|
||||||
|
VIA_PA2 := VIA+$F ; Port register A w/o handshake
|
||||||
|
|
||||||
|
; Values in ___oserror are the union of these FatFs errors and errno.inc
|
||||||
|
.enum
|
||||||
|
FR_OK = 32 ; Succeeded
|
||||||
|
FR_DISK_ERR ; A hard error occurred in the low level disk I/O layer
|
||||||
|
FR_INT_ERR ; Assertion failed
|
||||||
|
FR_NOT_READY ; The physical drive cannot work
|
||||||
|
FR_NO_FILE ; Could not find the file
|
||||||
|
FR_NO_PATH ; Could not find the path
|
||||||
|
FR_INVALID_NAME ; The path name format is invalid
|
||||||
|
FR_DENIED ; Access denied due to prohibited access or directory full
|
||||||
|
FR_EXIST ; Access denied due to prohibited access
|
||||||
|
FR_INVALID_OBJECT ; The file/directory object is invalid
|
||||||
|
FR_WRITE_PROTECTED ; The physical drive is write protected
|
||||||
|
FR_INVALID_DRIVE ; The logical drive number is invalid
|
||||||
|
FR_NOT_ENABLED ; The volume has no work area
|
||||||
|
FR_NO_FILESYSTEM ; There is no valid FAT volume
|
||||||
|
FR_MKFS_ABORTED ; The f_mkfs() aborted due to any problem
|
||||||
|
FR_TIMEOUT ; Could not get a grant to access the volume within defined period
|
||||||
|
FR_LOCKED ; The operation is rejected according to the file sharing policy
|
||||||
|
FR_NOT_ENOUGH_CORE ; LFN working buffer could not be allocated
|
||||||
|
FR_TOO_MANY_OPEN_FILES ; Number of open files > FF_FS_LOCK
|
||||||
|
FR_INVALID_PARAMETER ; Given parameter is invalid
|
||||||
|
.endenum
|
34
cfg/rp6502.cfg
Normal file
34
cfg/rp6502.cfg
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
SYMBOLS {
|
||||||
|
__STARTUP__: type = import;
|
||||||
|
__STACKSIZE__: type = weak, value = $0800;
|
||||||
|
}
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = "", define = yes, start = $0000, size = $0100;
|
||||||
|
CPUSTACK: file = "", start = $0100, size = $0100;
|
||||||
|
RAM: file = %O, define = yes, start = $0200, size = $FD00 - __STACKSIZE__;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp;
|
||||||
|
STARTUP: load = RAM, type = ro;
|
||||||
|
LOWCODE: load = RAM, type = ro, optional = yes;
|
||||||
|
ONCE: load = RAM, type = ro, optional = yes;
|
||||||
|
CODE: load = RAM, type = ro;
|
||||||
|
RODATA: load = RAM, type = ro;
|
||||||
|
DATA: load = RAM, type = rw, define = yes;
|
||||||
|
BSS: load = RAM, type = bss, define = yes;
|
||||||
|
}
|
||||||
|
FEATURES {
|
||||||
|
CONDES: type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__,
|
||||||
|
segment = ONCE;
|
||||||
|
CONDES: type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__,
|
||||||
|
segment = RODATA;
|
||||||
|
CONDES: type = interruptor,
|
||||||
|
label = __INTERRUPTOR_TABLE__,
|
||||||
|
count = __INTERRUPTOR_COUNT__,
|
||||||
|
segment = RODATA,
|
||||||
|
import = __CALLIRQ__;
|
||||||
|
}
|
|
@ -175,6 +175,9 @@
|
||||||
<tag><htmlurl url="plus4.html" name="plus4.html"></tag>
|
<tag><htmlurl url="plus4.html" name="plus4.html"></tag>
|
||||||
Topics specific to the Commodore Plus/4.
|
Topics specific to the Commodore Plus/4.
|
||||||
|
|
||||||
|
<tag><htmlurl url="rp6502.html" name="rp6502.html"></tag>
|
||||||
|
Topics specific to the Picocomputer 6502.
|
||||||
|
|
||||||
<tag><htmlurl url="supervision.html" name="supervision.html"></tag>
|
<tag><htmlurl url="supervision.html" name="supervision.html"></tag>
|
||||||
Topics specific to the Watara Supervision Console.
|
Topics specific to the Watara Supervision Console.
|
||||||
|
|
||||||
|
|
96
doc/rp6502.sgml
Normal file
96
doc/rp6502.sgml
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<!doctype linuxdoc system>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<title>Picocomputer 6502 - specific information for cc65
|
||||||
|
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
||||||
|
|
||||||
|
<abstract>
|
||||||
|
An overview over the Picocomputer 6502 and its interfaces to the cc65 C
|
||||||
|
compiler.
|
||||||
|
</abstract>
|
||||||
|
|
||||||
|
<!-- Table of contents -->
|
||||||
|
<toc>
|
||||||
|
|
||||||
|
<!-- Begin the document -->
|
||||||
|
|
||||||
|
<sect>Overview<p>
|
||||||
|
|
||||||
|
The Picocomputer 6502 is a modern W65C02S computer with a custom operating
|
||||||
|
system designed to be POSIX-like. The reference design includes a W65C02S,
|
||||||
|
W65C22S, RP6502-RIA, and optionally a RP6502-VGA. Peripheral devices like
|
||||||
|
keyboards, mice, and flash storage are connected by USB to the RP6502-RIA.
|
||||||
|
Audio is generated by the RP6502-RIA. Video is generated by the RP6502-VGA.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect>Binary format<p>
|
||||||
|
|
||||||
|
The standard binary output format generated by the linker for the RP6502 target
|
||||||
|
is a plain machine language program without any prefix or postfix.
|
||||||
|
|
||||||
|
The RP6502 Integrated Development Environment, based on Visual Studio Code,
|
||||||
|
will convert the cc65 binary output into RP6502 ROM files that can be loaded
|
||||||
|
directly from the RP6502 monitor or installed on the RIA to be loaded at boot.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect>Memory layout<p>
|
||||||
|
|
||||||
|
<descrip>
|
||||||
|
<tag/Stack/
|
||||||
|
The C run-time stack is located at $FEFF, and grows downward.
|
||||||
|
|
||||||
|
<tag/Heap/
|
||||||
|
The C heap is located at the end of the program, and grows toward the C
|
||||||
|
run-time stack.
|
||||||
|
|
||||||
|
<tag/RAM/
|
||||||
|
RAM is located at $0000 - $FEFF. Default binaries load and
|
||||||
|
start at $0200.
|
||||||
|
|
||||||
|
<tag/ROM/
|
||||||
|
The RP6502 is designed with no ROM in the 6502 address space.
|
||||||
|
|
||||||
|
<tag/VIA/
|
||||||
|
A Versatile Interface Adapter (6522) is 16 registers located
|
||||||
|
at $FFD0.
|
||||||
|
|
||||||
|
<tag/RIA/
|
||||||
|
The RP6502 Interface Adapter is 32 registers located at $FFE0.
|
||||||
|
|
||||||
|
<tag/User/
|
||||||
|
User I/O expansion is from $FF00 to $FFCF.
|
||||||
|
|
||||||
|
</descrip><p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect>Platform-specific header files<p>
|
||||||
|
|
||||||
|
Programs containing RP6502-specific code may use the <tt/rp6502.h/ or
|
||||||
|
<tt/rp6502.inc/ include files.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect>License<p>
|
||||||
|
|
||||||
|
This software is provided "as-is", without any expressed or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
<enum>
|
||||||
|
<item> The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated, but is not required.
|
||||||
|
<item> Altered source versions must be plainly marked as such, and must not
|
||||||
|
be misrepresented as being the original software.
|
||||||
|
<item> This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
</article>
|
264
include/rp6502.h
Normal file
264
include/rp6502.h
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* rp6502.h */
|
||||||
|
/* */
|
||||||
|
/* Picocomputer 6502 */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _RP6502_H
|
||||||
|
#define _RP6502_H
|
||||||
|
|
||||||
|
/* RP6502 VIA $FFD0-$FFDF */
|
||||||
|
|
||||||
|
#include <_6522.h>
|
||||||
|
#define VIA (*(volatile struct __6522 *)0xFFD0)
|
||||||
|
|
||||||
|
/* RP6502 RIA $FFE0-$FFF9 */
|
||||||
|
|
||||||
|
struct __RP6502
|
||||||
|
{
|
||||||
|
const unsigned char ready;
|
||||||
|
unsigned char tx;
|
||||||
|
const unsigned char rx;
|
||||||
|
const unsigned char vsync;
|
||||||
|
unsigned char rw0;
|
||||||
|
unsigned char step0;
|
||||||
|
unsigned int addr0;
|
||||||
|
unsigned char rw1;
|
||||||
|
unsigned char step1;
|
||||||
|
unsigned int addr1;
|
||||||
|
unsigned char xstack;
|
||||||
|
unsigned char errno_lo;
|
||||||
|
unsigned char errno_hi;
|
||||||
|
unsigned char op;
|
||||||
|
unsigned char irq;
|
||||||
|
const unsigned char spin;
|
||||||
|
const unsigned char busy;
|
||||||
|
const unsigned char lda;
|
||||||
|
unsigned char a;
|
||||||
|
const unsigned char ldx;
|
||||||
|
unsigned char x;
|
||||||
|
const unsigned char rts;
|
||||||
|
unsigned int sreg;
|
||||||
|
};
|
||||||
|
#define RIA (*(volatile struct __RP6502 *)0xFFE0)
|
||||||
|
|
||||||
|
#define RIA_READY_TX_BIT 0x80
|
||||||
|
#define RIA_READY_RX_BIT 0x40
|
||||||
|
#define RIA_BUSY_BIT 0x80
|
||||||
|
|
||||||
|
/* XSTACK helpers */
|
||||||
|
|
||||||
|
void __fastcall__ ria_push_long (unsigned long val);
|
||||||
|
void __fastcall__ ria_push_int (unsigned int val);
|
||||||
|
#define ria_push_char(v) RIA.xstack = v
|
||||||
|
|
||||||
|
long __fastcall__ ria_pop_long (void);
|
||||||
|
int __fastcall__ ria_pop_int (void);
|
||||||
|
#define ria_pop_char() RIA.xstack
|
||||||
|
|
||||||
|
/* Set the RIA fastcall register */
|
||||||
|
|
||||||
|
void __fastcall__ ria_set_axsreg (unsigned long axsreg);
|
||||||
|
void __fastcall__ ria_set_ax (unsigned int ax);
|
||||||
|
#define ria_set_a(v) RIA.a = v
|
||||||
|
|
||||||
|
/* Run an OS operation */
|
||||||
|
|
||||||
|
int __fastcall__ ria_call_int (unsigned char op);
|
||||||
|
long __fastcall__ ria_call_long (unsigned char op);
|
||||||
|
|
||||||
|
/* These run _mappederrno() on error */
|
||||||
|
|
||||||
|
int __fastcall__ ria_call_int_errno (unsigned char op);
|
||||||
|
long __fastcall__ ria_call_long_errno (unsigned char op);
|
||||||
|
|
||||||
|
/* OS operation numbers */
|
||||||
|
|
||||||
|
#define RIA_OP_EXIT 0xFF
|
||||||
|
#define RIA_OP_ZXSTACK 0x00
|
||||||
|
#define RIA_OP_XREG 0x01
|
||||||
|
#define RIA_OP_PHI2 0x02
|
||||||
|
#define RIA_OP_CODEPAGE 0x03
|
||||||
|
#define RIA_OP_LRAND 0x04
|
||||||
|
#define RIA_OP_STDIN_OPT 0x05
|
||||||
|
#define RIA_OP_CLOCK_GETRES 0x10
|
||||||
|
#define RIA_OP_CLOCK_GETTIME 0x11
|
||||||
|
#define RIA_OP_CLOCK_SETTIME 0x12
|
||||||
|
#define RIA_OP_CLOCK_GETTIMEZONE 0x13
|
||||||
|
#define RIA_OP_OPEN 0x14
|
||||||
|
#define RIA_OP_CLOSE 0x15
|
||||||
|
#define RIA_OP_READ_XSTACK 0x16
|
||||||
|
#define RIA_OP_READ_XRAM 0x17
|
||||||
|
#define RIA_OP_WRITE_XSTACK 0x18
|
||||||
|
#define RIA_OP_WRITE_XRAM 0x19
|
||||||
|
#define RIA_OP_LSEEK 0x1A
|
||||||
|
#define RIA_OP_UNLINK 0x1B
|
||||||
|
#define RIA_OP_RENAME 0x1C
|
||||||
|
|
||||||
|
/* C API for the operating system. */
|
||||||
|
|
||||||
|
int __cdecl__ xreg (char device, char channel, unsigned char address, ...);
|
||||||
|
int __fastcall__ phi2 (void);
|
||||||
|
int __fastcall__ codepage (void);
|
||||||
|
long __fastcall__ lrand (void);
|
||||||
|
int __fastcall__ stdin_opt (unsigned long ctrl_bits, unsigned char str_length);
|
||||||
|
int __fastcall__ read_xstack (void* buf, unsigned count, int fildes);
|
||||||
|
int __fastcall__ read_xram (unsigned buf, unsigned count, int fildes);
|
||||||
|
int __fastcall__ write_xstack (const void* buf, unsigned count, int fildes);
|
||||||
|
int __fastcall__ write_xram (unsigned buf, unsigned count, int fildes);
|
||||||
|
|
||||||
|
/* XREG location helpers */
|
||||||
|
|
||||||
|
#define xreg_ria_keyboard(...) xreg(0, 0, 0, __VA_ARGS__)
|
||||||
|
#define xreg_ria_mouse(...) xreg(0, 0, 1, __VA_ARGS__)
|
||||||
|
#define xreg_vga_canvas(...) xreg(1, 0, 0, __VA_ARGS__)
|
||||||
|
#define xreg_vga_mode(...) xreg(1, 0, 1, __VA_ARGS__)
|
||||||
|
|
||||||
|
/* XRAM structure helpers */
|
||||||
|
|
||||||
|
#define xram0_struct_set(addr, type, member, val) \
|
||||||
|
RIA.addr0 = (unsigned)(&((type *)0)->member) + (unsigned)addr; \
|
||||||
|
switch (sizeof(((type *)0)->member)) \
|
||||||
|
{ \
|
||||||
|
case 1: \
|
||||||
|
RIA.rw0 = val; \
|
||||||
|
break; \
|
||||||
|
case 2: \
|
||||||
|
RIA.step0 = 1; \
|
||||||
|
RIA.rw0 = val & 0xff; \
|
||||||
|
RIA.rw0 = (val >> 8) & 0xff; \
|
||||||
|
break; \
|
||||||
|
case 4: \
|
||||||
|
RIA.step0 = 1; \
|
||||||
|
RIA.rw0 = (unsigned long)val & 0xff; \
|
||||||
|
RIA.rw0 = ((unsigned long)val >> 8) & 0xff; \
|
||||||
|
RIA.rw0 = ((unsigned long)val >> 16) & 0xff; \
|
||||||
|
RIA.rw0 = ((unsigned long)val >> 24) & 0xff; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xram1_struct_set(addr, type, member, val) \
|
||||||
|
RIA.addr1 = (unsigned)(&((type *)0)->member) + (unsigned)addr; \
|
||||||
|
switch (sizeof(((type *)0)->member)) \
|
||||||
|
{ \
|
||||||
|
case 1: \
|
||||||
|
RIA.rw1 = val; \
|
||||||
|
break; \
|
||||||
|
case 2: \
|
||||||
|
RIA.step1 = 1; \
|
||||||
|
RIA.rw1 = val & 0xff; \
|
||||||
|
RIA.rw1 = (val >> 8) & 0xff; \
|
||||||
|
break; \
|
||||||
|
case 4: \
|
||||||
|
RIA.step1 = 1; \
|
||||||
|
RIA.rw1 = (unsigned long)val & 0xff; \
|
||||||
|
RIA.rw1 = ((unsigned long)val >> 8) & 0xff; \
|
||||||
|
RIA.rw1 = ((unsigned long)val >> 16) & 0xff; \
|
||||||
|
RIA.rw1 = ((unsigned long)val >> 24) & 0xff; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char x_wrap; // bool
|
||||||
|
unsigned char y_wrap; // bool
|
||||||
|
int x_pos_px;
|
||||||
|
int y_pos_px;
|
||||||
|
int width_chars;
|
||||||
|
int height_chars;
|
||||||
|
unsigned xram_data_ptr;
|
||||||
|
unsigned xram_palette_ptr;
|
||||||
|
unsigned xram_font_ptr;
|
||||||
|
} vga_mode1_config_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char x_wrap; // bool
|
||||||
|
unsigned char y_wrap; // bool
|
||||||
|
int x_pos_px;
|
||||||
|
int y_pos_px;
|
||||||
|
int width_tiles;
|
||||||
|
int height_tiles;
|
||||||
|
unsigned xram_data_ptr;
|
||||||
|
unsigned xram_palette_ptr;
|
||||||
|
unsigned xram_tile_ptr;
|
||||||
|
} vga_mode2_config_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char x_wrap; // bool
|
||||||
|
unsigned char y_wrap; // bool
|
||||||
|
int x_pos_px;
|
||||||
|
int y_pos_px;
|
||||||
|
int width_px;
|
||||||
|
int height_px;
|
||||||
|
unsigned xram_data_ptr;
|
||||||
|
unsigned xram_palette_ptr;
|
||||||
|
} vga_mode3_config_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x_pos_px;
|
||||||
|
int y_pos_px;
|
||||||
|
unsigned xram_sprite_ptr;
|
||||||
|
unsigned char log_size;
|
||||||
|
unsigned char has_opacity_metadata; // bool
|
||||||
|
} vga_mode4_sprite_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int transform[6];
|
||||||
|
int x_pos_px;
|
||||||
|
int y_pos_px;
|
||||||
|
unsigned xram_sprite_ptr;
|
||||||
|
unsigned char log_size;
|
||||||
|
unsigned char has_opacity_metadata; // bool
|
||||||
|
} vga_mode4_asprite_t;
|
||||||
|
|
||||||
|
/* Values in __oserror are the union of these FatFs errors and errno.h */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FR_OK = 32, /* Succeeded */
|
||||||
|
FR_DISK_ERR, /* A hard error occurred in the low level disk I/O layer */
|
||||||
|
FR_INT_ERR, /* Assertion failed */
|
||||||
|
FR_NOT_READY, /* The physical drive cannot work */
|
||||||
|
FR_NO_FILE, /* Could not find the file */
|
||||||
|
FR_NO_PATH, /* Could not find the path */
|
||||||
|
FR_INVALID_NAME, /* The path name format is invalid */
|
||||||
|
FR_DENIED, /* Access denied due to prohibited access or directory full */
|
||||||
|
FR_EXIST, /* Access denied due to prohibited access */
|
||||||
|
FR_INVALID_OBJECT, /* The file/directory object is invalid */
|
||||||
|
FR_WRITE_PROTECTED, /* The physical drive is write protected */
|
||||||
|
FR_INVALID_DRIVE, /* The logical drive number is invalid */
|
||||||
|
FR_NOT_ENABLED, /* The volume has no work area */
|
||||||
|
FR_NO_FILESYSTEM, /* There is no valid FAT volume */
|
||||||
|
FR_MKFS_ABORTED, /* The f_mkfs() aborted due to any problem */
|
||||||
|
FR_TIMEOUT, /* Could not get a grant to access the volume within defined period */
|
||||||
|
FR_LOCKED, /* The operation is rejected according to the file sharing policy */
|
||||||
|
FR_NOT_ENOUGH_CORE, /* LFN working buffer could not be allocated */
|
||||||
|
FR_TOO_MANY_OPEN_FILES, /* Number of open files > FF_FS_LOCK */
|
||||||
|
FR_INVALID_PARAMETER /* Given parameter is invalid */
|
||||||
|
} FRESULT;
|
||||||
|
|
||||||
|
#endif /* _RP6502_H */
|
|
@ -33,6 +33,7 @@ TARGETS = apple2 \
|
||||||
none \
|
none \
|
||||||
osic1p \
|
osic1p \
|
||||||
pce \
|
pce \
|
||||||
|
rp6502 \
|
||||||
sim6502 \
|
sim6502 \
|
||||||
sim65c02 \
|
sim65c02 \
|
||||||
supervision \
|
supervision \
|
||||||
|
|
8
libsrc/rp6502/close.c
Normal file
8
libsrc/rp6502/close.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int __fastcall__ close (int fd)
|
||||||
|
{
|
||||||
|
ria_set_ax (fd);
|
||||||
|
return ria_call_int_errno (RIA_OP_CLOSE);
|
||||||
|
}
|
6
libsrc/rp6502/codepage.c
Normal file
6
libsrc/rp6502/codepage.c
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ codepage (void)
|
||||||
|
{
|
||||||
|
return ria_call_int (RIA_OP_CODEPAGE);
|
||||||
|
}
|
51
libsrc/rp6502/crt0.s
Normal file
51
libsrc/rp6502/crt0.s
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
;
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; crt0.s
|
||||||
|
|
||||||
|
.export _init, _exit
|
||||||
|
.import _main
|
||||||
|
|
||||||
|
.export __STARTUP__ : absolute = 1
|
||||||
|
.import __RAM_START__, __RAM_SIZE__
|
||||||
|
|
||||||
|
.import copydata, zerobss, initlib, donelib
|
||||||
|
|
||||||
|
.include "rp6502.inc"
|
||||||
|
.include "zeropage.inc"
|
||||||
|
|
||||||
|
.segment "STARTUP"
|
||||||
|
|
||||||
|
; Essential 6502 startup the CPU doesn't do
|
||||||
|
_init:
|
||||||
|
ldx #$FF
|
||||||
|
txs
|
||||||
|
cld
|
||||||
|
|
||||||
|
; Set cc65 argument stack pointer
|
||||||
|
lda #<(__RAM_START__ + __RAM_SIZE__)
|
||||||
|
sta sp
|
||||||
|
lda #>(__RAM_START__ + __RAM_SIZE__)
|
||||||
|
sta sp+1
|
||||||
|
|
||||||
|
; Initialize memory storage
|
||||||
|
jsr zerobss ; Clear BSS segment
|
||||||
|
jsr copydata ; Initialize DATA segment
|
||||||
|
jsr initlib ; Run constructors
|
||||||
|
|
||||||
|
; Call main()
|
||||||
|
jsr _main
|
||||||
|
|
||||||
|
; Back from main() also the _exit entry
|
||||||
|
; Stack the exit value in case destructors call OS
|
||||||
|
_exit:
|
||||||
|
phx
|
||||||
|
pha
|
||||||
|
jsr donelib ; Run destructors
|
||||||
|
pla
|
||||||
|
sta RIA_A
|
||||||
|
plx
|
||||||
|
stx RIA_X
|
||||||
|
lda #$FF ; exit()
|
||||||
|
sta RIA_OP
|
||||||
|
stp
|
10
libsrc/rp6502/getres.c
Normal file
10
libsrc/rp6502/getres.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
extern int __clock_gettimespec (struct timespec* ts, unsigned char op);
|
||||||
|
|
||||||
|
int clock_getres (clockid_t clock_id, struct timespec* res)
|
||||||
|
{
|
||||||
|
ria_set_ax (clock_id);
|
||||||
|
return __clock_gettimespec (res, RIA_OP_CLOCK_GETRES);
|
||||||
|
}
|
12
libsrc/rp6502/gettime.c
Normal file
12
libsrc/rp6502/gettime.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
extern int __clock_gettimespec (struct timespec* ts, unsigned char op);
|
||||||
|
|
||||||
|
int clock_gettime (clockid_t clock_id, struct timespec* tp)
|
||||||
|
{
|
||||||
|
(void)clock_id;
|
||||||
|
/* time.s doesn't set the stack value for clock_id (bug?) */
|
||||||
|
ria_set_ax (CLOCK_REALTIME);
|
||||||
|
return __clock_gettimespec (tp, RIA_OP_CLOCK_GETTIME);
|
||||||
|
}
|
13
libsrc/rp6502/gettimespec.c
Normal file
13
libsrc/rp6502/gettimespec.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int __clock_gettimespec (struct timespec* ts, unsigned char op)
|
||||||
|
/* Internal method shared by clock_getres and clock_gettime. */
|
||||||
|
{
|
||||||
|
int ax = ria_call_int_errno (op);
|
||||||
|
if (ax >= 0) {
|
||||||
|
ts->tv_sec = ria_pop_long ();
|
||||||
|
ts->tv_nsec = ria_pop_long ();
|
||||||
|
}
|
||||||
|
return ax;
|
||||||
|
}
|
16
libsrc/rp6502/gettimezone.c
Normal file
16
libsrc/rp6502/gettimezone.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int clock_gettimezone (clockid_t clock_id, struct _timezone* tz)
|
||||||
|
{
|
||||||
|
int ax;
|
||||||
|
ria_set_ax (clock_id);
|
||||||
|
ax = ria_call_int_errno (RIA_OP_CLOCK_GETTIMEZONE);
|
||||||
|
if (ax >= 0) {
|
||||||
|
char i;
|
||||||
|
for (i = 0; i < sizeof (struct _timezone); i++) {
|
||||||
|
((char*)tz)[i] = ria_pop_char ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ax;
|
||||||
|
}
|
14
libsrc/rp6502/initenv.s
Normal file
14
libsrc/rp6502/initenv.s
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
;
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
|
||||||
|
.constructor initenv, 24
|
||||||
|
.import __environ, __envcount, __envsize
|
||||||
|
|
||||||
|
.segment "ONCE"
|
||||||
|
|
||||||
|
.proc initenv
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
50
libsrc/rp6502/irq.s
Normal file
50
libsrc/rp6502/irq.s
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
;
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; Enables the C IRQ tools
|
||||||
|
|
||||||
|
.export initirq, doneirq
|
||||||
|
.import callirq, _exit
|
||||||
|
|
||||||
|
.include "rp6502.inc"
|
||||||
|
|
||||||
|
.segment "ONCE"
|
||||||
|
|
||||||
|
initirq:
|
||||||
|
lda #<handler
|
||||||
|
ldx #>handler
|
||||||
|
sei
|
||||||
|
sta $FFFE
|
||||||
|
stx $FFFF
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
|
||||||
|
.code
|
||||||
|
|
||||||
|
doneirq:
|
||||||
|
sei
|
||||||
|
rts
|
||||||
|
|
||||||
|
.segment "LOWCODE"
|
||||||
|
|
||||||
|
handler:
|
||||||
|
cld
|
||||||
|
phx
|
||||||
|
tsx
|
||||||
|
pha
|
||||||
|
inx
|
||||||
|
inx
|
||||||
|
lda $100,X
|
||||||
|
and #$10
|
||||||
|
bne break
|
||||||
|
phy
|
||||||
|
jsr callirq
|
||||||
|
ply
|
||||||
|
pla
|
||||||
|
plx
|
||||||
|
rti
|
||||||
|
|
||||||
|
break:
|
||||||
|
lda #$FF
|
||||||
|
sta RIA_A
|
||||||
|
jmp _exit
|
6
libsrc/rp6502/lrand.c
Normal file
6
libsrc/rp6502/lrand.c
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
long __fastcall__ lrand (void)
|
||||||
|
{
|
||||||
|
return ria_call_long (RIA_OP_LRAND);
|
||||||
|
}
|
11
libsrc/rp6502/lseek.c
Normal file
11
libsrc/rp6502/lseek.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
off_t __fastcall__ lseek (int fd, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
/* Modified argument order for short stacking offset */
|
||||||
|
ria_push_long (offset);
|
||||||
|
ria_push_char (whence);
|
||||||
|
ria_set_ax (fd);
|
||||||
|
return ria_call_long_errno (RIA_OP_LSEEK);
|
||||||
|
}
|
15
libsrc/rp6502/mainargs.s
Normal file
15
libsrc/rp6502/mainargs.s
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
;
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; No arguments
|
||||||
|
|
||||||
|
.constructor initmainargs, 24
|
||||||
|
.import __argc, __argv
|
||||||
|
|
||||||
|
.segment "ONCE"
|
||||||
|
|
||||||
|
.proc initmainargs
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
16
libsrc/rp6502/open.c
Normal file
16
libsrc/rp6502/open.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int __cdecl__ open (const char* name, int flags, ...)
|
||||||
|
{
|
||||||
|
size_t namelen = strlen (name);
|
||||||
|
if (namelen > 255) {
|
||||||
|
return _mappederrno (EINVAL);
|
||||||
|
}
|
||||||
|
while (namelen) {
|
||||||
|
ria_push_char (name[--namelen]);
|
||||||
|
}
|
||||||
|
ria_set_ax (flags);
|
||||||
|
return ria_call_int_errno (RIA_OP_OPEN);
|
||||||
|
}
|
86
libsrc/rp6502/oserrlist.s
Normal file
86
libsrc/rp6502/oserrlist.s
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
;
|
||||||
|
; 2002-07-18, Ullrich von Bassewitz
|
||||||
|
; 2022, ChaN
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; Defines the platform-specific error list.
|
||||||
|
;
|
||||||
|
; The table is built as a list of entries:
|
||||||
|
;
|
||||||
|
; .byte entrylen
|
||||||
|
; .byte errorcode
|
||||||
|
; .asciiz errormsg
|
||||||
|
;
|
||||||
|
; and, terminated by an entry with length zero that is returned if the
|
||||||
|
; error code could not be found.
|
||||||
|
;
|
||||||
|
|
||||||
|
.export __sys_oserrlist
|
||||||
|
|
||||||
|
.include "rp6502.inc"
|
||||||
|
.include "errno.inc"
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Macros used to generate the list (may get moved to an include file?)
|
||||||
|
|
||||||
|
; Regular entry
|
||||||
|
.macro sys_oserr_entry code, msg
|
||||||
|
.local Start, End
|
||||||
|
Start:
|
||||||
|
.byte End - Start
|
||||||
|
.byte code
|
||||||
|
.asciiz msg
|
||||||
|
End:
|
||||||
|
.endmacro
|
||||||
|
|
||||||
|
; Sentinel entry
|
||||||
|
.macro sys_oserr_sentinel msg
|
||||||
|
.byte 0 ; Length is always zero
|
||||||
|
.byte 0 ; Code is unused
|
||||||
|
.asciiz msg
|
||||||
|
.endmacro
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; The error message table
|
||||||
|
|
||||||
|
.rodata
|
||||||
|
__sys_oserrlist:
|
||||||
|
|
||||||
|
sys_oserr_entry ENOENT , "No such file or directory"
|
||||||
|
sys_oserr_entry ENOMEM , "Out of memory"
|
||||||
|
sys_oserr_entry EACCES , "Permission denied"
|
||||||
|
sys_oserr_entry ENODEV , "No such device"
|
||||||
|
sys_oserr_entry EMFILE , "Too many open files"
|
||||||
|
sys_oserr_entry EBUSY , "Device or resource busy"
|
||||||
|
sys_oserr_entry EINVAL , "Invalid argument"
|
||||||
|
sys_oserr_entry ENOSPC , "No space left on device"
|
||||||
|
sys_oserr_entry EEXIST , "File exists"
|
||||||
|
sys_oserr_entry EAGAIN , "Try again"
|
||||||
|
sys_oserr_entry EIO , "I/O error"
|
||||||
|
sys_oserr_entry EINTR , "Interrupted system call"
|
||||||
|
sys_oserr_entry ENOSYS , "Function not implemented"
|
||||||
|
sys_oserr_entry ESPIPE , "Illegal seek"
|
||||||
|
sys_oserr_entry ERANGE , "Range error"
|
||||||
|
sys_oserr_entry EBADF , "Bad file number"
|
||||||
|
sys_oserr_entry ENOEXEC , "Exec format error"
|
||||||
|
sys_oserr_entry EUNKNOWN , "Unknown OS specific error"
|
||||||
|
sys_oserr_entry FR_DISK_ERR , "A hard error occurred in the low level disk I/O layer"
|
||||||
|
sys_oserr_entry FR_INT_ERR , "Assertion failed"
|
||||||
|
sys_oserr_entry FR_NOT_READY , "The physical drive cannot work"
|
||||||
|
sys_oserr_entry FR_NO_FILE , "Could not find the file"
|
||||||
|
sys_oserr_entry FR_NO_PATH , "Could not find the path"
|
||||||
|
sys_oserr_entry FR_INVALID_NAME , "The path name format is invalid"
|
||||||
|
sys_oserr_entry FR_DENIED , "Access denied due to prohibited access or directory full"
|
||||||
|
sys_oserr_entry FR_EXIST , "Access denied due to prohibited access"
|
||||||
|
sys_oserr_entry FR_INVALID_OBJECT , "The file/directory object is invalid"
|
||||||
|
sys_oserr_entry FR_WRITE_PROTECTED , "The physical drive is write protected"
|
||||||
|
sys_oserr_entry FR_INVALID_DRIVE , "The logical drive number is invalid"
|
||||||
|
sys_oserr_entry FR_NOT_ENABLED , "The volume has no work area"
|
||||||
|
sys_oserr_entry FR_NO_FILESYSTEM , "There is no valid FAT volume"
|
||||||
|
sys_oserr_entry FR_MKFS_ABORTED , "The f_mkfs() aborted due to any problem"
|
||||||
|
sys_oserr_entry FR_TIMEOUT , "Could not get a grant to access the volume within defined period"
|
||||||
|
sys_oserr_entry FR_LOCKED , "The operation is rejected according to the file sharing policy"
|
||||||
|
sys_oserr_entry FR_NOT_ENOUGH_CORE , "LFN working buffer could not be allocated"
|
||||||
|
sys_oserr_entry FR_TOO_MANY_OPEN_FILES , "Number of open files > FF_FS_LOCK"
|
||||||
|
sys_oserr_entry FR_INVALID_PARAMETER , "Given parameter is invalid"
|
||||||
|
sys_oserr_sentinel "Unknown error"
|
66
libsrc/rp6502/oserror.s
Normal file
66
libsrc/rp6502/oserror.s
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
;
|
||||||
|
; 2000-05-17, Ullrich von Bassewitz
|
||||||
|
; 2022, ChaN
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; int __fastcall__ __osmaperrno (unsigned char oserror);
|
||||||
|
;
|
||||||
|
; RP6502 will respond with a union of CC65 and FatFs errnos.
|
||||||
|
; This will map FatFs errors into the CC65 range for portable code.
|
||||||
|
|
||||||
|
EFATFS_START := 32
|
||||||
|
|
||||||
|
.include "rp6502.inc"
|
||||||
|
.include "errno.inc"
|
||||||
|
|
||||||
|
.code
|
||||||
|
|
||||||
|
___osmaperrno:
|
||||||
|
cmp #EFATFS_START
|
||||||
|
bmi @L2
|
||||||
|
|
||||||
|
ldx #ErrTabSize
|
||||||
|
@L1:
|
||||||
|
cmp ErrTab-2,x ; Search for the error code
|
||||||
|
beq @L3 ; Jump if found
|
||||||
|
dex
|
||||||
|
dex
|
||||||
|
bne @L1 ; Next entry
|
||||||
|
|
||||||
|
; Code not found, return EUNKNOWN
|
||||||
|
lda #<EUNKNOWN
|
||||||
|
ldx #>EUNKNOWN
|
||||||
|
@L2:
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Found the code
|
||||||
|
@L3:
|
||||||
|
lda ErrTab-1,x
|
||||||
|
ldx #$00 ; High byte always zero
|
||||||
|
rts
|
||||||
|
|
||||||
|
.rodata
|
||||||
|
|
||||||
|
ErrTab:
|
||||||
|
|
||||||
|
.byte FR_DISK_ERR , EIO ; A hard error occurred in the low level disk I/O layer
|
||||||
|
; .byte FR_INT_ERR , EUNKNOWN ; Assertion failed
|
||||||
|
.byte FR_NOT_READY , EBUSY ; The physical drive cannot work
|
||||||
|
.byte FR_NO_FILE , ENOENT ; Could not find the file
|
||||||
|
.byte FR_NO_PATH , ENOENT ; Could not find the path
|
||||||
|
.byte FR_INVALID_NAME , EINVAL ; The path name format is invalid
|
||||||
|
.byte FR_DENIED , EACCES ; Access denied due to prohibited access or directory full
|
||||||
|
.byte FR_EXIST , EEXIST ; Access denied due to prohibited access
|
||||||
|
.byte FR_INVALID_OBJECT , EINVAL ; The file/directory object is invalid
|
||||||
|
.byte FR_WRITE_PROTECTED , EACCES ; The physical drive is write protected
|
||||||
|
.byte FR_INVALID_DRIVE , ENODEV ; The logical drive number is invalid
|
||||||
|
; .byte FR_NOT_ENABLED , EUNKNOWN ; The volume has no work area
|
||||||
|
; .byte FR_NO_FILESYSTEM , EUNKNOWN ; There is no valid FAT volume
|
||||||
|
; .byte FR_MKFS_ABORTED , EUNKNOWN ; The f_mkfs() aborted due to any problem
|
||||||
|
; .byte FR_TIMEOUT , EUNKNOWN ; Could not get a grant to access the volume within defined period
|
||||||
|
.byte FR_LOCKED , EBUSY ; The operation is rejected according to the file sharing policy
|
||||||
|
.byte FR_NOT_ENOUGH_CORE , ENOMEM ; LFN working buffer could not be allocated
|
||||||
|
.byte FR_TOO_MANY_OPEN_FILES , EMFILE ; Number of open files > FF_FS_LOCK
|
||||||
|
.byte FR_INVALID_PARAMETER , EINVAL ; Given parameter is invalid
|
||||||
|
|
||||||
|
ErrTabSize = (* - ErrTab)
|
6
libsrc/rp6502/phi2.c
Normal file
6
libsrc/rp6502/phi2.c
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ phi2 (void)
|
||||||
|
{
|
||||||
|
return ria_call_int (RIA_OP_PHI2);
|
||||||
|
}
|
7
libsrc/rp6502/randomize.c
Normal file
7
libsrc/rp6502/randomize.c
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void _randomize (void)
|
||||||
|
{
|
||||||
|
srand (ria_call_int (RIA_OP_LRAND));
|
||||||
|
}
|
20
libsrc/rp6502/read.c
Normal file
20
libsrc/rp6502/read.c
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int __fastcall__ read (int fildes, void* buf, unsigned count)
|
||||||
|
{
|
||||||
|
int total = 0;
|
||||||
|
while (count) {
|
||||||
|
unsigned blockcount = (count > 256) ? 256 : count;
|
||||||
|
int bytes_read = read_xstack (&((char*)buf)[total], blockcount, fildes);
|
||||||
|
if (bytes_read < 0) {
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
total += bytes_read;
|
||||||
|
count -= bytes_read;
|
||||||
|
if (bytes_read < blockcount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
9
libsrc/rp6502/read_xram.c
Normal file
9
libsrc/rp6502/read_xram.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ read_xram (unsigned buf, unsigned count, int fildes)
|
||||||
|
{
|
||||||
|
ria_push_int (buf);
|
||||||
|
ria_push_int (count);
|
||||||
|
ria_set_ax (fildes);
|
||||||
|
return ria_call_int_errno (RIA_OP_READ_XRAM);
|
||||||
|
}
|
13
libsrc/rp6502/read_xstack.c
Normal file
13
libsrc/rp6502/read_xstack.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ read_xstack (void* buf, unsigned count, int fildes)
|
||||||
|
{
|
||||||
|
int i, ax;
|
||||||
|
ria_push_int (count);
|
||||||
|
ria_set_ax (fildes);
|
||||||
|
ax = ria_call_int_errno (RIA_OP_READ_XSTACK);
|
||||||
|
for (i = 0; i < ax; i++) {
|
||||||
|
((char*)buf)[i] = ria_pop_char ();
|
||||||
|
}
|
||||||
|
return ax;
|
||||||
|
}
|
89
libsrc/rp6502/ria.s
Normal file
89
libsrc/rp6502/ria.s
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
;
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; Helpers for building API shims
|
||||||
|
|
||||||
|
.include "rp6502.inc"
|
||||||
|
|
||||||
|
.export _ria_push_long, _ria_push_int
|
||||||
|
.export _ria_pop_long, _ria_pop_int
|
||||||
|
.export _ria_set_axsreg, _ria_set_ax
|
||||||
|
.export _ria_call_int, _ria_call_long
|
||||||
|
.export _ria_call_int_errno, _ria_call_long_errno
|
||||||
|
|
||||||
|
.importzp sp, sreg
|
||||||
|
.import ___mappederrno, incsp1
|
||||||
|
|
||||||
|
.code
|
||||||
|
|
||||||
|
; void __fastcall__ ria_push_long(unsigned long val);
|
||||||
|
_ria_push_long:
|
||||||
|
ldy sreg+1
|
||||||
|
sty RIA_XSTACK
|
||||||
|
ldy sreg
|
||||||
|
sty RIA_XSTACK
|
||||||
|
; void __fastcall__ ria_push_int(unsigned int val);
|
||||||
|
_ria_push_int:
|
||||||
|
stx RIA_XSTACK
|
||||||
|
sta RIA_XSTACK
|
||||||
|
rts
|
||||||
|
|
||||||
|
; long __fastcall__ ria_pop_long(void);
|
||||||
|
_ria_pop_long:
|
||||||
|
jsr _ria_pop_int
|
||||||
|
ldy RIA_XSTACK
|
||||||
|
sty sreg
|
||||||
|
ldy RIA_XSTACK
|
||||||
|
sty sreg+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; int __fastcall__ ria_pop_int(void);
|
||||||
|
_ria_pop_int:
|
||||||
|
lda RIA_XSTACK
|
||||||
|
ldx RIA_XSTACK
|
||||||
|
rts
|
||||||
|
|
||||||
|
; void __fastcall__ ria_set_axsreg(unsigned long axsreg);
|
||||||
|
_ria_set_axsreg:
|
||||||
|
ldy sreg
|
||||||
|
sty RIA_SREG
|
||||||
|
ldy sreg+1
|
||||||
|
sty RIA_SREG+1
|
||||||
|
; void __fastcall__ ria_set_ax(unsigned int ax);
|
||||||
|
_ria_set_ax:
|
||||||
|
stx RIA_X
|
||||||
|
sta RIA_A
|
||||||
|
rts
|
||||||
|
|
||||||
|
; int __fastcall__ ria_call_int(unsigned char op);
|
||||||
|
_ria_call_int:
|
||||||
|
sta RIA_OP
|
||||||
|
jmp RIA_SPIN
|
||||||
|
|
||||||
|
; long __fastcall__ ria_call_long(unsigned char op);
|
||||||
|
_ria_call_long:
|
||||||
|
sta RIA_OP
|
||||||
|
jsr RIA_SPIN
|
||||||
|
ldy RIA_SREG
|
||||||
|
sty sreg
|
||||||
|
ldy RIA_SREG+1
|
||||||
|
sty sreg+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; int __fastcall__ ria_call_int_errno(unsigned char op);
|
||||||
|
_ria_call_int_errno:
|
||||||
|
sta RIA_OP
|
||||||
|
jsr RIA_SPIN
|
||||||
|
ldx RIA_X
|
||||||
|
bmi ERROR
|
||||||
|
rts
|
||||||
|
|
||||||
|
; long __fastcall__ ria_call_long_errno(unsigned char op);
|
||||||
|
_ria_call_long_errno:
|
||||||
|
jsr _ria_call_long
|
||||||
|
bmi ERROR
|
||||||
|
rts
|
||||||
|
|
||||||
|
ERROR:
|
||||||
|
lda RIA_ERRNO
|
||||||
|
jmp ___mappederrno
|
10
libsrc/rp6502/settime.c
Normal file
10
libsrc/rp6502/settime.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int clock_settime (clockid_t clock_id, const struct timespec* tp)
|
||||||
|
{
|
||||||
|
ria_set_ax (clock_id);
|
||||||
|
ria_push_long (tp->tv_nsec);
|
||||||
|
ria_push_long (tp->tv_sec);
|
||||||
|
return ria_call_int_errno (RIA_OP_CLOCK_SETTIME);
|
||||||
|
}
|
9
libsrc/rp6502/stdin_opt.c
Normal file
9
libsrc/rp6502/stdin_opt.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ stdin_opt (unsigned long ctrl_bits, unsigned char str_length)
|
||||||
|
{
|
||||||
|
ria_push_long (ctrl_bits);
|
||||||
|
ria_set_a (str_length);
|
||||||
|
return ria_call_int_errno (RIA_OP_STDIN_OPT);
|
||||||
|
}
|
16
libsrc/rp6502/sysremove.c
Normal file
16
libsrc/rp6502/sysremove.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
unsigned char __fastcall__ _sysremove (const char* name)
|
||||||
|
{
|
||||||
|
size_t namelen;
|
||||||
|
namelen = strlen (name);
|
||||||
|
if (namelen > 255) {
|
||||||
|
return _mappederrno (EINVAL);
|
||||||
|
}
|
||||||
|
while (namelen) {
|
||||||
|
ria_push_char (name[--namelen]);
|
||||||
|
}
|
||||||
|
return ria_call_int_errno (RIA_OP_UNLINK);
|
||||||
|
}
|
21
libsrc/rp6502/sysrename.c
Normal file
21
libsrc/rp6502/sysrename.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
unsigned char __fastcall__ _sysrename (const char* oldpath, const char* newpath)
|
||||||
|
{
|
||||||
|
size_t oldpathlen, newpathlen;
|
||||||
|
oldpathlen = strlen (oldpath);
|
||||||
|
newpathlen = strlen (newpath);
|
||||||
|
if (oldpathlen + newpathlen > 254) {
|
||||||
|
return _mappederrno (EINVAL);
|
||||||
|
}
|
||||||
|
while (oldpathlen) {
|
||||||
|
ria_push_char (oldpath[--oldpathlen]);
|
||||||
|
}
|
||||||
|
ria_push_char (0);
|
||||||
|
while (newpathlen) {
|
||||||
|
ria_push_char (newpath[--newpathlen]);
|
||||||
|
}
|
||||||
|
return ria_call_int_errno (RIA_OP_RENAME);
|
||||||
|
}
|
20
libsrc/rp6502/write.c
Normal file
20
libsrc/rp6502/write.c
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int __fastcall__ write (int fildes, const void* buf, unsigned count)
|
||||||
|
{
|
||||||
|
int ax, total = 0;
|
||||||
|
while (count) {
|
||||||
|
int blockcount = (count > 256) ? 256 : count;
|
||||||
|
ax = write_xstack (&((char*)buf)[total], blockcount, fildes);
|
||||||
|
if (ax < 0) {
|
||||||
|
return ax;
|
||||||
|
}
|
||||||
|
total += ax;
|
||||||
|
count -= ax;
|
||||||
|
if (ax < blockcount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
9
libsrc/rp6502/write_xram.c
Normal file
9
libsrc/rp6502/write_xram.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ write_xram (unsigned buf, unsigned count, int fildes)
|
||||||
|
{
|
||||||
|
ria_push_int (buf);
|
||||||
|
ria_push_int (count);
|
||||||
|
ria_set_ax (fildes);
|
||||||
|
return ria_call_int_errno (RIA_OP_WRITE_XRAM);
|
||||||
|
}
|
11
libsrc/rp6502/write_xstack.c
Normal file
11
libsrc/rp6502/write_xstack.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <rp6502.h>
|
||||||
|
|
||||||
|
int __fastcall__ write_xstack (const void* buf, unsigned count, int fildes)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = count; i;) {
|
||||||
|
ria_push_char (((char*)buf)[--i]);
|
||||||
|
}
|
||||||
|
ria_set_ax (fildes);
|
||||||
|
return ria_call_int_errno (RIA_OP_WRITE_XSTACK);
|
||||||
|
}
|
37
libsrc/rp6502/xreg.s
Normal file
37
libsrc/rp6502/xreg.s
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
;
|
||||||
|
; 2023, Rumbledethumps
|
||||||
|
;
|
||||||
|
; CC65 will promote variadic char arguments to int. It will not demote longs.
|
||||||
|
; int __cdecl__ xreg(char device, char channel, unsigned char address, ...);
|
||||||
|
|
||||||
|
.export _xreg
|
||||||
|
.importzp sp
|
||||||
|
.import addysp, _ria_call_int_errno
|
||||||
|
|
||||||
|
.include "rp6502.inc"
|
||||||
|
|
||||||
|
.code
|
||||||
|
|
||||||
|
.proc _xreg
|
||||||
|
|
||||||
|
; save variadic size in X
|
||||||
|
tya
|
||||||
|
tax
|
||||||
|
|
||||||
|
@copy: ; copy stack
|
||||||
|
dey
|
||||||
|
lda (sp),y
|
||||||
|
sta RIA_XSTACK
|
||||||
|
tya
|
||||||
|
bne @copy
|
||||||
|
|
||||||
|
; recover variadic size and move sp
|
||||||
|
txa
|
||||||
|
tay
|
||||||
|
jsr addysp
|
||||||
|
|
||||||
|
; run RIA operation
|
||||||
|
lda #RIA_OP_XREG
|
||||||
|
jmp _ria_call_int_errno
|
||||||
|
|
||||||
|
.endproc
|
|
@ -346,6 +346,10 @@ static void SetSys (const char* Sys)
|
||||||
NewSymbol ("__KIM1__", 1);
|
NewSymbol ("__KIM1__", 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TGT_RP6502:
|
||||||
|
NewSymbol ("__RP6502__", 1);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
AbEnd ("Invalid target name: '%s'", Sys);
|
AbEnd ("Invalid target name: '%s'", Sys);
|
||||||
|
|
||||||
|
|
|
@ -303,6 +303,10 @@ static void SetSys (const char* Sys)
|
||||||
DefineNumericMacro ("__KIM1__", 1);
|
DefineNumericMacro ("__KIM1__", 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TGT_RP6502:
|
||||||
|
DefineNumericMacro ("__RP6502__", 1);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
AbEnd ("Unknown target system '%s'", Sys);
|
AbEnd ("Unknown target system '%s'", Sys);
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,7 @@ static const TargetEntry TargetMap[] = {
|
||||||
{ "pce", TGT_PCENGINE },
|
{ "pce", TGT_PCENGINE },
|
||||||
{ "pet", TGT_PET },
|
{ "pet", TGT_PET },
|
||||||
{ "plus4", TGT_PLUS4 },
|
{ "plus4", TGT_PLUS4 },
|
||||||
|
{ "rp6502", TGT_RP6502 },
|
||||||
{ "sim6502", TGT_SIM6502 },
|
{ "sim6502", TGT_SIM6502 },
|
||||||
{ "sim65c02", TGT_SIM65C02 },
|
{ "sim65c02", TGT_SIM65C02 },
|
||||||
{ "supervision", TGT_SUPERVISION },
|
{ "supervision", TGT_SUPERVISION },
|
||||||
|
@ -221,6 +222,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
|
||||||
{ "cx16", CPU_65C02, BINFMT_BINARY, CTPET },
|
{ "cx16", CPU_65C02, BINFMT_BINARY, CTPET },
|
||||||
{ "sym1", CPU_6502, BINFMT_BINARY, CTNone },
|
{ "sym1", CPU_6502, BINFMT_BINARY, CTNone },
|
||||||
{ "kim1", CPU_6502, BINFMT_BINARY, CTNone },
|
{ "kim1", CPU_6502, BINFMT_BINARY, CTNone },
|
||||||
|
{ "rp6502", CPU_65C02, BINFMT_BINARY, CTNone },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Target system */
|
/* Target system */
|
||||||
|
|
|
@ -88,6 +88,7 @@ typedef enum {
|
||||||
TGT_CX16,
|
TGT_CX16,
|
||||||
TGT_SYM1,
|
TGT_SYM1,
|
||||||
TGT_KIM1,
|
TGT_KIM1,
|
||||||
|
TGT_RP6502,
|
||||||
TGT_COUNT /* Number of target systems */
|
TGT_COUNT /* Number of target systems */
|
||||||
} target_t;
|
} target_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user