Merge branch 'master' into fptest

This commit is contained in:
mrdudz 2024-02-03 17:26:36 +01:00
commit 46be595d41
69 changed files with 3819 additions and 463 deletions

View File

@ -19,7 +19,7 @@ jobs:
- shell: bash
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Do some simple style checks
shell: bash
@ -44,7 +44,7 @@ jobs:
shell: bash
run: make -j2 doc
- name: Upload a documents snapshot.
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docs
path: ./html
@ -54,7 +54,7 @@ jobs:
make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=x86_64-w64-mingw32-
build_windows:
name: Build (Windows)
name: Build and Test (Windows)
runs-on: windows-latest
steps:
@ -62,10 +62,10 @@ jobs:
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: Build app (x86 debug)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug -property:Platform=Win32
@ -79,4 +79,14 @@ jobs:
- name: Build app (x64 release)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release -property:Platform=x64
- name: Build utils (MinGW)
shell: cmd
run: make -j2 util SHELL=cmd
- name: Build the platform libraries (make lib)
shell: cmd
run: make -j2 lib QUIET=1 SHELL=cmd
- name: Run the regression tests (make test)
shell: cmd
run: make test QUIET=1 SHELL=cmd

View File

@ -18,10 +18,10 @@ jobs:
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: Build app (debug)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug
@ -44,7 +44,7 @@ jobs:
- shell: bash
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Do some simple style checks
shell: bash
@ -86,18 +86,18 @@ jobs:
mv cc65.zip cc65-snapshot-win32.zip
- name: Upload a 32-bit Snapshot Zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cc65-snapshot-win32
path: cc65-snapshot-win32.zip
- name: Upload a 64-bit Snapshot Zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cc65-snapshot-win64
path: cc65-snapshot-win64.zip
- name: Get the online documents repo.
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: cc65/doc
# this token will expire, if it does, generate a new one as decribed in https://github.com/cc65/cc65/issues/2065
@ -120,7 +120,7 @@ jobs:
- name: Package offline documents.
run: 7z a cc65-snapshot-docs.zip ./html/*.*
- name: Upload a Documents Snapshot Zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cc65-snapshot-docs
path: cc65-snapshot-docs.zip

View File

@ -30,7 +30,7 @@ jobs:
run: mkdir ~/.cache-sha
- name: Cache SHA
uses: actions/cache@v3
uses: actions/cache@v4
id: check-sha
with:
path: ~/.cache-sha
@ -43,11 +43,11 @@ jobs:
- name: Checkout source
if: steps.check-sha.outputs.cache-hit != 'true'
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Add msbuild to PATH
if: steps.check-sha.outputs.cache-hit != 'true'
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: Build app (MSVC debug)
if: steps.check-sha.outputs.cache-hit != 'true'

View File

@ -9,7 +9,7 @@ For details look at the [Website](https://cc65.github.io).
Project founders:
* John R. Dunning: original implementation of the C compiler and runtime library, Atari hosted
* John R. Dunning: [original implementation](https://public.websites.umich.edu/~archive/atari/8bit/Languages/Cc65/) of the C compiler and runtime library, Atari hosted
* Ullrich von Bassewitz:
* move the code to modern systems
* rewrite most parts of the compiler

41
cfg/kim1-mtu60k.cfg Normal file
View File

@ -0,0 +1,41 @@
# kim1-mtu60k.cfg (4k)
#
# for expanded KIM-1 w/ K-1008 Graphics and 60K RAM
#
# ld65 --config kim1-mtu60k.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-mtuE000.cfg Normal file
View File

@ -0,0 +1,41 @@
# kim1-mtu60k.cfg (4k)
#
# for expanded KIM-1 w/ K-1008 Graphics and 60K RAM
#
# ld65 --config kim1-mtu60k.cfg -o <prog>.bin <prog>.o
FEATURES {
STARTADDRESS: default = $E000;
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 = $2000, size = $E000 - $2000 - __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;
}

View File

@ -62,7 +62,7 @@ Special locations:
</descrip><p>
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
However while running module constructors/destructors the Language Card is disabled.
However while running module constructors the Language Card is disabled.
Enabling the Language Card allows to use it as additional memory for cc65
generated code. However code is never automatically placed there. Rather code

View File

@ -63,7 +63,7 @@ Special locations:
</descrip><p>
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
However while running module constructors/destructors the Language Card is disabled.
However while running module constructors the Language Card is disabled.
Enabling the Language Card allows to use it as additional memory for cc65
generated code. However code is never automatically placed there. Rather code

View File

@ -86,6 +86,10 @@ extern FILE* stderr;
# define FILENAME_MAX (80+1)
#elif defined(__TELESTRAT__)
# define FILENAME_MAX (50+1)
#elif defined(__SIM6502__)
# define FILENAME_MAX (1024+1)
#elif defined(__SIM65C02__)
# define FILENAME_MAX (1024+1)
#else
# define FILENAME_MAX (16+1)
#endif

View File

@ -40,12 +40,15 @@ _exit: ldx #<exit
lda #>exit
jsr reset ; Setup RESET vector
; Switch in ROM, in case it wasn't already switched in by a RESET.
bit $C082
; Switch in LC bank 2 for R/O in case it was switched out by a RESET.
bit $C080
; Call the module destructors.
jsr donelib
; Switch in ROM.
bit $C082
; Restore the original RESET vector.
exit: ldx #$02
: lda rvsave,x

View File

@ -6,7 +6,7 @@
.export _statvfs
.import _dio_query_sectsize
.import mli_file_info, pushax, popax, popptr1
.import mli_file_info, pushax, popax, popptr1, pushptr1
.include "zeropage.inc"
.include "apple2.inc"
.include "errno.inc"
@ -45,9 +45,7 @@ _statvfs:
sty vol_sep ; Register '/' index
lda #$00
sta (ptr1),y ; Cut pathname at first slash
: lda ptr1
ldx ptr1+1
jsr pushax
: jsr pushptr1
jsr mli_file_info

View File

@ -19,7 +19,7 @@
.import findfreeiocb
.import incsp4
.import ldaxysp,addysp
.import ___oserror
.import ___oserror, returnFFFF
.ifdef UCASE_FILENAME
.import ucase_fn
.endif
@ -39,9 +39,7 @@ parmok: jsr findfreeiocb
lda #<EMFILE ; "too many open files"
seterr: jsr ___directerrno
jsr incsp4 ; clean up stack
lda #$FF
tax
rts ; return -1
jmp returnFFFF
; process the mode argument

View File

@ -40,7 +40,7 @@
.export _cbm_read
.importzp ptr1, ptr2, ptr3, tmp1
.import popax, popa
.import popax, popa, returnFFFF
.import ___oserror
@ -107,7 +107,4 @@ _cbm_read:
; CHKIN failed
@E1: sta ___oserror
lda #$FF
tax
rts ; return -1
jmp returnFFFF

View File

@ -32,7 +32,7 @@
.export _cbm_write
.importzp ptr1, ptr2, ptr3
.import popax, popa
.import popax, popa, returnFFFF
.import ___oserror
@ -88,7 +88,4 @@ _cbm_write:
; Error entry, error code is in A
@E2: sta ___oserror
lda #$FF
tax
rts ; return -1
jmp returnFFFF

View File

@ -13,6 +13,7 @@
.import _strlower, _strlen
.macpack generic
.macpack cpu
; ----------------------------------------------------------------------------
; We will store variables into the register bank in the zeropage. Define
@ -37,7 +38,11 @@ FCount = ptr2
GetFormatChar:
ldy #0
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (Format)
.else
lda (Format),y
.endif
IncFormatPtr:
inc Format
bne @L1
@ -110,7 +115,11 @@ GetIntArg:
lda (ArgList),y
tax
dey
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (ArgList)
.else
lda (ArgList),y
.endif
rts
; ----------------------------------------------------------------------------
@ -135,9 +144,9 @@ ReadInt:
pha ; Save digit value
lda ptr1
ldx ptr1+1
asl ptr1
asl a
rol ptr1+1 ; * 2
asl ptr1
asl a
rol ptr1+1 ; * 4, assume carry clear
adc ptr1
sta ptr1
@ -265,10 +274,16 @@ Save: lda regbank,y
; Initialize the output counter in the output descriptor to zero
lda #0
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (OutData)
ldy #$01
sta (OutData),y
.else
tay
sta (OutData),y
iny
sta (OutData),y
.endif
; Get the output function from the output descriptor and remember it
@ -338,7 +353,11 @@ MainLoop:
sta (sp),y
dey
lda FCount
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (sp)
.else
sta (sp),y
.endif
jsr CallOutFunc ; Call the output function
; We're back from out(), or we didn't call it. Check for end of string.
@ -551,10 +570,16 @@ CheckCount:
jsr GetIntArg
sta ptr1
stx ptr1+1 ; Get user supplied pointer
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (OutData) ; Low byte of OutData->ccount
sta (ptr1)
ldy #1
.else
ldy #0
lda (OutData),y ; Low byte of OutData->ccount
sta (ptr1),y
iny
.endif
lda (OutData),y ; High byte of OutData->ccount
sta (ptr1),y
jmp MainLoop ; Done

View File

@ -0,0 +1,24 @@
;
; Colin Leroy-Mira, 2024
;
; Helper to check for file opened, not eof, not ferror
; Expects file pointer in ptr1,
; Returns with Z flag set if everything is OK,
; Destroys A, X, Y,
; Sets file flags in A
;
.export checkferror
.importzp ptr1
.include "_file.inc"
checkferror:
ldy #_FILE::f_flags
lda (ptr1),y
tax
and #(_FOPEN|_FERROR|_FEOF); Check for file open, error/eof
tay
txa
cpy #_FOPEN
rts

View File

@ -7,7 +7,7 @@
.export _fclose
.import _close
.import _close, ___directerrno
.importzp ptr1
.include "errno.inc"
@ -31,10 +31,7 @@
; File is not open
lda #EINVAL
jsr ___seterrno
lda #$FF ; Return -1
tax
rts
jmp ___directerrno
; File is open. Reset the flags and close the file.
@ -47,4 +44,3 @@
jmp _close ; Will set errno and return an error flag
.endproc

View File

@ -1,58 +0,0 @@
/*
** fgetc.c
**
** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
**
*/
#include <stdio.h>
#include <unistd.h>
#include "_file.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
int __fastcall__ fgetc (register FILE* f)
{
unsigned char c;
/* Check if the file is open or if there is an error condition */
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
return EOF;
}
/* If we have a pushed back character, return it */
if (f->f_flags & _FPUSHBACK) {
f->f_flags &= ~_FPUSHBACK;
return f->f_pushback;
}
/* Read one byte */
switch (read (f->f_fd, &c, 1)) {
case -1:
/* Error */
f->f_flags |= _FERROR;
return EOF;
case 0:
/* EOF */
f->f_flags |= _FEOF;
return EOF;
default:
/* Char read */
return c;
}
}

94
libsrc/common/fgetc.s Normal file
View File

@ -0,0 +1,94 @@
;
; Colin Leroy-Mira, 2024
;
; int __fastcall__ fgetc (register FILE* f)
;
.export _fgetc
.import _read, checkferror
.import pusha0, pushax, popptr1, incsp2, returnFFFF
.importzp ptr1
.include "stdio.inc"
.include "_file.inc"
.macpack cpu
_fgetc:
sta ptr1
stx ptr1+1
jsr pushax ; Backup our ptr
jsr checkferror
bne ret_eof
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FPUSHBACK ; Check for pushed back char
beq do_read
.else
tax
and #_FPUSHBACK ; Check for pushed back char
beq do_read
txa
.endif
and #<(~_FPUSHBACK) ; Reset flag
sta (ptr1),y
.assert _FILE::f_pushback = _FILE::f_flags+1, error
iny
jsr incsp2 ; Drop our ptr copy
lda (ptr1),y ; Return pushed back char
ldx #$00
rts
do_read:
; Push _read parameters
ldy #_FILE::f_fd
lda (ptr1),y
jsr pusha0
lda #<c
ldx #>c
jsr pushax
lda #$01
ldx #$00
; Read
jsr _read
; Check for errors
cmp #$00
beq set_feof
cmp #<(-1)
beq set_ferror
jsr incsp2
; Return char
ldx #$00
lda c
rts
ret_eof:
jsr incsp2
jmp returnFFFF
set_ferror:
lda #_FERROR
bne set_err
set_feof:
lda #_FEOF
set_err:
pha
jsr popptr1
pla
ldy #_FILE::f_flags
ora (ptr1),y
sta (ptr1),y
jmp returnFFFF
.bss
c: .res 1

View File

@ -1,68 +0,0 @@
/*
** Ullrich von Bassewitz, 11.08.1998
**
** char* fgets (char* s, int size, FILE* f);
*/
#include <stdio.h>
#include <errno.h>
#include "_file.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* __fastcall__ fgets (char* s, unsigned size, register FILE* f)
{
register char* p = s;
unsigned i;
int c;
if (size == 0) {
/* Invalid size */
return (char*) _seterrno (EINVAL);
}
/* Read input */
i = 0;
while (--size) {
/* Get next character */
if ((c = fgetc (f)) == EOF) {
/* Error or EOF */
if ((f->f_flags & _FERROR) != 0 || i == 0) {
/* ERROR or EOF on first char */
*p = '\0';
return 0;
} else {
/* EOF with data already read */
break;
}
}
/* One char more */
*p = c;
++p;
++i;
/* Stop at end of line */
if ((char)c == '\n') {
break;
}
}
/* Terminate the string */
*p = '\0';
/* Done */
return s;
}

117
libsrc/common/fgets.s Normal file
View File

@ -0,0 +1,117 @@
;
; Colin Leroy-Mira, 2024
;
; char* __fastcall__ fgets (char* s, unsigned size, register FILE* f)
;
.export _fgets
.import _fgetc, popptr1, pushptr1, popax, pushax, return0, ___errno
.importzp ptr1, ptr4
.include "errno.inc"
.include "stdio.inc"
.include "_file.inc"
.macpack cpu
terminate_ptr:
lda #$00
tax
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (ptr4)
.else
tay
sta (ptr4),y
.endif
rts
_fgets:
sta ptr1
stx ptr1+1
jsr popax
sta size
stx size+1
jsr popax
sta ptr4
stx ptr4+1
sta buf
stx buf+1
.if (.cpu .bitand ::CPU_ISET_65SC02)
stz didread
.else
lda #$00 ; We have read nothing yet
sta didread
.endif
; Check size
lda size
ora size+1
bne read_loop
lda #EINVAL
sta ___errno
jmp return0
read_loop:
lda size ; Dec size
bne :+
dec size+1
: dec size
bne :+ ; Check bound
ldx size+1
beq done
: jsr pushptr1 ; Push ptr1 for backup and load it to AX for fgetc
jsr _fgetc ; Read a char
pha
jsr popptr1 ; Get ptr1 back
pla
cpx #<EOF
beq got_eof
ldy #$01
sty didread ; We read at least one char
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (ptr4)
.else
dey
sta (ptr4),y
.endif
inc ptr4
bne :+
inc ptr4+1
: cmp #$0A ; Stop at \n
beq done
bne read_loop
got_eof:
lda didread
beq stopped_at_first_char
ldy #_FILE::f_flags
lda (ptr1),y
and #_FERROR
bne stopped_at_first_char
done:
jsr terminate_ptr
ldx #>buf
lda #<buf
rts
stopped_at_first_char:
jmp terminate_ptr
.bss
c: .res 1
buf: .res 2
size: .res 2
didread:.res 1

View File

@ -5,7 +5,7 @@
;
.export _clearerr, _feof, _ferror, _fileno, _fflush
.import return0
.import return0, ___directerrno
.importzp ptr1
.include "_file.inc"
@ -78,10 +78,7 @@ err: rts
; If the file is not valid, fileno must set errno and return -1
error: lda #<EBADF
jsr ___seterrno
lda #$FF
tax
rts
jmp ___directerrno
.endproc
;
@ -89,5 +86,3 @@ error: lda #<EBADF
;
_fflush = return0

View File

@ -1,41 +0,0 @@
/*
** fputc.c
**
** Ullrich von Bassewitz, 02.06.1998
*/
#include <stdio.h>
#include <unistd.h>
#include "_file.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
int __fastcall__ fputc (int c, register FILE* f)
{
/* Check if the file is open or if there is an error condition */
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
goto ReturnEOF;
}
/* Write the byte */
if (write (f->f_fd, &c, 1) != 1) {
/* Error */
f->f_flags |= _FERROR;
ReturnEOF:
return EOF;
}
/* Return the byte written */
return c & 0xFF;
}

66
libsrc/common/fputc.s Normal file
View File

@ -0,0 +1,66 @@
;
; Colin Leroy-Mira, 2024
;
; int __fastcall__ fputc (int c, FILE* f);
;
.export _fputc
.importzp ptr1
.import _write, checkferror
.import pushax, pusha0, popax, incsp2
.import pushptr1, popptr1, returnFFFF
.include "stdio.inc"
.include "_file.inc"
_fputc:
sta ptr1
stx ptr1+1
jsr popax ; Get char, as we'll have
sta c ; to return it anyway
stx c+1
jsr checkferror
bne ret_eof
jsr pushptr1 ; Backup fp pointer
; Push _write parameters
ldy #_FILE::f_fd
lda (ptr1),y
jsr pusha0
lda #<c
ldx #>c
jsr pushax
lda #$01
ldx #$00
; Write
jsr _write
; Check for errors
cmp #$01
bne set_ferror
; Return char
lda c
ldx #$00
jmp incsp2 ; Drop fp pointer copy
ret_eof:
jmp returnFFFF
set_ferror:
jsr popptr1
lda #_FERROR
ldy #_FILE::f_flags
ora (ptr1),y
sta (ptr1),y
jmp returnFFFF
.bss
c: .res 2

View File

@ -1,28 +0,0 @@
/*
** int fputs (const char* s, FILE* f);
**
** Ullrich von Bassewitz, 11.08.1998
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "_file.h"
int __fastcall__ fputs (const char* s, register FILE* f)
{
/* Check if the file is open or if there is an error condition */
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
return EOF;
}
/* Write the string */
return write (f->f_fd, s, strlen (s));
}

36
libsrc/common/fputs.s Normal file
View File

@ -0,0 +1,36 @@
;
; Colin Leroy-Mira, 2024
;
; int __fastcall__ fputs (const char* s, register FILE* f)
;
.export _fputs
.importzp ptr1, ptr2
.import _write, _strlen, checkferror
.import swapstk, pushax, returnFFFF
.include "stdio.inc"
.include "_file.inc"
_fputs:
sta ptr1
stx ptr1+1
jsr checkferror
bne ret_eof
; Push _write parameters
ldy #_FILE::f_fd
lda (ptr1),y
ldx #$00
jsr swapstk ; Push fd, get s
jsr pushax ; Push s
jsr _strlen ; Get length
; Write
jmp _write
ret_eof:
jmp returnFFFF

View File

@ -20,6 +20,7 @@
.include "_file.inc"
.macpack generic
.macpack cpu
; ------------------------------------------------------------------------
; Code
@ -47,13 +48,21 @@
ldy #_FILE::f_flags
lda (file),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FOPEN ; Is the file open?
.else
and #_FOPEN ; Is the file open?
.endif
beq @L1 ; Branch if no
; Check if the stream is in an error state
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FERROR
.else
lda (file),y ; get file->f_flags again
and #_FERROR
.endif
beq @L2
; File not open or in error state
@ -65,11 +74,19 @@
; Remember if we have a pushed back character and reset the flag.
@L2: tax ; X = 0
@L2: .if (.cpu .bitand ::CPU_ISET_65SC02)
ldx #$00
bit #_FPUSHBACK
.else
tax ; X = 0
lda (file),y
and #_FPUSHBACK
.endif
beq @L3
.if (.not .cpu .bitand ::CPU_ISET_65SC02)
lda (file),y
.endif
and #<~_FPUSHBACK
sta (file),y ; file->f_flags &= ~_FPUSHBACK;
inx ; X = 1
@ -118,12 +135,20 @@
; Copy the buffer pointer into ptr1, and increment the pointer value passed
; to read() by one, so read() starts to store data at buf+1.
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (sp)
sta ptr1
add #1
sta (sp)
ldy #1
.else
ldy #0
lda (sp),y
sta ptr1
add #1
sta (sp),y
iny
.endif
lda (sp),y
sta ptr1+1
adc #0
@ -134,8 +159,12 @@
ldy #_FILE::f_pushback
lda (file),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (ptr1) ; *buf = file->f_pushback;
.else
ldy #0
sta (ptr1),y ; *buf = file->f_pushback;
.endif
; Restore the low byte of count and decrement count by one. This may result
; in count being zero, so check for that.
@ -210,4 +239,3 @@
.bss
save: .res 2
pb: .res 1

View File

@ -8,7 +8,7 @@
.export _fwrite
.import _write
.import pushax, incsp6, addysp, ldaxysp, pushwysp, return0
.import pushax, pusha0, incsp6, addysp, ldaxysp, pushwysp, return0
.import tosumulax, tosudivax
.importzp ptr1
@ -16,6 +16,7 @@
.include "errno.inc"
.include "_file.inc"
.macpack cpu
; ------------------------------------------------------------------------
; Code
@ -33,7 +34,11 @@
ldy #_FILE::f_flags
lda (ptr1),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FOPEN
.else
and #_FOPEN ; Is the file open?
.endif
bne @L2 ; Branch if yes
; File not open
@ -45,7 +50,9 @@
; Check if the stream is in an error state
@L2: lda (ptr1),y ; get file->f_flags again
@L2: .if (.not .cpu .bitand ::CPU_ISET_65SC02)
lda (ptr1),y ; get file->f_flags again
.endif
and #_FERROR
bne @L1
@ -53,8 +60,7 @@
ldy #_FILE::f_fd
lda (ptr1),y
ldx #$00
jsr pushax ; file->f_fd
jsr pusha0 ; file->f_fd
ldy #9
jsr pushwysp ; buf
@ -123,4 +129,3 @@
.bss
file: .res 2

View File

@ -1,63 +0,0 @@
/*
** gets.c
**
** Ullrich von Bassewitz, 11.08.1998
*/
#include <stdio.h>
#include "_file.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* __fastcall__ gets (char* s)
{
register char* p = s;
int c;
unsigned i = 0;
while (1) {
/* Get next character */
if ((c = fgetc (stdin)) == EOF) {
/* Error or EOF */
*p = '\0';
if (stdin->f_flags & _FERROR) {
/* ERROR */
return 0;
} else {
/* EOF */
if (i) {
return s;
} else {
return 0;
}
}
}
/* One char more. Newline ends the input */
if ((char) c == '\n') {
*p = '\0';
break;
} else {
*p = c;
++p;
++i;
}
}
/* Done */
return s;
}

47
libsrc/common/gets.s Normal file
View File

@ -0,0 +1,47 @@
;
; Colin Leroy-Mira, 2024
;
; char* __fastcall__ gets (char* s)
;
.export _gets
.import _fgets, _stdin, popax, pushax
.importzp ptr4
_gets:
; Push buffer
sta ptr4
stx ptr4+1
jsr pushax
; Push size (there's no limit!)
lda #$FF
tax
jsr pushax
lda _stdin
ldx _stdin+1
jsr _fgets
; Check return value
bne :+
cpx #$00
bne :+
rts
: ; At least one byte written.
jsr pushax ; Store returned pointer
; Remove \n if there is one.
lda ptr4 ; _fgets returns with ptr4 at
bne :+ ; end of buffer
dec ptr4+1
: dec ptr4
lda (ptr4),y ; _fgets returns with Y=0
cmp #$0A
bne :+
tya
sta (ptr4),y ; Set terminator over \n
: jmp popax

View File

@ -131,6 +131,7 @@ _malloc:
sta ptr1
bcc @L1
inc ptr1+1
beq OutOfHeapSpace ; if high byte's 0, we overflowed!
@L1: ldx ptr1+1
bne @L2
cmp #HEAP_MIN_BLOCKSIZE+1
@ -336,4 +337,3 @@ RetUserPtr:
bcc @L9
inx
@L9: rts

View File

@ -50,7 +50,6 @@
*/
int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
/* Allocate a block of memory with the given "size", which is aligned to a
** memory address that is a multiple of "alignment". "alignment" MUST NOT be
@ -64,20 +63,27 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
size_t rawsize;
size_t uppersize;
size_t lowersize;
char err;
register struct usedblock* b; /* points to raw Block */
register struct usedblock* u; /* points to User block */
register struct usedblock* p; /* Points to upper block */
/* Handle requests for zero-sized blocks */
if (size == 0) {
err_einval:
err = EINVAL;
err_out:
*memptr = NULL;
return EINVAL;
return err;
}
/* Test alignment: is it a power of two? There must be only one bit set. */
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
*memptr = NULL;
return EINVAL;
/* Test alignment: is it a power of two? There must be one and only one bit set. */
if (alignment == 0) {
goto err_einval;
}
if (alignment & (alignment - 1)) {
goto err_einval;
}
/* Augment the block size up to the alignment, and allocate memory.
@ -90,8 +96,8 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
/* Handle out-of-memory */
if (b == NULL) {
*memptr = NULL;
return ENOMEM;
err = ENOMEM;
goto err_out;
}
/* Create (and return) a new pointer that points to the user-visible

View File

@ -10,7 +10,7 @@
.import _malloc, _free
.import searchenv, copyenvptr
.import __environ, __envcount, __envsize
.import return0
.import return0, ___directerrno
.import ptr1:zp, ptr2:zp, ptr3:zp, tmp1:zp
.include "errno.inc"
@ -169,10 +169,7 @@ addentry:
; Error entries
nomem: lda #ENOMEM
error: jsr ___seterrno
lda #$FF ; Return -1
tax
rts
error: jmp ___directerrno
.endproc
@ -184,5 +181,3 @@ error: jsr ___seterrno
name: .addr 0 ; Pointer to name
newsize: .byte 0 ; New environment size

View File

@ -1,112 +0,0 @@
/*****************************************************************************/
/* */
/* realloc.c */
/* */
/* Change the size of an allocated memory block */
/* */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* 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. */
/* */
/*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <_heap.h>
void* __fastcall__ realloc (void* block, register size_t size)
{
register struct usedblock* b;
struct usedblock* newblock;
unsigned oldsize;
unsigned newhptr;
/* Check the block parameter */
if (!block) {
/* Block is NULL, same as malloc */
return malloc (size);
}
/* Check the size parameter */
if (size == 0) {
/* Block is not NULL, but size is: free the block */
free (block);
return 0;
}
/* Make the internal used size from the given size */
size += HEAP_ADMIN_SPACE;
if (size < sizeof (struct freeblock)) {
size = sizeof (struct freeblock);
}
/* The word below the user block contains a pointer to the start of the
** raw memory block. The first word of this raw memory block is the full
** size of the block. Get a pointer to the real block, get the old block
** size.
*/
b = (((struct usedblock*) block) - 1)->start;
oldsize = b->size;
/* Is the block at the current heap top? */
if (((unsigned) b) + oldsize == ((unsigned) __heapptr)) {
/* Check if we've enough memory at the heap top */
newhptr = ((unsigned) __heapptr) - oldsize + size;
if (newhptr <= ((unsigned) __heapend)) {
/* Ok, there's space enough */
__heapptr = (unsigned*) newhptr;
b->size = size;
b->start = b;
return block;
}
}
/* The given block was not located on top of the heap, or there's no
** room left. Try to allocate a new block and copy the data.
*/
if (newblock = malloc (size)) {
/* Adjust the old size to the user visible portion */
oldsize -= HEAP_ADMIN_SPACE;
/* If the new block is larger than the old one, copy the old
** data only
*/
if (size > oldsize) {
size = oldsize;
}
/* Copy the block data */
memcpy (newblock, block, size);
free (block);
}
return newblock;
}

213
libsrc/common/realloc.s Normal file
View File

@ -0,0 +1,213 @@
;
; Colin Leroy-Mira, 2024
;
; void* __fastcall__ realloc (void* block, register size_t size)
;
.importzp ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, tmp4, sp
.import _malloc, _memcpy, _free
.import pushax, popptr1, return0
.import incsp2, decsp2
.export _realloc
.include "_heap.inc"
.macpack generic
;----------------------------------------------------------------------------
; Aliases for clarity
block = ptr1
size = ptr2
ublock = ptr3
oldsize = ptr4
newblock = tmp1 ; (and tmp2)
orgblock = tmp3 ; (and tmp4)
;----------------------------------------------------------------------------
; Code
_realloc:
sta size ; Store size
stx size+1
jsr popptr1 ; Pop block
lda block+1 ; Is block null?
tax
ora block
bne :+
lda size ; Block is null, just malloc
ldx size+1
jmp _malloc
: lda size ; Is size 0?
ora size+1
bne :+
lda block ; It is: free block (high byte already in X)
jsr _free
jmp return0
: clc ; Add internal used size
lda size
adc #HEAP_ADMIN_SPACE
sta size
bcc :+
inc size+1
bne :+
lda #$00 ; Size high byte now 0: We overflowed!
tax
rts
: ldx size+1 ; Should we round size up?
bne :+
cmp #.sizeof (freeblock)
bcs :+
lda #.sizeof (freeblock)
sta size ; (we presuppose that sizeof (freeblock) is < 256)
: lda block ; Get pointer to raw memory block
sta orgblock ; Store original pointer
sec
sbc #.sizeof(usedblock)
sta ublock
lda block+1
sta orgblock+1 ; Finish storing original pointer
sbc #0
sta ublock+1 ; We have our usedblock struct
; Get block start
ldy #usedblock::start+1
lda (ublock),y
tax ; Backup ublock high
dey
lda (ublock),y
sta ublock ; Store ublock
stx ublock+1
; Remember oldsize
ldy #usedblock::size+1
lda (ublock),y
sta oldsize+1
dey
lda (ublock),y
sta oldsize
clc ; Is the block at heap top?
adc ublock
tay
lda ublock+1
adc oldsize+1
cmp ___heapptr+1
bne must_malloc_new
cpy ___heapptr
bne must_malloc_new
tya ; Put ___heapptr back in A
sec ; Check if we have enough memory at heap top
sbc oldsize ; Substract oldsize
sta newblock
lda ___heapptr+1
sbc oldsize+1
sta newblock+1
clc
lda newblock ; And add size
adc size
sta newblock
lda newblock+1
adc size+1
sta newblock+1
bcs must_malloc_new ; If we have a carry there we overflowed
cmp ___heapend+1
bne :+
lda newblock
cmp ___heapend
: bcc :+
bne must_malloc_new
: lda newblock ; There is enough space
sta ___heapptr ; Update heapptr
lda newblock+1
sta ___heapptr+1
ldy #usedblock::start+1
lda ublock+1
sta (ublock),y ; Update block start
dey
lda ublock
sta (ublock),y
dey
.assert usedblock::size = usedblock::start-2, error
lda size+1
sta (ublock),y ; Update block size
dey
lda size
sta (ublock),y
lda orgblock ; Return original block
ldx orgblock+1
rts
must_malloc_new: ; The block is not at heap top, or too big
lda size+1
pha ; Backup new size (at this point the only ptr
tax ; we'll need after malloc). tmp* are safe
lda size ; from malloc, memcpy and free.
pha
jsr _malloc
cmp #$00 ; Did malloc succeed?
bne :+
cpx #$00
bne :+
pla ; Pop size backup and return NULL
pla
txa ; X already 0
rts ; No
: sta newblock ; Yes, store newblock
stx newblock+1
jsr pushax ; Push newblock for memcpy
lda orgblock ; Push orgblock for memcpy
ldx orgblock+1
jsr pushax
sec ; Remove admin space from oldsize
lda oldsize
sbc #<HEAP_ADMIN_SPACE
sta oldsize
lda oldsize+1
sbc #>HEAP_ADMIN_SPACE
sta oldsize+1
pla ; Restore new size to AX
tay
pla
tax
tya
cmp oldsize ; Find the smallest size
bcc :+
cpx oldsize+1
bcc :+
lda oldsize
ldx oldsize+1
: jsr _memcpy ; And copy data
lda orgblock ; Free old block
ldx orgblock+1
jsr _free
lda newblock ; Return new block
ldx newblock+1
rts

View File

@ -62,10 +62,6 @@
; File is not open or the character is invalid
error: lda #EINVAL
jsr ___seterrno
lda #$FF ; Return -1
tax
rts
jmp ___directerrno
.endproc

View File

@ -6,7 +6,7 @@
; void BitOtherClip (void *proc1, void* proc2, char skipl, char skipr, int skipy,
; struct iconpic *myGfx);
; both proc1, proc2 should be: char __fastcall something (void);
; both proc1, proc2 should be: char foo (void);
; proc1 is called before reading a byte (.A returns next data)
; proc2 is called before reading each byte which is not pattern (code >219)

21
libsrc/runtime/aslax7.s Normal file
View File

@ -0,0 +1,21 @@
;
; Miloslaw Smyk, 2024
;
; CC65 runtime: Scale the primary register by 128, unsigned
;
.export shlax7, aslax7
aslax7:
shlax7: ; XXXXXXXL AAAAAAAl
tay
txa
lsr ; XXXXXXXL -> 0XXXXXXX, L->C
tya
ror ; AAAAAAAl -> LAAAAAAA, l->C
tax
lda #$00 ; LAAAAAAA 00000000
ror ; LAAAAAAA l0000000
rts
; 10 bytes, 16 cycles + rts

18
libsrc/runtime/asrax7.s Normal file
View File

@ -0,0 +1,18 @@
;
; Miloslaw Smyk, 2024
;
; CC65 runtime: Scale the primary register by 128, signed
;
.export asrax7
asrax7: ; HXXXXXXL hAAAAAAl
asl ; AAAAAAA0, h->C
txa
rol ; XXXXXXLh, H->C
ldx #$00 ; 00000000 XXXXXXLh
bcc :+
dex ; 11111111 XXXXXXLh if C
: rts
; 12 cycles max, 9 bytes

14
libsrc/runtime/pushptr1.s Normal file
View File

@ -0,0 +1,14 @@
;
; Colin Leroy-Mira, 2024
;
; CC65 runtime: Push ptr1 to stack.
; A/X destroyed (set to ptr1)
.export pushptr1
.import pushax
.importzp ptr1
pushptr1:
lda ptr1
ldx ptr1+1
jmp pushax

View File

@ -0,0 +1,15 @@
;
; Ullrich von Bassewitz, 25.10.2000
;
; CC65 runtime: Return -1 in a/x
;
.export returnFFFF
.proc returnFFFF
lda #$FF
tax
rts
.endproc

18
libsrc/runtime/shrax7.s Normal file
View File

@ -0,0 +1,18 @@
;
; Miloslaw Smyk, 2024
;
; CC65 runtime: Scale the primary register by 128, unsigned
;
.export shrax7
shrax7: ; HXXXXXXL hAAAAAAl
asl ; AAAAAAA0, h->C
txa
rol ; XXXXXXLh, H->C
ldx #$00 ; 00000000 XXXXXXLh
bcc :+
inx ; 0000000H XXXXXXLh if C
: rts
; 12 cycles max, 9 bytes

View File

@ -8,10 +8,15 @@
;
.export exit, args, _open, _close, _read, _write
.export __sysremove, ___osmaperrno
__sysremove := $FFF2
___osmaperrno := $FFF3
_open := $FFF4
_close := $FFF5
_read := $FFF6
_write := $FFF7
args := $FFF8
exit := $FFF9
; $FFFA-FFFF are hardware vectors, extend before not after!

View File

@ -31,9 +31,12 @@ else
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_kim1 = \
kimHello.bin \
kimSieve.bin
EXELIST_kim1 = \
kimHello.bin \
kimSieve.bin \
kimLife.bin \
kimTest.bin \
kimGFX.bin
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
@ -50,13 +53,65 @@ else
@echo > $(NULLDEV)
endif
subs.o: subs.asm
$(AS) subs.asm -o subs.o
ramfont.o: ramfont.asm
$(AS) ramfont.asm -o ramfont.o
kimLife.bin: kimLife.c
$(CL) -t kim1 -C kim1-60k.cfg -Oi -o kimLife.bin kimLife.c
kimTest.bin: kimTest.c
$(CL) -t kim1 -C kim1-60k.cfg -Oi -o kimTest.bin kimTest.c
kimGFX.bin: kimGFX.c subs.o ramfont.o
$(CL) -t kim1 --listing kimGFX.lst -C kim1-mtuE000.cfg -o kimGFX.bin kimGFX.c subs.o ramfont.o -Ln kimgfx.lbl
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
# To build an intel-format file for the CORSHAM SD card reader
kimLife.hex: kimLife.bin
srec_cat kimLife.bin -binary -offset 0x2000 -o kimLife.hex -Intel -address-length=2
kimTest.hex: kimTest.bin
srec_cat kimTest.bin -binary -offset 0x2000 -o kimTest.hex -Intel -address-length=2
kimGFX.hex: kimGFX.bin ramfont.o
srec_cat kimGFX.bin -binary -offset 0x2000 -o kimGFX.hex -Intel -address-length=2
# To build a paper tape file for uploading to the KIM-1 via terminal
kimLife.ptp: kimLife.bin
srec_cat kimLife.bin -binary -offset 0x2000 -o kimLife.ptp -MOS_Technologies
kimGFX.ptp: kimGFX.bin
srec_cat kimGFX.bin -binary -offset 0x2000 -o kimGFX.ptp -MOS_Technologies
kimTest.ptp: kimTest.bin
srec_cat kimTest.bin -binary -offset 0x2000 -o kimTest.ptp -MOS_Technologies
clean:
@$(DEL) kimSieve.bin 2>$(NULLDEV)
@$(DEL) kimHello.bin 2>$(NULLDEV)
@$(DEL) kimLife.bin 2>$(NULLDEV)
@$(DEL) kimLife.ptp 2>$(NULLDEV)
@$(DEL) kimLife.hex 2>$(NULLDEV)
@$(DEL) kimTest.bin 2>$(NULLDEV)
@$(DEL) kimTest.ptp 2>$(NULLDEV)
@$(DEL) kimTest.hex 2>$(NULLDEV)
@$(DEL) kimGFX.bin 2>$(NULLDEV)
@$(DEL) kimGFX.ptp 2>$(NULLDEV)
@$(DEL) kimGFX.hex 2>$(NULLDEV)
@$(DEL) kimgfx.lbl 2>$(NULLDEV)
@$(DEL) kimGFX.lst 2>$(NULLDEV)
@$(DEL) subs.o 2>$(NULLDEV)
@$(DEL) ramfont.o 2>$(NULLDEV)

0
samples/kim1/font.rom Normal file
View File

290
samples/kim1/kimGFX.c Normal file
View File

@ -0,0 +1,290 @@
// --------------------------------------------------------------------------
// Simple Graphics Test for KIM-1 with MTU Visible Memory Board
//
// Assumes the MTU Visible Memory Board mapped at 0xA000 for 8K of video RAM
//
// davepl@davepl.com
// --------------------------------------------------------------------------
#include <stdio.h> // For printf
#include <stdlib.h> // For rand, srand
#include <string.h> // For memcpy
#include <ctype.h>
typedef unsigned char byte;
extern void ClearScreen(void); // In subs.asm
extern void ScrollScreen(void);
extern void DrawCircle(void);
extern void SetPixel(void);
extern void ClearPixel(void);
extern void DrawChar(void);
extern void Demo(void);
extern void __fastcall__ Delay(byte loops);
extern void __fastcall__ DrawLine(byte bSet);
extern byte __fastcall__ AscToPet(byte in);
extern byte __fastcall__ PetToAsc(byte in);
extern byte __fastcall__ ReverseBits(byte in);
extern void __fastcall__ CharOut(byte asci_char);
extern byte __fastcall__ getch();
extern unsigned char font8x8_basic[256][8];
extern int x1cord;
extern int y1cord;
extern int x2cord;
extern int y2cord;
extern int cursorX;
extern int cursorY;
// If in zeropage:
//
// #pragma zpsym("x1cord")
// #pragma zpsym("x2cord")
// #pragma zpsym("y1cord")
// #pragma zpsym("y2cord")
// Screen memory is placed at A000-BFFF, 320x200 pixels, mapped right to left within each horizontal byte
byte * screen = (byte *) 0xA000;
// Cursor position
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200
#define CHARWIDTH 8
#define CHARHEIGHT 8
#define BYTESPERROW (SCREEN_WIDTH / 8)
#define BYTESPERCHARROW (BYTESPERROW * 8)
#define CHARSPERROW (SCREEN_WIDTH / CHARWIDTH)
#define ROWSPERCOLUMN (SCREEN_HEIGHT / CHARHEIGHT)
// SETPIXEL
//
// 0 <= x < 320
// 0 <= y < 200
//
// Draws a pixel on the screen in white or black at pixel pos x, y
void SETPIXEL(int x, int y, byte b)
{
x1cord = x;
y1cord = y;
if (b)
SetPixel();
else
ClearPixel();
}
// DRAWPIXEL
//
// 0 <= x < 320
// 0 <= y < 200
//
// Turns on a screen pixel at pixel pos x,y
void DRAWPIXEL(int x, int y)
{
x1cord = x;
y1cord = y;
SetPixel();
}
int c;
void DrawText(char * psz)
{
while (*psz)
{
while (cursorX >= CHARSPERROW)
{
cursorX -= CHARSPERROW;
cursorY += 1;
}
// If we've gone off the bottom of the screen, we scroll the screen and back up to the last line again
if (cursorY >= ROWSPERCOLUMN)
{
cursorY = ROWSPERCOLUMN - 1;
ScrollScreen();
}
// If we output a newline we advanced the cursor down one line and reset it to the left
if (*psz == 0x0A)
{
cursorX = 0;
cursorY++;
psz++;
}
else
{
c = *psz;
__asm__ ("ldx %v", cursorX);
__asm__ ("ldy %v", cursorY);
__asm__ ("lda %v", c);
DrawChar();
cursorX++;
psz++;
}
}
}
void DrawTextAt(int x, int y, char * psz)
{
cursorX = x;
cursorY = y;
DrawText(psz);
}
// Something like Bresenham's algorithm for drawing a line
/*
void DrawLine(int x0, int y0, int x1, int y1, byte val)
{
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2, e2;
while (1)
{
SETPIXEL(x0, y0, val);
if (x0 == x1 && y0 == y1)
break;
e2 = err;
if (e2 > -dx)
{
err -= dy;
x0 += sx;
}
if (e2 < dy)
{
err += dx;
y0 += sy;
}
}
}
*/
// DrawCircle
//
// Draw a circle without sin, cos, or floating point!
void DrawCircleC(int x0, int y0, int radius, byte)
{
x1cord = x0;
y1cord = y0;
y2cord = radius;
DrawCircle();
}
void DrawLineC(int x1, int y1, int x2, int y2, byte bSet)
{
x1cord = x1;
y1cord = y1;
x2cord = x2;
y2cord = y2;
DrawLine(bSet);
}
// MirrorFont
//
// RAM font is backwards left-right relative to the way memory is laid out on the KIM-1, so we swap all the
// bytes in place by reversing the order of the bits in every byte
void MirrorFont()
{
int c;
byte * pb = (byte *) font8x8_basic;
for (c = 0; c < 128 * 8; c++)
pb[c] = ReverseBits(pb[c]);
}
// DrawScreenMoire
//
// Draws a moire pattern on the screen without clearing it first
void DrawMoire(int left, int top, int right, int bottom, byte pixel)
{
int x, y;
for (x = left; x < right; x += 6)
DrawLineC(x, top, right - x + left, bottom, pixel);
for (y = top; y < bottom; y += 6)
DrawLineC(left, y, right, bottom - y + top, pixel);
}
void DrawScreenMoire(int left, int top, int right, int bottom)
{
int x, y;
DrawLineC(left, top, right, top, 1);
DrawLineC(left, bottom, right, bottom, 1);
DrawLineC(left, top, left, bottom, 1);
DrawLineC(right, top, right, bottom, 1);
left++; top++; right--; bottom--;
for (x = left; x < right; x += 6)
DrawLineC(x, top, right - x + left, bottom, 1);
for (y = top; y < bottom; y += 6)
DrawLineC(left, y, right, bottom - y + top, 1);
for (x = left; x < right; x += 6)
DrawLineC(x, top, right - x + left, bottom, 0);
for (y = top; y < bottom; y += 6)
DrawLineC(left, y, right, bottom - y + top, 0);
}
int main (void)
{
int i;
int c = 0;
Demo();
CharOut('R');
CharOut('E');
CharOut('A');
CharOut('D');
CharOut('Y');
CharOut('.');
CharOut('\n');
while(1)
{
c = toupper(getch());
if (c != EOF)
CharOut(c);
}
// Clear the screen memory
while(1)
{
Demo();
DrawScreenMoire(0,30, 319, 199);
Delay(10);
Demo();
for (i = 5; i < 80; i+=5)
{
DrawCircleC(SCREEN_WIDTH/2, SCREEN_HEIGHT/2 + 20, i, 1);
DrawCircleC(SCREEN_WIDTH/4, SCREEN_HEIGHT/2 + 20, i, 1);
DrawCircleC(SCREEN_WIDTH*3/4, SCREEN_HEIGHT/2 + 20, i, 1);
}
Delay(10);
}
printf("Done, exiting...\r\n");
return 0;
}

144
samples/kim1/kimLife.c Normal file
View File

@ -0,0 +1,144 @@
// --------------------------------------------------------------------------
// Conway's Game of Life for KIM-1
//
// Assumes the MTU Visible Memory Board mapped at 0x8000 for 8K of video RAM
//
// Dave Plummer on a rainy Thursday
//
// davepl@davepl.com
// --------------------------------------------------------------------------
#include <stdio.h> // For printf
#include <stdlib.h> // For rand, srand
#include <string.h> // For memcpy
typedef unsigned char byte;
// World size
#define WIDTH 320
#define HEIGHT 200
#define NUMBITS 64000
#define NUMBYTES 8000
#define DENSITY 50
// Screen memory is placed at 8000, our world copy at A000, and they use the same layout so
// that we can memcpy from one to the other without translating
byte * world = (byte *) 0x8000;
byte * new_world = (byte *) 0xA000;
// BITARRAY
//
// Access individual bits in a block of memory
// Access to the screen bitmap
byte GETBIT(byte *p, int n)
{
return (p[n >> 3] & (1 << (n & 7))) ? 1 : 0;
}
void SETBIT(byte *p, int n)
{
p[n >> 3] |= (1 << (n & 7));
}
void CLRBIT(byte *p, int n)
{
p[n >> 3] &= ~(1 << (n & 7));
}
void SETPIXEL(byte * p, int x, int y, byte b)
{
if (b)
SETBIT(p, y * WIDTH + x);
else
CLRBIT(p, y * WIDTH + x);
}
byte GETPIXEL(byte *p, int x, int y)
{
return GETBIT(p, y * WIDTH + x);
}
// RandomFillWorld
//
// Populates the initial world with random cells
void RandomFillWorld()
{
int x, y;
// I need a better way to see the RNG or it'll be the same game every time!
srand(0);
for (x = 0; x < WIDTH; x++)
{
for (y = 0; y < HEIGHT; y++)
{
byte b = ((rand() % 100) < DENSITY) ? 1 : 0;
SETPIXEL(world, x, y, b);
}
}
}
// CountNeighbors
//
// Count the number of live cells around the given spot, excluding the actual spot specified
int CountNeighbors(int x, int y)
{
int i, j, nx, ny, count = 0;
for (j = -1; j <= 1; j++)
{
for (i = -1; i <= 1; i++)
{
if (i != 0 || j != 0)
{
nx = (x + i + WIDTH) % WIDTH;
ny = (y + j + HEIGHT) % HEIGHT;
count += GETPIXEL(world, nx, ny) ? 1 : 0;
}
}
}
return count;
}
// UpdateWorld
//
// Applies the rules of Conway's Game of Life to the cells
void UpdateWorld()
{
int x, y;
for (y = 0; y < HEIGHT; y++)
{
for (x = 0; x < WIDTH; x++)
{
int neighbors = CountNeighbors(x, y);
if (GETPIXEL(world, x, y))
SETPIXEL(new_world, x, y, (neighbors == 2 || neighbors == 3));
else
SETPIXEL(new_world, x, y, (neighbors == 3));
}
}
}
int main (void)
{
printf("\r\nStarting Conway's Game of Life: Randomizing World...\r\n");
RandomFillWorld();
printf("World Ready, Running!\r\n");
for (;;)
{
UpdateWorld();
printf("[");
memcpy(world, new_world, NUMBYTES);
printf("]");
}
return 0;
}

262
samples/kim1/kimTest.c Normal file
View File

@ -0,0 +1,262 @@
// --------------------------------------------------------------------------
// Diagnostics Test for KIM-1
//
// Dave Plummer
// davepl@davepl.com
//
// Memory test examples by Michael Barr
//
// --------------------------------------------------------------------------
#include <stdio.h> // For printf
#include <stdlib.h> // For rand, srand
#include <string.h> // For memcpy
typedef unsigned char byte;
// RepeatChar
//
// Outputs a given character N times
void RepeatChar(char c, size_t count)
{
while (count--)
putc(c, stdout);
}
/**********************************************************************
*
* Function: memTestDataBus()
*
* Description: Test the data bus wiring in a memory region by
* performing a walking 1's test at a fixed address
* within that region. The address (and hence the
* memory region) is selected by the caller.
*
* Returns: 0 if the test succeeds.
* A non-zero result is the first pattern that failed.
*
**********************************************************************/
byte memTestDataBus(volatile byte * address)
{
byte pattern;
// Perform a walking 1's test at the given address.
for (pattern = 1; pattern != 0; pattern <<= 1)
{
// Write the test pattern.
*address = pattern;
// Read it back and check it
if (*address != pattern)
{
printf("\r\nmemTestDataBus: FAILED at %04x with pattern %02x\r\n", address, pattern);
return (pattern);
}
}
return (0);
}
/**********************************************************************
*
* Function: memTestAddressBus()
*
* Description: Test the address bus wiring in a memory region by
* performing a walking 1's test on the relevant bits
* of the address and checking for aliasing. This test
* will find single-bit address failures such as stuck
* -high, stuck-low, and shorted pins. The base address
* and size of the region are selected by the caller.
*
* Notes: For best results, the selected base address should
* have enough LSB 0's to guarantee single address bit
* changes. For example, to test a 64-Kbyte region,
* select a base address on a 64-Kbyte boundary. Also,
* select the region size as a power-of-two--if at all
* possible.
*
* Returns: NULL if the test succeeds.
* A non-zero result is the first address at which an
* aliasing problem was uncovered. By examining the
* contents of memory, it may be possible to gather
* additional information about the problem.
*
**********************************************************************/
byte * memTestAddressBus(volatile byte * baseAddress, unsigned long nBytes)
{
unsigned long addressMask = (nBytes/sizeof(byte) - 1);
unsigned long offset;
unsigned long testOffset;
byte pattern = (byte) 0xAAAAAAAA;
byte antipattern = (byte) 0x55555555;
//Write the default pattern at each of the power-of-two offsets.
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
baseAddress[offset] = pattern;
}
// Check for address bits stuck high.
testOffset = 0;
baseAddress[testOffset] = antipattern;
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
if (baseAddress[offset] != pattern)
{
printf("\r\nmemTestAddressBus: FAILED at %04x with pattern %02x\r\n", baseAddress+offset, pattern);
return ((byte *) &baseAddress[offset]);
}
if (offset % 1024 == 0)
printf(".");
}
baseAddress[testOffset] = pattern;
// Check for address bits stuck low or shorted.
for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
{
baseAddress[testOffset] = antipattern;
if (baseAddress[0] != pattern)
{
return ((byte *) &baseAddress[testOffset]);
}
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
if ((baseAddress[offset] != pattern) && (offset != testOffset))
{
printf("\r\nmemTestAddressBus: FAILED at %04x with pattern %02x\r\n", baseAddress+offset, pattern);
return ((byte *) &baseAddress[testOffset]);
}
}
baseAddress[testOffset] = pattern;
}
return (NULL);
}
/**********************************************************************
*
* Function: memTestDevice()
*
* Description: Test the integrity of a physical memory device by
* performing an increment/decrement test over the
* entire region. In the process every storage bit
* in the device is tested as a zero and a one. The
* base address and the size of the region are
* selected by the caller.
*
* Returns: NULL if the test succeeds.
*
* A non-zero result is the first address at which an
* incorrect value was read back. By examining the
* contents of memory, it may be possible to gather
* additional information about the problem.
*
**********************************************************************/
byte * memTestDevice(volatile byte * baseAddress, unsigned long nBytes)
{
unsigned long offset;
unsigned long nWords = nBytes / sizeof(byte);
byte pattern;
byte antipattern;
// Fill memory with a known pattern.
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
baseAddress[offset] = pattern;
// Check each location and invert it for the second pass.
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
{
if (offset % 1024 == 0)
printf("%04X ", (int) &baseAddress[offset]);
if (baseAddress[offset] != pattern)
{
printf("\r\nmemTestDevice: FAILED at %04x with pattern %02x\r\n", (int) &baseAddress[offset], pattern);
return ((byte *) &baseAddress[offset]);
}
antipattern = ~pattern;
baseAddress[offset] = antipattern;
}
// Check each location for the inverted pattern and zero it.
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
{
if (offset % 1024 == 0)
printf("%04X ", (int) &baseAddress[offset]);
antipattern = ~pattern;
if (baseAddress[offset] != antipattern)
{
printf("\r\nmemTestDevice: FAILED at %04x with antipattern %02x\r\n", (int) &baseAddress[offset], pattern);
return ((byte *) &baseAddress[offset]);
}
}
return (NULL);
}
// TestMemory
//
// Run all three memory tests
byte TestMemory(byte * startAddress, unsigned long size)
{
if ((memTestDataBus(startAddress) != 0) ||
(memTestAddressBus(startAddress, size) != NULL) ||
(memTestDevice(startAddress, size) != NULL))
{
return (-1);
}
else
{
return (0);
}
}
int main (void)
{
printf("\r\nTesting KIM-1...\r\n");
RepeatChar('-', 39);
printf("\r\nTesting RIOT RAM: 1780-17BF\r\n");
if (TestMemory((byte *)0x1780, 0x17BF - 0x1780))
return 0;
printf("\r\nTesting RIOT RAM: 17C0-17E6\r\n");
if (TestMemory((byte *)0x17C0, 0x17E6 - 0x17C0))
return 0;
printf("\r\nTesting Memory: 0400-13FF\r\n");
if (TestMemory((byte *)0x0400, 0x13FF - 0x0400))
return 0;
printf("\r\nTesting Memory: 4000-DFFF\r\n");
if (TestMemory((byte *)0x4000, 0xDFFF - 0x4000))
return 0;
printf("\r\nPASS!\r\n");
return 1;
}

272
samples/kim1/ramfont.asm Normal file
View File

@ -0,0 +1,272 @@
;-----------------------------------------------------------------------------------
; KIMGFX: Simple pixel graphics for the MOS/Commodore KIM-1
;-----------------------------------------------------------------------------------
; (c) Plummer's Software Ltd, 04/25/2023 Created
; David Plummer
;-----------------------------------------------------------------------------------
;
; File: ramfont.s
; Magnetic OCR (check number style) Font data
;
;-----------------------------------------------------------------------------------
.segment "CODE"
.export _font8x8_basic
_font8x8_basic:
.byte $1c, $22, $4a, $56, $4c, $20, $1e, $00 ; PETSCII code 0
.byte $3c, $24, $24, $7e, $62, $62, $62, $00 ; PETSCII code 1
.byte $78, $44, $44, $7c, $62, $62, $7e, $00 ; PETSCII code 2
.byte $7e, $42, $40, $60, $60, $62, $7e, $00 ; PETSCII code 3
.byte $7c, $46, $42, $62, $62, $66, $7c, $00 ; PETSCII code 4
.byte $7e, $40, $40, $7c, $60, $60, $7e, $00 ; PETSCII code 5
.byte $7e, $40, $40, $7e, $60, $60, $60, $00 ; PETSCII code 6
.byte $7e, $42, $40, $6e, $62, $62, $7e, $00 ; PETSCII code 7
.byte $42, $42, $42, $7e, $62, $62, $62, $00 ; PETSCII code 8
.byte $08, $08, $08, $0c, $0c, $0c, $0c, $00 ; PETSCII code 9
.byte $04, $04, $04, $06, $06, $46, $7e, $00 ; PETSCII code 10
.byte $42, $44, $48, $7c, $62, $62, $62, $00 ; PETSCII code 11
.byte $40, $40, $40, $60, $60, $60, $7e, $00 ; PETSCII code 12
.byte $7e, $4a, $4a, $6a, $6a, $6a, $6a, $00 ; PETSCII code 13
.byte $7e, $42, $42, $62, $62, $62, $62, $00 ; PETSCII code 14
.byte $7e, $46, $42, $42, $42, $42, $7e, $00 ; PETSCII code 15
.byte $7e, $42, $42, $7e, $60, $60, $60, $00 ; PETSCII code 16
.byte $7e, $42, $42, $42, $4a, $4e, $7e, $00 ; PETSCII code 17
.byte $7c, $44, $44, $7c, $62, $62, $62, $00 ; PETSCII code 18
.byte $7e, $42, $40, $7e, $06, $46, $7e, $00 ; PETSCII code 19
.byte $3e, $10, $10, $18, $18, $18, $18, $00 ; PETSCII code 20
.byte $42, $42, $42, $62, $62, $62, $7e, $00 ; PETSCII code 21
.byte $62, $62, $62, $66, $24, $24, $3c, $00 ; PETSCII code 22
.byte $4a, $4a, $4a, $6a, $6a, $6a, $7e, $00 ; PETSCII code 23
.byte $42, $42, $66, $18, $66, $62, $62, $00 ; PETSCII code 24
.byte $22, $22, $22, $3e, $18, $18, $18, $00 ; PETSCII code 25
.byte $7e, $42, $06, $18, $60, $62, $7e, $00 ; PETSCII code 26
.byte $3c, $20, $20, $20, $20, $20, $3c, $00 ; PETSCII code 27
.byte $00, $40, $20, $10, $08, $04, $02, $00 ; PETSCII code 28
.byte $3c, $04, $04, $04, $04, $04, $3c, $00 ; PETSCII code 29
.byte $00, $08, $1c, $2a, $08, $08, $14, $14 ; PETSCII code 30
.byte $00, $00, $10, $20, $7f, $20, $10, $00 ; PETSCII code 31
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 32
.byte $08, $08, $08, $0c, $0c, $00, $0c, $00 ; PETSCII code 33
.byte $6c, $24, $6c, $00, $00, $00, $00, $00 ; PETSCII code 34
.byte $24, $24, $7e, $24, $7e, $24, $24, $00 ; PETSCII code 35
.byte $08, $3e, $20, $3e, $06, $3e, $08, $00 ; PETSCII code 36
.byte $00, $62, $64, $08, $10, $26, $46, $00 ; PETSCII code 37
.byte $3c, $20, $24, $7e, $64, $64, $7c, $00 ; PETSCII code 38
.byte $1c, $18, $10, $00, $00, $00, $00, $00 ; PETSCII code 39
.byte $04, $08, $10, $10, $10, $08, $04, $00 ; PETSCII code 40
.byte $20, $10, $08, $08, $08, $10, $20, $00 ; PETSCII code 41
.byte $08, $2a, $1c, $3e, $1c, $2a, $08, $00 ; PETSCII code 42
.byte $00, $08, $08, $3e, $08, $08, $00, $00 ; PETSCII code 43
.byte $00, $00, $00, $00, $00, $18, $18, $08 ; PETSCII code 44
.byte $00, $00, $00, $7e, $00, $00, $00, $00 ; PETSCII code 45
.byte $00, $00, $00, $00, $00, $18, $18, $00 ; PETSCII code 46
.byte $00, $02, $04, $08, $10, $20, $40, $00 ; PETSCII code 47
.byte $7e, $62, $52, $4a, $46, $46, $7e, $00 ; PETSCII code 48
.byte $18, $08, $08, $18, $18, $1a, $3e, $00 ; PETSCII code 49
.byte $7e, $42, $02, $7e, $60, $60, $7e, $00 ; PETSCII code 50
.byte $7c, $44, $04, $1e, $06, $46, $7e, $00 ; PETSCII code 51
.byte $44, $44, $44, $44, $7e, $0c, $0c, $00 ; PETSCII code 52
.byte $7e, $40, $7e, $06, $06, $46, $7e, $00 ; PETSCII code 53
.byte $7e, $42, $40, $7e, $46, $46, $7e, $00 ; PETSCII code 54
.byte $7e, $02, $02, $06, $06, $06, $06, $00 ; PETSCII code 55
.byte $3c, $24, $24, $7e, $46, $46, $7e, $00 ; PETSCII code 56
.byte $7e, $42, $42, $7e, $06, $06, $06, $00 ; PETSCII code 57
.byte $00, $00, $18, $00, $00, $18, $00, $00 ; PETSCII code 58
.byte $00, $00, $18, $00, $00, $18, $18, $08 ; PETSCII code 59
.byte $0e, $18, $30, $60, $30, $18, $0e, $00 ; PETSCII code 60
.byte $00, $00, $7e, $00, $7e, $00, $00, $00 ; PETSCII code 61
.byte $70, $18, $0c, $06, $0c, $18, $70, $00 ; PETSCII code 62
.byte $7e, $02, $02, $7e, $60, $00, $60, $00 ; PETSCII code 63
.byte $00, $00, $00, $00, $ff, $00, $00, $00 ; PETSCII code 64
.byte $08, $1c, $3e, $7f, $7f, $1c, $3e, $00 ; PETSCII code 65
.byte $10, $10, $10, $10, $10, $10, $10, $10 ; PETSCII code 66
.byte $00, $00, $00, $ff, $00, $00, $00, $00 ; PETSCII code 67
.byte $00, $00, $ff, $00, $00, $00, $00, $00 ; PETSCII code 68
.byte $00, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 69
.byte $00, $00, $00, $00, $00, $ff, $00, $00 ; PETSCII code 70
.byte $20, $20, $20, $20, $20, $20, $20, $20 ; PETSCII code 71
.byte $04, $04, $04, $04, $04, $04, $04, $04 ; PETSCII code 72
.byte $00, $00, $00, $00, $e0, $10, $08, $08 ; PETSCII code 73
.byte $08, $08, $08, $04, $03, $00, $00, $00 ; PETSCII code 74
.byte $08, $08, $08, $10, $e0, $00, $00, $00 ; PETSCII code 75
.byte $80, $80, $80, $80, $80, $80, $80, $ff ; PETSCII code 76
.byte $80, $40, $20, $10, $08, $04, $02, $01 ; PETSCII code 77
.byte $01, $02, $04, $08, $10, $20, $40, $80 ; PETSCII code 78
.byte $ff, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 79
.byte $ff, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 80
.byte $00, $3c, $7e, $7e, $7e, $7e, $3c, $00 ; PETSCII code 81
.byte $00, $00, $00, $00, $00, $00, $ff, $00 ; PETSCII code 82
.byte $36, $7f, $7f, $7f, $3e, $1c, $08, $00 ; PETSCII code 83
.byte $40, $40, $40, $40, $40, $40, $40, $40 ; PETSCII code 84
.byte $00, $00, $00, $00, $03, $04, $08, $08 ; PETSCII code 85
.byte $81, $42, $24, $18, $18, $24, $42, $81 ; PETSCII code 86
.byte $00, $3c, $42, $42, $42, $42, $3c, $00 ; PETSCII code 87
.byte $08, $1c, $2a, $77, $2a, $08, $08, $00 ; PETSCII code 88
.byte $02, $02, $02, $02, $02, $02, $02, $02 ; PETSCII code 89
.byte $08, $1c, $3e, $7f, $3e, $1c, $08, $00 ; PETSCII code 90
.byte $08, $08, $08, $08, $ff, $08, $08, $08 ; PETSCII code 91
.byte $a0, $50, $a0, $50, $a0, $50, $a0, $50 ; PETSCII code 92
.byte $08, $08, $08, $08, $08, $08, $08, $08 ; PETSCII code 93
.byte $00, $00, $01, $3e, $54, $14, $14, $00 ; PETSCII code 94
.byte $ff, $7f, $3f, $1f, $0f, $07, $03, $01 ; PETSCII code 95
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 96
.byte $f0, $f0, $f0, $f0, $f0, $f0, $f0, $f0 ; PETSCII code 97
.byte $00, $00, $00, $00, $ff, $ff, $ff, $ff ; PETSCII code 98
.byte $ff, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 99
.byte $00, $00, $00, $00, $00, $00, $00, $ff ; PETSCII code 100
.byte $80, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 101
.byte $aa, $55, $aa, $55, $aa, $55, $aa, $55 ; PETSCII code 102
.byte $01, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 103
.byte $00, $00, $00, $00, $aa, $55, $aa, $55 ; PETSCII code 104
.byte $ff, $fe, $fc, $f8, $f0, $e0, $c0, $80 ; PETSCII code 105
.byte $03, $03, $03, $03, $03, $03, $03, $03 ; PETSCII code 106
.byte $08, $08, $08, $08, $0f, $08, $08, $08 ; PETSCII code 107
.byte $00, $00, $00, $00, $0f, $0f, $0f, $0f ; PETSCII code 108
.byte $08, $08, $08, $08, $0f, $00, $00, $00 ; PETSCII code 109
.byte $00, $00, $00, $00, $f8, $08, $08, $08 ; PETSCII code 110
.byte $00, $00, $00, $00, $00, $00, $ff, $ff ; PETSCII code 111
.byte $00, $00, $00, $00, $0f, $08, $08, $08 ; PETSCII code 112
.byte $08, $08, $08, $08, $ff, $00, $00, $00 ; PETSCII code 113
.byte $00, $00, $00, $00, $ff, $08, $08, $08 ; PETSCII code 114
.byte $08, $08, $08, $08, $f8, $08, $08, $08 ; PETSCII code 115
.byte $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 ; PETSCII code 116
.byte $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0 ; PETSCII code 117
.byte $07, $07, $07, $07, $07, $07, $07, $07 ; PETSCII code 118
.byte $ff, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 119
.byte $ff, $ff, $ff, $00, $00, $00, $00, $00 ; PETSCII code 120
.byte $00, $00, $00, $00, $00, $ff, $ff, $ff ; PETSCII code 121
.byte $01, $01, $01, $01, $01, $01, $01, $ff ; PETSCII code 122
.byte $00, $00, $00, $00, $f0, $f0, $f0, $f0 ; PETSCII code 123
.byte $0f, $0f, $0f, $0f, $00, $00, $00, $00 ; PETSCII code 124
.byte $08, $08, $08, $08, $f8, $00, $00, $00 ; PETSCII code 125
.byte $f0, $f0, $f0, $f0, $00, $00, $00, $00 ; PETSCII code 126
.byte $f0, $f0, $f0, $f0, $0f, $0f, $0f, $0f ; PETSCII code 127
.byte $1c, $22, $4a, $56, $4c, $20, $1e, $00 ; PETSCII code 128
.byte $00, $00, $3c, $04, $7c, $64, $7c, $00 ; PETSCII code 129
.byte $40, $40, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 130
.byte $00, $00, $7e, $42, $60, $62, $7e, $00 ; PETSCII code 131
.byte $02, $02, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 132
.byte $00, $00, $7e, $42, $7e, $60, $7e, $00 ; PETSCII code 133
.byte $1e, $12, $10, $7c, $18, $18, $18, $00 ; PETSCII code 134
.byte $00, $00, $7e, $42, $62, $7e, $02, $7e ; PETSCII code 135
.byte $40, $40, $7e, $42, $62, $62, $62, $00 ; PETSCII code 136
.byte $18, $00, $10, $10, $18, $18, $18, $00 ; PETSCII code 137
.byte $0c, $00, $08, $0c, $0c, $0c, $44, $7c ; PETSCII code 138
.byte $40, $40, $44, $48, $78, $64, $64, $00 ; PETSCII code 139
.byte $10, $10, $10, $10, $18, $18, $18, $00 ; PETSCII code 140
.byte $00, $00, $7f, $49, $6d, $6d, $6d, $00 ; PETSCII code 141
.byte $00, $00, $7e, $42, $62, $62, $62, $00 ; PETSCII code 142
.byte $00, $00, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 143
.byte $00, $00, $7e, $42, $62, $7e, $40, $40 ; PETSCII code 144
.byte $00, $00, $7e, $42, $46, $7e, $02, $02 ; PETSCII code 145
.byte $00, $00, $7e, $40, $60, $60, $60, $00 ; PETSCII code 146
.byte $00, $00, $7e, $40, $7e, $06, $7e, $00 ; PETSCII code 147
.byte $10, $10, $7c, $10, $18, $18, $18, $00 ; PETSCII code 148
.byte $00, $00, $42, $42, $62, $62, $7e, $00 ; PETSCII code 149
.byte $00, $00, $62, $62, $66, $24, $3c, $00 ; PETSCII code 150
.byte $00, $00, $49, $49, $6d, $6d, $7f, $00 ; PETSCII code 151
.byte $00, $00, $42, $42, $3c, $62, $62, $00 ; PETSCII code 152
.byte $00, $00, $62, $62, $42, $7e, $02, $7e ; PETSCII code 153
.byte $00, $00, $7e, $06, $18, $60, $7e, $00 ; PETSCII code 154
.byte $3c, $20, $20, $20, $20, $20, $3c, $00 ; PETSCII code 155
.byte $00, $40, $20, $10, $08, $04, $02, $00 ; PETSCII code 156
.byte $3c, $04, $04, $04, $04, $04, $3c, $00 ; PETSCII code 157
.byte $00, $08, $1c, $2a, $08, $08, $14, $14 ; PETSCII code 158
.byte $00, $00, $10, $20, $7f, $20, $10, $00 ; PETSCII code 159
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 160
.byte $08, $08, $08, $0c, $0c, $00, $0c, $00 ; PETSCII code 161
.byte $6c, $24, $6c, $00, $00, $00, $00, $00 ; PETSCII code 162
.byte $24, $24, $7e, $24, $7e, $24, $24, $00 ; PETSCII code 163
.byte $08, $3e, $20, $3e, $06, $3e, $08, $00 ; PETSCII code 164
.byte $00, $62, $64, $08, $10, $26, $46, $00 ; PETSCII code 165
.byte $3c, $20, $24, $7e, $64, $64, $7c, $00 ; PETSCII code 166
.byte $1c, $18, $10, $00, $00, $00, $00, $00 ; PETSCII code 167
.byte $04, $08, $10, $10, $10, $08, $04, $00 ; PETSCII code 168
.byte $20, $10, $08, $08, $08, $10, $20, $00 ; PETSCII code 169
.byte $08, $2a, $1c, $3e, $1c, $2a, $08, $00 ; PETSCII code 170
.byte $00, $08, $08, $3e, $08, $08, $00, $00 ; PETSCII code 171
.byte $00, $00, $00, $00, $00, $18, $18, $08 ; PETSCII code 172
.byte $00, $00, $00, $7e, $00, $00, $00, $00 ; PETSCII code 173
.byte $00, $00, $00, $00, $00, $18, $18, $00 ; PETSCII code 174
.byte $00, $02, $04, $08, $10, $20, $40, $00 ; PETSCII code 175
.byte $7e, $62, $52, $4a, $46, $46, $7e, $00 ; PETSCII code 176
.byte $38, $08, $08, $18, $18, $1a, $3e, $00 ; PETSCII code 177
.byte $7e, $42, $02, $7e, $60, $60, $7e, $00 ; PETSCII code 178
.byte $7c, $44, $04, $1e, $06, $46, $7e, $00 ; PETSCII code 179
.byte $44, $44, $44, $44, $7e, $0c, $0c, $00 ; PETSCII code 180
.byte $7e, $40, $7e, $06, $06, $46, $7e, $00 ; PETSCII code 181
.byte $7e, $42, $40, $7e, $46, $46, $7e, $00 ; PETSCII code 182
.byte $7e, $02, $02, $06, $06, $06, $06, $00 ; PETSCII code 183
.byte $3c, $24, $24, $7e, $46, $46, $7e, $00 ; PETSCII code 184
.byte $7e, $42, $42, $7e, $06, $06, $06, $00 ; PETSCII code 185
.byte $00, $00, $18, $00, $00, $18, $00, $00 ; PETSCII code 186
.byte $00, $00, $18, $00, $00, $18, $18, $08 ; PETSCII code 187
.byte $0e, $18, $30, $60, $30, $18, $0e, $00 ; PETSCII code 188
.byte $00, $00, $7e, $00, $7e, $00, $00, $00 ; PETSCII code 189
.byte $70, $18, $0c, $06, $0c, $18, $70, $00 ; PETSCII code 190
.byte $7e, $02, $02, $7e, $60, $00, $60, $00 ; PETSCII code 191
.byte $00, $00, $00, $00, $ff, $00, $00, $00 ; PETSCII code 192
.byte $3c, $24, $24, $7e, $62, $62, $62, $00 ; PETSCII code 193
.byte $78, $44, $44, $7c, $62, $62, $7e, $00 ; PETSCII code 194
.byte $7e, $42, $40, $60, $60, $62, $7e, $00 ; PETSCII code 195
.byte $7c, $46, $42, $62, $62, $66, $7c, $00 ; PETSCII code 196
.byte $7e, $40, $40, $78, $60, $60, $7e, $00 ; PETSCII code 197
.byte $7e, $40, $40, $7e, $60, $60, $60, $00 ; PETSCII code 198
.byte $7e, $42, $40, $6e, $62, $62, $7e, $00 ; PETSCII code 199
.byte $42, $42, $42, $7e, $62, $62, $62, $00 ; PETSCII code 200
.byte $08, $08, $08, $0c, $0c, $0c, $0c, $00 ; PETSCII code 201
.byte $04, $04, $04, $06, $06, $46, $7e, $00 ; PETSCII code 202
.byte $42, $44, $48, $7c, $62, $62, $62, $00 ; PETSCII code 203
.byte $40, $40, $40, $60, $60, $60, $7e, $00 ; PETSCII code 204
.byte $7e, $4a, $4a, $6a, $6a, $6a, $6a, $00 ; PETSCII code 205
.byte $7e, $42, $42, $62, $62, $62, $62, $00 ; PETSCII code 206
.byte $7e, $46, $42, $42, $42, $42, $7e, $00 ; PETSCII code 207
.byte $7e, $42, $42, $7e, $60, $60, $60, $00 ; PETSCII code 208
.byte $7e, $42, $42, $42, $4a, $4e, $7e, $00 ; PETSCII code 209
.byte $7c, $44, $44, $7c, $62, $62, $62, $00 ; PETSCII code 210
.byte $7e, $42, $40, $7e, $06, $46, $7e, $00 ; PETSCII code 211
.byte $3e, $10, $10, $18, $18, $18, $18, $00 ; PETSCII code 212
.byte $42, $42, $42, $62, $62, $62, $7e, $00 ; PETSCII code 213
.byte $62, $62, $62, $66, $24, $24, $3c, $00 ; PETSCII code 214
.byte $4a, $4a, $4a, $6a, $6a, $6a, $7e, $00 ; PETSCII code 215
.byte $42, $42, $66, $3c, $66, $62, $62, $00 ; PETSCII code 216
.byte $22, $22, $22, $3e, $18, $18, $18, $00 ; PETSCII code 217
.byte $7e, $42, $06, $18, $60, $62, $7e, $00 ; PETSCII code 218
.byte $08, $08, $08, $08, $ff, $08, $08, $08 ; PETSCII code 219
.byte $a0, $50, $a0, $50, $a0, $50, $a0, $50 ; PETSCII code 220
.byte $08, $08, $08, $08, $08, $08, $08, $08 ; PETSCII code 221
.byte $cc, $cc, $33, $33, $cc, $cc, $33, $33 ; PETSCII code 222
.byte $cc, $66, $33, $99, $cc, $66, $33, $99 ; PETSCII code 223
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 224
.byte $f0, $f0, $f0, $f0, $f0, $f0, $f0, $f0 ; PETSCII code 225
.byte $00, $00, $00, $00, $ff, $ff, $ff, $ff ; PETSCII code 226
.byte $ff, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 227
.byte $00, $00, $00, $00, $00, $00, $00, $ff ; PETSCII code 228
.byte $80, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 229
.byte $aa, $55, $aa, $55, $aa, $55, $aa, $55 ; PETSCII code 230
.byte $01, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 231
.byte $00, $00, $00, $00, $aa, $55, $aa, $55 ; PETSCII code 232
.byte $99, $33, $66, $cc, $99, $33, $66, $cc ; PETSCII code 233
.byte $03, $03, $03, $03, $03, $03, $03, $03 ; PETSCII code 234
.byte $08, $08, $08, $08, $0f, $08, $08, $08 ; PETSCII code 235
.byte $00, $00, $00, $00, $0f, $0f, $0f, $0f ; PETSCII code 236
.byte $08, $08, $08, $08, $0f, $00, $00, $00 ; PETSCII code 237
.byte $00, $00, $00, $00, $f8, $08, $08, $08 ; PETSCII code 238
.byte $00, $00, $00, $00, $00, $00, $ff, $ff ; PETSCII code 239
.byte $00, $00, $00, $00, $0f, $08, $08, $08 ; PETSCII code 240
.byte $08, $08, $08, $08, $ff, $00, $00, $00 ; PETSCII code 241
.byte $00, $00, $00, $00, $ff, $08, $08, $08 ; PETSCII code 242
.byte $08, $08, $08, $08, $f8, $08, $08, $08 ; PETSCII code 243
.byte $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 ; PETSCII code 244
.byte $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0 ; PETSCII code 245
.byte $07, $07, $07, $07, $07, $07, $07, $07 ; PETSCII code 246
.byte $ff, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 247
.byte $ff, $ff, $ff, $00, $00, $00, $00, $00 ; PETSCII code 248
.byte $00, $00, $00, $00, $00, $ff, $ff, $ff ; PETSCII code 249
.byte $01, $02, $44, $48, $50, $60, $40, $00 ; PETSCII code 250
.byte $00, $00, $00, $00, $f0, $f0, $f0, $f0 ; PETSCII code 251
.byte $0f, $0f, $0f, $0f, $00, $00, $00, $00 ; PETSCII code 252
.byte $08, $08, $08, $08, $f8, $00, $00, $00 ; PETSCII code 253
.byte $f0, $f0, $f0, $f0, $00, $00, $00, $00 ; PETSCII code 254
.byte $f0, $f0, $f0, $f0, $0f, $0f, $0f, $0f ; PETSCII code 255

1140
samples/kim1/subs.asm Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3608,6 +3608,14 @@ void g_asr (unsigned flags, unsigned long val)
}
val -= 8;
}
if (val == 7) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shrax7");
} else {
AddCodeLine ("jsr asrax7");
}
val = 0;
}
if (val >= 4) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shrax4");
@ -3751,6 +3759,14 @@ void g_asl (unsigned flags, unsigned long val)
AddCodeLine ("lda #$00");
val -= 8;
}
if (val == 7) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shlax7");
} else {
AddCodeLine ("jsr aslax7");
}
val = 0;
}
if (val >= 4) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shlax4");

View File

@ -99,6 +99,7 @@ static const FuncInfo FuncInfoTable[] = {
{ "aslax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslax7", REG_AX, PSTATE_ALL | REG_AXY },
{ "aslaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "asleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
@ -108,6 +109,7 @@ static const FuncInfo FuncInfoTable[] = {
{ "asrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asrax7", REG_AX, PSTATE_ALL | REG_AX },
{ "asraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "asreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
@ -245,6 +247,7 @@ static const FuncInfo FuncInfoTable[] = {
{ "shlax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlax7", REG_AX, PSTATE_ALL | REG_AXY },
{ "shlaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "shleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
@ -254,6 +257,7 @@ static const FuncInfo FuncInfoTable[] = {
{ "shrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shrax7", REG_AX, PSTATE_ALL | REG_AX },
{ "shraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "shreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },

View File

@ -1488,7 +1488,7 @@ static const OptFuncDesc FuncTable[] = {
};
static const OptFuncDesc FuncRegATable[] = {
{ "tosandax", Opt_a_tosand, REG_NONE, OP_NONE },
{ "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
@ -1496,13 +1496,13 @@ static const OptFuncDesc FuncRegATable[] = {
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
{ "tosorax", Opt_a_tosor, REG_NONE, OP_NONE },
{ "tosorax", Opt_a_tosor, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
{ "tossubax", Opt_a_tossub, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
{ "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE },
{ "tosultax", Opt_a_tosult, REG_NONE, OP_NONE },
{ "tosxorax", Opt_a_tosxor, REG_NONE, OP_NONE },
{ "tosxorax", Opt_a_tosxor, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
};
#define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0]))

View File

@ -163,7 +163,7 @@ static void PVArgs (CPURegs* Regs)
static void PVOpen (CPURegs* Regs)
{
char Path[PVOPEN_PATH_SIZE];
char Path[PV_PATH_SIZE];
int OFlag = O_INITIAL;
int OMode = 0;
unsigned RetVal, I = 0;
@ -184,7 +184,7 @@ static void PVOpen (CPURegs* Regs)
break;
}
++I;
if (I >= PVOPEN_PATH_SIZE) {
if (I >= PV_PATH_SIZE) {
Error("PVOpen path too long at address $%04X",Name);
}
}
@ -253,6 +253,35 @@ static void PVClose (CPURegs* Regs)
static void PVSysRemove (CPURegs* Regs)
{
char Path[PV_PATH_SIZE];
unsigned RetVal, I = 0;
unsigned Name = GetAX (Regs);
Print (stderr, 2, "PVSysRemove ($%04X)\n", Name);
do {
if (!(Path[I] = MemReadByte ((Name + I) & 0xFFFF))) {
break;
}
++I;
if (I >= PV_PATH_SIZE) {
Error("PVSysRemove path too long at address $%04X", Name);
}
}
while (1);
Print (stderr, 2, "PVSysRemove (\"%s\")\n", Path);
RetVal = remove (Path);
SetAX (Regs, RetVal);
}
static void PVRead (CPURegs* Regs)
{
unsigned char* Data;
@ -305,7 +334,17 @@ static void PVWrite (CPURegs* Regs)
static void PVOSMapErrno (CPURegs* Regs)
{
unsigned err = GetAX(Regs);
SetAX (Regs, err != 0 ? -1 : 0);
}
static const PVFunc Hooks[] = {
PVSysRemove,
PVOSMapErrno,
PVOpen,
PVClose,
PVRead,

View File

@ -44,11 +44,11 @@
#define PARAVIRT_BASE 0xFFF4
#define PARAVIRT_BASE 0xFFF2
/* Lowest address used by a paravirtualization hook */
#define PVOPEN_PATH_SIZE 1024
/* Maximum path size supported by PVOpen */
#define PV_PATH_SIZE 1024
/* Maximum path size supported by PVOpen/PVSysRemove */

67
test/ref/test_fgets.c Normal file
View File

@ -0,0 +1,67 @@
/*
!!DESCRIPTION!! fgets test
!!LICENCE!! Public domain
*/
#include "common.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
FILE *in, *out;
char buf[32];
#define INFILE "cf.in"
int main(int argc,char **argv)
{
static char outfile_path[FILENAME_MAX+1];
sprintf(outfile_path, "%s.test.out", argv[0]);
out = fopen(outfile_path, "wb");
if (out == NULL) {
return EXIT_FAILURE;
}
if (fgets(buf, sizeof(buf), out) != NULL) {
printf("Error, could fgets with write-only file\n");
return 1;
}
if (!ferror(out)) {
printf("Error: file pointer should be in error state\n");
}
fclose(out);
unlink(outfile_path);
in = fopen(INFILE, "rb");
if (in == NULL) {
return EXIT_FAILURE;
}
if (fgets(NULL, 0, in) != NULL) {
printf("Error, could fgets with zero size\n");
return 1;
}
/* Test ungetc while we're at it */
buf[0] = fgetc(in);
ungetc(buf[0], in);
while (fgets(buf, sizeof(buf), in) != NULL)
{
printf("%s",buf);
}
if (!feof(in))
{
printf("We should have EOF!\n");
}
fclose(in);
return 0;
}

39
test/ref/test_fputc.c Normal file
View File

@ -0,0 +1,39 @@
/*
!!DESCRIPTION!! fgets test
!!LICENCE!! Public domain
*/
#include "common.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
FILE *in, *out;
int c, err;
#define INFILE "cf.in"
int main(int argc,char **argv)
{
in = fopen(INFILE, "rb");
if (in == NULL) {
return EXIT_FAILURE;
}
if (fputc(c, in) != EOF) {
printf("Error: can fputc to a file opened for reading\n");
return EXIT_FAILURE;
}
clearerr(in);
while ((c = fgetc(in)) != EOF) {
fputc(c, stdout);
}
fclose(in);
return 0;
}

40
test/ref/test_fputs.c Normal file
View File

@ -0,0 +1,40 @@
/*
!!DESCRIPTION!! fgets test
!!LICENCE!! Public domain
*/
#include "common.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
FILE *in, *out;
char buf[512], err;
#define INFILE "cf.in"
int main(int argc,char **argv)
{
in = fopen(INFILE, "rb");
if (in == NULL) {
return EXIT_FAILURE;
}
strcpy(buf, "test");
if (fputs(buf, in) != EOF) {
printf("Error: can fputs to a file opened for reading\n");
return EXIT_FAILURE;
}
clearerr(in);
while (fgets(buf, 512, in) != NULL) {
fputs(buf, stdout);
}
fclose(in);
return 0;
}

70
test/ref/test_fread.c Normal file
View File

@ -0,0 +1,70 @@
/*
!!DESCRIPTION!! fgets test
!!LICENCE!! Public domain
*/
#include "common.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
FILE *in, *out;
char buf[32];
#define INFILE "cf.in"
int main(int argc,char **argv)
{
static char outfile_path[FILENAME_MAX+1];
static int r;
sprintf(outfile_path, "%s.test.out", argv[0]);
out = fopen(outfile_path, "wb");
if (out == NULL) {
return EXIT_FAILURE;
}
if (fread(buf, 1, sizeof(buf), out) != NULL) {
printf("Error, could fread with write-only file\n");
return 1;
}
if (!ferror(out)) {
printf("Error: file pointer should be in error state\n");
}
fclose(out);
unlink(outfile_path);
in = fopen(INFILE, "rb");
if (in == NULL) {
return EXIT_FAILURE;
}
/* Test that ungetc doesn't break fread */
buf[0] = fgetc(in);
ungetc(buf[0], in);
r = fread(buf, 1, sizeof(buf), out);
if (r == 0) {
printf("Error: could not start reading.\n");
}
fwrite(buf, 1, r, stdout);
/* Finish reading file. */
while ((r = fread(buf, 1, sizeof(buf), out)) != 0)
{
fwrite(buf, 1, r, stdout);
}
if (!feof(in))
{
printf("We should have EOF!\n");
}
fclose(in);
return 0;
}

44
test/ref/test_gets.c Normal file
View File

@ -0,0 +1,44 @@
/*
!!DESCRIPTION!! gets test
!!LICENCE!! Public domain
*/
#include "common.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
char buf[512];
#define INFILE "cf.in"
#ifndef __CC65__
/* Force declaration on host compiler, as gets() is deprecated for
* being dangerous as hell */
char *gets (char *__s);
#endif
#ifdef NO_OLD_FUNC_DECL
int main(int argc,char **argv)
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
/* Fake stdin with the reference file */
if (freopen(INFILE, "rb", stdin) == NULL) {
return EXIT_FAILURE;
}
while (gets(buf) != NULL)
{
printf("%s",buf);
}
fclose(stdin);
return 0;
}

44
test/val/bug2395.c Normal file
View File

@ -0,0 +1,44 @@
/* bug #2395: Bitwise operators with a boolean expression fail when optimized */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char a, b;
unsigned char c = 199;
unsigned char d = 100;
int main(void) {
int fails = 0;
a = c ^ (d != 0);
b = c ^ 1;
printf("%u ^ (%u != 0) => %u\n", c, d, a);
if (a != b) {
printf("XOR error: a %d instead of %d\n", a, b);
fails++;
}
a = c | (d != 0);
b = c | 1;
printf("%u | (%u != 0) => %u\n", c, d, a);
if (a != b) {
printf("OR error: a %d instead of %d\n", a, b);
fails++;
}
a = c & (d != 0);
b = c & 1;
printf("%u & (%u != 0) => %u\n", c, d, a);
if (a != b) {
printf("AND error: a %d instead of %d\n", a, b);
fails++;
}
printf("%d errors\n", fails);
return fails;
}

View File

@ -0,0 +1,34 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "unittest.h"
TEST
{
char *buf, *buf2;
unsigned int i;
buf = malloc(0);
ASSERT_IsTrue (buf == NULL, "malloc (0) returned something");
for (i = 1; i < 10; i++) {
buf = malloc(i);
ASSERT_IsTrue (buf != NULL, "small returned nothing");
}
buf = malloc(4096);
ASSERT_IsTrue (buf != NULL, "malloc (4096) returned nothing");
buf = malloc(61000UL);
ASSERT_IsTrue (buf == NULL, "malloc (61000) returned something");
for (i = 65535UL; i > _heapmaxavail(); i--) {
buf = malloc(i);
ASSERT_IsTrue (buf == NULL, "malloc returned something but shouldn't have");
}
buf = malloc(i);
ASSERT_IsTrue (buf != NULL, "malloc returned nothing but should have");
ASSERT_IsTrue(_heapmaxavail() == 0, "heapmaxavail should be 0");
}
ENDTEST

View File

@ -0,0 +1,31 @@
#include <errno.h>
#include <stdlib.h>
#include "unittest.h"
TEST
{
void *buf;
int r;
r = posix_memalign(&buf, 123, 1024);
ASSERT_IsTrue(r == EINVAL, "posix_memalign did not return EINVAL with wrong alignment");
ASSERT_IsTrue(buf == NULL, "posix_memalign did not set buf to NULL with wrong alignment");
r = posix_memalign(&buf, 0, 1024);
ASSERT_IsTrue(r == EINVAL, "posix_memalign did not return EINVAL with 0 alignment");
ASSERT_IsTrue(buf == NULL, "posix_memalign did not set buf to NULL with 0 alignment");
r = posix_memalign(&buf, 256, 0);
ASSERT_IsTrue(r == EINVAL, "posix_memalign did not return EINVAL with 0 size");
ASSERT_IsTrue(buf == NULL, "posix_memalign did not set buf to NULL with 0 size");
r = posix_memalign(&buf, 256, 32768U);
ASSERT_IsTrue(r == 0, "posix_memalign did not return 0 on correct call");
ASSERT_IsTrue(buf != NULL, "posix_memalign left buf set to NULL on correct call");
ASSERT_IsTrue(((unsigned int)buf & 0x00FF) == 0x00, "posix_memalign did not align memory");
r = posix_memalign(&buf, 256, 32768U);
ASSERT_IsTrue(r == ENOMEM, "posix_memalign did not return ENOMEM when no memory is available");
ASSERT_IsTrue(buf == NULL, "posix_memalign did not set buf to NULL when no memory is available");
}
ENDTEST

View File

@ -0,0 +1,81 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "unittest.h"
TEST
{
char *buf, *buf2;
unsigned int i;
buf = realloc(NULL, 0);
ASSERT_IsTrue (buf == NULL, "realloc (NULL, 0) returned something");
for (i = 1; i < 10; i++) {
buf2 = realloc(buf, i);
ASSERT_IsTrue (buf2 != NULL, "small realloc returned nothing");
if (i > 1) {
ASSERT_IsTrue (buf2 == buf, "buf shouldn't have moved");
}
buf = buf2;
}
buf = realloc(NULL, 15);
ASSERT_IsTrue (buf != NULL, "realloc (NULL, 15) returned nothing");
buf = realloc(buf, 0);
ASSERT_IsTrue (buf == NULL, "realloc (buf, 0) returned something");
buf = realloc(buf, 32);
memset(buf, 'a', 32);
for (i = 0; i < 32; i++) {
ASSERT_IsTrue(buf[i] == 'a', "wrong contents in buf");
}
/* Now realloc larger, while there's nothing else in the heap */
buf = realloc(buf, 64);
memset(buf+32, 'b', 32);
for (i = 0; i < 32; i++) {
ASSERT_IsTrue(buf[i] == 'a', "wrong contents in start of buf");
}
for (i = 32; i < 64; i++) {
ASSERT_IsTrue(buf[i] == 'b', "wrong contents in end of buf");
}
/* Now realloc smaller, while there's nothing else in the heap */
buf = realloc(buf, 40);
for (i = 0; i < 32; i++) {
ASSERT_IsTrue(buf[i] == 'a', "wrong contents in start of buf");
}
for (i = 32; i < 40; i++) {
ASSERT_IsTrue(buf[i] == 'b', "wrong contents in end of buf");
}
/* Allocate something else, so next realloc has to change block */
malloc(50);
/* Now realloc larger, with something else in the heap */
buf = realloc(buf, 128);
for (i = 0; i < 32; i++) {
ASSERT_IsTrue(buf[i] == 'a', "wrong contents in start of buf");
}
for (i = 32; i < 40; i++) {
ASSERT_IsTrue(buf[i] == 'b', "wrong contents in end of buf");
}
for (i = 129; i < 8192; i++) {
buf = realloc(buf, i);
ASSERT_IsTrue(buf != NULL, "realloc failed");
}
malloc(4096);
buf2 = realloc(buf, 58000UL);
ASSERT_IsTrue (buf2 == NULL, "realloc (buf, 58000) returned something");
for (i = 65535UL; i > 65527UL; i--) {
buf2 = realloc(buf, i);
ASSERT_IsTrue (buf2 == NULL, "realloc returned something but shouldn't have");
}
}
ENDTEST

View File

@ -0,0 +1,44 @@
/*
!!DESCRIPTION!! A small test for aslax7.
!!ORIGIN!!
!!LICENCE!!
!!AUTHOR!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
int main (void)
{
signed int ai = -32768, ti, refi;
signed char ac = -128, tc, refc;
do {
refi = ai << 4;
refi = refi << 3;
ti = ai << 7;
if (ti != refi) {
printf("wrong result on int %d << 7: %04X, expected %04X\n", ai, ti, refi);
return 1;
}
} while (++ai != -32768);
do {
refc = ac << 4;
refc = refc << 3;
tc = ac << 7;
if (tc != refc) {
printf("wrong result on char %d << 7: %04X, expected %04X\n", ac, tc, refc);
return 1;
}
} while (++ac != -128);
return 0;
}

View File

@ -0,0 +1,44 @@
/*
!!DESCRIPTION!! A small test for asrax7.
!!ORIGIN!!
!!LICENCE!!
!!AUTHOR!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
int main (void)
{
signed int ai = -32768, ti, refi;
signed char ac = -128, tc, refc;
do {
refi = ai >> 4;
refi = refi >> 3;
ti = ai >> 7;
if (ti != refi) {
printf("wrong result on int %d >> 7: %04X, expected %04X\n", ai, ti, refi);
return 1;
}
} while (++ai != -32768);
do {
refc = ac >> 4;
refc = refc >> 3;
tc = ac >> 7;
if (tc != refc) {
printf("wrong result on char %d >> 7: %04X, expected %04X\n", ac, tc, refc);
return 1;
}
} while (++ac != -128);
return 0;
}

View File

@ -0,0 +1,44 @@
/*
!!DESCRIPTION!! A small test for shlax7.
!!ORIGIN!!
!!LICENCE!!
!!AUTHOR!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
int main (void)
{
unsigned int ai = 0, ti, refi;
unsigned char ac = 0, tc, refc;
do {
refi = ai << 4;
refi = refi << 3;
ti = ai << 7;
if (ti != refi) {
printf("wrong result on int %u << 7: %04X, expected %04X\n", ai, ti, refi);
return 1;
}
} while (++ai != 0);
do {
refc = ac << 4;
refc = refc << 3;
tc = ac << 7;
if (tc != refc) {
printf("wrong result on char %u << 7: %04X, expected %04X\n", ac, tc, refc);
return 1;
}
} while (++ac != 0);
return 0;
}

View File

@ -0,0 +1,44 @@
/*
!!DESCRIPTION!! A small test for shrax7.
!!ORIGIN!!
!!LICENCE!!
!!AUTHOR!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
int main (void)
{
unsigned int ai = 0, ti, refi;
unsigned char ac = 0, tc, refc;
do {
refi = ai >> 4;
refi = refi >> 3;
ti = ai >> 7;
if (ti != refi) {
printf("wrong result on int %d >> 7: %04X, expected %04X\n", ai, ti, refi);
return 1;
}
} while (++ai != 0);
do {
refc = ac >> 4;
refc = refc >> 3;
tc = ac >> 7;
if (tc != refc) {
printf("wrong result on char %d >> 7: %04X, expected %04X\n", ac, tc, refc);
return 1;
}
} while (++ac != 0);
return 0;
}

55
test/val/remove.c Normal file
View File

@ -0,0 +1,55 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int fails = 0;
static void create_out_file(const char *outfile_path) {
FILE *out;
out = fopen(outfile_path, "wb");
if (out == NULL) {
printf("Could not create %s\n", outfile_path);
fails++;
return;
}
fclose(out);
}
int main (int argc, char **argv)
{
int r;
static char outfile_path[FILENAME_MAX+1];
sprintf(outfile_path, "%s.test.out", argv[0]);
create_out_file(outfile_path);
r = remove(outfile_path);
if (r != 0) {
printf("could not remove() %s\n", outfile_path);
fails++;
}
create_out_file(outfile_path);
r = unlink(outfile_path);
if (r != 0) {
printf("could not unlink() %s\n", outfile_path);
fails++;
}
r = remove("klsdfjqlsjdflkqjdsoizu");
if (r == 0) {
printf("remove()ing non-existent file succeeded\n");
fails++;
}
r = unlink("klsdfjqlsjdflkqjdsoizu");
if (r == 0) {
printf("unlink()ing non-existent file succeeded\n");
fails++;
}
return fails;
}