mirror of
https://github.com/cc65/cc65.git
synced 2024-12-26 08:32:00 +00:00
commit
c43b3582db
27
asminc/kim1.inc
Normal file
27
asminc/kim1.inc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; KIM-1 definitions
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
RAMSTART := $0200 ; Entry point
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Monitor Functions
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
OUTCHR := $1EA0 ; Output character
|
||||||
|
INTCHR := $1E5A ; Input character without case conversion
|
||||||
|
DUMPT := $1800 ; Dump memory to tape
|
||||||
|
LOADT := $1873 ; Load memory from tape
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; System Memory
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
SAL := $17F5 ; Tape load address low
|
||||||
|
SAH := $17F6 ; Tape load address high
|
||||||
|
EAL := $17F7 ; Tape address end low
|
||||||
|
EAH := $17F8 ; Tape address end high
|
||||||
|
ID := $17F9 ; Tape Identification number
|
41
cfg/kim1-60k.cfg
Normal file
41
cfg/kim1-60k.cfg
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# kim1-60k.cfg (4k)
|
||||||
|
#
|
||||||
|
# for expanded KIM-1
|
||||||
|
#
|
||||||
|
# ld65 --config kim1-60k.cfg -o <prog>.bin <prog>.o
|
||||||
|
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $2000;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYMBOLS {
|
||||||
|
__STACKSIZE__: type = weak, value = $0080; # 128 byte program stack
|
||||||
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = %O, define = yes, start = $0000, size = $00EE;
|
||||||
|
CPUSTACK: file = "", define = yes, start = $0100, size = $0100;
|
||||||
|
RAM: file = %O, define = yes, start = %S, size = $E000 - %S - __STACKSIZE__;
|
||||||
|
MAINROM: file = "", define = yes, start = $E000, size = $1000;
|
||||||
|
TOP: file = "", define = yes, start = $F000, size = $1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||||
|
STARTUP: load = RAM, type = ro, define = yes;
|
||||||
|
CODE: load = RAM, type = ro, define = yes;
|
||||||
|
RODATA: load = RAM, type = ro, define = yes;
|
||||||
|
ONCE: load = RAM, type = ro, define = yes;
|
||||||
|
DATA: load = RAM, type = rw, define = yes;
|
||||||
|
BSS: load = RAM, type = bss, define = yes;
|
||||||
|
}
|
||||||
|
|
41
cfg/kim1.cfg
Normal file
41
cfg/kim1.cfg
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# kim1.cfg (4k)
|
||||||
|
#
|
||||||
|
# for unexpanded KIM-1
|
||||||
|
#
|
||||||
|
# ld65 --config kim1.cfg -o <prog>.bin <prog>.o
|
||||||
|
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $0200;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYMBOLS {
|
||||||
|
__STACKSIZE__: type = weak, value = $0080; # 128 byte program stack
|
||||||
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = %O, define = yes, start = $0000, size = $00EE;
|
||||||
|
CPUSTACK: file = "", define = yes, start = $0100, size = $0100;
|
||||||
|
RAM: file = %O, define = yes, start = %S, size = $1000 - %S - __STACKSIZE__;
|
||||||
|
MAINROM: file = "", define = yes, start = $E000, size = $1000;
|
||||||
|
TOP: file = "", define = yes, start = $F000, size = $1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||||
|
STARTUP: load = RAM, type = ro, define = yes;
|
||||||
|
CODE: load = RAM, type = ro, define = yes;
|
||||||
|
RODATA: load = RAM, type = ro, define = yes;
|
||||||
|
ONCE: load = RAM, type = ro, define = yes;
|
||||||
|
DATA: load = RAM, type = rw, define = yes;
|
||||||
|
BSS: load = RAM, type = bss, define = yes;
|
||||||
|
}
|
||||||
|
|
@ -154,6 +154,9 @@
|
|||||||
<tag><htmlurl url="gamate.html" name="gamate.html"></tag>
|
<tag><htmlurl url="gamate.html" name="gamate.html"></tag>
|
||||||
Topics specific to the Bit Corporation Gamate Console.
|
Topics specific to the Bit Corporation Gamate Console.
|
||||||
|
|
||||||
|
<tag><htmlurl url="kim1.html" name="kim1.html"></tag>
|
||||||
|
Topics specific to the MOS Technology KIM-1.
|
||||||
|
|
||||||
<tag><htmlurl url="lynx.html" name="lynx.html"></tag>
|
<tag><htmlurl url="lynx.html" name="lynx.html"></tag>
|
||||||
Topics specific to the Atari Lynx Game Console.
|
Topics specific to the Atari Lynx Game Console.
|
||||||
|
|
||||||
|
148
doc/kim1.sgml
Normal file
148
doc/kim1.sgml
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<!doctype linuxdoc system>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<title>MOS Technology KIM-1 specific information for cc65
|
||||||
|
<author><url url="mailto:davepl@davepl.com" name="Dave Plummer">
|
||||||
|
|
||||||
|
<abstract>
|
||||||
|
An overview of the KIM-1 runtime system as it is implemented for the cc65 C compiler.
|
||||||
|
</abstract>
|
||||||
|
|
||||||
|
<!-- Table of contents -->
|
||||||
|
<toc>
|
||||||
|
|
||||||
|
<!-- Begin the document -->
|
||||||
|
|
||||||
|
<sect>Overview<p>
|
||||||
|
|
||||||
|
This file contains an overview of the KIM-1 runtime system as it comes with the cc65 C compiler.
|
||||||
|
It describes the memory layout, KIM-1 specific header files, available drivers, and any pitfalls
|
||||||
|
specific to the platform.
|
||||||
|
|
||||||
|
Please note that KIM-1 specific functions are just mentioned here, they are described in detail
|
||||||
|
in the separate <url url="funcref.html" name="function reference">. Even functions marked as
|
||||||
|
"platform dependent" may be available on more than one platform. Please see the
|
||||||
|
function reference for more information.
|
||||||
|
|
||||||
|
<sect>Binary format<p>
|
||||||
|
|
||||||
|
The output format generated by the linker for the KIM-1 target is a raw binary BIN file, which
|
||||||
|
is essentially a memory image. You can convert this to a papertape format file using
|
||||||
|
Convert8bithexformat or KIMPaper, which are open-source conversion utility programs.
|
||||||
|
A papertape format files can be transferred to the KIM-1 using the RS-232 terminal port (TTY),
|
||||||
|
just as if the machine-code was entered by hand. Enter 'L' in the TTY and start the paper tape file
|
||||||
|
transfer.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Included with this distribution is a 4k configuration file and a 60k config file. The KIM-1
|
||||||
|
on-board memory is limited to 4 kbytes but system memory can be increased to 60 kbytes of
|
||||||
|
contiguous RAM with aftermarket add-on boards. So choose the config file that matches your
|
||||||
|
system configuration before compiling and linking user programs.
|
||||||
|
|
||||||
|
<sect>Memory layout<p>
|
||||||
|
|
||||||
|
The ROMs and I/O areas are defined in the configuration files, as are most of the entry points
|
||||||
|
for useful subroutines in the KIM-1 monitor ROM. cc65 generated programs compiled and linked
|
||||||
|
using 4k config run in the memory range of $200 - $0FFF. The 60k config expands
|
||||||
|
this range to $DFFF. The starting memory location and entry point for running the program is
|
||||||
|
$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'.
|
||||||
|
|
||||||
|
Special locations:
|
||||||
|
|
||||||
|
<descrip>
|
||||||
|
<tag/Text screen/
|
||||||
|
Conio support is not currently available for the KIM-1. But stdio console functions are available.
|
||||||
|
|
||||||
|
<tag/Stack/
|
||||||
|
The C runtime stack is located at $0FFF on 4kb KIM-1s, or at $DFFF for 60kb systems.
|
||||||
|
The stack always grows downwards.
|
||||||
|
|
||||||
|
<tag/Heap/
|
||||||
|
The C heap is located at the end of the program and grows towards the C runtime stack.
|
||||||
|
|
||||||
|
</descrip><p>
|
||||||
|
|
||||||
|
<sect>Platform specific header files<p>
|
||||||
|
|
||||||
|
Programs containing KIM-1 code may use the <tt/kim.h/ header file. See the header file for more information.
|
||||||
|
|
||||||
|
<sect>Loadable drivers<p>
|
||||||
|
|
||||||
|
<sect1>Graphics drivers<p>
|
||||||
|
|
||||||
|
No graphics drivers are currently available for the KIM-1.
|
||||||
|
|
||||||
|
<sect1>Joystick drivers<p>
|
||||||
|
|
||||||
|
No joystick driver is currently available for the KIM-1.
|
||||||
|
|
||||||
|
<sect1>Mouse drivers<p>
|
||||||
|
|
||||||
|
No mouse drivers are currently available for the KIM-1.
|
||||||
|
|
||||||
|
<sect1>RS232 device drivers<p>
|
||||||
|
|
||||||
|
No communication port drivers are currently available for the KIM-1. It has only the "master console"
|
||||||
|
e.g. stdin and stdout.
|
||||||
|
|
||||||
|
<sect>Limitations<p>
|
||||||
|
|
||||||
|
<sect1>Disk I/O<p>
|
||||||
|
|
||||||
|
The existing library for the KIM-1 doesn't implement C file I/O.
|
||||||
|
|
||||||
|
To be more specific, this limitation means that you cannot use any of the following functions (and a few others):
|
||||||
|
|
||||||
|
<itemize>
|
||||||
|
<item>fopen
|
||||||
|
<item>fclose
|
||||||
|
<item>fread
|
||||||
|
<item>fwrite
|
||||||
|
<item>...
|
||||||
|
</itemize>
|
||||||
|
|
||||||
|
<sect>Other hints<p>
|
||||||
|
|
||||||
|
<sect1>kim1.h<p>
|
||||||
|
This header exposes KIM-1 specific I/O functions that are useful for reading and writing its ports and front panel.
|
||||||
|
See the <tt/kim1.h/ include file for a list of the functions available.
|
||||||
|
|
||||||
|
<sect1>Limited memory applications<p>
|
||||||
|
|
||||||
|
As stated earlier, there are config files for 4kb and 60kb systems. If you have 60kb RAM, then you will probably
|
||||||
|
want to use the kim1-60k configuration, but if not - if you are using the kim1-4k configuration - then you may
|
||||||
|
want to use functions like getchar, putchar, gets and puts rather than functions like scanf and printf.
|
||||||
|
Printf, for example, requires about 1KB because it needs to know how to process all the format specifiers.
|
||||||
|
|
||||||
|
<sect1>Sample programs<p>
|
||||||
|
|
||||||
|
These sample programs can be found in the samples/kim1 directory:
|
||||||
|
|
||||||
|
<itemize>
|
||||||
|
<item>kimHello prints "Hello World!" and then inputs characters, which are echoed on the screen.
|
||||||
|
This program will run on both 4kb and 60kb systems.</item>
|
||||||
|
<item>kimSieve finds the prime numbers up to 100,000 using the Sieve of Eratosthenes algorithm, and prints how many
|
||||||
|
prime numbers were found. This program requires a 60kb system to run.</item>
|
||||||
|
</itemize>
|
||||||
|
|
||||||
|
<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>
|
67
include/kim1.h
Normal file
67
include/kim1.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* kim1.h */
|
||||||
|
/* */
|
||||||
|
/* KIM-1 system-specific definitions */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2022 Dave Plummer */
|
||||||
|
/* Email: davepl@davepl.com */
|
||||||
|
/* */
|
||||||
|
/* 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 _KIM1_H
|
||||||
|
#define _KIM1_H
|
||||||
|
|
||||||
|
/* Check for errors */
|
||||||
|
#if !defined(__KIM1__)
|
||||||
|
# error This module may only be used when compiling for the KIM-1!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Hardware */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// Todo (davepl)
|
||||||
|
//
|
||||||
|
// #include <_6530.h>
|
||||||
|
// #define RIOT3 (*(struct __6530*)0x1700) // U25
|
||||||
|
// #define RIOT2 (*(struct __6530*)0x1740) // U28
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* Read from tape */
|
||||||
|
int __fastcall__ loadt (unsigned char);
|
||||||
|
|
||||||
|
/* Write to tape */
|
||||||
|
int __fastcall__ dumpt (unsigned char, const void*, const void*);
|
||||||
|
|
||||||
|
/* End of sym1.h */
|
||||||
|
#endif
|
@ -27,6 +27,7 @@ TARGETS = apple2 \
|
|||||||
$(CBMS) \
|
$(CBMS) \
|
||||||
$(GEOS) \
|
$(GEOS) \
|
||||||
gamate \
|
gamate \
|
||||||
|
kim1 \
|
||||||
lynx \
|
lynx \
|
||||||
nes \
|
nes \
|
||||||
none \
|
none \
|
||||||
|
47
libsrc/kim1/crt0.s
Normal file
47
libsrc/kim1/crt0.s
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
;
|
||||||
|
; Startup code for cc65 (KIM-1 version)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _init, _exit
|
||||||
|
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||||
|
|
||||||
|
.import _main
|
||||||
|
.import initlib, donelib, copydata, zerobss
|
||||||
|
.import __RAM_START__, __RAM_SIZE__ ; Linker generated
|
||||||
|
.import __STACKSIZE__ ; Linker generated
|
||||||
|
|
||||||
|
.include "zeropage.inc"
|
||||||
|
.include "kim1.inc"
|
||||||
|
|
||||||
|
|
||||||
|
; Place the startup code in a special segment
|
||||||
|
|
||||||
|
.segment "STARTUP"
|
||||||
|
|
||||||
|
|
||||||
|
; A little light housekeeping
|
||||||
|
|
||||||
|
_init: cld ; Clear decimal mode
|
||||||
|
|
||||||
|
; 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 (this is also the _exit entry). There may be a more elegant way to
|
||||||
|
; return to the monitor on the KIM-1, but I don't know it!
|
||||||
|
|
||||||
|
_exit: brk
|
||||||
|
|
5
libsrc/kim1/ctype.s
Normal file
5
libsrc/kim1/ctype.s
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
; Character specification table.
|
||||||
|
;
|
||||||
|
; uses the "common" definition
|
||||||
|
|
||||||
|
.include "ctype_common.inc"
|
51
libsrc/kim1/read.s
Normal file
51
libsrc/kim1/read.s
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
;
|
||||||
|
; int __fastcall__ read (int fd, void* buf, unsigned count);
|
||||||
|
;
|
||||||
|
|
||||||
|
.include "kim1.inc"
|
||||||
|
|
||||||
|
.import popax, popptr1
|
||||||
|
.importzp ptr1, ptr2, ptr3
|
||||||
|
|
||||||
|
.export _read
|
||||||
|
|
||||||
|
.proc _read
|
||||||
|
|
||||||
|
sta ptr3
|
||||||
|
stx ptr3+1 ; Count in ptr3
|
||||||
|
inx
|
||||||
|
stx ptr2+1 ; Increment and store in ptr2
|
||||||
|
tax
|
||||||
|
inx
|
||||||
|
stx ptr2
|
||||||
|
jsr popptr1 ; Buffer address in ptr1
|
||||||
|
jsr popax
|
||||||
|
|
||||||
|
begin: dec ptr2
|
||||||
|
bne getch
|
||||||
|
dec ptr2+1
|
||||||
|
beq done ; If buffer full, return
|
||||||
|
|
||||||
|
getch: jsr INTCHR ; Get character using Monitor ROM call
|
||||||
|
;jsr OUTCHR ; Echo it
|
||||||
|
and #$7F ; Clear top bit
|
||||||
|
cmp #$07 ; Check for '\a'
|
||||||
|
bne chkcr ; ...if BEL character
|
||||||
|
;jsr BEEP ; Make beep sound TODO
|
||||||
|
chkcr: cmp #$0D ; Check for '\r'
|
||||||
|
bne putch ; ...if CR character
|
||||||
|
lda #$0A ; Replace with '\n'
|
||||||
|
jsr OUTCHR ; and echo it
|
||||||
|
|
||||||
|
putch: ldy #$00 ; Put char into return buffer
|
||||||
|
sta (ptr1),y
|
||||||
|
inc ptr1 ; Increment pointer
|
||||||
|
bne begin
|
||||||
|
inc ptr1+1
|
||||||
|
bne begin
|
||||||
|
|
||||||
|
done: lda ptr3
|
||||||
|
ldx ptr3+1
|
||||||
|
rts ; Return count
|
||||||
|
|
||||||
|
.endproc
|
39
libsrc/kim1/tapeio.s
Normal file
39
libsrc/kim1/tapeio.s
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
;
|
||||||
|
; int __fastcall__ loadt (unsigned char id);
|
||||||
|
; int __fastcall__ dumpt (unsigned char id, void* start_addr, void* end_addr);
|
||||||
|
;
|
||||||
|
|
||||||
|
.include "kim1.inc"
|
||||||
|
|
||||||
|
.import popa, popax, return0, return1
|
||||||
|
|
||||||
|
.export _loadt, _dumpt
|
||||||
|
|
||||||
|
.segment "CODE"
|
||||||
|
|
||||||
|
.proc _loadt: near
|
||||||
|
|
||||||
|
sta ID ; Tape record ID to P1L
|
||||||
|
jsr LOADT ; Read data from tape
|
||||||
|
bcs error
|
||||||
|
jmp return0 ; Return 0 if sucessful
|
||||||
|
error: jmp return1 ; or 1 if not
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
.proc _dumpt: near
|
||||||
|
|
||||||
|
sta EAL ; End address
|
||||||
|
stx EAH
|
||||||
|
jsr popax
|
||||||
|
sta SAL ; Start address
|
||||||
|
stx SAH
|
||||||
|
jsr popa
|
||||||
|
sta ID ; Tape Record ID
|
||||||
|
ldx #$00
|
||||||
|
jsr DUMPT ; Write data to tape
|
||||||
|
bcs error
|
||||||
|
jmp return0 ; Return 0 if sucessful
|
||||||
|
error: jmp return1 ; or 1 if not
|
||||||
|
|
||||||
|
.endproc
|
49
libsrc/kim1/write.s
Normal file
49
libsrc/kim1/write.s
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
;
|
||||||
|
; int __fastcall__ write (int fd, const void* buf, int count);
|
||||||
|
;
|
||||||
|
|
||||||
|
.include "kim1.inc"
|
||||||
|
|
||||||
|
.import popax, popptr1
|
||||||
|
.importzp ptr1, ptr2, ptr3
|
||||||
|
|
||||||
|
.export _write
|
||||||
|
|
||||||
|
.proc _write
|
||||||
|
|
||||||
|
sta ptr3
|
||||||
|
stx ptr3+1 ; Count in ptr3
|
||||||
|
inx
|
||||||
|
stx ptr2+1 ; Increment and store in ptr2
|
||||||
|
tax
|
||||||
|
inx
|
||||||
|
stx ptr2
|
||||||
|
jsr popptr1 ; Buffer address in ptr1
|
||||||
|
jsr popax
|
||||||
|
|
||||||
|
begin: dec ptr2
|
||||||
|
bne outch
|
||||||
|
dec ptr2+1
|
||||||
|
beq done
|
||||||
|
|
||||||
|
outch: ldy #0
|
||||||
|
lda (ptr1),y
|
||||||
|
jsr OUTCHR ; Send character using Monitor call
|
||||||
|
cmp #$07 ; Check for '\a'
|
||||||
|
bne chklf ; ...if BEL character
|
||||||
|
;jsr BEEP ; Make beep sound
|
||||||
|
chklf: cmp #$0A ; Check for 'n'
|
||||||
|
bne next ; ...if LF character
|
||||||
|
lda #$0D ; Add a carriage return
|
||||||
|
jsr OUTCHR
|
||||||
|
|
||||||
|
next: inc ptr1
|
||||||
|
bne begin
|
||||||
|
inc ptr1+1
|
||||||
|
jmp begin
|
||||||
|
|
||||||
|
done: lda ptr3
|
||||||
|
ldx ptr3+1
|
||||||
|
rts ; Return count
|
||||||
|
|
||||||
|
.endproc
|
@ -154,7 +154,7 @@ endif
|
|||||||
# Lists of subdirectories
|
# Lists of subdirectories
|
||||||
|
|
||||||
# disasm depends on cpp
|
# disasm depends on cpp
|
||||||
DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 cbm
|
DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 kim1 cbm
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# Lists of executables
|
# Lists of executables
|
||||||
@ -329,6 +329,9 @@ EXELIST_supervision = \
|
|||||||
EXELIST_sym1 = \
|
EXELIST_sym1 = \
|
||||||
notavailable
|
notavailable
|
||||||
|
|
||||||
|
EXELIST_kim1 = \
|
||||||
|
notavailable
|
||||||
|
|
||||||
EXELIST_telestrat = \
|
EXELIST_telestrat = \
|
||||||
ascii \
|
ascii \
|
||||||
checkversion \
|
checkversion \
|
||||||
@ -395,6 +398,7 @@ TARGETS := \
|
|||||||
creativision \
|
creativision \
|
||||||
cx16 \
|
cx16 \
|
||||||
gamate \
|
gamate \
|
||||||
|
kim1 \
|
||||||
lunix \
|
lunix \
|
||||||
lynx \
|
lynx \
|
||||||
nes \
|
nes \
|
||||||
|
62
samples/kim1/Makefile
Normal file
62
samples/kim1/Makefile
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
# Run 'make SYS=<target>'; or, set a SYS env.
|
||||||
|
# var. to build for another target system.
|
||||||
|
SYS ?= kim1
|
||||||
|
|
||||||
|
# Just the usual way to find out if we're
|
||||||
|
# using cmd.exe to execute make rules.
|
||||||
|
ifneq ($(shell echo),)
|
||||||
|
CMD_EXE = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef CMD_EXE
|
||||||
|
NULLDEV = nul:
|
||||||
|
DEL = -del /f
|
||||||
|
RMDIR = rmdir /s /q
|
||||||
|
else
|
||||||
|
NULLDEV = /dev/null
|
||||||
|
DEL = $(RM)
|
||||||
|
RMDIR = $(RM) -r
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef CC65_HOME
|
||||||
|
AS = $(CC65_HOME)/bin/ca65
|
||||||
|
CC = $(CC65_HOME)/bin/cc65
|
||||||
|
CL = $(CC65_HOME)/bin/cl65
|
||||||
|
LD = $(CC65_HOME)/bin/ld65
|
||||||
|
else
|
||||||
|
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
|
||||||
|
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
|
||||||
|
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
|
||||||
|
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
|
||||||
|
endif
|
||||||
|
|
||||||
|
EXELIST_kim1 = \
|
||||||
|
kimHello.bin \
|
||||||
|
kimSieve.bin
|
||||||
|
|
||||||
|
ifneq ($(EXELIST_$(SYS)),)
|
||||||
|
samples: $(EXELIST_$(SYS))
|
||||||
|
else
|
||||||
|
samples: notavailable
|
||||||
|
endif
|
||||||
|
|
||||||
|
# empty target used to skip systems that will not work with any program in this dir
|
||||||
|
notavailable:
|
||||||
|
ifeq ($(MAKELEVEL),0)
|
||||||
|
@echo "info: kim1 tests not available for" $(SYS)
|
||||||
|
else
|
||||||
|
# suppress the "nothing to be done for 'samples' message
|
||||||
|
@echo > $(NULLDEV)
|
||||||
|
endif
|
||||||
|
|
||||||
|
kimSieve.bin: kimSieve.c
|
||||||
|
$(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c
|
||||||
|
|
||||||
|
kimHello.bin: kimHello.c
|
||||||
|
$(CL) -t kim1 -O -o kimHello.bin kimHello.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$(DEL) kimSieve.bin 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimHello.bin 2>$(NULLDEV)
|
||||||
|
|
BIN
samples/kim1/kimHello
Normal file
BIN
samples/kim1/kimHello
Normal file
Binary file not shown.
24
samples/kim1/kimHello.c
Normal file
24
samples/kim1/kimHello.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Hello World for KIM-1
|
||||||
|
//
|
||||||
|
// Dave Plummer based on Sym-1 sample by Wayne Parham
|
||||||
|
//
|
||||||
|
// davepl@davepl.com
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <kim1.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
char str[100];
|
||||||
|
char c = 0x00;
|
||||||
|
|
||||||
|
printf ("\nHello World!\n\n");
|
||||||
|
printf ("Type a line and press ENTER, please.\n\n");
|
||||||
|
|
||||||
|
gets( str );
|
||||||
|
|
||||||
|
printf ("\n\nThanks: %s\n\n", str);
|
||||||
|
return 0;
|
||||||
|
}
|
125
samples/kim1/kimSieve.c
Normal file
125
samples/kim1/kimSieve.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short int ushort;
|
||||||
|
typedef unsigned long int ulong;
|
||||||
|
|
||||||
|
#define LIMIT 100000L
|
||||||
|
|
||||||
|
// BITARRAY
|
||||||
|
//
|
||||||
|
// My bit-access macros pre-divide by two on the presumption that you'll never
|
||||||
|
// try try access both odd and even bits!
|
||||||
|
|
||||||
|
#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7)))
|
||||||
|
#define SETBIT(array, bit) (array[bit >> 4] |= (1 << ((bit >> 1) & 7)))
|
||||||
|
#define CLRBIT(array, bit) (array[bit >> 4] &= ~(1 << ((bit >> 1) & 7)))
|
||||||
|
|
||||||
|
// RepeatChar
|
||||||
|
//
|
||||||
|
// Outputs a given character N times
|
||||||
|
|
||||||
|
void RepeatChar(char c, size_t count)
|
||||||
|
{
|
||||||
|
while (count--)
|
||||||
|
putc(c, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sqrti
|
||||||
|
//
|
||||||
|
// Binary search integer square root
|
||||||
|
|
||||||
|
ushort sqrti(ulong num)
|
||||||
|
{
|
||||||
|
long i;
|
||||||
|
ulong ret = 0;
|
||||||
|
|
||||||
|
for(i = 15; i >= 0; i--)
|
||||||
|
{
|
||||||
|
ulong temp = ret | (1L << (ulong)i);
|
||||||
|
if(temp * temp <= num)
|
||||||
|
{
|
||||||
|
ret = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// main()
|
||||||
|
//
|
||||||
|
// CC65 main function receives no parameters
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// CC65 cannot mix code and data so we have to declare all variables here in the function prolog
|
||||||
|
|
||||||
|
ulong iNumber;
|
||||||
|
ushort currentFactor;
|
||||||
|
ulong numBytesAllocated, rootOfLimit;
|
||||||
|
byte *array;
|
||||||
|
ulong countOfPrimes;
|
||||||
|
|
||||||
|
rootOfLimit = sqrti(LIMIT);
|
||||||
|
puts("\r\n\r\n");
|
||||||
|
RepeatChar('*', 70);
|
||||||
|
puts("\r\n** Prime Number Sieve - Dave Plummer 2022 **");
|
||||||
|
RepeatChar('*', 70);
|
||||||
|
|
||||||
|
printf("\r\n\r\nCalculating primes to %ld using a sqrt of %ld...\r\n", LIMIT, rootOfLimit);
|
||||||
|
|
||||||
|
// Calculate how much memory should be allocated
|
||||||
|
|
||||||
|
numBytesAllocated = (LIMIT + 15) / 16;
|
||||||
|
array = malloc(numBytesAllocated);
|
||||||
|
if (!array)
|
||||||
|
{
|
||||||
|
printf("Unable to allocate %ld bytes for %ld bits\r\n", numBytesAllocated, LIMIT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Allocated %ld bytes for %ld slots\r\n", numBytesAllocated, LIMIT);
|
||||||
|
|
||||||
|
// Preset all the bits to true
|
||||||
|
|
||||||
|
for (iNumber = 0; iNumber < numBytesAllocated; iNumber++)
|
||||||
|
array[iNumber] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for next unmarked factor
|
||||||
|
|
||||||
|
currentFactor = 3;
|
||||||
|
while (currentFactor <= rootOfLimit)
|
||||||
|
{
|
||||||
|
ulong num, n;
|
||||||
|
|
||||||
|
for (num = currentFactor; num <= LIMIT; num += 2)
|
||||||
|
{
|
||||||
|
if (GETBIT(array, num))
|
||||||
|
{
|
||||||
|
currentFactor = num;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = (ulong) currentFactor * currentFactor; n <= LIMIT; n += currentFactor * 2)
|
||||||
|
CLRBIT(array, n);
|
||||||
|
|
||||||
|
currentFactor += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display results
|
||||||
|
//
|
||||||
|
// printf("The following primes were found at or below %ld:\r\n2, ", LIMIT);
|
||||||
|
|
||||||
|
countOfPrimes = 1;
|
||||||
|
for (iNumber = 3; iNumber <= LIMIT; iNumber += 2)
|
||||||
|
if (GETBIT(array, iNumber))
|
||||||
|
countOfPrimes++;
|
||||||
|
|
||||||
|
printf("[END: Count = %ld]\r\n", countOfPrimes);
|
||||||
|
|
||||||
|
free(array);
|
||||||
|
return 1;
|
||||||
|
}
|
@ -342,6 +342,10 @@ static void SetSys (const char* Sys)
|
|||||||
NewSymbol ("__SYM1__", 1);
|
NewSymbol ("__SYM1__", 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TGT_KIM1:
|
||||||
|
NewSymbol ("__KIM1__", 1);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
AbEnd ("Invalid target name: '%s'", Sys);
|
AbEnd ("Invalid target name: '%s'", Sys);
|
||||||
|
|
||||||
|
@ -299,6 +299,10 @@ static void SetSys (const char* Sys)
|
|||||||
DefineNumericMacro ("__SYM1__", 1);
|
DefineNumericMacro ("__SYM1__", 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TGT_KIM1:
|
||||||
|
DefineNumericMacro ("__KIM1__", 1);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
AbEnd ("Unknown target system '%s'", Sys);
|
AbEnd ("Unknown target system '%s'", Sys);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,7 @@ static const TargetEntry TargetMap[] = {
|
|||||||
{ "geos", TGT_GEOS_CBM },
|
{ "geos", TGT_GEOS_CBM },
|
||||||
{ "geos-apple", TGT_GEOS_APPLE },
|
{ "geos-apple", TGT_GEOS_APPLE },
|
||||||
{ "geos-cbm", TGT_GEOS_CBM },
|
{ "geos-cbm", TGT_GEOS_CBM },
|
||||||
|
{ "kim1", TGT_KIM1 },
|
||||||
{ "lunix", TGT_LUNIX },
|
{ "lunix", TGT_LUNIX },
|
||||||
{ "lynx", TGT_LYNX },
|
{ "lynx", TGT_LYNX },
|
||||||
{ "module", TGT_MODULE },
|
{ "module", TGT_MODULE },
|
||||||
@ -219,6 +220,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
|
|||||||
{ "c65", CPU_4510, BINFMT_BINARY, CTPET },
|
{ "c65", CPU_4510, BINFMT_BINARY, CTPET },
|
||||||
{ "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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Target system */
|
/* Target system */
|
||||||
|
@ -87,6 +87,7 @@ typedef enum {
|
|||||||
TGT_C65,
|
TGT_C65,
|
||||||
TGT_CX16,
|
TGT_CX16,
|
||||||
TGT_SYM1,
|
TGT_SYM1,
|
||||||
|
TGT_KIM1,
|
||||||
TGT_COUNT /* Number of target systems */
|
TGT_COUNT /* Number of target systems */
|
||||||
} target_t;
|
} target_t;
|
||||||
|
|
||||||
|
@ -742,6 +742,7 @@ TARGETS := \
|
|||||||
creativision \
|
creativision \
|
||||||
cx16 \
|
cx16 \
|
||||||
gamate \
|
gamate \
|
||||||
|
kim1 \
|
||||||
lunix \
|
lunix \
|
||||||
lynx \
|
lynx \
|
||||||
nes \
|
nes \
|
||||||
|
Loading…
Reference in New Issue
Block a user