1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 00:29:31 +00:00

Merge branch 'cc65:master' into master

This commit is contained in:
rumbledethumps 2024-02-17 14:54:12 -08:00 committed by GitHub
commit b8b263b38c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 3044 additions and 228 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

@ -259,30 +259,44 @@ SND_INTERRUPT = TIMER7_INTERRUPT
INTRST = $FD80
INTSET = $FD81
MAGRDY0 = $FD84
MAGRDY1 = $FD85
AUDIN = $FD86
SYSCTL1 = $FD87
MIKEYHREV = $FD88
MIKEYSREV = $FD89
IODIR = $FD8A
IODAT = $FD8B
TxIntEnable = %10000000
RxIntEnable = %01000000
TxParEnable = %00010000
ResetErr = %00001000
TxOpenColl = %00000100
TxBreak = %00000010
ParEven = %00000001
TxReady = %10000000
RxReady = %01000000
TxEmpty = %00100000
RxParityErr = %00010000
RxOverrun = %00001000
RxFrameErr = %00000100
RxBreak = %00000010
ParityBit = %00000001
SERCTL = $FD8C
IODIR = $FD8A
IODAT = $FD8B
; IODIR and IODAT bit definitions
AUDIN_BIT = $10 ; Note that there is also the address AUDIN
READ_ENABLE = $10 ; Same bit for AUDIN_BIT
RESTLESS = $08
NOEXP = $04 ; If set, redeye is not connected
CART_ADDR_DATA = $02
CART_POWER_OFF = $02 ; Same bit for CART_ADDR_DATA
EXTERNAL_POWER = $01
SERCTL = $FD8C
; SERCTL bit definitions for write operations
TXINTEN = $80
RXINTEN = $40
PAREN = $10
RESETERR = $08
TXOPEN = $04
TXBRK = $02
PAREVEN = $01
; SERCTL bit definitions for read operations
TXRDY = $80
RXRDY = $40
TXEMPTY = $20
PARERR = $10
OVERRUN = $08
FRAMERR = $04
RXBRK = $02
PARBIT = $01
SERDAT = $FD8D
SDONEACK = $FD90
CPUSLEEP = $FD91

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

@ -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

@ -5,31 +5,33 @@
;
.export _fgetc
.import _read, pusha0, pushax, popptr1, incsp2, returnFFFF
.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
ldy #_FILE::f_flags
lda (ptr1),y
tax
and #_FOPEN ; Check for file open
beq ret_eof
txa
and #(_FERROR|_FEOF); Check for error/eof
jsr checkferror
bne ret_eof
txa
.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

View File

@ -90,9 +90,7 @@ read_loop:
: cmp #$0A ; Stop at \n
beq done
clc
bcc read_loop
bne read_loop
got_eof:
lda didread

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

@ -68,7 +68,7 @@ MikeyInitData: .byte $9e,$18,$68,$1f,$00,$00,$00,$00,$00,$ff,$1a,$1b,$04,$0d,$2
; Disable the TX/RX IRQ; set to 8E1.
lda #%00011101
lda #PAREN|RESETERR|TXOPEN|PAREVEN ; #%00011101
sta SERCTL
; Clear all pending interrupts.

View File

@ -73,7 +73,12 @@ SER_UNINSTALL:
; Must return an SER_ERR_xx code in a/x.
SER_CLOSE:
; Disable interrupts
; Disable interrupts and stop timer 4 (serial)
lda #TXOPEN|RESETERR
sta SERCTL
stz TIM4CTLA ; Disable count and no reload
stz SerialStat ; Reset status
; Done, return an error code
lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error
@ -108,17 +113,17 @@ SER_OPEN:
stz TxPtrIn
stz TxPtrOut
; clock = 8 * 15625
lda #%00011000
sta TIM4CTLA
ldy #SER_PARAMS::BAUDRATE
lda (ptr1),y
; Source period is 1 us
ldy #%00011000 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_1
ldx #1
cmp #SER_BAUD_62500
beq setbaudrate
ldx #2
ldx #3
cmp #SER_BAUD_31250
beq setbaudrate
@ -134,6 +139,10 @@ SER_OPEN:
cmp #SER_BAUD_2400
beq setbaudrate
ldx #68
cmp #SER_BAUD_1800
beq setbaudrate
ldx #103
cmp #SER_BAUD_1200
beq setbaudrate
@ -142,65 +151,22 @@ SER_OPEN:
cmp #SER_BAUD_600
beq setbaudrate
; clock = 6 * 15625
ldx #%00011010
stx TIM4CTLA
; Source period is 8 us
ldy #%00011011 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_8
ldx #12
cmp #SER_BAUD_7200
beq setbaudrate
ldx #25
cmp #SER_BAUD_3600
beq setbaudrate
ldx #207
stx TIM4BKUP
; clock = 4 * 15625
ldx #%00011100
ldx #51
cmp #SER_BAUD_300
beq setprescaler
; clock = 6 * 15625
ldx #%00011110
cmp #SER_BAUD_150
beq setprescaler
; clock = 1 * 15625
ldx #%00011111
stx TIM4CTLA
cmp #SER_BAUD_75
beq baudsuccess
ldx #141
cmp #SER_BAUD_110
beq setbaudrate
; clock = 2 * 15625
ldx #%00011010
stx TIM4CTLA
ldx #68
cmp #SER_BAUD_1800
beq setbaudrate
; clock = 6 * 15625
ldx #%00011110
stx TIM4CTLA
ldx #231
cmp #SER_BAUD_134_5
beq setbaudrate
lda #SER_ERR_BAUD_UNAVAIL
ldx #0 ; return value is char
rts
setprescaler:
stx TIM4CTLA
bra baudsuccess
setbaudrate:
sty TIM4CTLA
stx TIM4BKUP
baudsuccess:
ldx #TxOpenColl|ParEven
ldx #TXOPEN|PAREVEN
stx contrl
ldy #SER_PARAMS::DATABITS ; Databits
lda (ptr1),y
@ -218,15 +184,15 @@ baudsuccess:
beq checkhs
cmp #SER_PAR_SPACE
bne @L0
ldx #TxOpenColl
ldx #TXOPEN
stx contrl
bra checkhs
@L0:
ldx #TxParEnable|TxOpenColl|ParEven
ldx #PAREN|TXOPEN|PAREVEN
stx contrl
cmp #SER_PAR_EVEN
beq checkhs
ldx #TxParEnable|TxOpenColl
ldx #PAREN|TXOPEN
stx contrl
checkhs:
ldx contrl
@ -234,15 +200,27 @@ checkhs:
ldy #SER_PARAMS::HANDSHAKE ; Handshake
lda (ptr1),y
cmp #SER_HS_NONE
beq redeye_ok
cmp #SER_HS_SW ; Software handshake will check for connected redeye
bne invparameter
lda IODAT
and #NOEXP ; Check if redeye bit flag is unset
beq redeye_ok
lda #SER_ERR_NO_DEVICE ; ComLynx cable is not inserted
ldx #0
rts
redeye_ok:
lda SERDAT
lda contrl
ora #RxIntEnable|ResetErr
ora #RXINTEN|RESETERR ; Turn on interrupts for receive
sta SERCTL
lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error
tax
rts
invparameter:
lda #SER_ERR_INIT_FAILED
ldx #0 ; return value is char
@ -264,8 +242,8 @@ GetByte:
ldy RxPtrOut
lda RxBuffer,y
inc RxPtrOut
sta (ptr1)
ldx #$00
sta (ptr1,x)
txa ; Return code = 0
rts
@ -279,24 +257,26 @@ SER_PUT:
ina
cmp TxPtrOut
bne PutByte
lda #SER_ERR_OVERFLOW
ldx #0 ; return value is char
rts
PutByte:
ldy TxPtrIn
txa
sta TxBuffer,y
inc TxPtrIn
bit TxDone
bmi @L1
bit TxDone ; Check bit 7 of TxDone (TXINTEN)
bmi @L1 ; Was TXINTEN already set?
php
sei
lda contrl
ora #TxIntEnable|ResetErr
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ
lda contrl ; contrl does not include RXINTEN setting
ora #TXINTEN|RESETERR
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ (no receive while transmitting)
sta TxDone
plp
plp ; Restore processor and interrupt enable
@L1:
lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error
@ -308,9 +288,9 @@ PutByte:
; Must return an SER_ERR_xx code in a/x.
SER_STATUS:
ldy SerialStat
lda SerialStat
sta (ptr1)
ldx #$00
sta (ptr1,x)
txa ; Return code = 0
rts
@ -342,48 +322,56 @@ SER_IRQ:
@L0:
bit TxDone
bmi @tx_irq ; Transmit in progress
ldx SERDAT
lda SERCTL
and #RxParityErr|RxOverrun|RxFrameErr|RxBreak
beq @rx_irq
ldx SERDAT ; Read received data
lda contrl
and #PAREN ; Parity enabled implies SER_PAR_EVEN or SER_PAR_ODD
tay
ora #OVERRUN|FRAMERR|RXBRK
and SERCTL ; Check presence of relevant error flags in SERCTL
beq @rx_irq ; No errors so far
tsb SerialStat ; Save error condition
bit #RxBreak
bit #RXBRK ; Check for break signal
beq @noBreak
stz TxPtrIn ; Break received - drop buffers
stz TxPtrOut
stz RxPtrIn
stz RxPtrOut
@noBreak:
lda contrl
ora #RxIntEnable|ResetErr
sta SERCTL
lda #$10
sta INTRST
bra @IRQexit
bra @exit0
@rx_irq:
tya
bne @2 ; Parity was enabled so no marker bit check needed
lda contrl
ora #RxIntEnable|ResetErr
sta SERCTL
eor SERCTL ; Should match current parity bit
and #PARBIT ; Check for mark or space value
bne @exit0
@2:
txa
ldx RxPtrIn
sta RxBuffer,x
txa
inx
@cont0:
cpx RxPtrOut
beq @1
stx RxPtrIn
lda #SERIAL_INTERRUPT
sta INTRST
bra @IRQexit
@1:
sta RxPtrIn
lda #$80
tsb SerialStat
bra @exit0
@tx_irq:
ldx TxPtrOut ; Has all bytes been sent?
ldx TxPtrOut ; Have all bytes been sent?
cpx TxPtrIn
beq @allSent
@ -393,24 +381,24 @@ SER_IRQ:
@exit1:
lda contrl
ora #TxIntEnable|ResetErr
ora #TXINTEN|RESETERR
sta SERCTL
lda #SERIAL_INTERRUPT
sta INTRST
bra @IRQexit
@allSent:
lda SERCTL ; All bytes sent
bit #TxEmpty
bit #TXEMPTY
beq @exit1
bvs @exit1
stz TxDone
@exit0:
lda contrl
ora #RxIntEnable|ResetErr
ora #RXINTEN|RESETERR ; Re-enable receive interrupt
sta SERCTL
@IRQexit:
lda #SERIAL_INTERRUPT
sta INTRST
@IRQexit:
clc
rts

View File

@ -40,14 +40,14 @@ cont1:
bra loop1
read_byte:
bit SERCTL
bit SERCTL ; Check for RXRDY ($40)
bvc read_byte
lda SERDAT
rts
_UpLoaderIRQ:
lda INTSET
and #$10
and #SERIAL_INTERRUPT
bne @L0
clc
rts
@ -69,7 +69,7 @@ again:
; last action : clear interrupt
;
exit:
lda #$10
lda #SERIAL_INTERRUPT
sta INTRST
clc
rts

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

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

@ -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

@ -3260,6 +3260,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");
@ -3402,6 +3410,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]))

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;
}

View File

@ -30,9 +30,7 @@ char *argv[];
#endif
{
/* Fake stdin with the reference file */
fclose(stdin);
stdin = fopen(INFILE, "r");
if (stdin == NULL) {
if (freopen(INFILE, "rb", stdin) == NULL) {
return EXIT_FAILURE;
}

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,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;
}