Compare commits

..

No commits in common. "main" and "v1.3.73" have entirely different histories.

341 changed files with 12274 additions and 131770 deletions

12
.gitignore vendored
View File

@ -343,14 +343,4 @@ make/oscar64
*.int
*.bcs
*.crt
**/*.d64
*.tlog
*.res
*.recipe
*.exe
*.dbj
*.json
*.mapd
*.idb
oscar64/Releasex64/oscar64.vcxproj.FileListAbsolute.txt
/oscar64/Debugx64
*.crt

View File

@ -1,67 +0,0 @@
cmake_minimum_required(VERSION 3.15)
# Project name and version
project(oscar64 VERSION 1.0 LANGUAGES CXX)
# Define the executable
add_executable(oscar64)
# Glob all source files in the oscar64/ directory
file(GLOB OSCAR64_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/oscar64/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/oscar64/*.h")
# Add the sources to the target
target_sources(${PROJECT_NAME} PRIVATE ${OSCAR64_SOURCES})
# Add header files
target_include_directories(oscar64 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Compiler settings based on configuration
set_target_properties(oscar64 PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
# Set debug and release configurations
target_compile_definitions(oscar64 PRIVATE $<$<CONFIG:Debug>:_DEBUG;_CONSOLE> $<$<CONFIG:Release>:NDEBUG;_CONSOLE>)
target_compile_options(oscar64 PRIVATE $<$<CONFIG:Debug>:/W3 /WX> $<$<CONFIG:Release>:/O2 /W3>)
# Post-build steps (only for Release builds)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_custom_command(TARGET oscar64 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:oscar64> ${CMAKE_BINARY_DIR}/bin
)
endif()
if (WIN32)
target_link_libraries(oscar64 PRIVATE kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32 version)
elseif (APPLE)
# Add macOS-specific frameworks to replace Windows libraries
target_link_libraries(${PROJECT_NAME}
"-framework Cocoa" # For GUI and application support
"-framework CoreFoundation" # For Core Foundation utilities (similar to advapi32 or shell32)
"-framework CoreGraphics" # For graphics and rendering (similar to gdi32)
"-framework IOKit" # For hardware interaction
"-framework AppKit" # For GUI (equivalent to user32)
)
elseif (UNIX)
# Add Linux-specific libraries for equivalent functionality
target_link_libraries(${PROJECT_NAME}
pthread # For threading (similar to kernel32)
dl # For dynamic library loading (similar to LoadLibrary)
m # For math library (optional but common on Linux)
X11 # For X Window System (similar to user32 for GUI support)
)
endif()
# Output directories
set_target_properties(oscar64 PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Debug
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Release
)

309
README.md
View File

@ -1,40 +1,291 @@
# oscar64
Optimizing small space C Compiler Assembler and Runtime for C64
Oscar64 is a C/C++ cross compiler running on a modern system (such as a Windows PC, Mac or Linux machine) and targets the classic 6502 family of processors. It is mainly focused on Commodore systems such as the C64, PET or VIC20. The compiler supports C99 and many C++ features up to variadic templates and lambda functions.
## History and motivation
The purpose of this compiler is to eliminate the need to write 6502 assembler code to achieve high code density and fast execution speed. It continues to improve with all the games, demos and tools written by it. It supports disk overlays and banked cartridges for larger projects.
It is a sad fact that the 6502 used in the Commodore64 and other home computers of the 80s has a poor code density when it comes to 16 bit code. The C standard requires computations to be made with ints which work best if they have the same size as a pointer.
The C64 executes 442 dhrystone V2.2 iteration per second, when compiled with Oscar64 and -O3 (which shows that the ancient dhrystone benchmark is no match to an optimizing compiler).
The 6502 also has a very small stack of 256 bytes which cannot be easily addressed and thus cannot be used for local variables. Therefore a second stack for variables has to be maintained, resulting in costly indexing operations.
[Full reference manual](oscar64.md)
[Additional samples and tutorials](https://github.com/drmortalwombat/OscarTutorials)
A C compiler for the 6502 thus generates large binaries if it translates to native machine code. The idea for the **oscar64** compiler is to translate the C source to an intermediate 16 bit byte code with the option to use native machine code for crucial functions. Using embedded assembly for runtime libraries or critical code should also be possible.
# References
The resulting compiler is a frankenstein constructed from a converted javascript parser a intermediate code optimizer based on a 15 year old compiler for 64bit x86 code and some new components for the backend.
This is a list of the games written with Oscar64, have a look if you are not convinced that fast paced action games can be written in C/C++ on a C64 (they are all free).
The performance of interpreted code is clearly not as good as native machine code but the penalty for 16bit code is around 40-50% and less than 10% for floating point. Code that can use 8bit may suffer up to a factor of 10 to 20.
The goal is to implement the actual C standard and not some subset for performance reasons. So the compiler must support:
* Floating point
* Recursion
* Multi dimensional arrays
* Pointer to structs
## Limits and Errors
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 68 iterations per second with byte code (11266) and 295 iterations with native code (11784 Bytes).
### Language
* Missing const checks for structs and enums
* Missing warnings for all kind of abuses
### Linker
### Standard Libraries
* No standard file functions, but CBM based file ops
### Runtime
* No NaN support for floats
* Basic zero page variables not restored on stop/restore
### Optimizing
* Auto variables placed on fixed stack for known call sequence
### Intermediate code generation
* No check for running out of temporary registers
* Wasted 7 codes for far jumps
### Native code generation
## Compiler arguments
The compiler is command line driven, and creates an executable .prg file.
oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-e] [-n] [-dSYMBOL[=value]] {source.c}
* -v : verbose output for diagnostics
* -i : additional include paths
* -o : optional output file name
* -rt : alternative runtime library, replaces the crt.c
* -e : execute the result in the integrated emulator
* -n : create pure native code for all functions
* -d : define a symbol (e.g. NOFLOAT or NOLONG to avoid float/long code in printf)
* -O1 or -O : default optimizations
* -O0: disable optimizations
* -O2: more aggressive speed optimizations including auto inline of small functions
* -O3: aggressive optimization for speed
* -Os: optimize for size
A list of source files can be provided.
## Console input and output
The C64 does not use ASCII it uses a derivative called PETSCII. There are two fonts, one with uppercase and one with uppercase and lowercase characters. It also used CR (13) as line terminator instead of LF (10). The stdio and conio libaries can perform translations.
The translation mode is selected in conio with the variable "giocharmap" and the function "iocharmap" which will also switch the font.
iocharmap(IOCHM_PETSCII_2);
printf("Hello World\n");
Will switch to the lowercase PETSCII font and translate the strings while printing.
PETSCII string literals can also be generated using a "p" or "P" prefix such as:
printf(p"Hello World\n");
Screen codes can be generated similar using "s" or "S" prefix.
Input from the console will also be translated accordingly.
## Embedding binary data
The compiler supports the #embed preprocessor directive to import binary data. It converts a section of an external binary file into a sequence of numbers that can be placed into an initializer of an array.
byte data[] = {
#embed "data.bin"
};
A section of the file can be selected by providing a limit and or an offset into the file before the file name.
byte data[] = {
#embed 4096 126 "data.bin"
};
## Language extensions for optimization
### Additional Optimizer information using __assume()
The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion.
### Marking functions as native
Routines can be marked to be compiled to 6502 machine code with the native pragma:
void Plot(int x, int y)
{
(*Bitmap)[y >> 3][x >> 3][y & 7] |= 0x80 >> (x & 7);
}
#pragma native(Plot)
Or alternatively with a __native storage class specifier
__native void Plot(int x, int y)
{
(*Bitmap)[y >> 3][x >> 3][y & 7] |= 0x80 >> (x & 7);
}
### Linker control
The linker includes only objects that are referenced, starting by the startup code into main() and so on.
If you need to have a function or variable present regardless, you can specify it with the __export storage class specifier or use the #pragma reference(name) pragma.
## Inline Assembler
Inline assembler can be embedded inside of any functions, regardles of their compilation target of byte code or native.
### Accessing variables in assembler
Access to local variables and parameters is done with zero page registers, global variables are accessed using absolute addressing.
void putchar(char c)
{
__asm {
lda c
bne w1
lda #13
w1:
jsr 0xffd2
}
}
A function return value can be provided in the zero page addresses ACCU (+0..+3).
char getchar(void)
{
__asm {
jsr 0xffcf
sta accu
lda #0
sta accu + 1
}
}
Labels are defined with a colon after the name. Pure assembler functions can be defined outside of the scope of a function and accessed using their name inside of other assembler function. One can e.g. set up an interrupt
### Interrupt routines
The C compiler will not generate good interrupt code, it is simply too greedy with the zero page registers. Interrupt code should therefore be written in assembler.
#include <math.h>
// Next line for interrupt
volatile char npos;
// Interrupt routine
__asm irq
{
lda $d019 // Check if it is raster IRQ
and #$01
beq w1
inc $d020 // Start colored section
inc $d021
ldx #20 // Wait for 2/3 lines
l1: dex
bne l1
dec $d020 // End colored section
dec $d021
lda npos // Setup next interrupt
sta $d012
w1:
asl $d019 // Ack interrupt
jmp $ea31 // System IRQ routine
}
int main(void)
{
__asm { sei } // Disable interrupt
*(void **)0x0314 = irq; // Install interrupt routine
*(char *)0xd01a = 1; // Enable raster interrupt
*(char *)0xd011 &= 0x7f; // Set raster line for IRQ
*(char *)0xd012 = 100;
npos = 100;
__asm { cli } // Re-enable interrupt
// Move the interrupt raster line up/down
float f = 0;
while (true)
{
npos = 130 + (int)(100 * sin(f));
f += 0.1;
}
return 0;
}
## Implementation Details
The compiler does a full program compile, the linker step is part of the compilation. It knows all functions during the compilation run and includes only reachable code in the output. Source files are added to the build with the help of a pragma:
#pragma compile("stdio.c")
The character map for string and char constants can be changed with a pragma to match a custon character set or PETSCII.
#pragma charmap(char, code [,count])
The byte code interpreter is compiled by the compiler itself and placed in the source file "crt.c". Functions implementing byte codes are marked with a pragma:
#pragma bytecode(BC_CONST_P8, inp_const_p8)
The functions are written in 6502 assembly with the __asm keyword
__asm inp_const_p8
{
lda (ip), y
tax
iny
lda (ip), y
sta $00, x
lda #0
sta $01, x
iny
jmp startup.exec
}
The current byte code program counter is (ip),y. The interpreter loop guarantees that y is always <= 128 and can thus be used to index the additional byte code arguments without the need to check the 16 bit pointer. The interpreter loop itself is quite compact and takes 21 cycles (including the final jump of the byte code function itself). Moving it to zero page would reduce this by another two cycles but is most likely not worth the waste of temporary space.
exec:
lda (ip), y
sta execjmp + 1
iny
bmi incip
execjmp:
jmp (0x0900)
The intermediate code generator assumes a large number of registers so the zero page is used for this purpose. The allocation is not yet final:
* **0x02-0x02** spilling of y register
* **0x03-0x09** workspace for mul/div and floating point routines
* **0x19-0x1a** instruction pointer
* **0x1b-0x1e** integer and floating point accumulator
* **0x1f-0x22** pointers for indirect addressing
* **0x23-0x24** stack pointer
* **0x25-0x26** frame pointer
* **0x43-0x52** caller saved registers
* **0x53-0x8f** callee saved registers
[Ball and Chain](https://drmortalwombat.itch.io/ball-and-chain)
[Balls like a Frog](https://drmortalwombat.itch.io/balls-like-a-frog)
![cores4](https://github.com/user-attachments/assets/15c2bcc7-eafb-44fb-aec2-e5cb101c687b)
[Corescape](https://drmortalwombat.itch.io/corescape)
[MetalMayhem](https://drmortalwombat.itch.io/metal-mayhem)
[Mineshaft Gap](https://drmortalwombat.itch.io/mineshaft-gap)
[Minotrace](https://drmortalwombat.itch.io/minotrace)
[Missile Defence](https://drmortalwombat.itch.io/missile-defence)
![cl1b](https://github.com/user-attachments/assets/0d249274-6dab-4284-89e5-ada07fac1986)
[Portal Buster](https://drmortalwombat.itch.io/portal-buster)
[Roguebot](https://drmortalwombat.itch.io/roguebot)
[Shallow Domains](https://drmortalwombat.itch.io/shallow-domains)
[Veggies vs Undead](https://drmortalwombat.itch.io/veggies-vs-undead)

View File

@ -1,152 +0,0 @@
#include <assert.h>
int t, n, m, k;
struct C1
{
int a;
C1(void);
~C1(void);
C1(const C1 & c);
C1 & operator=(const C1 & c);
};
struct C2
{
C1 nc[10], mc[20];
};
C1::C1(void)
{
a = 1;
n++;
t++;
}
C1::C1(const C1 & c)
{
a = c.a;
k++;
t++;
}
C1 & C1::operator=(const C1 & c)
{
a = c.a;
m++;
return *this;
}
C1::~C1(void)
{
t--;
}
void test_local_init(void)
{
n = 0;
{
C1 c[10];
}
assert(n == 10 && t == 0);
}
void test_member_init(void)
{
n = 0;
{
C2 d;
}
assert(n == 30 && t == 0);
}
void test_member_array_init(void)
{
n = 0;
{
C2 d[5];
}
assert(n == 150 && t == 0);
}
void test_local_copy(void)
{
n = 0;
k = 0;
{
C1 c[10];
C1 d(c[4]);
}
assert(n == 10 && k == 1 && t == 0);
}
void test_member_copy(void)
{
n = 0;
k = 0;
{
C2 d;
C2 e(d);
}
assert(n == 30 && k == 30 && t == 0);
}
void test_local_assign(void)
{
n = 0;
k = 0;
m = 0;
{
C1 c[10];
C1 d[5];
d[4] = c[2];
}
assert(n == 15 && k == 0 && m == 1 && t == 0);
}
void test_member_assign(void)
{
n = 0;
k = 0;
m = 0;
{
C2 d;
C2 e;
e = d;
}
assert(n == 60 && k == 0 && m == 30 && t == 0);
}
int main(void)
{
test_local_init();
test_member_init();
test_member_array_init();
test_local_copy();
test_member_copy();
test_local_assign();
test_member_assign();
return 0;
}

View File

@ -1,22 +0,0 @@
int a[10];
int get(int i)
{
return a[i];
}
void put(int i, int x)
{
a[i] = x;
}
int main(void)
{
for(int j=0; j<10; j++)
put(j, j);
int s = -45;
for(int j=0; j<10; j++)
s += get(j);
return s;
}

View File

@ -79,7 +79,6 @@ int main(void)
}
assert(sum(a, 100) == 450);
copy(b, a, 100);
assert(sum(b, 100) == 450);
reverse(c, a, 100);

View File

@ -3,7 +3,7 @@
int asum(int a, int b)
{
return __asm
__asm
{
clc
lda a
@ -12,14 +12,14 @@ int asum(int a, int b)
lda a + 1
adc b + 1
sta accu + 1
};
}
}
int bsum(int a, int b)
{
puts("Hello\n");
return __asm
__asm
{
clc
lda a
@ -28,7 +28,7 @@ int bsum(int a, int b)
lda a + 1
adc b + 1
sta accu + 1
};
}
}
int b, t[10];

View File

@ -1,77 +0,0 @@
#include <stdio.h>
#include <assert.h>
struct X
{
char t;
long l;
};
__striped X xs[16];
X xf[16];
char xp;
__noinline long tt(long n)
{
return n;
}
inline auto & tas(void)
{
return xs[xp].l;
}
inline auto & taf(void)
{
return xf[xp].l;
}
long ts(char n)
{
return tt(tas());
}
long tf(char n)
{
return tt(taf());
}
inline auto bas(void)
{
return xs[xp].l;
}
inline auto baf(void)
{
return xs[xp].l;
}
long bs(char n)
{
return tt(bas());
}
long bf(char n)
{
return tt(baf());
}
int main(void)
{
for(char i=0; i<16; i++)
{
xs[i].l = i * i;
xf[i].l = i * i;
}
for(char i=0; i<16; i++)
{
xp = i;
assert(ts(0) == i * i);
assert(tf(0) == i * i);
assert(bs(0) == i * i);
assert(bf(0) == i * i);
}
return 0;
}

View File

@ -1,75 +1,6 @@
rem @echo off
@call :test rolrortest.cpp
@if %errorlevel% neq 0 goto :error
@call :test bitfields.cpp
@if %errorlevel% neq 0 goto :error
@call :testn autorefreturn.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_string.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_array.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_vector.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_static_vector.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_vector_string.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_string_init.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_streamtest.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_pairtest.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_parts.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_list.cpp
@if %errorlevel% neq 0 goto :error
@call :testn opp_functional.cpp
@if %errorlevel% neq 0 goto :error
@call :testh operatoroverload.cpp
@if %errorlevel% neq 0 goto :error
@call :testh virtualdestruct.cpp
@if %errorlevel% neq 0 goto :error
@call :testh vcalltest.cpp
@if %errorlevel% neq 0 goto :error
@call :testh vcalltree.cpp
@if %errorlevel% neq 0 goto :error
@call :testh constructortest.cpp
@if %errorlevel% neq 0 goto :error
@call :testn copyconstructor.cpp
@if %errorlevel% neq 0 goto :error
@call :testh copyassign.cpp
@if %errorlevel% neq 0 goto :error
@call :testh arrayconstruct.cpp
@if %errorlevel% neq 0 goto :error
@call :testh stdlibtest.c
@if %errorlevel% neq 0 goto :error
@call :test mathtest.c
@call :test stdlibtest.c
@if %errorlevel% neq 0 goto :error
@call :test testint16.c
@ -81,33 +12,18 @@ rem @echo off
@call :test testint16mul.c
@if %errorlevel% neq 0 goto :error
@call :test testsigned16mul.c
@if %errorlevel% neq 0 goto :error
@call :test testsigned16div.c
@if %errorlevel% neq 0 goto :error
@call :test recursiontest.c
@if %errorlevel% neq 0 goto :error
@call :test copyinitmove.c
@if %errorlevel% neq 0 goto :error
@call :test fastcalltest.c
@if %errorlevel% neq 0 goto :error
@call :test strlen.c
@if %errorlevel% neq 0 goto :error
@call :test strcmptest.c
@if %errorlevel% neq 0 goto :error
@call :test strcmptest2.c
@if %errorlevel% neq 0 goto :error
@call :test memmovetest.c
@if %errorlevel% neq 0 goto :error
@call :test arraytest.c
@if %errorlevel% neq 0 goto :error
@ -123,18 +39,12 @@ rem @echo off
@call :test floatmultest.c
@if %errorlevel% neq 0 goto :error
@call :test floatinttest.c
@if %errorlevel% neq 0 goto :error
@call :test staticconsttest.c
@if %errorlevel% neq 0 goto :error
@call :test arrayinittest.c
@if %errorlevel% neq 0 goto :error
@call :test arrayindexintrangecheck.c
@if %errorlevel% neq 0 goto :error
@call :test array2stringinittest.c
@if %errorlevel% neq 0 goto :error
@ -147,9 +57,6 @@ rem @echo off
@call :test testint32cmp.c
@if %errorlevel% neq 0 goto :error
@call :test mixsigncmptest.c
@if %errorlevel% neq 0 goto :error
@call :test testinterval.c
@if %errorlevel% neq 0 goto :error
@ -159,15 +66,9 @@ rem @echo off
@call :test floatstringtest.c
@if %errorlevel% neq 0 goto :error
@call :test sprintftest.c
@if %errorlevel% neq 0 goto :error
@call :test qsorttest.c
@if %errorlevel% neq 0 goto :error
@call :testn plasma.c
@if %errorlevel% neq 0 goto :error
@call :test loopdomtest.c
@if %errorlevel% neq 0 goto :error
@ -195,12 +96,6 @@ rem @echo off
@call :test divmodtest.c
@if %errorlevel% neq 0 goto :error
@call :test divmod32test.c
@if %errorlevel% neq 0 goto :error
@call :test fixmathtest.c
@if %errorlevel% neq 0 goto :error
@call :test enumswitch.c
@if %errorlevel% neq 0 goto :error
@ -213,18 +108,12 @@ rem @echo off
@call :test funcvartest.c
@if %errorlevel% neq 0 goto :error
@call :test funcarraycall.c
@if %errorlevel% neq 0 goto :error
@call :test structassigntest.c
@if %errorlevel% neq 0 goto :error
@call :test structmembertest.c
@if %errorlevel% neq 0 goto :error
@call :test structarraycopy.c
@if %errorlevel% neq 0 goto :error
@call :test randsumtest.c
@if %errorlevel% neq 0 goto :error
@ -237,164 +126,50 @@ rem @echo off
@call :test charwintest.c
@if %errorlevel% neq 0 goto :error
@call :test linetest.c
@if %errorlevel% neq 0 goto :error
@call :test ptrinittest.c
@if %errorlevel% neq 0 goto :error
@call :test ptrarraycmptest.c
@if %errorlevel% neq 0 goto :error
@call :test cplxstructtest.c
@if %errorlevel% neq 0 goto :error
@call :testn stripedarraytest.c
@if %errorlevel% neq 0 goto :error
@call :testn mmultest.c
@if %errorlevel% neq 0 goto :error
@call :test tileexpand.cpp
@if %errorlevel% neq 0 goto :error
@exit /b 0
:error
echo Failed with error #%errorlevel%.
exit /b %errorlevel%
:testh
..\bin\oscar64 -e -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -n -dHEAPCHECK %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Oo -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Ox -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O0 -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O0 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -Os -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -Os -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -n -dHEAPCHECK %~1
@if %errorlevel% neq 0 goto :error
@exit /b 0
:test
..\bin\oscar64 -e -bc %~1
..\release\oscar64 -e %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -n %~1
..\release\oscar64 -e -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -bc %~1
..\release\oscar64 -e -O2 %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -n %~1
..\release\oscar64 -e -O2 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O0 -bc %~1
..\release\oscar64 -e -O0 %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O0 -n %~1
..\release\oscar64 -e -O0 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -Os -bc %~1
..\release\oscar64 -e -O3 %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -Os -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Oo -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Ox -n %~1
..\release\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
@exit /b 0
:testb
..\bin\oscar64 -e -bc %~1
..\release\oscar64 -e %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -bc -O2 %~1
..\release\oscar64 -e -O2 %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -bc -O0 %~1
..\release\oscar64 -e -O0 %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -bc -Os %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -bc -O3 %~1
@if %errorlevel% neq 0 goto :error
@exit /b 0
:testn
..\bin\oscar64 -e -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O0 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -Os -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Oo -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Ox -n %~1
..\release\oscar64 -e -O3 %~1
@if %errorlevel% neq 0 goto :error
@exit /b 0

View File

@ -1,354 +0,0 @@
#include <assert.h>
struct A
{
char x : 4;
char y : 1;
char z : 3;
};
A a = {7, 1, 2};
void test_char_fit(void)
{
assert(a.x == 7);
assert(a.y == 1);
assert(a.z == 2);
assert(sizeof(A) == 1);
for(int i=0; i<16; i++)
{
a.x = i;
a.y = 0;
a.z = 3;
assert(a.x == i);
assert(a.y == 0);
assert(a.z == 3);
}
}
struct B
{
char x : 6;
char y : 6;
char z : 6;
char w : 6;
};
B b = {11, 22, 33, 44};
void test_char_cross(void)
{
assert(b.x == 11);
assert(b.y == 22);
assert(b.z == 33);
assert(b.w == 44);
assert(sizeof(B) == 3);
for(int i=0; i<64; i++)
{
b.x = i * 1;
b.y = i * 3;
b.z = i * 5;
b.w = i * 7;
assert(b.x == ((i * 1) & 0x3f));
assert(b.y == ((i * 3) & 0x3f));
assert(b.z == ((i * 5) & 0x3f));
assert(b.w == ((i * 7) & 0x3f));
}
}
struct C
{
unsigned x : 4;
unsigned y : 1;
unsigned z : 3;
};
C c = {7, 1, 2};
void test_word_fit(void)
{
assert(c.x == 7);
assert(c.y == 1);
assert(c.z == 2);
assert(sizeof(C) == 1);
for(int i=0; i<16; i++)
{
c.x = i;
c.y = 0;
c.z = 3;
assert(c.x == i);
assert(c.y == 0);
assert(c.z == 3);
}
}
struct D
{
unsigned x : 10;
unsigned y : 10;
unsigned z : 10;
unsigned w : 10;
};
D d = {111, 222, 333, 444};
void test_word_cross(void)
{
assert(d.x == 111);
assert(d.y == 222);
assert(d.z == 333);
assert(d.w == 444);
assert(sizeof(D) == 5);
for(int i=0; i<1024; i++)
{
d.x = i * 1;
d.y = i * 3;
d.z = i * 5;
d.w = i * 7;
assert(d.x == ((i * 1) & 0x3ff));
assert(d.y == ((i * 3) & 0x3ff));
assert(d.z == ((i * 5) & 0x3ff));
assert(d.w == ((i * 7) & 0x3ff));
}
}
struct E
{
unsigned long x : 4;
unsigned long y : 1;
unsigned long z : 3;
};
E e = {7, 1, 2};
void test_dword_fit(void)
{
assert(e.x == 7);
assert(e.y == 1);
assert(e.z == 2);
assert(sizeof(E) == 1);
for(int i=0; i<16; i++)
{
e.x = i;
e.y = 0;
e.z = 3;
assert(e.x == i);
assert(e.y == 0);
assert(e.z == 3);
}
}
struct F
{
unsigned long x : 20;
unsigned long y : 20;
unsigned long z : 20;
unsigned long w : 20;
};
F f = {111111UL, 222222UL, 333333UL, 444444UL};
void test_dword_cross(void)
{
assert(f.x == 111111UL);
assert(f.y == 222222UL);
assert(f.z == 333333UL);
assert(f.w == 444444UL);
assert(sizeof(F) == 10);
for(int i=0; i<1024; i++)
{
f.x = i * 11UL;
f.y = i * 33UL;
f.z = i * 55UL;
f.w = i * 77UL;
assert(f.x == ((i * 11UL) & 0xfffffUL));
assert(f.y == ((i * 33UL) & 0xfffffUL));
assert(f.z == ((i * 55UL) & 0xfffffUL));
assert(f.w == ((i * 77UL) & 0xfffffUL));
}
}
struct G
{
signed char x : 1;
signed char y : 5;
signed char z : 2;
};
G g = {0, -1, -2};
void test_char_signed(void)
{
assert(g.x == 0);
assert(g.y == -1);
assert(g.z == -2);
assert(sizeof(G) == 1);
for(int i=-16; i<16; i++)
{
g.x = -1;
g.y = i;
g.z = 1;
assert(g.x == -1);
assert(g.y == i);
assert(g.z == 1);
}
}
struct H
{
int x : 10;
int y : 10;
int z : 10;
int w : 10;
};
H h = {111, -222, -333, 444};
void test_word_signed(void)
{
assert(h.x == 111);
assert(h.y == -222);
assert(h.z == -333);
assert(h.w == 444);
assert(sizeof(H) == 5);
for(int i=-32; i<32; i++)
{
h.x = i * 1;
h.y = i * 3;
h.z = i * 5;
h.w = i * 7;
assert(h.x == i * 1);
assert(h.y == i * 3);
assert(h.z == i * 5);
assert(h.w == i * 7);
}
}
void test_inc_char_fit(void)
{
A ai;
ai.x = 7;
ai.y = 1;
ai.z = 2;
for(int i=0; i<16; i++)
{
assert(ai.x == ((7 + i) & 15));
assert(ai.y == ((1 + i) & 1));
assert(ai.z == ((2 + i) & 7));
ai.x++;
ai.y++;
ai.z++;
}
}
void test_inc_char_cross(void)
{
B bi;
bi.x = 11;
bi.y = 22;
bi.z = 33;
bi.w = 44;
for(int i=0; i<64; i++)
{
assert(bi.x == ((11 + i) & 0x3f));
assert(bi.y == ((22 + i) & 0x3f));
assert(bi.z == ((33 + i) & 0x3f));
assert(bi.w == ((44 + i) & 0x3f));
bi.x++;
bi.y++;
bi.z++;
bi.w++;
}
}
void test_add_char_cross(void)
{
B bi= {0};
bi.x = 11;
bi.y = 22;
bi.z = 33;
bi.w = 44;
for(int i=0; i<64; i++)
{
assert(bi.x == ((11 + 5 * i) & 0x3f));
assert(bi.y == ((22 + 21 * i) & 0x3f));
assert(bi.z == ((33 - 4 * i) & 0x3f));
assert(bi.w == ((44 - 11 * i) & 0x3f));
bi.x += 5;
bi.y += 21;
bi.z -= 4;
bi.w -= 11;
}
}
void test_add_word_fit(void)
{
C ci = {0};
ci.x = 7;
ci.y = 1;
ci.z = 2;
for(int i=0; i<16; i++)
{
assert(ci.x == ((7 + 5 * i) & 15));
assert(ci.y == ((1 + 21 * i) & 1));
assert(ci.z == ((2 - 4 * i) & 7));
ci.x += 5;
ci.y += 21;
ci.z -= 4;
}
}
void test_add_word_cross(void)
{
D di = {0};
di.x = 111;
di.y = 222;
di.z = 333;
di.w = 444;
for(int i=0; i<1024; i++)
{
assert(di.x == ((111 + 5 * i) & 0x3ff));
assert(di.y == ((222 + 21 * i) & 0x3ff));
assert(di.z == ((333 - 4 * i) & 0x3ff));
assert(di.w == ((444 - 11 * i) & 0x3ff));
di.x += 5;
di.y += 21;
di.z -= 4;
di.w -= 11;
}
}
int main(void)
{
test_char_fit();
test_char_cross();
test_word_fit();
test_word_cross();
test_dword_fit();
test_dword_cross();
test_char_signed();
test_word_signed();
test_inc_char_fit();
test_inc_char_cross();
test_add_char_cross();
test_add_word_fit();
test_add_word_cross();
return 0;
}

View File

@ -303,18 +303,6 @@ void shr32n(unsigned long xu, long xi)
}
}
void shl1_32n(void)
{
static const unsigned long m[] = {
#for(i, 32) 1ul << i,
};
for(int i=0; i<32; i++)
{
assert(1ul << i == m[i]);
}
}
#pragma native(shl32n)
#pragma native(shr32n)
@ -374,7 +362,6 @@ int main(void)
shr16b(0xfedc, 0xfedc);
shl16n(0x0000, 0x0000);
shl16n(0xffff, 0xffff);
shl16n(0x1234, 0x1234);
shl16n(0xfedc, 0xfedc);
@ -385,30 +372,24 @@ int main(void)
shr16n(0xfedc, 0xfedc);
shl32b(0x00000000UL, 0x00000000L);
shl32b(0x00000001UL, 0x00000001L);
shl32b(0xffffffffUL, 0xffffffffL);
shl32b(0x12345678UL, 0x12345678L);
shl32b(0xfedcba98UL, 0xfedcba98L);
shr32b(0x00000000UL, 0x00000000L);
shr32b(0x00000001UL, 0x00000001L);
shr32b(0xffffffffUL, 0xffffffffL);
shr32b(0x12345678UL, 0x12345678L);
shr32b(0xfedcba98UL, 0xfedcba98L);
shl32n(0x00000000UL, 0x00000000L);
shl32n(0x00000001UL, 0x00000001L);
shl32n(0xffffffffUL, 0xffffffffL);
shl32n(0x12345678UL, 0x12345678L);
shl32n(0xfedcba98UL, 0xfedcba98L);
shr32n(0x00000000UL, 0x00000000L);
shr32n(0x00000001UL, 0x00000001L);
shr32n(0xffffffffUL, 0xffffffffL);
shr32n(0x12345678UL, 0x12345678L);
shr32n(0xfedcba98UL, 0xfedcba98L);
shl1_32n();
return 0;
}

View File

@ -1,165 +0,0 @@
#include <assert.h>
int t, n;
struct C1
{
int a;
C1(int x);
~C1(void);
};
C1::C1(int x) : a(x)
{
t += a;
n++;
}
C1::~C1(void)
{
t -= a;
}
void test_base(void)
{
n = 0;
{
C1 x(2);
C1 y(1);
}
assert(t == 0 && n == 2);
}
void test_base_loop(void)
{
n = 0;
for(int i=0; i<10; i++)
{
C1 x(2);
C1 y(1);
}
assert(t == 0 && n == 20);
}
struct C2
{
C1 c, d;
C2(void);
};
C2::C2(void)
: c(7), d(11)
{
}
void test_member(void)
{
n = 0;
{
C2 x();
C2 y();
}
assert(t == 0 && n == 4);
}
void test_member_loop(void)
{
n = 0;
for(int i=0; i<10; i++)
{
C2 x();
C2 y();
}
assert(t == 0 && n == 40);
}
struct C3
{
C2 x, y;
};
void test_default(void)
{
n = 0;
{
C3 x();
C3 y();
}
assert(t == 0 && n == 8);
}
void test_default_loop(void)
{
n = 0;
for(int i=0; i<10; i++)
{
C3 x();
C3 y();
}
assert(t == 0 && n == 80);
}
inline void test_inline_x(void)
{
C1 x(1), y(2);
}
void test_inline(void)
{
n = 0;
test_inline_x();
assert(t == 0 && n == 2);
}
inline void test_inline_xr(void)
{
C1 x(1), y(2);
{
C1 x(3);
return;
}
}
void test_inline_return(void)
{
n = 0;
test_inline_xr();
assert(t == 0 && n == 3);
}
int main(void)
{
test_base();
test_base_loop();
test_member();
test_member_loop();
test_default();
test_default_loop();
test_inline();
test_inline_return();
return 0;
}

View File

@ -1,126 +0,0 @@
#include <assert.h>
int t, n;
struct C0
{
int u;
C0(int a);
~C0(void);
};
C0::C0(int a) : u(a)
{
t += u;
n++;
}
C0::~C0(void)
{
t -= u;
}
struct C1
{
int u;
C1(int a);
~C1(void);
C1(const C1 & c);
C1 & operator=(const C1 & c);
};
C1::C1(int a) : u(a)
{
t += u;
n++;
}
C1::~C1(void)
{
t -= u;
}
C1::C1(const C1 & c) : u(c.u)
{
t += u;
n++;
}
C1 & C1::operator=(const C1 & c)
{
t -= u;
u = c.u;
t += u;
return *this;
}
void test_assign(void)
{
n = 0;
{
C1 c(4);
C1 d(5);
c = d;
}
assert(n == 2 && t == 0);
}
struct C2
{
C1 a, b;
C2(int x, int y) : a(x), b(y)
{}
};
void test_assign_deflt(void)
{
n = 0;
{
C2 c(2, 3);
C2 d(5, 10);
c = d;
}
assert(n == 4 && t == 0);
}
int k;
C2 test_ret_v(void)
{
C2 c(5, 10);
return c;
}
C2 & test_ret_r(C2 & r)
{
return r;
}
void test_assign_return_value(void)
{
n = 0;
{
C2 c(2, 3);
c = test_ret_v();
}
assert(n == 6 && t == 0);
}
int main(void)
{
test_assign();
test_assign_deflt();
test_assign_return_value();
return 0;
}

View File

@ -1,215 +0,0 @@
#include <assert.h>
#include <stdio.h>
int t, n;
struct C0
{
int u;
C0(int a);
~C0(void);
};
C0::C0(int a) : u(a)
{
t += u;
n++;
}
C0::~C0(void)
{
t -= u;
}
struct C1
{
int u;
C1(int a);
~C1(void);
C1(const C1 & c);
};
C1::C1(int a) : u(a)
{
t += u;
n++;
}
C1::~C1(void)
{
t -= u;
}
C1::C1(const C1 & c) : u(c.u)
{
t += u;
n++;
}
void test_dcopy_init(void)
{
n = 0;
{
C0 x(4);
C0 y(x);
}
assert(n == 1 && t == -4);
t = 0;
}
void test_copy_init(void)
{
n = 0;
{
C1 x(4);
C1 y(x);
}
assert(n == 2 && t == 0);
}
struct C2
{
C1 a, b;
C2(void);
};
C2::C2(void) : a(1), b(3)
{}
void test_minit(void)
{
n = 0;
{
C2 x;
}
assert(n == 2 && t == 0);
}
void test_minit_copy(void)
{
n = 0;
{
C2 x;
C2 y(x);
}
assert(n == 4 && t == 0);
}
int k;
void test_param_fv(C2 c)
{
k += c.a.u;
}
void test_param_fr(C2 & c)
{
k += c.a.u;
}
void test_param_value(void)
{
n = 0;
{
C2 x;
test_param_fv(x);
}
assert(n == 4 && t == 0);
}
void test_param_ref(void)
{
n = 0;
{
C2 x;
test_param_fr(x);
}
assert(n == 2 && t == 0);
}
C2 test_ret_v(void)
{
C2 c;
return c;
}
C2 & test_ret_r(C2 & r)
{
return r;
}
void test_return_value(void)
{
n = 0;
{
C2 c(test_ret_v());
}
assert(n == 6 && t == 0);
}
void test_return_reference(void)
{
n = 0;
{
C2 d;
C2 c(test_ret_r(d));
}
assert(n == 2 && t == 0);
}
void test_retparam_value(void)
{
n = 0;
{
test_param_fv(test_ret_v());
}
assert(n == 6 && t == 0);
}
void test_retparam_reference(void)
{
n = 0;
{
test_param_fr(test_ret_v());
}
assert(n == 4 && t == 0);
}
int main(void)
{
test_dcopy_init();
test_copy_init();
test_minit();
test_minit_copy();
test_param_value();
test_param_ref();
test_return_value();
test_retparam_value();
test_retparam_reference();
return 0;
}

View File

@ -1,27 +0,0 @@
int val(char * c)
{
return c[0];
}
void set(char * c, int a)
{
c[0] = a;
}
int main(void)
{
int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
for(int i=0; i<10; i++)
{
char t[10] = {1};
sum0 += val(t);
sum2 += t[0];
set(t, i);
sum1 += val(t);
sum3 += t[0];
}
return (sum1 - 45) | (sum0 - 10) | (sum3 - 45) | (sum2 - 10);
}

View File

@ -1,97 +0,0 @@
#include <stdio.h>
#include <math.h>
#include <assert.h>
struct cplx
{
float r, i;
};
cplx cplx_add(cplx a, cplx b)
{
cplx c;
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
cplx cplx_sub(cplx a, cplx b)
{
cplx c;
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
cplx cplx_mul(cplx a, cplx b)
{
cplx c;
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
float cplx_abs(cplx a)
{
return sqrt(a.r * a.r + a.i * a.i);
}
cplx cplx_sum(cplx p, const cplx * a, int n)
{
cplx s = {0.0, 0.0};
cplx c = {1.0, 0.0};
for(int i=0; i<n; i++)
{
s = cplx_add(s, cplx_mul(a[i], c));
c = cplx_mul(c, p);
}
return s;
}
int main(void)
{
cplx sig[100];
for(int i=0; i<100; i++)
{
sig[i].r = cos(i * 1.3);
sig[i].i = sin(i * 1.3);
}
cplx c = {1.0, 0.0};
float phi = 0.1 * PI;
cplx t;
t.r = cos(phi); t.i = sin(phi);
float p[20], q[20];
for(int i=0; i<20; i++)
{
p[i] = cplx_abs(cplx_sum(c, sig, 100));
c = cplx_mul(c, t);
}
for(int i=0; i<20; i++)
{
float sumr = 0.0, sumi = 0.0;
for(int j=0; j<100; j++)
{
float co = cos(i * j * 0.1 * PI), si = sin(i * j * 0.1 * PI);
sumr += co * sig[j].r - si * sig[j].i;
sumi += si * sig[j].r + co * sig[j].i;
}
q[i] = sqrt(sumr * sumr + sumi * sumi);
}
#if 1
for(int i=0; i<20; i++)
{
printf("%d, %f - %f\n", i, p[i], q[i]);
}
#endif
for(int i=0; i<20; i++)
assert(fabs(p[i] - q[i]) < 1.0);
return 0;
}

View File

@ -1,36 +0,0 @@
#include <assert.h>
void check(unsigned long l, unsigned long r)
{
unsigned long d = l / r, m = l % r;
assert(d * r + m == l);
assert(m < r);
}
int main(void)
{
for(char i=0; i<28; i++)
{
for(char j=0; j<28; j++)
{
check(0xb3ul << i, 0x2bul << j);
check(0xb3ul << i, 0x01ul << j);
check(0x01ul << i, 0xc2ul << j);
check(0xb31ful << i, 0x2bul << j);
check(0xb354ul << i, 0x01ul << j);
check(0xb3ul << i, 0x2b1cul << j);
check(0xb3ul << i, 0x013ful << j);
check(0xb31ful << i, 0x2b23ul << j);
check(0xb354ul << i, 0x0145ul << j);
check(0xb31f24ul << i, 0x2bul << j);
check(0xb35421ul << i, 0x01ul << j);
check(0xb31f24ul << i, 0x2b23ul << j);
check(0xb35421ul << i, 0x0145ul << j);
check(0xb31f24ul << i, 0x2b2356ul << j);
check(0xb35421ul << i, 0x0145a7ul << j);
}
}
return 0;
}

View File

@ -1,90 +0,0 @@
#include <fixmath.h>
#include <assert.h>
#include <stdlib.h>
unsigned tval[] = {
1, 2, 16, 128, 255, 256, 4096, 32768, 65535
};
void testmuldiv16u(void)
{
for (char i=0; i<9; i++)
{
assert(lmuldiv16u(tval[i], 0, tval[i]) == 0);
assert(lmuldiv16u(0, tval[i], tval[i]) == 0);
for(char j=0; j<9; j++)
{
assert(lmuldiv16u(tval[i], tval[j], tval[i]) == tval[j]);
assert(lmuldiv16u(tval[j], tval[i], tval[i]) == tval[j]);
}
}
for(int i=0; i<10000; i++)
{
unsigned a = rand();
unsigned b = rand();
unsigned c = rand();
if (c > 0)
{
unsigned long d = (unsigned long)a * (unsigned long) b / c;
if (d < 0x10000l)
assert(lmuldiv16u(a, b, c) == d);
}
}
}
unsigned ival[] = {
1, 2, 16, 128, 255, 256, 4096, 32767,
-1, -2, -16, -128, -255, -256, -4096, -32767
};
void testmuldiv16s(void)
{
for (char i=0; i<16; i++)
{
assert(lmuldiv16s(ival[i], 0, ival[i]) == 0);
assert(lmuldiv16s(0, ival[i], ival[i]) == 0);
for(char j=0; j<16; j++)
{
assert(lmuldiv16s(ival[i], ival[j], ival[i]) == ival[j]);
assert(lmuldiv16s(ival[j], ival[i], ival[i]) == ival[j]);
}
}
for(int i=0; i<10000; i++)
{
int a = rand();
int b = rand();
int c = rand();
if (c > 0)
{
long d = (long)a * (long)b / c;
if (d >= -32768 && d <= 32767)
assert(lmuldiv16s(a, b, c) == d);
}
}
}
void testlmul4f12s(void)
{
for(int i=0; i<20000; i++)
{
int a = rand();
int b = rand();
long d = ((long)a * (long)b) >> 12;
if (d >= -32768 && d <= 32767)
assert(lmul4f12s(a, b) == d);
}
}
int main(void)
{
testlmul4f12s();
testmuldiv16u();
testmuldiv16s();
return 0;
}

View File

@ -12,50 +12,16 @@ bool flt(float a, float b)
return a < b;
}
bool fle(float a, float b)
{
return a <= b;
}
bool fgt(float a, float b)
{
return a > b;
}
bool fge(float a, float b)
void cmpflt(float a, float b, bool eq, bool lt, bool gt)
{
return a >= b;
}
volatile float f;
inline void cmpflt(float a, float b, bool eq, bool lt, bool gt)
{
bool le = eq || lt;
bool ge = eq || gt;
assert(feq(a, b) == eq);
assert(flt(a, b) == lt);
assert(fgt(a, b) == gt);
assert(fle(a, b) == le);
assert(fge(a, b) == ge);
f = a;
assert(feq(f, b) == eq);
assert(flt(f, b) == lt);
assert(fgt(f, b) == gt);
assert(fle(f, b) == le);
assert(fge(f, b) == ge);
f = b;
assert(feq(a, f) == eq);
assert(flt(a, f) == lt);
assert(fgt(a, f) == gt);
assert(fle(a, f) == le);
assert(fge(a, f) == ge);
}
int main(void)

View File

@ -1,75 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
float a;
int i;
long li;
unsigned u;
unsigned long lu;
a = 1.0;
i = 1;
for(int j=0; j<15; j++)
{
assert(i == (int)a);
assert(a == (float)i);
a *= 2.0;
i <<= 1;
}
a = -1.0;
i = -1;
for(int j=0; j<15; j++)
{
assert(i == (int)a);
assert(a == (float)i);
a *= 2.0;
i <<= 1;
}
a = 1.0;
u = 1;
for(int j=0; j<16; j++)
{
assert(u == (unsigned)a);
assert(a == (float)u);
a *= 2.0;
u <<= 1;
}
a = 1.0;
li = 1;
for(int j=0; j<31; j++)
{
assert(li == (long)a);
assert(a == (float)li);
a *= 2.0;
li <<= 1;
}
a = -1.0;
li = -1;
for(int j=0; j<31; j++)
{
assert(li == (long)a);
assert(a == (float)li);
a *= 2.0;
li <<= 1;
}
a = 1.0;
lu = 1;
for(int j=0; j<32; j++)
{
assert(lu == (unsigned long)a);
assert(a == (float)lu);
a *= 2.0;
lu <<= 1;
}
return 0;
}

View File

@ -15,7 +15,7 @@ int main(void)
ftoa(x, xb); float xr = atof(xb);
ftoa(y, yb); float yr = atof(yb);
printf("%20g (%s) %20g : %20g (%s) %20g : %10f %10f \n", x, xb, xr, y, yb, yr, fabs(x - xr) / x, fabs(y - yr) / y);
printf("%20g (%s) %20g : %20g (%s) %20g : %10f %10f \n", x, xb, xr, y, yb, y, fabs(x - xr) / x, fabs(y - yr) / y);
if (fabs(x - xr) / x > 0.00001 || fabs(y - yr) / y > 0.00001)
return -1;

View File

@ -1,30 +0,0 @@
int (*funcs[10])(int);
#assign x 0
#repeat
int f##x(int i)
{
return i + x;
}
#assign x x + 1
#until x == 10
int test(int k)
{
for(char i=0; i<10; i++)
k = funcs[i](k);
return k;
}
int main(void)
{
#assign x 0
#repeat
funcs[x] = f##x;
#assign x x + 1
#until x == 10
int k = test(-45);
return k;
}

View File

@ -1,25 +0,0 @@
#include <gfx/bitmap.h>
#include <assert.h>
char * const Hires = (char *)0x4000;
Bitmap Screen;
ClipRect cr = {0, 0, 320, 200};
int main(void)
{
bm_init(&Screen, Hires, 40, 25);
bmu_rect_clear(&Screen, 0, 0, 320, 200);
bm_line(&Screen, &cr, 0, 0, 199, 199, 0xff, LINOP_SET);
for(int i=0; i<200; i++)
{
assert(Hires[(i & 7) + 320 * (i >> 3) + (i & ~7)] == 0x80 >> (i & 7));
}
return 0;
}

View File

@ -1,60 +0,0 @@
SRCS=$(filter-out opp_part1.cpp opp_part2.cpp, $(wildcard *.c *.cpp))
EXES=$(patsubst %.c,%,$(SRCS))
EXES:=$(patsubst %.cpp,%,$(EXES))
all: $(EXES)
%: %.c
$(OSCAR64_CC) -e -bc $<
$(OSCAR64_CC) -e -n $<
$(OSCAR64_CC) -e -O2 -bc $<
$(OSCAR64_CC) -e -O2 -n $<
$(OSCAR64_CC) -e -O0 -bc $<
$(OSCAR64_CC) -e -O0 -n $<
$(OSCAR64_CC) -e -Os -bc $<
$(OSCAR64_CC) -e -Os -n $<
$(OSCAR64_CC) -e -O3 -bc $<
$(OSCAR64_CC) -e -O3 -n $<
%: %.cpp
$(OSCAR64_CXX) -e -bc $<
$(OSCAR64_CXX) -e -n $<
$(OSCAR64_CXX) -e -O2 -bc $<
$(OSCAR64_CXX) -e -O2 -n $<
$(OSCAR64_CXX) -e -O0 -bc $<
$(OSCAR64_CXX) -e -O0 -n $<
$(OSCAR64_CXX) -e -Os -bc $<
$(OSCAR64_CXX) -e -Os -n $<
$(OSCAR64_CXX) -e -O3 -bc $<
$(OSCAR64_CXX) -e -O3 -n $<
# testb
bitshifttest: bitshifttest.c
$(OSCAR64_CC) -e -bc $<
$(OSCAR64_CC) -e -bc -O2 $<
$(OSCAR64_CC) -e -bc -O0 $<
$(OSCAR64_CC) -e -bc -Os $<
$(OSCAR64_CC) -e -bc -O3 $<
$(OSCAR64_CC) -e -n $<
# testn
stripedarraytest: stripedarraytest.c
$(OSCAR64_CC) -e -O2 -n $<
$(OSCAR64_CC) -e -O0 -n $<
$(OSCAR64_CC) -e -Os -n $<
$(OSCAR64_CC) -e -O3 -n $<
autorefreturn: autorefreturn.cpp
$(OSCAR64_CC) -e -O2 -n $<
$(OSCAR64_CC) -e -O0 -n $<
$(OSCAR64_CC) -e -Os -n $<
$(OSCAR64_CC) -e -O3 -n $<
copyconstructor: copyconstructor.cpp
$(OSCAR64_CC) -e -O2 -n $<
$(OSCAR64_CC) -e -O0 -n $<
$(OSCAR64_CC) -e -Os -n $<
$(OSCAR64_CC) -e -O3 -n $<
clean:
@$(RM) *.asm *.bcs *.int *.lbl *.map *.prg

View File

@ -1,49 +0,0 @@
#include <string.h>
#include <assert.h>
#include <stdio.h>
unsigned b[4096];
void testfwd(unsigned sz)
{
for(unsigned i=0; i<4096; i++)
b[i] = i;
memmove(b + 100, b + 101, 2 * sz);
for(unsigned i=0; i<100; i++)
assert(b[i] == i);
for(unsigned i=100; i<100 + sz; i++)
assert(b[i] == i + 1);
for(unsigned i=100 + sz; i<4096; i++)
assert(b[i] == i);
}
void testback(unsigned sz)
{
for(unsigned i=0; i<4096; i++)
b[i] = i;
memmove(b + 101, b + 100, 2 * sz);
for(unsigned i=0; i<101; i++)
assert(b[i] == i);
for(unsigned i=101; i<101 + sz; i++)
assert(b[i] == i - 1);
for(unsigned i=101 + sz; i<4096; i++)
assert(b[i] == i);
}
int main(void)
{
for(unsigned i=1; i<2048; i *= 2)
{
testfwd(i - 1);
testfwd(i);
testback(i);
testback(i - 1);
}
return 0;
}

View File

@ -1,64 +0,0 @@
#include <assert.h>
int main(void)
{
unsigned n1, n0;
n1 = 0; n0 = 0;
for(int i=-1000; i<2000; i+=37)
{
for(char j=0; j<255; j++)
{
if (i < j)
n1++;
else
n0++;
}
}
assert(n1 == 7893 && n0 == 13017);
n1 = 0; n0 = 0;
for(int i=-1000; i<2000; i+=37)
{
for(char j=0; j<255; j++)
{
if (i <= j)
n1++;
else
n0++;
}
}
assert(n1 == 7899 && n0 == 13011);
n1 = 0; n0 = 0;
for(int i=-1000; i<2000; i+=37)
{
for(char j=0; j<255; j++)
{
if (i >= j)
n1++;
else
n0++;
}
}
assert(n0 == 7893 && n1 == 13017);
n1 = 0; n0 = 0;
for(int i=-1000; i<2000; i+=37)
{
for(char j=0; j<255; j++)
{
if (i > j)
n1++;
else
n0++;
}
}
assert(n0 == 7899 && n1 == 13011);
return 0;
}

View File

@ -1,43 +0,0 @@
#include <gfx/vector3d.h>
#include <assert.h>
#include <stdio.h>
Matrix4 ml, mr;
int main(void)
{
for(char i=0; i<16; i++)
{
for(char j=0; j<16; j++)
{
for(char k=0; k<16; k++)
{
ml.m[k] = (i == k) ? 1.0 : 0.0;
mr.m[k] = (j == k) ? 1.0 : 0.0;
}
mat4_mmul(&ml, &mr);
#if 0
printf("%d, %d\n", i, j);
for(char k=0; k<16; k++)
printf("%f ", ml.m[k]);
printf("\n");
#endif
for(char k=0; k<16; k++)
{
char ix = i & 3, iy = i >> 2;
char jx = j & 3, jy = j >> 2;
char kx = k & 3, ky = k >> 2;
if (ky == jy && kx == ix && jx == iy)
assert(ml.m[k] == 1.0);
else
assert(ml.m[k] == 0.0);
}
}
}
return 0;
}

View File

@ -1,90 +0,0 @@
#include <assert.h>
struct A
{
int n;
A(int n_)
: n(n_) {}
A(const A & a)
: n(a.n) {}
A operator+(const A & a) const
{
return A(n + a.n);
}
A operator-(const A & a) const
{
return A(n - a.n);
}
A & operator+=(const A & a)
{
n += a.n;
return *this;
}
A & operator-=(const A & a)
{
n -= a.n;
return *this;
}
A operator-(void) const
{
return A(-n);
}
A & operator++(void)
{
n++;
return *this;
}
A & operator--(void)
{
n--;
return *this;
}
A operator++(int);
A operator--(int);
};
A A::operator++(int)
{
A a(*this);
n++;
return a;
}
A A::operator--(int)
{
A a(*this);
n--;
return a;
}
int main(void)
{
A a(7), b(8), c(9);
assert((++a).n == 8);
assert(a.n == 8);
assert((--a).n == 7);
assert(a.n == 7);
assert((a++).n == 7);
assert(a.n == 8);
assert((a--).n == 8);
assert(a.n == 7);
assert((a + b - c + -a + -b - -c).n == 0);
return 0;
}

View File

@ -1,23 +0,0 @@
#include <opp/array.h>
#include <assert.h>
int main(void)
{
opp::array<int, 10> a10;
opp::array<int, 20> a20;
for(int i=0; i<10; i++)
a10[i] = i;
for(int i=0; i<20; i++)
a20[i] = i;
int s = 0;
for(int i=0; i<10; i++)
s += a10[i];
for(int i=10; i<20; i++)
s -= a20[i];
assert(s == -100);
return 0;
}

View File

@ -1,46 +0,0 @@
#include <opp/functional.h>
class Node
{
public:
virtual int eval(void) const = 0;
};
class ConstNode : public Node
{
private:
int v;
public:
ConstNode(int v_) : v(v_) {}
virtual int eval(void) const
{
return v;
}
};
class BinaryNode : public Node
{
private:
opp::function<int(int, int)> op;
Node * left, * right;
public:
BinaryNode(opp::function<int(int, int)> op_, Node * left_, Node * right_);
virtual int eval(void) const
{
return op(left->eval(), right->eval());
}
};
inline BinaryNode::BinaryNode(opp::function<int(int, int)> op_, Node * left_, Node * right_)
: op(op_), left(left_), right(right_) {}
int main(void)
{
Node * s1 =
new BinaryNode([=](int a, int b){return a + b;},
new ConstNode(7), new ConstNode(11)
);
return s1->eval() - 18;
}

View File

@ -1,57 +0,0 @@
#include <opp/list.h>
#include <opp/algorithm.h>
#include <assert.h>
#include <opp/iostream.h>
int main(void)
{
opp::list<int> a;
for(int i=0; i<10; i++)
a.push_back(i);
int s = 0;
for(auto i : a)
s += i;
assert(s == 45);
auto li = a.begin();
for(int i=0; i<5; i++)
{
li = a.erase(li);
li++;
}
s = 0;
for(auto i : a)
s += i;
assert(s == 1 + 3 + 5 + 7 + 9);
opp::list<int> b;
b = a;
s = 0;
for(auto i : b)
s += i;
assert(s == 1 + 3 + 5 + 7 + 9);
opp::list<int> c = opp::list<int>(b);
s = 0;
for(auto i : c)
s += i;
assert(s == 1 + 3 + 5 + 7 + 9);
s = 0;
for(auto i : b)
s += i;
assert(s == 1 + 3 + 5 + 7 + 9);
return 0;
}

View File

@ -1,28 +0,0 @@
#include <assert.h>
#include <opp/vector.h>
#include <opp/utility.h>
#include <opp/iostream.h>
using namespace opp;
int main(void)
{
vector<pair<int, int> > vii;
for(int i=0; i<100; i++)
vii.push_back(make_pair(i, i * i));
int sum1 = 0;
long sum2 = 0;
for(const auto & v : vii)
{
sum1 += v.first;
sum2 += v.second;
}
assert(sum1 == 4950);
assert(sum2 == 328350l);
return 0;
}

View File

@ -1,2 +0,0 @@
#include "opp_part1.h"

View File

@ -1,40 +0,0 @@
#pragma once
#include <opp/vector.h>
class A
{
protected:
int a, b;
public:
A(int a_, int b_)
: a(a_), b(b_)
{}
int sum(void) const
{
return a * b;
}
};
class AS
{
protected:
opp::vector<A> va;
public:
AS(const opp::vector<A> & v)
: va(v)
{}
int sum(void)
{
int s = 0;
for(const auto & a : va)
s += a.sum();
return s;
}
};
#pragma compile("opp_part1.cpp")

View File

@ -1,13 +0,0 @@
#include "opp_part2.h"
BS::BS(const opp::vector<A> & v)
: va(v)
{}
int BS::sum(void)
{
int s = 0;
for(const auto & a : va)
s += a.sum();
return s;
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "opp_part1.h"
class BS
{
protected:
opp::vector<A> va;
public:
BS(const opp::vector<A> & v);
int sum(void);
};
#pragma compile("opp_part2.cpp")

View File

@ -1,25 +0,0 @@
#include <assert.h>
#include "opp_part1.h"
#include "opp_part2.h"
int main(void)
{
opp::vector<A> va;
va.push_back(A(1, 2));
va.push_back(A(3, 4));
va.push_back(A(6, 4));
va.push_back(A(0, 9));
AS as(va);
va.push_back(A(7, 1));
BS bs(va);
assert(bs.sum() == 2 + 12 + 24 + 7);
assert(as.sum() == 2 + 12 + 24);
return 0;
}

View File

@ -1,78 +0,0 @@
#include <opp/static_vector.h>
#include <opp/algorithm.h>
#include <assert.h>
#include <opp/iostream.h>
int main(void)
{
opp::static_vector<int, 20> a;
for(int i=0; i<10; i++)
a.push_back(i);
int s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 45);
for(int i=0; i<5; i++)
a.erase(i);
s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 1 + 3 + 5 + 7 + 9);
opp::static_vector<int, 100> v;
for(int i=0; i<10; i++)
v.push_back(i);
assert(v.size() == 10);
v.insert(0, 20);
assert(v.size() == 11);
v.insert(6, 21);
assert(v.size() == 12);
v.insert(12, 22);
int * fi = opp::find(v.begin(), v.end(), 21);
fi = v.insert(fi, 30);
fi = v.insert(fi, 31);
fi = v.insert(fi, 32);
assert(v.size() == 16);
assert(v[0] == 20);
assert(v[15] == 22);
assert(v[8] == 32);
fi = opp::find(v.begin(), v.end(), 32);
for(int i=0; i<30; i++)
{
fi = v.insert(fi, i + 40);
}
assert(v.size() == 46);
assert(v[28] == 60);
v.erase(10, 10);
for(int i : v)
opp::cout << i << ", ";
opp::cout << "\n";
assert(v.size() == 36);
assert(v[18] == 60);
v.assign(42, 11);
assert(v.size() == 42);
assert(v[0] == 11);
assert(v[15] == 11);
assert(v[41] == 11);
return 0;
}

View File

@ -1,83 +0,0 @@
#include <opp/string.h>
#include <stdlib.h>
#include <assert.h>
#include <opp/sstream.h>
#include <math.h>
using opp::ostringstream;
using opp::istringstream;
using opp::endl;
float fdist(float a, float b)
{
float d = fabs(a - b);
a = fabs(a);
b = fabs(b);
return d / (a > b ? a : b);
}
int main(void)
{
ostringstream os;
for(int i=0; i<40; i++)
{
os << i << endl;
}
istringstream is(os.str());
int j = 0, k = 47;
#if 1
while (is >> k)
{
assert(k == j++);
}
assert(j == 40);
#endif
os.str(opp::string());
#if 0
cout << "[" << os.str() << "]" << endl;
os << "HELLO";
cout << "[" << os.str() << "]" << endl;
#endif
#if 1
float f = 1.0, g = 1.0;
for(int i=0; i<10; i++)
{
os << f << " " << g << endl;
// cout << os.str();
f *= 5.1;
g *= 0.12;
}
is.str(os.str());
f = 1.0, g = 1.0;
float fr, gr;
j = 0;
while (is >> fr >> gr)
{
// cout << f << " " << fr << ", " << g << " " << gr << ", " << fdist(fr, f) << endl;
assert(fdist(fr, f) < 1.0e-5);
assert(fdist(gr, g) < 1.0e-5);
f *= 5.1;
g *= 0.12;
j++;
}
assert(j == 10);
#endif
return 0;
}

View File

@ -1,103 +0,0 @@
#include <opp/string.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
using opp::string;
static const char HelloWorld[] = "Hello World";
static const char AndBeyond[] = "And Beyond";
static const char And[] = "And";
static const char HelloWorldAndBeyond[] = "Hello World And Beyond";
__noinline void test_create(void)
{
string s1();
string s2(HelloWorld);
string s3(s2);
string s4('a');
assert(!strcmp(s2.tocstr(), HelloWorld));
assert(!strcmp(s3.tocstr(), HelloWorld));
assert(s4.size() == 1 && s4[0] == 'a');
}
__noinline void test_concat(void)
{
string s1();
string s2(HelloWorld);
string s3(AndBeyond);
string s4 = s1 + s2;
string s5 = s2 + " " + s3;
string s6 = s2 + " " + AndBeyond;
assert(!strcmp(s4.tocstr(), HelloWorld));
assert(!strcmp(s5.tocstr(), HelloWorldAndBeyond));
assert(!strcmp(s6.tocstr(), HelloWorldAndBeyond));
}
__noinline void test_find(void)
{
string s1(HelloWorldAndBeyond);
string s2(And);
assert(s1.find(HelloWorld) == 0);
assert(s1.find(AndBeyond) == 12);
assert(s1.find(And) == 12);
assert(s1.find(s2) == 12);
assert(s1.find(' ') == 5);
assert(s1.find(' ', 6) == 11);
}
__noinline void test_assign(void)
{
string s1(HelloWorld);
string s2(AndBeyond);
string s3;
s3 = s1;
s3 = s2;
s3 = s1;
s3 += " ";
s3 += s2;
assert(!strcmp(s3.tocstr(), HelloWorldAndBeyond));
s3 <<= 12;
assert(!strcmp(s3.tocstr(), AndBeyond));
s3 = HelloWorldAndBeyond;
assert(!strcmp(s3.tocstr(), HelloWorldAndBeyond));
s3 >>= 11;
assert(!strcmp(s3.tocstr(), HelloWorld));
}
static char * test;
int main(void)
{
test = new char;
unsigned avail = heapfree();
test_create();
assert(avail == heapfree());
test_concat();
assert(avail == heapfree());
test_find();
assert(avail == heapfree());
test_assign();
assert(avail == heapfree());
delete test;
return 0;
}

View File

@ -1,193 +0,0 @@
#include <opp/string.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
using opp::string;
const string s1;
const string s2 = "Hello";
const string s3{"World"};
const string a1[2];
const string a2[2] = {"Hello", "World"};
const string a3[2] = {opp::string("Hello"), opp::string("World")};
const string d1[3][2];
const string d2[3][2] = {{"Hello", "World"}, {"aaa", "bbb"}, {"ccc", "ddd"}};
const string d3[3][2] =
{{opp::string("Hello"), opp::string("World")},
{opp::string("aaa"), opp::string("bbb")},
{opp::string("ccc"), opp::string("ddd")}};
void test_global_init(void)
{
assert(!strcmp(s1.tocstr(), ""));
assert(!strcmp(s2.tocstr(), "Hello"));
assert(!strcmp(s3.tocstr(), "World"));
}
void test_global_ainit(void)
{
assert(!strcmp(a1[0].tocstr(), ""));
assert(!strcmp(a1[1].tocstr(), ""));
assert(!strcmp(a2[0].tocstr(), "Hello"));
assert(!strcmp(a2[1].tocstr(), "World"));
assert(!strcmp(a3[0].tocstr(), "Hello"));
assert(!strcmp(a3[1].tocstr(), "World"));
}
void test_global_dinit(void)
{
assert(!strcmp(d1[0][0].tocstr(), ""));
assert(!strcmp(d1[2][1].tocstr(), ""));
assert(!strcmp(d2[0][0].tocstr(), "Hello"));
assert(!strcmp(d2[2][1].tocstr(), "ddd"));
assert(!strcmp(d3[0][0].tocstr(), "Hello"));
assert(!strcmp(d3[2][1].tocstr(), "ddd"));
}
void test_local_init(void)
{
const string s1;
const string s2 = "Hello";
const string s3{"World"};
assert(!strcmp(s1.tocstr(), ""));
assert(!strcmp(s2.tocstr(), "Hello"));
assert(!strcmp(s3.tocstr(), "World"));
}
void test_local_ainit(void)
{
const string a1[2];
const string a2[2] = {"Hello", "World"};
const string a3[2] = {opp::string("Hello"), opp::string("World")};
assert(!strcmp(a1[0].tocstr(), ""));
assert(!strcmp(a1[1].tocstr(), ""));
assert(!strcmp(a2[0].tocstr(), "Hello"));
assert(!strcmp(a2[1].tocstr(), "World"));
assert(!strcmp(a3[0].tocstr(), "Hello"));
assert(!strcmp(a3[1].tocstr(), "World"));
}
void test_local_dinit(void)
{
const string d1[3][2];
const string d2[3][2] = {{"Hello", "World"}, {"aaa", "bbb"}, {"ccc", "ddd"}};
const string d3[3][2] =
{{opp::string("Hello"), opp::string("World")},
{opp::string("aaa"), opp::string("bbb")},
{opp::string("ccc"), opp::string("ddd")}};
assert(!strcmp(d1[0][0].tocstr(), ""));
assert(!strcmp(d1[2][1].tocstr(), ""));
assert(!strcmp(d2[0][0].tocstr(), "Hello"));
assert(!strcmp(d2[2][1].tocstr(), "ddd"));
assert(!strcmp(d3[0][0].tocstr(), "Hello"));
assert(!strcmp(d3[2][1].tocstr(), "ddd"));
}
class X
{
public:
const string s1;
const string s2 = "Hello";
const string s3;
const string a1[2];
const string a2[2] = {"Hello", "World"};
const string d1[3][2];
const string d2[3][2] = {{"Hello", "World"}, {"aaa", "bbb"}, {"ccc", "ddd"}};
X() : s3("World") {}
};
void test_member_init(void)
{
X x;
assert(!strcmp(x.s1.tocstr(), ""));
assert(!strcmp(x.s2.tocstr(), "Hello"));
assert(!strcmp(x.s3.tocstr(), "World"));
}
void test_member_ainit(void)
{
X x;
assert(!strcmp(x.a1[0].tocstr(), ""));
assert(!strcmp(x.a1[1].tocstr(), ""));
assert(!strcmp(x.a2[0].tocstr(), "Hello"));
assert(!strcmp(x.a2[1].tocstr(), "World"));
}
void test_member_dinit(void)
{
X x;
assert(!strcmp(x.d1[0][0].tocstr(), ""));
assert(!strcmp(x.d1[2][1].tocstr(), ""));
assert(!strcmp(x.d2[0][0].tocstr(), "Hello"));
assert(!strcmp(x.d2[2][1].tocstr(), "ddd"));
}
void test_copy_init(void)
{
X x;
X y(x);
assert(!strcmp(y.s1.tocstr(), ""));
assert(!strcmp(y.s2.tocstr(), "Hello"));
assert(!strcmp(y.s3.tocstr(), "World"));
}
void test_copy_ainit(void)
{
X x;
X y(x);
assert(!strcmp(y.a1[0].tocstr(), ""));
assert(!strcmp(y.a1[1].tocstr(), ""));
assert(!strcmp(y.a2[0].tocstr(), "Hello"));
assert(!strcmp(y.a2[1].tocstr(), "World"));
}
int main(void)
{
test_global_init();
test_global_ainit();
test_global_dinit();
for(int i=0; i<10000; i++)
{
test_local_init();
test_local_ainit();
}
test_member_init();
test_member_ainit();
test_copy_init();
test_copy_ainit();
return 0;
}

View File

@ -1,78 +0,0 @@
#include <opp/vector.h>
#include <opp/algorithm.h>
#include <assert.h>
#include <opp/iostream.h>
int main(void)
{
opp::vector<int> a;
for(int i=0; i<10; i++)
a.push_back(i);
int s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 45);
for(int i=0; i<5; i++)
a.erase(i);
s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 1 + 3 + 5 + 7 + 9);
opp::vector<int> v;
for(int i=0; i<10; i++)
v.push_back(i);
assert(v.size() == 10);
v.insert(0, 20);
assert(v.size() == 11);
v.insert(6, 21);
assert(v.size() == 12);
v.insert(12, 22);
int * fi = opp::find(v.begin(), v.end(), 21);
fi = v.insert(fi, 30);
fi = v.insert(fi, 31);
fi = v.insert(fi, 32);
assert(v.size() == 16);
assert(v[0] == 20);
assert(v[15] == 22);
assert(v[8] == 32);
fi = opp::find(v.begin(), v.end(), 32);
for(int i=0; i<30; i++)
{
fi = v.insert(fi, i + 40);
}
assert(v.size() == 46);
assert(v[28] == 60);
v.erase(10, 10);
for(int i : v)
opp::cout << i << ", ";
opp::cout << "\n";
assert(v.size() == 36);
assert(v[18] == 60);
v.assign(42, 11);
assert(v.size() == 42);
assert(v[0] == 11);
assert(v[15] == 11);
assert(v[41] == 11);
return 0;
}

View File

@ -1,38 +0,0 @@
#include <opp/vector.h>
#include <opp/string.h>
#include <assert.h>
#include <stdlib.h>
#include <opp/iostream.h>
using opp::string;
using opp::vector;
string join(const vector<string> & vs)
{
string sj;
for(int i=0; i<vs.size(); i++)
sj += vs[i];
return sj;
}
int main(void)
{
vector<string> vs;
string a;
for(int i=0; i<10; i++)
{
vs.push_back(a);
a += "x";
}
int s = 0;
for(int i=0; i<10; i++)
s += vs[i].size();
assert(s == 45);
assert(join(vs).size() == 45);
return 0;
}

View File

@ -1,145 +0,0 @@
#include <stdlib.h>
static const char sintab[] = {
128, 131, 134, 137, 140, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 179, 182, 185, 188, 191, 193, 196, 199, 201, 204, 206, 209, 211, 213, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 239, 240, 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 239, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220, 218, 216, 213, 211, 209, 206, 204, 201, 199, 196, 193, 191, 188, 185, 182, 179, 177, 174, 171, 168, 165, 162, 159, 156, 153, 150, 147, 144, 140, 137, 134, 131,
128, 125, 122, 119, 116, 112, 109, 106, 103, 100, 97, 94, 91, 88, 85, 82, 79, 77, 74, 71, 68, 65, 63, 60, 57, 55, 52, 50, 47, 45, 43, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 21, 19, 17, 16, 15, 13, 12, 11, 10, 8, 7, 6, 6, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 19, 21, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, 45, 47, 50, 52, 55, 57, 60, 63, 65, 68, 71, 74, 77, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 116, 119, 122, 125
};
char Screen0[1024], Screen1[1024];
char colormap0[256], colormap1[256];
char colors0[] = {0, 6, 14, 1, 13, 5, 0};
char colors1[] = {0, 9, 7, 1, 15, 12, 0};
unsigned c1A, c1B, c2A, c2B, c3A, c3B;
int d1A, d1B, d2A, d2B, d3A, d3B;
void inithires(void)
{
for(int i=0; i<256; i++)
{
colormap0[i] = colors0[i / 37];
colormap1[i] = colors1[i / 37] << 4;
}
}
inline void doplasma(char * scrn)
{
char xbuf0[40], xbuf1[40];
char ybuf0[25], ybuf1[25];
char c2a = c2A >> 8;
char c2b = c2B >> 8;
char c1a = c1A >> 8;
char c1b = c1B >> 8;
for (char i = 0; i < 25; i++) {
ybuf0[i] = sintab[(c1a + c2a) & 0xff] + sintab[c1b];
c1a += 13;
c1b -= 5;
}
for (char i = 0; i < 40; i++) {
xbuf0[i] = sintab[(c2a + c1b) & 0xff] + sintab[c2b];
c2a += 11;
c2b -= 7;
}
c2a = c2B >> 8;
c2b = c3A >> 8;
c1a = c1B >> 8;
c1b = c3B >> 8;
for (char i = 0; i < 25; i++) {
ybuf1[i] = sintab[(c1b + c2a) & 0xff] + sintab[c1a];
c1a += 4;
c1b -= 6;
}
for (char i = 0; i < 40; i++) {
xbuf1[i] = sintab[(c2b + c1a) & 0xff] + sintab[c2a];
c2a += 7;
c2b -= 9;
}
#pragma unroll(full)
for (char k=0; k<5; k++)
{
char tbuf0[5], tbuf1[5];
#pragma unroll(full)
for (char i = 0; i < 4; i++)
{
tbuf0[i] = ybuf0[5 * k + i + 1] - ybuf0[5 * k + i];
tbuf1[i] = ybuf1[5 * k + i + 1] - ybuf1[5 * k + i];
}
for (signed char i = 39; i >= 0; i--)
{
char t = xbuf0[i] + ybuf0[5 * k];
char u = xbuf1[i] + ybuf1[5 * k];
#pragma unroll(full)
for (char j = 0; j < 5; j++)
{
scrn[40 * j + 200 * k + i] = colormap0[u] | colormap1[u];
t += tbuf0[j];
u += tbuf1[j];
}
}
}
c1A += 8 * ((int)sintab[d1A] - 128);
c1B += 16 * ((int)sintab[d1B] - 128);
c2A += 8 * ((int)sintab[d2A] - 128);
c2B += 16 * ((int)sintab[d2B] - 128);
c3A += 6 * ((int)sintab[d3A] - 128);
c3B += 12 * ((int)sintab[d3B] - 128);
d1A += 3;
d1B += rand() & 3;
d2A += 5;
d2B += rand() & 3;
d3A += 2;
d3B += rand() & 3;
}
void doplasma0(void)
{
doplasma(Screen0);
}
void doplasma1(void)
{
doplasma(Screen1);
}
unsigned checksum(const char * scr)
{
unsigned s = 0x1234;
for(int i=0; i<1024; i++)
{
unsigned m = s & 1;
s >>= 1;
if (m)
s ^= 0x2152;
s ^= scr[i];
}
return s;
}
int main(void)
{
inithires();
doplasma0();
doplasma1();
doplasma0();
doplasma1();
doplasma0();
doplasma1();
return checksum(Screen0) + checksum(Screen1) - 16337;
}

View File

@ -1,39 +0,0 @@
#include <assert.h>
struct X
{
int a;
};
X x[5] = {
{1}, {2}, {3}, {4}, {5}
};
X * y;
int main(void)
{
y = x;
assert(y == x);
y = x + 1;
assert(y == x + 1);
y = &(x[2]);
assert(y == x + 2);
y = x + 3;
assert(y == &(x[3]));
y = x ;
assert(y == (struct X*)x);
y = x;
assert(x == y);
y = x + 1;
assert(x + 1 == y);
y = &(x[2]);
assert(x + 2 == y);
y = x + 3;
assert(&(x[3]) == y);
y = x ;
assert((struct X*)x == y);
return 0;
}

View File

@ -1,37 +0,0 @@
#if 1
const struct A {
char w;
int b[5];
struct {
int c[5];
} o;
} a = {22,
{4, 5, 6, 7, 8},
{
{4, 5, 6, 7, 8}
}
};
const int * t[4] = {
a.b + 1 + 1
};
const int * v[4] = {
a.o.c + 1 + 1
};
int q[5] = {4, 5, 6, 7, 8};
const int * u[4] = {
q + 2
};
int main(void)
{
return
u[0][0] + (q + 2)[2] - 6 - 8 +
v[0][0] + (a.o.c + 2)[2] - 6 - 8 +
t[0][0] + (a.b + 2)[2] - 6 - 8;
}

View File

@ -20,7 +20,7 @@ void qsort(Node * n, int s)
{
n[pi] = n[i];
pi++;
n[i] = n[pi];
n[i] = n[pi]
}
}
n[pi] = pn;

View File

@ -11,6 +11,6 @@ int main(void)
assert(lsum == 32157742L);
return 0;
return 0
}

View File

@ -1,76 +0,0 @@
#include <assert.h>
__noinline unsigned long rollright32(unsigned long a) {
unsigned long tmp = a & 1;
return ( a >> 1) + (tmp << 31);
}
__noinline unsigned rollright16(unsigned a) {
unsigned tmp = a & 1;
return ( a >> 1) + (tmp << 15);
}
__noinline char rollright8(char a) {
char tmp = a & 1;
return ( a >> 1) + (tmp << 7);
}
__noinline unsigned long rollleft32(unsigned long a) {
unsigned long tmp = (a >> 31) & 1;
return ( a << 1) + tmp;
}
__noinline unsigned rollleft16(unsigned a) {
unsigned tmp = (a >> 15) & 1;
return ( a << 1) + tmp;
}
__noinline char rollleft8(char a) {
char tmp = (a >> 7) & 1;
return ( a << 1) + tmp;
}
int main() {
unsigned long lv = 0x12345678ul;
unsigned val = 0x1234;
char c=0x12;
unsigned long lvt[33];
unsigned valt[17];
char ct[9];
lvt[0] = lv;
valt[0] = val;
ct[0] = c;
assert(rollleft8(rollright8(c)) == c);
assert(rollleft16(rollright16(val)) == val);
assert(rollleft32(rollright32(lv)) == lv);
for(int i=0; i<32; i++)
lvt[i + 1] = rollright32(lvt[i]);
for(int i=0; i<16; i++)
valt[i + 1] = rollright16(valt[i]);
for(int i=0; i<8; i++)
ct[i + 1] = rollright8(ct[i]);
for(int i=0; i<=32; i++)
{
assert(lvt[32 - i] == lv);
lv = rollleft32(lv);
}
for(int i=0; i<=16; i++)
{
assert(valt[16 - i] == val);
val = rollleft16(val);
}
for(int i=0; i<=8; i++)
{
assert(ct[8 - i] == c);
c = rollleft8(c);
}
return 0;
}

View File

@ -1,321 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
void testi(const char * fmt, int val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testu(const char * fmt, unsigned val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testil(const char * fmt, long val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testul(const char * fmt, unsigned long val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
void testf(const char * fmt, float val, const char * tst)
{
char buffer[32];
sprintf(buffer, fmt, val);
printf("%s:%s\n", buffer, tst);
assert(!strcmp(buffer, tst));
}
int main(void)
{
testi("%d", 0, "0");
testi("%d", 1, "1");
testi("%d", -1, "-1");
testi("%d", 12, "12");
testi("%d", 123, "123");
testi("%d", 1234, "1234");
testi("%d", 12345, "12345");
testi("%d", -12345, "-12345");
testi("%d", 32767, "32767");
testi("%d", -32768, "-32768");
testi("%3d", 0, " 0");
testi("%3d", 1, " 1");
testi("%3d", -1, " -1");
testi("%3d", 12, " 12");
testi("%3d", 123, "123");
testi("%3d", 1234, "1234");
testi("%3d", 12345, "12345");
testi("%3d", -12345, "-12345");
testi("%3d", 32767, "32767");
testi("%3d", -32768, "-32768");
testi("%03d", 0, "000");
testi("%03d", 1, "001");
// testi("%03d", -1, "-01");
testi("%03d", 12, "012");
testi("%03d", 123, "123");
testi("%03d", 1234, "1234");
testi("%03d", 12345, "12345");
testi("%03d", -12345, "-12345");
testi("%03d", 32767, "32767");
testi("%03d", -32768, "-32768");
testi("%-4d", 0, "0 ");
testi("%-4d", 1, "1 ");
testi("%-4d", -1, "-1 ");
testi("%-4d", 12, "12 ");
testi("%-4d", 123, "123 ");
testi("%-4d", 1234, "1234");
testi("%-4d", 12345, "12345");
testi("%-4d", -12345, "-12345");
testi("%-4d", 32767, "32767");
testi("%-4d", -32768, "-32768");
testi("%+d", 0, "+0");
testi("%+d", 1, "+1");
testi("%+d", -1, "-1");
testi("%+d", 12, "+12");
testi("%+d", 123, "+123");
testi("%+d", 1234, "+1234");
testi("%+d", 12345, "+12345");
testi("%+d", -12345, "-12345");
testi("%+d", 32767, "+32767");
testi("%+d", -32768, "-32768");
testil("%ld", 0l, "0");
testil("%ld", 1l, "1");
testil("%ld", -1l, "-1");
testil("%ld", 12l, "12");
testil("%ld", 123l, "123");
testil("%ld", 1234l, "1234");
testil("%ld", 12345l, "12345");
testil("%ld", -12345l, "-12345");
testil("%ld", 32767l, "32767");
testil("%ld", -32768l, "-32768");
testil("%ld", 2147483647l, "2147483647");
testil("%ld", -2147483648l, "-2147483648");
testil("%3ld", 0l, " 0");
testil("%3ld", 1l, " 1");
testil("%3ld", -1l, " -1");
testil("%3ld", 12l, " 12");
testil("%3ld", 123l, "123");
testil("%3ld", 1234l, "1234");
testil("%3ld", 12345l, "12345");
testil("%3ld", -12345l, "-12345");
testil("%3ld", 32767l, "32767");
testil("%3ld", -32768l, "-32768");
testil("%3ld", 2147483647l, "2147483647");
testil("%3ld", -2147483648l, "-2147483648");
testil("%03ld", 0l, "000");
testil("%03ld", 1l, "001");
// testil("%03ld", -1l, "-01");
testil("%03ld", 12l, "012");
testil("%03ld", 123l, "123");
testil("%03ld", 1234l, "1234");
testil("%03ld", 12345l, "12345");
testil("%03ld", -12345l, "-12345");
testil("%03ld", 32767l, "32767");
testil("%03ld", -32768l, "-32768");
testil("%03ld", 2147483647l, "2147483647");
testil("%03ld", -2147483648l, "-2147483648");
testil("%-4ld", 0l, "0 ");
testil("%-4ld", 1l, "1 ");
testil("%-4ld", -1l, "-1 ");
testil("%-4ld", 12l, "12 ");
testil("%-4ld", 123l, "123 ");
testil("%-4ld", 1234l, "1234");
testil("%-4ld", 12345l, "12345");
testil("%-4ld", -12345l, "-12345");
testil("%-4ld", 32767l, "32767");
testil("%-4ld", -32768l, "-32768");
testil("%-4ld", 2147483647l, "2147483647");
testil("%-4ld", -2147483648l, "-2147483648");
testil("%+ld", 0l, "+0");
testil("%+ld", 1l, "+1");
testil("%+ld", -1l, "-1");
testil("%+ld", 12l, "+12");
testil("%+ld", 123l, "+123");
testil("%+ld", 1234l, "+1234");
testil("%+ld", 12345l, "+12345");
testil("%+ld", -12345l, "-12345");
testil("%+ld", 32767l, "+32767");
testil("%+ld", -32768l, "-32768");
testil("%+ld", 2147483647l, "+2147483647");
testil("%+ld", -2147483648l, "-2147483648");
testu("%u", 0, "0");
testu("%u", 1, "1");
testu("%u", 12, "12");
testu("%u", 123, "123");
testu("%u", 1234, "1234");
testu("%u", 12345, "12345");
testu("%u", 32767, "32767");
testu("%u", 32768, "32768");
testu("%u", 65535, "65535");
testu("%x", 0, "0");
testu("%x", 0x49bf, "49BF");
testu("%x", 0xffff, "FFFF");
testu("%3u", 0, " 0");
testu("%3u", 1, " 1");
testu("%3u", 12, " 12");
testu("%3u", 123, "123");
testu("%3u", 1234, "1234");
testu("%3u", 12345, "12345");
testu("%3u", 32767, "32767");
testu("%3u", 32768, "32768");
testu("%3u", 65535, "65535");
testu("%3x", 0, " 0");
testu("%3x", 0x49bf, "49BF");
testu("%3x", 0xffff, "FFFF");
testu("%03u", 0, "000");
testu("%03u", 1, "001");
testu("%03u", 12, "012");
testu("%03u", 123, "123");
testu("%03u", 1234, "1234");
testu("%03u", 12345, "12345");
testu("%03u", 32767, "32767");
testu("%03u", 32768, "32768");
testu("%03u", 65535, "65535");
testu("%03x", 0, "000");
testu("%03x", 0x49bf, "49BF");
testu("%03x", 0xffff, "FFFF");
testu("%-4u", 0, "0 ");
testu("%-4u", 1, "1 ");
testu("%-4u", 12, "12 ");
testu("%-4u", 123, "123 ");
testu("%-4u", 1234, "1234");
testu("%-4u", 12345, "12345");
testu("%-4u", 32767, "32767");
testu("%-4u", 32768, "32768");
testu("%-4u", 65535, "65535");
testu("%-4x", 0, "0 ");
testu("%-4x", 0x49bf, "49BF");
testu("%-4x", 0xffff, "FFFF");
testul("%3lu", 0l, " 0");
testul("%3lu", 1l, " 1");
testul("%3lu", 12l, " 12");
testul("%3lu", 123l, "123");
testul("%3lu", 1234l, "1234");
testul("%3lu", 12345l, "12345");
testul("%3lu", 32767l, "32767");
testul("%3lu", 2147483647l, "2147483647");
testul("%3lu", 4294967295l, "4294967295");
testul("%3lx", 0, " 0");
testul("%3lx", 0x3576fbcdl, "3576FBCD");
testul("%3lx", 0xffffffffl, "FFFFFFFF");
testul("%03lu", 0l, "000");
testul("%03lu", 1l, "001");
testul("%03lu", 12l, "012");
testul("%03lu", 123l, "123");
testul("%03lu", 1234l, "1234");
testul("%03lu", 12345l, "12345");
testul("%03lu", 32767l, "32767");
testul("%03lu", 2147483647l, "2147483647");
testul("%03lu", 4294967295l, "4294967295");
testul("%03lx", 0, "000");
testul("%03lx", 0x3576fbcdl, "3576FBCD");
testul("%03lx", 0xffffffffl, "FFFFFFFF");
testul("%-4lu", 0l, "0 ");
testul("%-4lu", 1l, "1 ");
testul("%-4lu", 12l, "12 ");
testul("%-4lu", 123l, "123 ");
testul("%-4lu", 1234l, "1234");
testul("%-4lu", 12345l, "12345");
testul("%-4lu", 32767l, "32767");
testul("%-4lu", 2147483647l, "2147483647");
testul("%-4lu", 4294967295l, "4294967295");
testul("%-4lx", 0, "0 ");
testul("%-4lx", 0x3576fbcdl, "3576FBCD");
testul("%-4lx", 0xffffffffl, "FFFFFFFF");
testul("%+lu", 0l, "+0");
testul("%+lu", 1l, "+1");
testul("%+lu", 12l, "+12");
testul("%+lu", 123l, "+123");
testul("%+lu", 1234l, "+1234");
testul("%+lu", 12345l, "+12345");
testul("%+lu", 32767l, "+32767");
testul("%+lu", 2147483647l, "+2147483647");
testul("%+lu", 4294967295l, "+4294967295");
testf("%f", 0., "0.000000");
testf("%f", 1., "1.000000");
testf("%f", -1., "-1.000000");
testf("%f", 12., "12.000000");
testf("%f", 123., "123.000000");
testf("%f", 1234., "1234.000000");
testf("%f", 12345., "12345.000000");
testf("%f", 123456., "123456.000000");
testf("%f", 1234567., "1234567.000000");
testf("%f", 0.1, "0.100000");
testf("%f", 0.01, "0.010000");
testf("%f", 0.001, "0.001000");
testf("%f", 0.0001, "0.000100");
testf("%f", 0.00001, "0.000010");
testf("%f", 0.000001, "0.000001");
testf("%5.1f", 0, " 0.0");
testf("%5.1f", 1, " 1.0");
testf("%5.1f", -1, " -1.0");
testf("%5.1f", 10, " 10.0");
testf("%5.1f", -10, "-10.0");
testf("%5.1f", 100, "100.0");
testf("%5.1f", -100, "-100.0");
testf("%5.1f", 0.1, " 0.1");
testf("%5.1f", -0.1, " -0.1");
testf("%5.1f", 0.04, " 0.0");
testf("%5.1f", -0.04, " -0.0");
testf("%5.1f", 0.051, " 0.1");
testf("%5.1f", -0.051, " -0.1");
testf("%+5.1f", 0, " +0.0");
testf("%+5.1f", 1, " +1.0");
testf("%+5.1f", -1, " -1.0");
testf("%+5.1f", 10, "+10.0");
testf("%+5.1f", -10, "-10.0");
testf("%+5.1f", 100, "+100.0");
testf("%+5.1f", -100, "-100.0");
testf("%+5.1f", 0.1, " +0.1");
testf("%+5.1f", -0.1, " -0.1");
testf("%+5.1f", 0.04, " +0.0");
testf("%+5.1f", -0.04, " -0.0");
testf("%+5.1f", 0.051, " +0.1");
testf("%+5.1f", -0.051, " -0.1");
return 0;
}

View File

@ -1,6 +1,5 @@
// stdlibtest
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -51,15 +50,16 @@ void heapcheck(void)
for(i=0; i<s; i++)
{
if (p[i] != n)
{
printf("MemError %d at %d:%d != %d\n", k, i, n, p[i]);
exit(-2);
}
}
free(memp[n]);
s = rand() % 100 + 3;
mems[n] = s;
memp[n] = malloc(s);
if (!memp[n])
exit(-3);
memset(memp[n], n, s);
}
}

View File

@ -1,299 +0,0 @@
#include <assert.h>
int a100[100];
__striped int b100[100];
__striped int c100[100];
unsigned a256[256];
__striped unsigned b256[256];
__striped unsigned c256[256];
#pragma align(c100, 256)
#pragma align(c256, 256)
void test_ab100(void)
{
for(char i=0; i<100; i++)
{
a100[i] = i * i;
b100[i] = i * i;
c100[i] = i * i;
}
a100[31] = 4711;
b100[31] = 4711;
c100[31] = 4711;
for(char i=0; i<100; i++)
{
a100[i] += i; a100[i] -= 5; a100[i] = a100[i] + a100[99 - i];
b100[i] += i; b100[i] -= 5; b100[i] = b100[i] + b100[99 - i];
c100[i] += i; c100[i] -= 5; c100[i] = c100[i] + c100[99 - i];
}
for(char i=0; i<100; i++)
{
assert(a100[i] == b100[i]);
assert(a100[i] == c100[i]);
}
}
void test_ab256(void)
{
for(unsigned i=0; i<256; i++)
{
a256[i] = i * i;
b256[i] = i * i;
c256[i] = i * i;
}
a256[31] = 4711;
b256[31] = 4711;
c256[31] = 4711;
for(unsigned i=0; i<256; i++)
{
a256[i] += i; a256[i] -= 5; a256[i] = a256[i] + a256[255 - i];
b256[i] += i; b256[i] -= 5; b256[i] = b256[i] + b256[255 - i];
c256[i] += i; c256[i] -= 5; c256[i] = c256[i] + c256[255 - i];
}
for(unsigned i=0; i<256; i++)
{
assert(a256[i] == b256[i]);
assert(a256[i] == c256[i]);
}
}
long la50[50];
__striped long lb50[50];
__striped long lc50[50];
unsigned long la256[256];
__striped unsigned long lb256[256];
__striped unsigned long lc256[256];
#pragma align(lc50, 256)
#pragma align(lc256, 256)
void test_lab50(void)
{
for(char i=0; i<50; i++)
{
long j = i * i;
la50[i] = j * j;
lb50[i] = j * j;
lc50[i] = j * j;
}
la50[31] = 47110815l;
lb50[31] = 47110815l;
lc50[31] = 47110815l;
for(char i=0; i<50; i++)
{
la50[i] += i; la50[i] -= 12345678l; la50[i] = la50[i] + la50[49 - i];
lb50[i] += i; lb50[i] -= 12345678l; lb50[i] = lb50[i] + lb50[49 - i];
lc50[i] += i; lc50[i] -= 12345678l; lc50[i] = lc50[i] + lc50[49 - i];
}
for(char i=0; i<50; i++)
{
assert(la50[i] == lb50[i]);
assert(la50[i] == lc50[i]);
}
}
void test_lab256(void)
{
for(unsigned i=0; i<256; i++)
{
unsigned long j = i * i;
la256[i] = j * j;
lb256[i] = j * j;
lc256[i] = j * j;
}
la256[31] = 47110815ul;
lb256[31] = 47110815ul;
lc256[31] = 47110815ul;
for(unsigned i=0; i<256; i++)
{
la256[i] += i; la256[i] -= 12345678ul; la256[i] = la256[i] + la256[255 - i];
lb256[i] += i; lb256[i] -= 12345678ul; lb256[i] = lb256[i] + lb256[255 - i];
lc256[i] += i; lc256[i] -= 12345678ul; lc256[i] = lc256[i] + lc256[255 - i];
}
for(unsigned i=0; i<256; i++)
{
assert(la256[i] == lb256[i]);
assert(la256[i] == lc256[i]);
}
}
float fa50[50];
__striped float fb50[50];
__striped float fc50[50];
float fa256[256];
__striped float fb256[256];
__striped float fc256[256];
#pragma align(fc50, 256)
#pragma align(fc256, 256)
void test_fab50(void)
{
for(char i=0; i<50; i++)
{
fa50[i] = i * i;
fb50[i] = i * i;
fc50[i] = i * i;
}
fa50[31] = 4711.0815;
fb50[31] = 4711.0815;
fc50[31] = 4711.0815;
for(char i=0; i<50; i++)
{
fa50[i] += i; fa50[i] -= 1234.5678; fa50[i] = fa50[i] + fa50[49 - i];
fb50[i] += i; fb50[i] -= 1234.5678; fb50[i] = fb50[i] + fb50[49 - i];
fc50[i] += i; fc50[i] -= 1234.5678; fc50[i] = fc50[i] + fc50[49 - i];
}
for(char i=0; i<50; i++)
{
assert(fa50[i] == fb50[i]);
assert(fa50[i] == fc50[i]);
}
}
void test_fab256(void)
{
for(unsigned i=0; i<256; i++)
{
fa256[i] = i * i;
fb256[i] = i * i;
fc256[i] = i * i;
}
fa256[31] = 4711.0815;
fb256[31] = 4711.0815;
fc256[31] = 4711.0815;
for(unsigned i=0; i<256; i++)
{
fa256[i] += i; fa256[i] -= 1234.5678; fa256[i] = fa256[i] + fa256[255 - i];
fb256[i] += i; fb256[i] -= 1234.5678; fb256[i] = fb256[i] + fb256[255 - i];
fc256[i] += i; fc256[i] -= 1234.5678; fc256[i] = fc256[i] + fc256[255 - i];
}
for(unsigned i=0; i<256; i++)
{
assert(fa256[i] == fb256[i]);
assert(fa256[i] == fc256[i]);
}
}
unsigned da50[50], db50[50], dc50[50];
unsigned * pa50[50];
__striped unsigned * pb50[50];
__striped unsigned * pc50[50];
#pragma align(pc50, 256)
void test_pab50(void)
{
for(char i=0; i<50; i++)
{
pa50[i] = da50 + (i * 17) % 50;
pb50[i] = db50 + (i * 17) % 50;
pc50[i] = dc50 + (i * 17) % 50;
}
for(char i=0; i<50; i++)
{
*pa50[i] = i * i;
*pb50[i] = i * i;
*pc50[i] = i * i;
}
for(char i=0; i<50; i++)
{
*pa50[i] += i; *pa50[i] -= 5; *pa50[i] = *pa50[i] + *pa50[49 - i];
*pb50[i] += i; *pb50[i] -= 5; *pb50[i] = *pb50[i] + *pb50[49 - i];
*pc50[i] += i; *pc50[i] -= 5; *pc50[i] = *pc50[i] + *pc50[49 - i];
}
for(char i=0; i<50; i++)
{
assert(*pa50[i] == *pb50[i]);
assert(*pa50[i] == *pc50[i]);
assert(da50[i] == db50[i]);
assert(da50[i] == dc50[i]);
}
}
unsigned da50_4[50][4], db50_4[50][4], dc50_4[50][4];
void test_pab50_4(void)
{
for(char i=0; i<50; i++)
{
pa50[i] = da50_4[(i * 17) % 50];
pb50[i] = db50_4[(i * 17) % 50];
pc50[i] = dc50_4[(i * 17) % 50];
}
for(char k=0; k<4; k++)
{
for(char i=0; i<50; i++)
{
pa50[i][k] = i * i;
pb50[i][k] = i * i;
pc50[i][k] = i * i;
}
}
for(char k=0; k<4; k++)
{
for(char i=0; i<50; i++)
{
pa50[i][k] += i; pa50[i][k] -= 5; pa50[i][k] = pa50[i][k] + pa50[49 - i][k];
pb50[i][k] += i; pb50[i][k] -= 5; pb50[i][k] = pb50[i][k] + pb50[49 - i][k];
pc50[i][k] += i; pc50[i][k] -= 5; pc50[i][k] = pc50[i][k] + pc50[49 - i][k];
}
}
for(char k=0; k<4; k++)
{
for(char i=0; i<50; i++)
{
assert(pa50[i][k] == pb50[i][k]);
assert(pa50[i][k] == pc50[i][k]);
assert(da50_4[i][k] == db50_4[i][k]);
assert(da50_4[i][k] == dc50_4[i][k]);
}
}
}
int main(void)
{
test_ab100();
test_ab256();
test_lab50();
test_lab256();
test_fab50();
test_fab256();
test_pab50();
test_pab50_4();
return 0;
}

View File

@ -1,27 +0,0 @@
#include <string.h>
#include <assert.h>
char lstr[1025];
int main(void)
{
#if 1
assert(strlen("") == 0);
assert(strlen("1") == 1);
assert(strlen("12") == 2);
assert(strlen("123") == 3);
assert(strlen("1234") == 4);
assert(strlen("12345") == 5);
assert(strlen("123456") == 6);
#endif
#if 1
char * dp = lstr;
for(int i=0; i<1024; i++)
{
*dp = 0;
assert(strlen(lstr) == i);
*dp++ = 'a';
}
#endif
return 0;
}

View File

@ -1,49 +0,0 @@
struct Point
{
int x, y;
};
Point tcorners[8], pcorners[8];
int bm_line(void)
{
return 0;
}
void drawCube(void)
{
for(char i=0; i<8; i++)
{
if (!(i & 1))
bm_line();
if (!(i & 2))
bm_line();
if (!(i & 4))
bm_line();
pcorners[i] = tcorners[i];
}
}
int main(void)
{
for(int i=0; i<8; i++)
{
tcorners[i].x = (i + 1) * 3;
tcorners[i].y = (i + 1) * 7;
}
drawCube();
int sum = 0;
for(int i=0; i<8; i++)
{
sum += pcorners[i].x;
sum -= tcorners[i].y;
}
return sum + 144;
}

View File

@ -5,11 +5,6 @@ void testmuli(long a, long b, long ab)
assert (a * b == ab);
}
void testmulu(unsigned long a, unsigned long b, unsigned long ab)
{
assert (a * b == ab);
}
void testdivi(long a, long b, long ab)
{
assert (a / b == ab);
@ -59,6 +54,7 @@ long sieve(long size)
int main(void)
{
testmuli(0, 0, 0);
testmuli(1, 0, 0);
testmuli(0, 1, 0);
@ -69,42 +65,11 @@ int main(void)
testmuli( 1, -1, -1);
testmuli(5, 5, 25);
testmuli( 127, 255, 32385);
testmuli(-127, 255, -32385);
testmuli( 127, -255, -32385);
testmuli(-127, -255, 32385);
testmuli( 1237, 1024, 1266688l);
testmuli(-1237, 1024, -1266688l);
testmuli( 1237, -1024, -1266688l);
testmuli(-1237, -1024, 1266688l);
testmuli( 1024, 1237, 1266688l);
testmuli( 1024,-1237, -1266688l);
testmuli( -1024, 1237, -1266688l);
testmuli( -1024,-1237, 1266688l);
testmulu(0x00000001, 0x0000003c, 0x0000003c);
testmulu(0x00000100, 0x0000003c, 0x00003c00);
testmulu(0x00010000, 0x0000003c, 0x003c0000);
testmulu(0x01000000, 0x0000003c, 0x3c000000);
testmulu(0x0000003c, 0x00000001, 0x0000003c);
testmulu(0x0000003c, 0x00000100, 0x00003c00);
testmulu(0x0000003c, 0x00010000, 0x003c0000);
testmulu(0x0000003c, 0x01000000, 0x3c000000);
testmulu(0x0000004b, 0x0000003c, 0x00001194);
testmulu(0x00004b00, 0x0000003c, 0x00119400);
testmulu(0x004b0000, 0x0000003c, 0x11940000);
testmulu(0x4b000000, 0x0000003c, 0x94000000);
testmulu(0x0000003c, 0x0000004b, 0x00001194);
testmulu(0x0000003c, 0x00004b00, 0x00119400);
testmulu(0x0000003c, 0x004b0000, 0x11940000);
testmulu(0x0000003c, 0x4b000000, 0x94000000);
testdivi( 1, 1, 1);
testdivi(-1, 1, -1);
testdivi( 1, -1, -1);
@ -135,6 +100,7 @@ int main(void)
assert(sieve(200) == 47);
assert(sieve(1000) == 169);
long a = 0, b = 0;
for(long i=0; i<10000; i++)
{
@ -153,14 +119,5 @@ int main(void)
d -= 10000;
}
long e = 0, f = 0;
for(long i=0; i<177000l; i += 1000)
{
assert( 1024 * i == e);
assert(-1024 * i == f);
e += 1024000l;
f -= 1024000l;
}
return 0;
}

View File

@ -63,33 +63,6 @@ bool nge(long a, long b)
inline bool ieq(long a, long b)
{
return a == b;
}
inline bool ilt(long a, long b)
{
return a < b;
}
inline bool igt(long a, long b)
{
return a > b;
}
inline bool ile(long a, long b)
{
return a <= b;
}
inline bool ige(long a, long b)
{
return a >= b;
}
bool beqz(long a)
{
return a == 0;
@ -215,71 +188,7 @@ bool nge1(long a)
bool beqm(long a)
{
return a == -1;
}
bool bltm(long a)
{
return a < -1;
}
bool bgtm(long a)
{
return a > -1;
}
bool blem(long a)
{
return a <= -1;
}
bool bgem(long a)
{
return a >= -1;
}
bool neqm(long a)
{
return a == -1;
}
#pragma native(neqm)
bool nltm(long a)
{
return a < -1;
}
#pragma native(nltm)
bool ngtm(long a)
{
return a > -1;
}
#pragma native(ngtm)
bool nlem(long a)
{
return a <= -1;
}
#pragma native(nlem)
bool ngem(long a)
{
return a >= -1;
}
#pragma native(ngem)
void cmpc(long a, long b)
void cmp(long a, long b)
{
bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = ble(a, b), bgef = bge(a, b);
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
@ -294,27 +203,6 @@ void cmpc(long a, long b)
assert(bgef == ngef);
}
void cmpi(long a, long b)
{
bool ieqf = ieq(a, b), iltf = ilt(a, b), igtf = igt(a, b), ilef = ile(a, b), igef = ige(a, b);
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
printf("INLINE %ld, %ld : EQ %d LT %d GT %d\r", a, b, ieqf, iltf, igtf);
printf("NATIVE %ld, %ld : EQ %d LT %d GT %d\r", a, b, neqf, nltf, ngtf);
assert(ieqf == neqf);
assert(iltf == nltf);
assert(igtf == ngtf);
assert(ilef == nlef);
assert(igef == ngef);
}
void cmp(long a, long b)
{
cmpc(a, b);
cmpi(a, b);
}
void cmpz(long a)
{
bool beqf = beqz(a), bltf = bltz(a), bgtf = bgtz(a), blef = blez(a), bgef = bgez(a);
@ -345,21 +233,6 @@ void cmp1(long a)
assert(bgef == ngef);
}
void cmpm(long a)
{
bool beqf = beqm(a), bltf = bltm(a), bgtf = bgtm(a), blef = blem(a), bgef = bgem(a);
bool neqf = neqm(a), nltf = nltm(a), ngtf = ngtm(a), nlef = nlem(a), ngef = ngem(a);
printf("BYTE %ld, 1 : EQ %d LT %d GT %d LE %d GE %d\r", a, beqf, bltf, bgtf, blef, bgef);
printf("NATIVE %ld, 1 : EQ %d LT %d GT %d LE %d GE %d\r", a, neqf, nltf, ngtf, nlef, ngef);
assert(beqf == neqf);
assert(bltf == nltf);
assert(bgtf == ngtf);
assert(blef == nlef);
assert(bgef == ngef);
}
int main(void)
{
cmp( 0, 1);
@ -454,10 +327,6 @@ int main(void)
cmp1(256);
cmp1(10000);
cmp1(20000);
cmp1(1000000l);
cmp1(2000000l);
cmp1(100000000l);
cmp1(200000000l);
cmp1(-1);
cmp1(-2);
cmp1(-3);
@ -465,34 +334,6 @@ int main(void)
cmp1(-256);
cmp1(-10000);
cmp1(-20000);
cmp1(-1000000l);
cmp1(-2000000l);
cmp1(-100000000l);
cmp1(-200000000l);
cmpm(0);
cmpm(1);
cmpm(2);
cmpm(3);
cmpm(255);
cmpm(256);
cmpm(10000);
cmpm(20000);
cmpm(1000000l);
cmpm(2000000l);
cmpm(100000000l);
cmpm(200000000l);
cmpm(-1);
cmpm(-2);
cmpm(-3);
cmpm(-255);
cmpm(-256);
cmpm(-10000);
cmpm(-20000);
cmpm(-1000000l);
cmpm(-2000000l);
cmpm(-100000000l);
cmpm(-200000000l);
return 0;

View File

@ -1,29 +0,0 @@
#include <assert.h>
int multab[32];
void fill_mulli(int m)
{
#pragma unroll(full)
for(int i=-16; i<16; i++)
if (i != 0)
multab[i + 16] = m / i;
}
void check_mulli(int m)
{
for(int i=-16; i<16; i++)
if (i != 0)
assert(multab[i + 16] == m / i);
}
int main(void)
{
for(int i=-1024; i<=1024; i++)
{
fill_mulli(i);
check_mulli(i);
}
return 0;
}

View File

@ -1,27 +0,0 @@
#include <assert.h>
int multab[32];
void fill_mulli(int m)
{
#pragma unroll(full)
for(int i=-16; i<16; i++)
multab[i + 16] = m * i;
}
void check_mulli(int m)
{
for(int i=-16; i<16; i++)
assert(multab[i + 16] == m * i);
}
int main(void)
{
for(int i=-1024; i<=1024; i++)
{
fill_mulli(i);
check_mulli(i);
}
return 0;
}

View File

@ -1,83 +0,0 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#define MAP_WIDTH 10
#define MAP_HEIGHT 2
#define TITLE_TILE_WIDTH 4
#define TITLE_TILE_HEIGHT 4
#define PTR_SCREEN ((char *)0xc000)
#define PTR_BUFFER ((char *)0xc400)
#define PTR_COLOR ((char *)0xd800)
#define PTR_FONTCHARSET ((char *)0xd800)
const char TitleMap[1024] = {
#for(i, 1024) i * 17,
};
const char TitleTiles[4096] = {
#for(i, 4096) i * 31,
};
// Custom screen address
extern char* const Screen = PTR_SCREEN;
// Color mem address
extern char* const Color = PTR_COLOR;
void RenderLogo(char screenY)
{
char * sp = Screen;
char * cp = Color;
const char * mp = TitleMap;
for(char ty=0; ty < MAP_HEIGHT; ty++)
{
for(char tx=0; tx< MAP_WIDTH; tx++)
{
char ti = mp[tx];
const char* tp = TitleTiles + (TITLE_TILE_WIDTH * TITLE_TILE_HEIGHT) * ti;
for(char y=0; y<TITLE_TILE_HEIGHT; y++)
{
for(char x=0; x<TITLE_TILE_WIDTH; x++)
{
char c = tp[TITLE_TILE_WIDTH * y + x];
sp[40 * (y + screenY) + x] = c;
cp[40 * (y + screenY) + x] = 1;
}
}
sp += TITLE_TILE_WIDTH;
cp += TITLE_TILE_WIDTH;
}
sp += 120;
cp += 120;
mp += MAP_WIDTH;
}
}
void VerifyLogo(char screenY)
{
for(char dy=0; dy<MAP_HEIGHT * TITLE_TILE_HEIGHT; dy++)
{
for(char dx=0; dx<MAP_WIDTH * TITLE_TILE_WIDTH; dx++)
{
char ty = dy / TITLE_TILE_HEIGHT, iy = dy % TITLE_TILE_HEIGHT;
char tx = dx / TITLE_TILE_WIDTH, ix = dx % TITLE_TILE_WIDTH;
int si = TitleMap[MAP_WIDTH * ty + tx] * TITLE_TILE_WIDTH * TITLE_TILE_HEIGHT + TITLE_TILE_WIDTH * iy + ix;
int di = 40 * (dy + screenY) + dx;
assert(Screen[di] == TitleTiles[si]);
}
}
}
int main(void)
{
RenderLogo(1);
VerifyLogo(1);
return 0;
}

View File

@ -1,93 +0,0 @@
#include <assert.h>
struct A
{
virtual int f(int x);
};
struct B : A
{
virtual int f(int x);
};
struct C : A
{
virtual int f(int x);
virtual int g(int y, int z);
};
struct D : B
{
virtual int f(int x);
};
struct E : C
{
virtual int f(int x);
virtual int g(int y, int z);
};
struct F : C
{
virtual int g(int y, int z);
};
int A::f(int x)
{
return x * 1;
}
int B::f(int x)
{
return x * 2;
}
int C::f(int x)
{
return x * 3;
}
int C::g(int y, int z)
{
return (y + z) * 3;
}
int D::f(int x)
{
return x * 4;
}
int E::f(int x)
{
return x * 5;
}
int E::g(int y, int z)
{
return (y + z) * 5;
}
int F::g(int y, int z)
{
return (y + z) * 6;
}
int main(void)
{
A a;
B b;
C c;
D d;
E e;
F f;
assert(a.f(3) == c.f(1));
assert(b.f(4) == d.f(2));
assert(e.f(2) == b.f(5));
assert(f.f(5) == e.f(3));
assert(c.g(3, 2) == e.g(1, 2));
assert(c.g(1, 5) == f.g(0, 3));
return 0;
}

View File

@ -1,79 +0,0 @@
#include <assert.h>
struct Node
{
virtual float eval(void)
{
return 1.0e6;
}
};
struct ConstNode : Node
{
float c;
ConstNode(float c_)
: c(c_) {}
virtual float eval(void)
{
return c;
}
};
struct BinopNode : Node
{
Node * left, * right;
BinopNode(Node * left_, Node * right_)
: left(left_), right(right_)
{}
};
struct AddNode : BinopNode
{
AddNode(Node * left_, Node * right_)
: BinopNode(left_, right_)
{}
virtual float eval(void)
{
return left->eval() + right->eval();
}
};
struct SubNode : BinopNode
{
SubNode(Node * left_, Node * right_)
: BinopNode(left_, right_)
{}
virtual float eval(void)
{
return left->eval() - right->eval();
}
};
struct MulNode : BinopNode
{
MulNode(Node * left_, Node * right_)
: BinopNode(left_, right_)
{}
virtual float eval(void)
{
return left->eval() * right->eval();
}
};
int main(void)
{
Node * n =
new SubNode(
new MulNode(new ConstNode(4), new ConstNode(5)),
new AddNode(new ConstNode(12), new ConstNode(7)));
assert(n->eval() == 1.0);
return 0;
}

View File

@ -1,63 +0,0 @@
#include <assert.h>
int a, b, c;
struct A
{
A(void)
{
a++;
}
virtual ~A(void)
{
a--;
}
};
struct B : A
{
B(void)
{
b++;
}
virtual ~B(void)
{
b--;
}
};
struct C : B
{
C(void)
{
c++;
}
virtual ~C(void)
{
c--;
}
};
int main()
{
A * t[3];
t[0] = new A();
t[1] = new B();
t[2] = new C();
assert(a == 3 && b == 2 && c == 1);
delete t[0];
delete t[1];
delete t[2];
assert(a == 0 && b == 0 && c == 0);
return 0;
}

View File

@ -1,201 +0,0 @@
#include "sidfx.h"
enum SIDFXState
{
SIDFX_IDLE,
SIDFX_RESET_0,
SIDFX_RESET_1,
SIDFX_READY,
SIDFX_PLAY,
SIDFX_WAIT
};
__striped static struct SIDFXChannel
{
const SIDFX * volatile com;
byte delay, priority;
volatile byte cnt;
volatile SIDFXState state;
unsigned freq, pwm;
} channels[3];
void sidfx_init(void)
{
for(char i=0; i<3; i++)
{
channels[i].com = nullptr;
channels[i].state = SIDFX_IDLE;
channels[i].priority = 0;
channels[i].delay = 1;
}
}
bool sidfx_idle(byte chn)
{
return channels[chn].state == SIDFX_IDLE;
}
char sidfx_cnt(byte chn)
{
return channels[chn].cnt;
}
void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
{
SIDFXState ns = channels[chn].state;
if (ns == SIDFX_IDLE)
ns = SIDFX_READY;
else if (channels[chn].priority <= fx->priority)
ns = SIDFX_RESET_0;
else
return;
channels[chn].state = SIDFX_IDLE;
channels[chn].delay = 1;
channels[chn].com = fx;
channels[chn].cnt = cnt - 1;
channels[chn].priority = fx->priority;
channels[chn].state = ns;
}
void sidfx_stop(byte chn)
{
channels[chn].com = nullptr;
if (channels[chn].state != SIDFX_IDLE)
{
channels[chn].state = SIDFX_RESET_0;
channels[chn].delay = 1;
}
}
inline void sidfx_loop_ch(byte ch)
{
if (channels[ch].state)
{
const SIDFX * com = channels[ch].com;
channels[ch].delay--;
if (channels[ch].delay)
{
if (com->dfreq)
{
channels[ch].freq += com->dfreq;
sid.voices[ch].freq = channels[ch].freq;
}
if (com->dpwm)
{
channels[ch].pwm += com->dpwm;
sid.voices[ch].pwm = channels[ch].pwm;
}
}
while (!channels[ch].delay)
{
switch (channels[ch].state)
{
case SIDFX_IDLE:
channels[ch].delay = 1;
break;
case SIDFX_RESET_0:
sid.voices[ch].ctrl = 0;
sid.voices[ch].attdec = 0;
sid.voices[ch].susrel = 0;
if (com)
channels[ch].state = SIDFX_READY;
else
channels[ch].state = SIDFX_IDLE;
channels[ch].delay = 1;
break;
case SIDFX_RESET_1:
sid.voices[ch].ctrl = SID_CTRL_TEST;
sid.voices[ch].ctrl = 0;
sid.voices[ch].attdec = 0;
sid.voices[ch].susrel = 0;
channels[ch].state = SIDFX_READY;
break;
case SIDFX_READY:
channels[ch].freq = com->freq;
channels[ch].pwm = com->pwm;
sid.voices[ch].freq = com->freq;
sid.voices[ch].pwm = com->pwm;
sid.voices[ch].attdec = com->attdec;
sid.voices[ch].susrel = com->susrel;
sid.voices[ch].ctrl = com->ctrl;
if (com->ctrl & SID_CTRL_GATE)
{
channels[ch].delay = com->time1;
channels[ch].state = SIDFX_PLAY;
}
else
{
channels[ch].delay = com->time0;
channels[ch].state = SIDFX_PLAY;
}
break;
case SIDFX_PLAY:
if (com->time0)
{
sid.voices[ch].ctrl = com->ctrl & ~SID_CTRL_GATE;
channels[ch].delay = com->time0 - 1;
channels[ch].state = SIDFX_WAIT;
}
else if (channels[ch].cnt)
{
char sr = com->susrel & 0xf0;
com++;
char ctrl = com->ctrl;
if ((com->attdec & 0xef) == 0 && (ctrl & SID_CTRL_GATE) && (com->susrel & 0xf0) > sr)
{
sid.voices[ch].ctrl = ctrl & ~SID_CTRL_GATE;
sid.voices[ch].ctrl = ctrl | SID_CTRL_GATE;
}
channels[ch].cnt--;
channels[ch].com = com;
channels[ch].priority = com->priority;
channels[ch].state = SIDFX_READY;
}
else
{
com = nullptr;
channels[ch].state = SIDFX_RESET_0;
}
break;
case SIDFX_WAIT:
if (channels[ch].cnt)
{
com++;
channels[ch].cnt--;
channels[ch].com = com;
channels[ch].priority = com->priority;
if (com->ctrl & SID_CTRL_GATE)
channels[ch].state = SIDFX_RESET_0;
else
channels[ch].state = SIDFX_READY;
}
else
{
com = nullptr;
channels[ch].state = SIDFX_RESET_0;
}
break;
}
}
}
}
void sidfx_loop_2(void)
{
sidfx_loop_ch(2);
}
void sidfx_loop(void)
{
for(byte ch=0; ch<3; ch++)
sidfx_loop_ch(ch);
}

View File

@ -1,31 +0,0 @@
#ifndef SIDFX_H
#define SIDFX_H
#include <c64/sid.h>
struct SIDFX
{
unsigned freq, pwm;
byte ctrl, attdec, susrel;
int dfreq, dpwm;
byte time1, time0;
byte priority;
};
void sidfx_init(void);
inline bool sidfx_idle(byte chn);
inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt);
void sidfx_stop(byte chn);
char sidfx_cnt(byte chn);
void sidfx_loop(void);
void sidfx_loop_2(void);
#pragma compile("sidfx.c")
#endif

View File

@ -1,84 +0,0 @@
#include "bank1.h"
#include "mmu.h"
#include <string.h>
void bnk1_init(void)
{
mmu.cr = 0x3e;
memcpy((char *)0xfc00, (char *)0xf000, 0x0300);
xmmu.rcr |= 0x0c;
mmu.cr = 0x3f;
}
#pragma code(bnk1code)
char bnk1_readb(volatile char * p)
{
mmu.bank1 = 0;
char c = *p;
mmu.bank0 = 0;
return c;
}
unsigned bnk1_readw(volatile unsigned * p)
{
mmu.bank1 = 0;
unsigned w = *p;
mmu.bank0 = 1;
return w;
}
unsigned long bnk1_readl(volatile unsigned long * p)
{
mmu.bank1 = 0;
unsigned long l = *p;
mmu.bank0 = 3;
return l;
}
void bnk1_readm(char * dp, volatile char * sp, unsigned size)
{
while (size > 0)
{
mmu.bank1 = 0;
char c = * sp++;
mmu.bank0 = c;
*dp++ = c;
size--;
}
}
void bnk1_writeb(volatile char * p, char b)
{
mmu.bank1 = b;
*p = b;
mmu.bank0 = b;
}
void bnk1_writew(volatile unsigned * p, unsigned w)
{
mmu.bank1 = w;
*p = w;
mmu.bank0 = w;
}
void bnk1_writel(volatile unsigned long * p, unsigned long l)
{
mmu.bank1 = l;
*p = l;
mmu.bank0 = l;
}
void bnk1_writem(volatile char * dp, const char * sp, unsigned size)
{
while (size > 0)
{
char c = * sp++;
mmu.bank1 = c;
*dp++ = c;
mmu.bank0 = c;
size--;
}
}
#pragma code(code)

View File

@ -1,34 +0,0 @@
#ifndef C128_BANK1_H
#define C128_BANK1_H
#pragma section( bnk1code, 0)
#pragma region( bnk1code, 0xf000, 0xf300, , , {bnk1code}, 0xfc00 )
void bnk1_init(void);
#pragma code(bnk1code)
__noinline char bnk1_readb(volatile char * p);
__noinline unsigned bnk1_readw(volatile unsigned * p);
__noinline unsigned long bnk1_readl(volatile unsigned long * p);
__noinline void bnk1_readm(char * dp, volatile char * sp, unsigned size);
__noinline void bnk1_writeb(volatile char * p, char b);
__noinline void bnk1_writew(volatile unsigned * p, unsigned w);
__noinline void bnk1_writel(volatile unsigned long * p, unsigned long l);
__noinline void bnk1_writem(volatile char * dp, const char * sp, unsigned size);
#pragma code(code)
#pragma compile("bank1.c")
#endif

View File

@ -1,8 +0,0 @@
#include "mmu.h"
inline char mmu_set(char cr)
{
char pcr = mmu.cr;
mmu.cr = cr;
return pcr;
}

View File

@ -1,35 +0,0 @@
#ifndef C128_MMU_H
#define C128_MMU_H
#include <c64/types.h>
struct MMU
{
volatile byte cr;
volatile byte bank0;
volatile byte bank1;
volatile byte bank14;
volatile byte bankx;
};
struct XMMU
{
volatile byte cr;
volatile byte pcr[4];
volatile byte mcr;
volatile byte rcr;
volatile word page0;
volatile word page1;
volatile byte vr;
};
#define mmu (*((struct MMU *)0xff00))
#define xmmu (*((struct XMMU *)0xd500))
inline char mmu_set(char cr);
#pragma compile("mmu.c")
#endif

View File

@ -1,84 +0,0 @@
#include "vdc.h"
inline void vdc_reg(VDCRegister reg)
{
vdc.addr = reg;
}
inline void vdc_write(byte data)
{
do {} while (vdc.addr < 128);
vdc.data = data;
}
inline byte vdc_read(void)
{
do {} while (vdc.addr < 128);
return vdc.data;
}
void vdc_reg_write(VDCRegister reg, byte data)
{
vdc_reg(reg);
vdc_write(data);
}
byte vdc_reg_read(VDCRegister reg)
{
vdc_reg(reg);
return vdc_read();
}
void vdc_mem_addr(unsigned addr)
{
#pragma callinline()
vdc_reg_write(VDCR_ADDRH, addr >> 8);
#pragma callinline()
vdc_reg_write(VDCR_ADDRL, addr);
#pragma callinline()
vdc_reg(VDCR_DATA);
}
inline void vdc_mem_write(char data)
{
vdc_write(data);
}
inline char vdc_mem_read(void)
{
return vdc_read();
}
void vdc_mem_write_at(unsigned addr, char data)
{
#pragma callinline()
vdc_mem_addr(addr);
vdc_write(data);
}
char vdc_mem_read_at(unsigned addr)
{
#pragma callinline()
vdc_mem_addr(addr);
return vdc_read();
}
void vdc_mem_write_buffer(unsigned addr, const char * data, char size)
{
vdc_mem_addr(addr);
for(char i=0; i<size; i++)
vdc_write(data[i]);
}
void vdc_mem_read_buffer(unsigned addr, char * data, char size)
{
vdc_mem_addr(addr);
for(char i=0; i<size; i++)
data[i] = vdc_read();
}

View File

@ -1,95 +0,0 @@
#ifndef C128_VDC_H
#define C128_VDC_H
#include <c64/types.h>
enum VDCRegister
{
VDCR_HTOTAL,
VDCR_HDISPLAY,
VDCR_HSYNC,
VDCR_SYNCSIZE,
VDCR_VTOTAL,
VDCR_VADJUST,
VDCR_VDISPLAY,
VDCR_VSYNC,
VDCR_LACE,
VDCR_CSIZE,
VDCR_CURSOR_START,
VDCR_CURSOR_END,
VDCR_DISP_ADDRH,
VDCR_DISP_ADDRL,
VDCR_CURSOR_ADDRH,
VDCR_CURSOR_ADDRL,
VDCR_LPEN_Y,
VDCR_LPEN_X,
VDCR_ADDRH,
VDCR_ADDRL,
VDCR_ATTR_ADDRH,
VDCR_ATTR_ADDRL,
VDCR_CWIDTH,
VDCR_CHEIGHT,
VDCR_VSCROLL,
VDCR_HSCROLL,
VDCR_COLOR,
VDCR_ROWINC,
VDCR_CHAR_ADDRH,
VDCR_UNDERLINE,
VDCR_DSIZE,
VDCR_DATA,
VDCR_BLOCK_ADDRH,
VDCR_BLOCK_ADDRL,
VDCR_HSTART,
VDCR_HEND,
VDCR_REFRESH
};
struct VDC
{
volatile char addr;
volatile char data;
};
#define vdc (*((struct VDC *)0xd600))
inline void vdc_reg(VDCRegister reg);
inline void vdc_write(byte data);
inline byte vdc_read(void);
void vdc_reg_write(VDCRegister reg, byte data);
byte vdc_reg_read(VDCRegister reg);
void vdc_mem_addr(unsigned addr);
inline void vdc_mem_write(char data);
inline char vdc_mem_read(void);
void vdc_mem_write_at(unsigned addr, char data);
char vdc_mem_read_at(unsigned addr);
void vdc_mem_write_buffer(unsigned addr, const char * data, char size);
void vdc_mem_read_buffer(unsigned addr, char * data, char size);
#pragma compile("vdc.c")
#endif

View File

@ -19,10 +19,10 @@ inline byte asm_zp(byte * ip, AsmIns ins, byte addr)
return 2;
}
inline byte asm_rl(byte * ip, AsmIns ins, sbyte addr)
inline byte asm_rl(byte * ip, AsmIns ins, byte addr)
{
ip[0] = ins & 0xff;
ip[1] = (byte)addr;
ip[1] = addr;
return 2;
}

View File

@ -97,7 +97,7 @@ inline byte asm_ac(byte * ip, AsmIns ins);
inline byte asm_zp(byte * ip, AsmIns ins, byte addr);
// relative branch
inline byte asm_rl(byte * ip, AsmIns ins, sbyte addr);
inline byte asm_rl(byte * ip, AsmIns ins, byte addr);
// immediate
inline byte asm_im(byte * ip, AsmIns ins, byte value);

View File

@ -9,7 +9,7 @@ static const unsigned mul40[25] = {
800, 840, 880, 920, 960
};
static __native inline void copy_fwd(char * sdp, const char * ssp, char * cdp, const char * csp, char n)
static void copy_fwd(char * sdp, const char * ssp, char * cdp, const char * csp, char n)
{
for(char i=0; i<n; i++)
{
@ -18,7 +18,9 @@ static __native inline void copy_fwd(char * sdp, const char * ssp, char * cdp, c
}
}
static __native inline void fill_fwd(char * sdp, char * cdp, char ch, char color, char n)
#pragma native(copy_fwd)
static void fill_fwd(char * sdp, char * cdp, char ch, char color, char n)
{
for(char i=0; i<n; i++)
{
@ -27,7 +29,9 @@ static __native inline void fill_fwd(char * sdp, char * cdp, char ch, char color
}
}
static __native inline void copy_bwd(char * sdp, const char * ssp, char * cdp, const char * csp, char n)
#pragma native(fill_fwd)
static void copy_bwd(char * sdp, const char * ssp, char * cdp, const char * csp, char n)
{
while (n)
{
@ -37,6 +41,9 @@ static __native inline void copy_bwd(char * sdp, const char * ssp, char * cdp, c
}
}
#pragma native(copy_bwd)
void cwin_init(CharWin * win, char * screen, char sx, char sy, char wx, char wy)
{
@ -174,19 +181,17 @@ bool cwin_cursor_backward(CharWin * win)
return false;
}
//static char p2smap[] = {0x00, 0x20, 0x00, 0x40, 0x00, 0x60, 0x40, 0x60};
static char p2smap[] = {0x00, 0x00, 0x40, 0x20, 0x80, 0xc0, 0x80, 0x80};
//static char s2pmap[] = {0x40, 0x20, 0x60, 0xa0, 0x40, 0x20, 0x60, 0xa0};
static char s2pmap[] = {0x40, 0x00, 0x20, 0xc0, 0xc0, 0x80, 0xa0, 0x40};
static char p2smap[] = {0x00, 0x20, 0x00, 0x40, 0x00, 0x60, 0x40, 0x60};
static char s2pmap[] = {0x40, 0x20, 0x60, 0xb0, 0x40, 0x20, 0x60, 0xb0};
static inline char p2s(char ch)
{
return ch ^ p2smap[ch >> 5];
return (ch & 0x1f) | p2smap[ch >> 5];
}
static inline char s2p(char ch)
{
return ch ^ s2pmap[ch >> 5];
return (ch & 0x1f) | s2pmap[ch >> 5];
}
void cwin_read_string(CharWin * win, char * buffer)
@ -284,17 +289,6 @@ void cwin_put_chars_raw(CharWin * win, const char * chars, char num, char color)
}
}
char cwin_put_string_raw(CharWin * win, const char * str, char color)
{
char n = cwin_putat_string_raw(win, win->cx, win->cy, str, color);
win->cx += n;
if (win->cx >= win->wx)
{
win->cx = 0;
win->cy++;
}
return n;
}
@ -346,6 +340,7 @@ char cwin_putat_string(CharWin * win, char x, char y, const char * str, char col
#pragma native(cwin_putat_string)
void cwin_putat_char_raw(CharWin * win, char x, char y, char ch, char color)
{
int offset = mul40[y] + x;
@ -374,25 +369,6 @@ void cwin_putat_chars_raw(CharWin * win, char x, char y, const char * chars, cha
#pragma native(cwin_putat_chars_raw)
char cwin_putat_string_raw(CharWin * win, char x, char y, const char * str, char color)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
char * cp = win->cp + offset;
char i = 0;
while (char ch = str[i])
{
sp[i] = ch;
cp[i] = color;
i++;
}
return i;
}
#pragma native(cwin_putat_string_raw)
char cwin_getat_char(CharWin * win, char x, char y)
{
@ -422,7 +398,7 @@ char cwin_getat_char_raw(CharWin * win, char x, char y)
return *sp;
}
#pragma native(cwin_getat_chars_raw)
#pragma native(cwin_getat_char_raw)
void cwin_getat_chars_raw(CharWin * win, char x, char y, char * chars, char num)
{
@ -434,98 +410,6 @@ void cwin_getat_chars_raw(CharWin * win, char x, char y, char * chars, char num)
}
}
#pragma native(cwin_put_rect_raw)
void cwin_put_rect_raw(CharWin * win, char x, char y, char w, char h, const char * chars, char color)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
char * cp = win->cp + offset;
for(char i=0; i<h; i++)
{
for(char j=0; j<w; j++)
{
sp[j] = chars[j];
cp[j] = color;
}
chars += w;
sp += 40;
cp += 40;
}
}
#pragma native(cwin_put_rect)
void cwin_put_rect(CharWin * win, char x, char y, char w, char h, const char * chars, char color)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
char * cp = win->cp + offset;
for(char i=0; i<h; i++)
{
for(char j=0; j<w; j++)
{
sp[j] = p2s(chars[j]);
cp[j] = color;
}
chars += w;
sp += 40;
cp += 40;
}
}
#pragma native(cwin_get_rect_raw)
void cwin_get_rect_raw(CharWin * win, char x, char y, char w, char h, char * chars)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
for(char i=0; i<h; i++)
{
for(char j=0; j<w; j++)
{
chars[j] = sp[j];
}
chars += w;
sp += 40;
}
}
#pragma native(cwin_get_rect)
void cwin_get_rect(CharWin * win, char x, char y, char w, char h, char * chars)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
for(char i=0; i<h; i++)
{
for(char j=0; j<w; j++)
{
chars[j] = s2p(sp[j]);
}
chars += w;
sp += 40;
}
}
#pragma native(cwin_getat_chars_raw)
void cwin_insert_char(CharWin * win)
@ -595,18 +479,6 @@ int cwin_getch(void)
}
}
int cwin_checkch(void)
{
__asm
{
L1:
jsr 0xffe4
sta accu
lda #0
sta accu + 1
}
}
bool cwin_edit_char(CharWin * win, char ch)
{
switch (ch)

View File

@ -71,10 +71,6 @@ void cwin_put_char_raw(CharWin * win, char ch, char color);
//
void cwin_put_chars_raw(CharWin * win, const char * chars, char num, char color);
// Put a zero terminated raw string at the cursor location and advance the cursor
//
char cwin_put_string_raw(CharWin * win, const char * str, char color);
// Put a single char at the given window location
@ -98,10 +94,6 @@ void cwin_putat_char_raw(CharWin * win, char x, char y, char ch, char color);
//
void cwin_putat_chars_raw(CharWin * win, char x, char y, const char * chars, char num, char color);
// Put a zero terminated string at the given window location
//
char cwin_putat_string_raw(CharWin * win, char x, char y, const char * str, char color);
// Get a single char at the given window location
//
@ -122,17 +114,6 @@ char cwin_getat_char_raw(CharWin * win, char x, char y);
void cwin_getat_chars_raw(CharWin * win, char x, char y, char * chars, char num);
// Put an array of characters into a rectangle in the char win
void cwin_put_rect_raw(CharWin * win, char x, char y, char w, char h, const char * chars, char color);
void cwin_put_rect(CharWin * win, char x, char y, char w, char h, const char * chars, char color);
// Get an array of characters from a rectangle of a char win
void cwin_get_rect_raw(CharWin * win, char x, char y, char w, char h, char * chars);
void cwin_get_rect(CharWin * win, char x, char y, char w, char h, char * chars);
// Insert one space character at the cursor position
//
@ -144,8 +125,6 @@ void cwin_delete_char(CharWin * win);
int cwin_getch(void);
int cwin_checkch(void);
// Edit the window position using the char as the input
//
bool cwin_edit_char(CharWin * win, char ch);
@ -171,8 +150,6 @@ inline void cwin_fill_rect(CharWin * win, char x, char y, char w, char h, char c
//
void cwin_fill_rect_raw(CharWin * win, char x, char y, char w, char h, char ch, char color);
#pragma compile("charwin.c")
#endif

View File

@ -1,7 +1,5 @@
#include "cia.h"
byte ciaa_pra_def;
void cia_init(void)
{
cia1.icr = 0x7f;
@ -16,11 +14,6 @@ void cia_init(void)
cia2.ddrb = 0x00;
cia1.ddra = 0xff;
cia2.pra = 0x07;
cia2.prb = 0x07;
cia2.ddra = 0x3f;
char i0 = cia1.icr;
char i1 = cia2.icr;
ciaa_pra_def = 0x7f;
}

View File

@ -6,19 +6,17 @@
struct CIA
{
volatile byte pra, prb;
volatile byte ddra, ddrb;
volatile word ta, tb;
volatile byte todt, tods, todm, todh;
volatile byte sdr;
volatile byte icr;
volatile byte cra, crb;
byte ddra, ddrb;
word ta, tb;
byte todt, tods, todm, todh;
byte sdr;
byte icr;
byte cra, crb;
};
#define cia1 (*((struct CIA *)0xdc00))
#define cia2 (*((struct CIA *)0xdd00))
extern byte ciaa_pra_def;
void cia_init(void);
#pragma compile("cia.c")

View File

@ -5,9 +5,9 @@
struct EasyFlash
{
volatile byte bank;
byte bank;
byte pad1;
volatile byte control;
byte control;
};
#define EFCTRL_GAME 0x01
@ -18,46 +18,6 @@ struct EasyFlash
#define eflash (*(EasyFlash *)0xde00)
#ifdef __cplusplus
#ifdef EFPROX_SECTION
#pragma code(EFPROX_SECTION)
#endif
template<int back, class fn, class ... P>
__noinline auto ef_call_p(P... p)
{
if (back != __bankof(fn))
eflash.bank = __bankof(fn);
auto r = fn(p...);
if (back != 0xff && back != __bankof(fn))
eflash.bank = back;
return r;
}
#ifdef EFPROX_SECTION
#pragma code(code)
#endif
template<class fn>
class EFlashCall
{
public:
template<class ... P>
__forceinline auto operator()(P ... p) const
{
switch(__bankof(0))
{
#for(i,64) case i: return ef_call_p<i, fn, P...>(p...);
default:
return ef_call_p<0xff, fn, P...>(p...);
}
}
};
#define EF_CALL(fn) EFlashCall<fn##_p> fn
#endif
#endif

View File

@ -1,608 +0,0 @@
#include "flossiec.h"
#include <c64/iecbus.h>
#include <c64/vic.h>
#include <c64/cia.h>
#include <c64/kernalio.h>
#ifndef FLOSSIEC_NODISPLAY
#define FLOSSIEC_NODISPLAY 0
#endif
#ifndef FLOSSIEC_NOIRQ
#define FLOSSIEC_NOIRQ 0
#endif
#ifndef FLOSSIEC_BORDER
#define FLOSSIEC_BORDER 0
#endif
#define VIA_ATNIN 0x80
#define VIA_ATNOUT 0x10
#define VIA_CLKOUT 0x08
#define VIA_DATAOUT 0x02
#define VIA_CLKIN 0x04
#define VIA_DATAIN 0x01
#define PORTB1 0x1800
#define PORTB2 0x1c00
#define WR 0x1d
#ifdef FLOSSIEC_CODE
#pragma code(FLOSSIEC_CODE)
#endif
#ifdef FLOSSIEC_BSS
#pragma bss(FLOSSIEC_BSS)
#endif
__asm diskcode
{
nop
nop
lda #VIA_CLKOUT
sta PORTB1
lda 0x0202
sta 0x0c
lda 0x0203
sta 0x0d
lda #$80
sta 0x03
ldx #0
l0:
txa
lsr
lsr
lsr
lsr
sta 0x0700,x
inx
bne l0
lr:
lda 0x03
bmi lr
sei
ldx #0
l2:
lda #0
sta PORTB1
lda 0x0600, x
tay
and #0x0f
ora #VIA_DATAIN
l1:
bit PORTB1
bne l1
l3:
sta PORTB1
tya
asl
and #0x0a
sta PORTB1
lda 0x0700,y
nop
sta PORTB1
asl
nop
and #0x0a
sta PORTB1
inx
bne l2
lda #VIA_CLKOUT
sta PORTB1
lda 0x0600
beq w1
sta 0x0c
lda 0x0601
sta 0x0d
lda #$80
sta 0x03
cli
bne lr
w1:
sta PORTB1
cli
rts
}
#define CIA2B_ATNOUT 0x08
#define CIA2B_CLKOUT 0x10
#define CIA2B_DATAOUT 0x20
#define CIA2B_CLKIN 0x40
#define CIA2B_DATAIN 0x80
#define CIA2PRA 0xdd00
static char remap[256];
static char rbuffer[256];
static char xbuffer[256];
static char flpos;
static char xcmd;
static char xi, xj;
static char fldrive;
static char flvxor;
__noinline void fl_read_buf(void)
{
__asm
{
#if FLOSSIEC_NOIRQ
php
sei
#endif
lda CIA2PRA
and #~CIA2B_CLKOUT
sta accu
sta CIA2PRA
and #~CIA2B_DATAOUT
sta accu + 1
l0:
lda CIA2PRA
and #CIA2B_CLKIN
beq l0
#if !FLOSSIEC_NOIRQ
php
pla
and #$04
beq iq
#endif
ldy #0
sec
l1:
ldx accu + 1
#if !FLOSSIEC_NODISPLAY
l2:
lda 0xd012
sbc #50
bcc w1
and #7
beq l2
#endif
w1:
stx CIA2PRA
#if FLOSSIEC_BORDER
inc 0xd020
#else
nop
nop
nop
#endif
ldx accu
nop
lda CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
sec
eor CIA2PRA
stx CIA2PRA
sta rbuffer, y
iny
bne l1
jmp done
#if !FLOSSIEC_NOIRQ
iq:
ldy #0
sec
l1i:
ldx accu + 1
l2i:
cli
sei
#if !FLOSSIEC_NODISPLAY
lda 0xd012
sbc #50
bcc w1i
and #7
beq l2i
w1i:
#endif
stx CIA2PRA
#if FLOSSIEC_BORDER
inc 0xd020
#else
nop
nop
nop
#endif
ldx accu
nop
lda CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
sec
eor CIA2PRA
stx CIA2PRA
sta rbuffer, y
iny
bne l1i
cli
#endif
done:
#if FLOSSIEC_NOIRQ
plp
#endif
}
}
inline char flossiec_get(void)
{
if (!flpos)
{
fl_read_buf();
flpos = 2;
}
return remap[rbuffer[flpos++]];
}
void flossiec_decompress(void)
{
char i = 0, j = xj, cmd = xcmd;
xi = 0;
for(;;)
{
if (cmd & 0x80)
{
if (i < cmd)
{
char t = i - cmd;
do {
char ch = xbuffer[j++];
xbuffer[i++] = ch;
} while (i != t);
cmd = 0;
}
else
{
cmd -= i;
do {
char ch = xbuffer[j++];
xbuffer[i++] = ch;
} while (i);
break;
}
}
else
{
char ch = flossiec_get();
if (cmd)
{
xbuffer[i++] = ch;
cmd--;
if (!i)
break;
}
else
{
cmd = ch;
if (!cmd)
break;
if (cmd & 0x80)
{
cmd ^= 0x7f;
cmd++;
j = i - flossiec_get();
}
}
}
}
xj = j;
xcmd = cmd;
}
inline char flossiec_get_lzo(void)
{
if (!xi)
flossiec_decompress();
return xbuffer[xi++];
}
inline bool flossiec_eof(void)
{
return !remap[rbuffer[0]] && flpos >= remap[rbuffer[1]];
}
char * flossiec_read(char * dp, unsigned size)
{
while (size)
{
*dp++ = flossiec_get();
size--;
}
return dp;
}
char * flossiec_read_lzo(char * dp, unsigned size)
{
char i = xi;
dp -= i;
size += i;
while (size)
{
if (!i)
flossiec_decompress();
if (size >= 256)
{
do {
dp[i] = xbuffer[i];
i++;
} while (i);
dp += 256;
size -= 256;
}
else
{
do {
dp[i] = xbuffer[i];
i++;
} while (i != (char)size);
dp += i;
break;
}
}
xi = i;
return dp;
}
static void vxorcheck(void)
{
char vxor = cia2.pra & 7;
vxor ^= vxor >> 2;
vxor ^= 0xff;
if (vxor != flvxor)
{
flvxor = vxor;
for(int i=0; i<256; i++)
{
char j = i ^ vxor;
char d = ((j & 0x11) << 3) |
(j & 0x66) |
((j & 0x88) >> 3);
remap[i] = d;
}
}
}
bool flossiec_init(char drive)
{
fldrive = drive;
flvxor = 0;
iec_open(drive, 2, "#2");
iec_listen(drive, 2);
for(char j=0; j<127; j++)
iec_write(((char *)diskcode)[j]);
iec_unlisten();
iec_close(drive, 2);
iec_open(drive, 15, "");
return true;
}
void flossiec_shutdown(void)
{
iec_close(fldrive, 15);
}
bool flossiec_open(char track, char sector)
{
iec_listen(fldrive, 15);
iec_write(P'U');
iec_write(P'4');
iec_write(track);
iec_write(sector);
iec_unlisten();
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 &= ~VIC_CTRL1_DEN;
#endif
vic_waitFrame();
vxorcheck();
vic_waitFrame();
flpos = 0;
xi = 0;
return true;
}
void flossiec_close(void)
{
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 |= VIC_CTRL1_DEN;
#endif
}
bool flosskio_init(char drive)
{
fldrive = drive;
flvxor = 0;
krnio_setnam_n("#2", 2);
krnio_open(2, drive, 2);
krnio_write(2, (char *)diskcode, 128);
krnio_close(2);
krnio_setnam_n(nullptr, 0);
krnio_open(15, drive, 15);
return true;
}
void flosskio_shutdown(void)
{
krnio_close(15);
}
bool flosskio_open(char track, char sector)
{
krnio_chkout(15);
krnio_chrout(P'U');
krnio_chrout(P'4');
krnio_chrout(track);
krnio_chrout(sector);
krnio_clrchn();
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 &= ~VIC_CTRL1_DEN;
#endif
vic_waitFrame();
vxorcheck();
vic_waitFrame();
flpos = 0;
xi = 0;
return true;
}
void flosskio_close(void)
{
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 |= VIC_CTRL1_DEN;
#endif
}
static bool mapdir(const char * fnames, floss_blk * blks)
{
do {
fl_read_buf();
char si = 0;
do
{
if (remap[rbuffer[si + 2]] == 0x82)
{
char fname[17];
char j = 0;
while (j < 16 && remap[rbuffer[si + j + 5]] != 0xa0)
{
fname[j] = remap[rbuffer[si + j + 5]];
j++;
}
fname[j] = 0;
char sj = 0;
char k = 0;
while (fnames[sj])
{
j = 0;
while (fname[j] && fname[j] == fnames[sj])
{
j++;
sj++;
}
if (!fname[j] && (!fnames[sj] || fnames[sj] == ','))
{
__assume(k < 128);
blks[k].track = remap[rbuffer[si + 3]];
blks[k].sector = remap[rbuffer[si + 4]];
break;
}
while (fnames[sj] && fnames[sj++] != ',')
;
k++;
}
}
si += 32;
} while (si);
} while (remap[rbuffer[0]]);
return true;
}
bool flosskio_mapdir(const char * fnames, floss_blk * blks)
{
if (flosskio_open(18, 1))
{
mapdir(fnames, blks);
flosskio_close();
return true;
}
return false;
}
bool flossiec_mapdir(const char * fnames, floss_blk * blks)
{
if (flossiec_open(18, 1))
{
mapdir(fnames, blks);
flossiec_close();
return true;
}
return false;
}

View File

@ -1,79 +0,0 @@
#ifndef FLOSSIEC_H
#define FLOSSIEC_H
// When building you can use various defines to change the behaviour
// FLOSSIEC_BORDER=1 Enable border flashing while loading
// FLOSSIEC_NODISPLAY=1 Disable the display while loading
// FLOSSIEC_NOIRQ=1 Disable IRQ during load
// FLOSSIEC_CODE=cseg Code segment to be used, when defined
// FLOSSIEC_BSS=bseg BSS segment to be used, when defined
// Initialize the fastloader to be used without the kernal
bool flossiec_init(char drive);
// Shutdown the fastloader when used without the kernal
void flossiec_shutdown(void);
// Open a file for read with the fastloader without the kernal.
// The file has to be read to completion before you can close
// it again,
bool flossiec_open(char track, char sector);
// Close a file after reading
void flossiec_close(void);
// Initialize the fastloader to be used with the kernal
bool flosskio_init(char drive);
// Shutdown the fastloader when used with the kernal
void flosskio_shutdown(void);
// Open a file for read with the fastloader with the kernal
// The file has to be read to completion before you can close
// it again,
bool flosskio_open(char track, char sector);
// Close a file after reading
void flosskio_close(void);
// Track and sector start of a file
struct floss_blk
{
char track, sector;
};
// Map a comma separated list of filenames to an array of
// block start positions by reading the directory, using the
// kernal.
bool flosskio_mapdir(const char * fnames, floss_blk * blks);
// Map a comma separated list of filenames to an array of
// block start positions by reading the directory, without the
// kernal.
bool flossiec_mapdir(const char * fnames, floss_blk * blks);
// Check for end of file while reading
inline bool flossiec_eof(void);
// Get one char from uncompressed file
inline char flossiec_get(void);
// Get one char from compressed file
inline char flossiec_get_lzo(void);
// Read a section of a file into memory up to size bytes,
// returns the first address after the read
char * flossiec_read(char * dp, unsigned size);
// Read and expand section of a file into memory up to size
// bytes, returns the first address after the read
char * flossiec_read_lzo(char * dp, unsigned size);
#pragma compile("flossiec.c")
#endif

View File

@ -1,353 +0,0 @@
#include "iecbus.h"
#include <c64/cia.h>
#include <c64/vic.h>
IEC_STATUS iec_status;
char iec_queue;
#define CIA2B_ATNOUT 0x08
#define CIA2B_CLKOUT 0x10
#define CIA2B_DATAOUT 0x20
#define CIA2B_CLKIN 0x40
#define CIA2B_DATAIN 0x80
#pragma optimize(push)
#pragma optimize(1)
// multiples of 5us
static void delay(char n)
{
__asm {
ldx n
l1:
dex
bne l1
}
}
static inline void data_true(void)
{
cia2.pra &= ~CIA2B_DATAOUT;
}
static inline void data_false(void)
{
cia2.pra |= CIA2B_DATAOUT;
}
static inline void clock_true(void)
{
cia2.pra &= ~CIA2B_CLKOUT;
}
static inline void cdata_true(void)
{
cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT);
}
static inline void clock_false(void)
{
cia2.pra |= CIA2B_CLKOUT;
}
static inline void atn_true(void)
{
cia2.pra &= ~CIA2B_ATNOUT;
}
static inline void atn_false(void)
{
cia2.pra |= CIA2B_ATNOUT;
}
static inline bool data_in(void)
{
return (cia2.pra & CIA2B_DATAIN) != 0;
}
static inline bool clock_in(void)
{
return (cia2.pra & CIA2B_CLKIN) != 0;
}
static bool data_check(void)
{
char cnt = 200;
while (cnt > 0 && data_in())
{
delay(5);
cnt--;
}
if (cnt)
return true;
else
{
iec_status = IEC_DATA_CHECK;
return false;
}
}
static bool iec_eoib(void)
{
clock_true();
while (!data_in());
delay(40);
return data_check();
}
static void iec_writeb(char b)
{
clock_true();
while (!data_in());
delay(5);
for(char i=0; i<8; i++)
{
clock_false();
delay(5);
if (b & 1)
data_true();
else
data_false();
clock_true();
b >>= 1;
delay(5);
}
clock_false();
data_true();
}
bool iec_write(char b)
{
if (iec_status == IEC_QUEUED)
{
__asm
{
php
sei
}
iec_status = IEC_OK;
iec_writeb(iec_queue);
__asm
{
plp
}
data_check();
}
if (iec_status < IEC_ERROR)
{
iec_queue = b;
iec_status = IEC_QUEUED;
return true;
}
return false;
}
char iec_read(void)
{
while (!clock_in());
__asm
{
php
sei
}
data_true();
char cnt = 100;
while (cnt > 0 && clock_in())
cnt--;
if (cnt == 0)
{
iec_status = IEC_EOF;
data_false();
delay(10);
data_true();
cnt = 200;
while (cnt > 0 && clock_in())
cnt--;
if (cnt == 0)
{
iec_status = IEC_TIMEOUT;
__asm
{
plp
}
return 0;
}
}
char b = 0;
for(char i=0; i<8; i++)
{
char c;
while (!((c = cia2.pra) & CIA2B_CLKIN))
;
b >>= 1;
b |= c & 0x80;
while (cia2.pra & CIA2B_CLKIN)
;
}
data_false();
__asm
{
plp
}
return b;
}
void iec_atn(char dev, char sec)
{
clock_true();
data_true();
atn_false();
clock_false();
delay(200);
while (data_in());
iec_writeb(dev);
data_check();
if (sec != 0xff)
{
iec_writeb(sec);
data_check();
}
atn_true();
}
void iec_talk(char dev, char sec)
{
iec_status = IEC_OK;
iec_atn(dev | 0x40, sec | 0x60);
data_false();
__asm
{
php
sei
}
clock_true();
char cnt = 200;
while (cnt > 0 && clock_in())
cnt--;
__asm
{
plp
}
delay(10);
}
void iec_untalk(void)
{
iec_atn(0x5f, 0xff);
}
void iec_listen(char dev, char sec)
{
iec_status = IEC_OK;
iec_atn(dev | 0x20, sec | 0x60);
}
void iec_unlisten(void)
{
__asm
{
php
sei
}
if (iec_status == IEC_QUEUED)
{
iec_status = IEC_OK;
iec_eoib();
iec_writeb(iec_queue);
data_check();
}
iec_atn(0x3f, 0xff);
clock_true();
__asm
{
plp
}
}
void iec_open(char dev, char sec, const char * fname)
{
iec_status = IEC_OK;
iec_atn(dev | 0x20, sec | 0xf0);
char i = 0;
while (fname[i])
{
iec_write(fname[i]);
i++;
}
iec_unlisten();
}
void iec_close(char dev, char sec)
{
iec_atn(dev | 0x20, sec | 0xe0);
iec_unlisten();
}
int iec_write_bytes(const char * data, int num)
{
for(int i=0; i<num; i++)
{
if (!iec_write(data[i]))
return i;
}
return num;
}
int iec_read_bytes(char * data, int num)
{
int i = 0;
while (i < num)
{
char ch = iec_read();
if (iec_status < IEC_ERROR)
data[i++] = ch;
if (iec_status != IEC_OK)
return i;
}
return num;
}
#pragma optimize(pop)

View File

@ -1,43 +0,0 @@
#ifndef C64_IECBUS_H
#define C64_IECBUS_H
enum IEC_STATUS
{
IEC_OK = 0x00,
IEC_EOF = 0x01,
IEC_QUEUED = 0x02,
IEC_ERROR = 0x80,
IEC_TIMEOUT,
IEC_DATA_CHECK,
};
extern IEC_STATUS iec_status;
bool iec_write(char b);
char iec_read(void);
void iec_atn(char dev, char sec);
void iec_talk(char dev, char sec);
void iec_untalk(void);
void iec_listen(char dev, char sec);
void iec_unlisten(void);
void iec_open(char dev, char sec, const char * fname);
void iec_close(char dev, char sec);
int iec_write_bytes(const char * data, int num);
int iec_read_bytes(char * data, int num);
#pragma compile("iecbus.c")
#endif

View File

@ -5,7 +5,7 @@ bool joyb[2];
void joy_poll(char n)
{
char b = ((volatile char *)0xdc00)[n];
char b = ((char *)0xdc00)[n];
if (!(b & 1))
joyy[n] = -1;

View File

@ -2,32 +2,7 @@
krnioerr krnio_pstatus[16];
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
void krnio_setbnk(char filebank, char namebank)
{
__asm
{
lda filebank
ldx namebank
jsr $ff68 // setbnk
}
}
#pragma native(krnio_setbnk)
#endif
#if defined(__PLUS4__)
#pragma code(lowcode)
#define BANKIN sta 0xff3e
#define BANKOUT sta 0xff3f
#define BANKINLINE __noinline
#else
#define BANKIN
#define BANKOUT
#define BANKINLINE
#endif
BANKINLINE void krnio_setnam(const char * name)
void krnio_setnam(const char * name)
{
__asm
{
@ -42,41 +17,22 @@ BANKINLINE void krnio_setnam(const char * name)
tya
W1: ldx name
ldy name + 1
BANKIN
jsr $ffbd // setnam
BANKOUT
}
}
#pragma native(krnio_setnam)
BANKINLINE void krnio_setnam_n(const char * name, char len)
{
__asm
{
lda len
ldx name
ldy name + 1
BANKIN
jsr $ffbd // setnam
BANKOUT
}
}
#pragma native(krnio_setnam_n)
BANKINLINE bool krnio_open(char fnum, char device, char channel)
bool krnio_open(char fnum, char device, char channel)
{
krnio_pstatus[fnum] = KRNIO_OK;
return char(__asm
__asm
{
lda #0
sta accu
sta accu + 1
BANKIN
lda fnum
ldx device
ldy channel
@ -91,48 +47,46 @@ BANKINLINE bool krnio_open(char fnum, char device, char channel)
W1:
lda #1
sta accu
BANKOUT
E2:
});
}
}
#pragma native(krnio_open)
BANKINLINE void krnio_close(char fnum)
void krnio_close(char fnum)
{
__asm
{
BANKIN
lda fnum
jsr $ffc3 // close
BANKOUT
}
}
#pragma native(krnio_close)
BANKINLINE krnioerr krnio_status(void)
krnioerr krnio_status(void)
{
return __asm
__asm
{
BANKIN
jsr $ffb7 // readst
BANKOUT
sta accu
lda #0
sta accu + 1
};
}
}
#pragma native(krnio_status)
BANKINLINE bool krnio_load(char fnum, char device, char channel)
bool krnio_load(char fnum, char device, char channel)
{
return char(__asm
__asm
{
BANKIN
lda #0
sta accu
sta accu + 1
lda fnum
ldx device
ldy channel
@ -141,123 +95,89 @@ BANKINLINE bool krnio_load(char fnum, char device, char channel)
lda #0
ldx #0
ldy #0
jsr $FFD5 // load
BANKOUT
jsr $FFD5 // open
bcc W1
lda #0
rol
eor #1
jmp E2
W1:
lda #1
sta accu
});
E2:
}
}
#pragma native(krnio_load)
BANKINLINE bool krnio_save(char device, const char* start, const char* end)
bool krnio_chkout(char fnum)
{
return char(__asm
__asm
{
BANKIN
lda #0
ldx device
ldy #0
jsr $ffba // setlfs
lda #start
ldx end
ldy end+1
jsr $FFD8 // save
BANKOUT
lda #0
rol
eor #1
sta accu
});
}
#pragma native(krnio_save)
BANKINLINE bool krnio_chkout(char fnum)
{
return char(__asm
{
BANKIN
ldx fnum
jsr $ffc9 // chkout
BANKOUT
lda #0
rol
eor #1
sta accu
});
sta accu + 1
bcs W1
lda #1
W1: sta accu
}
}
#pragma native(krnio_chkout)
BANKINLINE bool krnio_chkin(char fnum)
bool krnio_chkin(char fnum)
{
return char(__asm
__asm
{
BANKIN
ldx fnum
jsr $ffc6 // chkin
BANKOUT
lda #0
rol
eor #1
sta accu
});
sta accu + 1
bcs W1
lda #1
W1: sta accu
}
}
#pragma native(krnio_chkin)
BANKINLINE void krnio_clrchn(void)
void krnio_clrchn(void)
{
__asm
{
BANKIN
jsr $ffcc // clrchn
BANKOUT
}
}
#pragma native(krnio_clrchn)
BANKINLINE bool krnio_chrout(char ch)
bool krnio_chrout(char ch)
{
return char(__asm
__asm
{
BANKIN
lda ch
jsr $ffd2 // chrout
sta accu
BANKOUT
});
lda #0
sta accu + 1
}
}
#pragma native(krnio_chrout)
BANKINLINE char krnio_chrin(void)
int krnio_chrin(void)
{
return __asm
__asm
{
BANKIN
jsr $ffcf // chrin
sta accu
BANKOUT
};
lda #0
sta accu + 1
}
}
#pragma native(krnio_chrin)
#if defined(__PLUS4__)
#pragma code(code)
#endif
int krnio_getch(char fnum)
{
if (krnio_pstatus[fnum] == KRNIO_EOF)
@ -354,66 +274,6 @@ int krnio_read(char fnum, char * data, int num)
#pragma native(krnio_read)
int krnio_read_lzo(char fnum, char * data)
{
if (krnio_pstatus[fnum] == KRNIO_EOF)
return 0;
if (krnio_chkin(fnum))
{
int i = 0;
char ch;
char cmd = 0;
krnioerr err;
for(;;)
{
ch = krnio_chrin();
err = krnio_status();
if (err && err != KRNIO_EOF)
break;
if (cmd & 0x80)
{
char * dp = data + i, * cp = dp - ch;
cmd &= 0x7f;
i += cmd;
char n = 0x00;
do {
dp[n] = cp[n];
n++;
} while (n != cmd);
cmd = 0;
}
else if (cmd)
{
data[i++] = (char)ch;
cmd--;
}
else if (ch)
cmd = ch;
else
break;
if (err)
break;
}
krnio_pstatus[fnum] = err;
krnio_clrchn();
return i;
}
else
return -1;
}
#pragma native(krnio_read_lzo)
int krnio_gets(char fnum, char * data, int num)
{
if (krnio_pstatus[fnum] == KRNIO_EOF)
@ -421,7 +281,7 @@ int krnio_gets(char fnum, char * data, int num)
if (krnio_chkin(fnum))
{
krnioerr err = KRNIO_OK;
krnioerr err;
int i = 0;
int ch;
while (i + 1 < num)

View File

@ -1,5 +1,5 @@
#ifndef C64_KERNALIO_H
#define C64_KERNALIO_H
#ifndef C64_KERNALIO_H
// Error and status codes returned by krnio_status
@ -18,18 +18,11 @@ enum krnioerr
extern krnioerr krnio_pstatus[16];
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
// C128: Set bank for load/save and filename for next file operations
void krnio_setbnk(char filebank, char namebank);
#endif
// Set filename for next krnio_open operation, make sure
// that the string is still valid when calling krnio_open
void krnio_setnam(const char * name);
void krnio_setnam_n(const char * name, char len);
// open a kernal file/stream/io channel, returns true on success
bool krnio_open(char fnum, char device, char channel);
@ -44,8 +37,6 @@ krnioerr krnio_status(void);
bool krnio_load(char fnum, char device, char channel);
bool krnio_save(char device, const char* start, const char* end);
// select the given file for stream output
bool krnio_chkout(char fnum);
@ -64,7 +55,7 @@ bool krnio_chrout(char ch);
// read a single byte from the current input channel
char krnio_chrin(void);
int krnio_chrin(void);
// read a single byte from the given file/channel, returns
// a negative result on failure. If this was the last byte
@ -90,8 +81,6 @@ int krnio_puts(char fnum, const char * data);
int krnio_read(char fnum, char * data, int num);
int krnio_read_lzo(char fnum, char * data);
// read a line from the given file, terminated by a CR or LF character
// and appends a zero byte.

View File

@ -8,8 +8,8 @@ const char keyb_codes[128] = {
'7', 'y', 'g', '8', 'b', 'h', 'u', 'v',
'9', 'i', 'j', '0', 'm', 'k', 'o', 'n',
'+', 'p', 'l', '-', '.', ':', '@', ',',
0 , '*', ';', KEY_HOME, 0, '=', '^', '/',
'1', KEY_ARROW_LEFT, 0, '2', ' ', 0, 'q', KEY_ESC,
0 , '*', ';', 0, 0, '=', '^', '/',
'1', 0, 0, '2', ' ', 0, 'q', KEY_ESC,
KEY_INST, KEY_RETURN, KEY_CSR_LEFT, KEY_F8, KEY_F2, KEY_F4, KEY_F6, KEY_CSR_UP,
'#', 'W', 'A', '$', 'Z', 'S', 'E', 0,
@ -17,18 +17,16 @@ const char keyb_codes[128] = {
'\'', 'Y', 'G', '(', 'B', 'H', 'U', 'V',
')', 'I', 'J', '0', 'M', 'K', 'O', 'N',
0, 'P', 'L', 0, '>', '[', '@', '<',
0, 0, ']', KEY_CLR, 0, 0, '^', '?',
0, 0, ']', 0, 0, 0, '^', '?',
'!', 0, 0, '"', ' ', 0, 'Q', KEY_ESC,
};
byte keyb_matrix[8];
KeyScanCode keyb_key;
byte keyb_matrix[8], keyb_key;
static byte keyb_pmatrix[8];
bool key_pressed(KeyScanCode code)
bool key_pressed(char code)
{
return !(keyb_matrix[code >> 3] & (1 << (code & 7)));
}
@ -43,7 +41,6 @@ bool key_shift(void)
void keyb_poll(void)
{
cia1.ddra = 0xff;
cia1.pra = 0xff;
keyb_key = 0x00;
if (cia1.prb == 0xff)
@ -96,5 +93,5 @@ void keyb_poll(void)
}
}
cia1.pra = ciaa_pra_def;
cia1.pra = 0xff;
}

View File

@ -8,16 +8,11 @@
#define KEY_CSR_UP (17 + 128)
#define KEY_CSR_LEFT (29 + 128)
#define KEY_ARROW_LEFT (95)
#define KEY_ESC (27)
#define KEY_DEL (20)
#define KEY_INST (148)
#define KEY_RETURN (13)
#define KEY_HOME (19)
#define KEY_CLR (147)
#define KEY_F1 (133)
#define KEY_F3 (134)
#define KEY_F5 (135)
@ -28,86 +23,10 @@
#define KEY_F6 (139)
#define KEY_F8 (140)
enum KeyScanCode
{
KSCAN_DEL,
KSCAN_RETURN,
KSCAN_CSR_RIGHT,
KSCAN_F7,
KSCAN_F1,
KSCAN_F3,
KSCAN_F5,
KSCAN_CSR_DOWN,
KSCAN_3,
KSCAN_W,
KSCAN_A,
KSCAN_4,
KSCAN_Z,
KSCAN_S,
KSCAN_E,
KSCAN_SHIFT_LOCK,
KSCAN_5,
KSCAN_R,
KSCAN_D,
KSCAN_6,
KSCAN_C,
KSCAN_F,
KSCAN_T,
KSCAN_X,
KSCAN_7,
KSCAN_Y,
KSCAN_G,
KSCAN_8,
KSCAN_B,
KSCAN_H,
KSCAN_U,
KSCAN_V,
KSCAN_9,
KSCAN_I,
KSCAN_J,
KSCAN_0,
KSCAN_M,
KSCAN_K,
KSCAN_O,
KSCAN_N,
KSCAN_PLUS,
KSCAN_P,
KSCAN_L,
KSCAN_MINUS,
KSCAN_DOT,
KSCAN_COLON,
KSCAN_AT,
KSCAN_COMMA,
KSCAN_POUND,
KSCAN_STAR,
KSCAN_SEMICOLON,
KSCAN_HOME,
KSCAN_RSHIFT,
KSCAN_EQUAL,
KSCAN_ARROW_UP,
KSCAN_SLASH,
KSCAN_1,
KSCAN_ARROW_LEFT,
KSCAN_CONTROL,
KSCAN_2,
KSCAN_SPACE,
KSCAN_COMMODORE,
KSCAN_Q,
KSCAN_STOP,
KSCAN_QUAL_SHIFT = 0x40,
KSCAN_QUAL_MASK = 0x7f,
KSCAN_QUAL_DOWN = 0x80,
KSCAN_MAX = 0xff
};
#define KEY_CODE_CSR_RIGHT (2)
#define KEY_CODE_CSR_DOWN (7)
#define KEY_CODE_LSHIFT (15)
#define KEY_CODE_RSHIFT (48)
// map of keyboard codes to PETSCII, first 64 without shift
// second 64 with shift
@ -117,15 +36,14 @@ extern const char keyb_codes[128];
// current status of key matrix
extern byte keyb_matrix[8];
// current key in scan code - the top level bit KSCAN_QUAL_DOWN is
// used to indicate a key is pressed, so 0 is no key
extern KeyScanCode keyb_key;
// current key
extern byte keyb_key;
// poll keyboard matrix
void keyb_poll(void);
inline bool key_pressed(KeyScanCode code);
inline bool key_pressed(char code);
inline bool key_shift(void);

View File

@ -1,8 +1,11 @@
#include "memmap.h"
volatile char PLAShadow;
__asm DoneTrampoline
{
stx $01
lda PLAShadow
sta $01
pla
tax
pla
@ -14,6 +17,8 @@ __asm IRQTrampoline
pha
txa
pha
lda #$36
sta $01
lda #>DoneTrampoline
pha
@ -22,10 +27,7 @@ __asm IRQTrampoline
tsx
lda $0105, x
pha
ldx $01
lda #$36
sta $01
jmp ($fffe)
jmp ($fffa)
}
__asm NMITrampoline
@ -33,6 +35,8 @@ __asm NMITrampoline
pha
txa
pha
lda #$36
sta $01
lda #>DoneTrampoline
pha
@ -41,23 +45,19 @@ __asm NMITrampoline
tsx
lda $0105, x
pha
ldx $01
lda #$36
sta $01
jmp ($fffa)
jmp ($fffe)
}
void mmap_trampoline(void)
{
*((void **)0xfffa) = NMITrampoline;
*((void **)0xfffe) = IRQTrampoline;
*((void **)0xfffa) = IRQTrampoline;
*((void **)0xfffe) = NMITrampoline;
}
#pragma native(mmap_trampoline)
char mmap_set(char pla)
void mmap_set(char pla)
{
char ppla = *((char *)0x01);
*((volatile char *)0x01) = pla;
return ppla;
PLAShadow = pla;
*((char *)0x01) = pla;
}

View File

@ -8,7 +8,6 @@
#define MMAP_NO_ROM 0x35
#define MMAP_RAM 0x30
#define MMAP_CHAR_ROM 0x31
#define MMAP_ALL_ROM 0x33
// Install an IRQ an NMI trampoline, that routes the kernal interrupts
// through an intermediate trampoline when the kernal ROM is not paged
@ -18,9 +17,9 @@
void mmap_trampoline(void);
// Set the memory map in a way that is compatible with the IRQ
// trampoline, returns the previous state
// trampoline
inline char mmap_set(char pla);
inline void mmap_set(char pla);
#pragma compile("memmap.c")

View File

@ -1,52 +0,0 @@
#include "mouse.h"
#include "sid.h"
#include "cia.h"
sbyte mouse_dx, mouse_dy;
bool mouse_lb, mouse_rb;
static char mouse_px, mouse_py;
static char mouse_port;
inline signed char dpos(char * old, char mnew)
{
mnew = (mnew & 0x7f) >> 1;
char diff = (mnew - *old) & 0x3f;
if (diff >= 0x20)
{
*old = mnew;
return diff | 0xe0;
}
else if (diff)
{
*old = mnew;
return diff;
}
return 0;
}
void mouse_poll(void)
{
char b = ((volatile char *)0xdc00)[mouse_port];
mouse_rb = (b & 0x01) == 0;
mouse_lb = (b & 0x10) == 0;
char x = sid.potx, y = sid.poty;
mouse_dx = dpos(&mouse_px, x);
mouse_dy = dpos(&mouse_py, y);
}
void mouse_arm(char n)
{
mouse_port = n;
cia1.pra = ciaa_pra_def = n ? 0x7f : 0xbf;
}
void mouse_init(void)
{
mouse_arm(1);
mouse_poll();
}

View File

@ -1,26 +0,0 @@
#ifndef C64_MOUSE_H
#define C64_MOUSE_H
#include "types.h"
extern sbyte mouse_dx, mouse_dy;
extern bool mouse_lb, mouse_rb;
void mouse_init(void);
// arm the potentiometer input for the selected mouse input
// needs ~4ms to stabilize
void mouse_arm(char n);
// poll mouse input for selected mouse, but the relative
// movement into mouse_dx/dy and the button state into
// mouse_lb/mouse_rb
void mouse_poll(void);
#pragma compile("mouse.c")
#endif

View File

@ -5,230 +5,36 @@
#include <c64/asm6502.h>
#include <stdlib.h>
volatile byte rirq_count;
static byte rirq_pcount;
volatile char npos = 1, tpos = 0;
byte rasterIRQRows[NUM_IRQS + 1];
byte rasterIRQIndex[NUM_IRQS + 1]; // Sort order of interrupt index, offset by one
#ifdef ZPAGE_IRQS
__zeropage
#endif
byte rasterIRQNext[NUM_IRQS + 1]; // Rasterline of interrupt, terminated by 0xff
byte rasterIRQLow[NUM_IRQS]; // Address of interrupt code
byte rasterIRQRows[NUM_IRQS];
byte rasterIRQIndex[NUM_IRQS];
byte rasterIRQNext[NUM_IRQS];
byte rasterIRQLow[NUM_IRQS];
byte rasterIRQHigh[NUM_IRQS];
#ifdef ZPAGE_IRQS
__zeropage
#endif
byte nextIRQ;
// nextIRQ is the index of the next expected IRQ, or $ff if no IRQ is scheduled
__asm rirq_isr_ram_io
{
stx plrx + 1
ldx nextIRQ
bmi exi
sta plra + 1
sty plry + 1
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
ji:
jsr $0000
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
beq e2
dey
sty $d012
dey
cpy $d012
bcc l1
plry:
ldy #0
plra:
lda #0
plrx:
ldx #0
rti
exi:
asl $d019
jmp plrx
// No more interrupts to service
e2:
inc rirq_count
ldy rasterIRQNext
dey
sty $d012
ldx #0
stx nextIRQ
beq plry
}
__asm rirq_isr_io
__asm irq0
{
pha
txa
pha
tya
pha
kentry:
ldx nextIRQ
bmi exi
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
cmp #$ff
beq e1
ji:
jsr $0000
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
beq e2
dey
sty $d012
dey
cpy $d012
bcc l1
exd:
pla
tay
pla
ldy rasterIRQIndex, x
tax
pla
rti
exi:
asl $d019
jmp exd
e2:
inc rirq_count
ldy rasterIRQNext
dey
sty $d012
ldx #0
stx nextIRQ
beq exd
}
__asm rirq_isr_noio
{
pha
txa
pha
tya
pha
kentry:
lda $01
pha
lda #$35
sta $01
ldx nextIRQ
bmi exi
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
ji:
jsr $0000
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
beq e2
dey
sty $d012
dey
cpy $d012
bcc l1
exd:
pla
sta $01
pla
tay
pla
tax
pla
rti
exi:
asl $d019
jmp exd
e2:
inc rirq_count
ldy rasterIRQNext
dey
sty $d012
ldx #0
stx nextIRQ
beq exd
}
__asm rirq_isr_kernal_io
{
lda $d019
bpl ex2
ldx nextIRQ
bmi exi
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
lda rasterIRQLow, y
sta ji + 1
lda rasterIRQHigh, y
sta ji + 2
ji:
jsr $0000
@ -237,63 +43,71 @@ jx:
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
lda rasterIRQNext, x
cmp #$ff
beq e2
dey
dey
sty $d012
dey
cpy $d012
tay
sec
sbc #4
cmp $d012
bcc l1
exd:
jmp $ea81
exi:
asl $d019
jmp $ea81
e2:
inc rirq_count
ldy rasterIRQNext
dey
dey
sty $d012
w1:
jmp ex
e2:
ldx npos
stx tpos
bit $d011
bmi e1
sta $d012
asl $d019
jmp ex
e1:
ldx #0
stx nextIRQ
jmp $ea81
lda rasterIRQNext, x
sec
sbc #1
sta $d012
ex:
asl $d019
pla
tay
pla
tax
pla
rti
ex2:
LDA $DC0D
cli
jmp $ea31
}
__asm rirq_isr_kernal_noio
__asm irq1
{
lda $01
pha
lda #$36
sta $01
lda $d019
bpl ex2
ldx nextIRQ
bmi exi
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
cmp #$ff
beq e1
ldy rasterIRQIndex, x
tax
lda rasterIRQLow, y
sta ji + 1
lda rasterIRQHigh, y
sta ji + 2
ji:
jsr $0000
@ -302,46 +116,48 @@ jx:
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
lda rasterIRQNext, x
cmp #$ff
beq e2
dey
tay
sec
sbc #4
cmp $d012
bcc l1
dey
sty $d012
dey
cpy $d012
bcc l1
exd:
pla
sta $01
jmp $ea81
exi:
asl $d019
jmp exd
w1:
jmp ex
e2:
inc rirq_count
ldx npos
stx tpos
ldy rasterIRQNext
dey
dey
sty $d012
bit $d011
bmi e1
sta $d012
jmp ex
e1:
ldx #0
stx nextIRQ
beq exd
lda rasterIRQNext, x
sec
sbc #1
sta $d012
ex:
asl $d019
jmp $ea81
ex2:
LDA $DC0D
cli
pla
sta $01
jmp $ea31
}
@ -360,27 +176,21 @@ ex2:
void rirq_build(RIRQCode * ic, byte size)
{
__assume(size < 26);
ic->size = size;
asm_im(ic->code + 0, ASM_LDY, 0);
asm_im(ic->code + 2, ASM_LDX, 0);
asm_ab(ic->code + 4, ASM_CMP, 0xd012);
asm_im(ic->code + 2, ASM_LDA, 0);
asm_ab(ic->code + 4, ASM_CPX, 0xd012);
asm_rl(ic->code + 7, ASM_BCS, -5);
asm_ab(ic->code + 9, ASM_STY, 0x0000);
if (size == 0)
{
asm_np(ic->code + 0, ASM_RTS);
}
else if (size == 1)
if (size == 1)
{
asm_np(ic->code + 12, ASM_RTS);
}
else
{
asm_ab(ic->code + 12, ASM_STX, 0x0000);
asm_ab(ic->code + 12, ASM_STA, 0x0000);
byte p = 15;
for(byte i=2; i<size; i++)
@ -409,18 +219,14 @@ void rirq_set(byte n, byte row, RIRQCode * write)
rasterIRQRows[n] = row;
}
static const byte irqai[26] = {
static const byte irqai[16] = {
RIRQ_ADDR_0, RIRQ_ADDR_1, RIRQ_ADDR_2, RIRQ_ADDR_3, RIRQ_ADDR_4, RIRQ_ADDR_5, RIRQ_ADDR_6, RIRQ_ADDR_7,
RIRQ_ADDR_8, RIRQ_ADDR_9, RIRQ_ADDR_10, RIRQ_ADDR_11, RIRQ_ADDR_12, RIRQ_ADDR_13, RIRQ_ADDR_14, RIRQ_ADDR_15,
RIRQ_ADDR_16, RIRQ_ADDR_17, RIRQ_ADDR_18, RIRQ_ADDR_19, RIRQ_ADDR_20, RIRQ_ADDR_21, RIRQ_ADDR_22, RIRQ_ADDR_23,
RIRQ_ADDR_24, RIRQ_ADDR_25
RIRQ_ADDR_8, RIRQ_ADDR_9, RIRQ_ADDR_10, RIRQ_ADDR_11, RIRQ_ADDR_12, RIRQ_ADDR_13, RIRQ_ADDR_14, RIRQ_ADDR_15
};
static const byte irqdi[26] = {
static const byte irqdi[16] = {
RIRQ_DATA_0, RIRQ_DATA_1, RIRQ_DATA_2, RIRQ_DATA_3, RIRQ_DATA_4, RIRQ_DATA_5, RIRQ_DATA_6, RIRQ_DATA_7,
RIRQ_DATA_8, RIRQ_DATA_9, RIRQ_DATA_10, RIRQ_DATA_11, RIRQ_DATA_12, RIRQ_DATA_13, RIRQ_DATA_14, RIRQ_DATA_15,
RIRQ_DATA_16, RIRQ_DATA_17, RIRQ_DATA_18, RIRQ_DATA_19, RIRQ_DATA_20, RIRQ_DATA_21, RIRQ_DATA_22, RIRQ_DATA_23,
RIRQ_DATA_24, RIRQ_DATA_25
RIRQ_DATA_8, RIRQ_DATA_9, RIRQ_DATA_10, RIRQ_DATA_11, RIRQ_DATA_12, RIRQ_DATA_13, RIRQ_DATA_14, RIRQ_DATA_15
};
void rirq_addr(RIRQCode * ic, byte n, void * addr)
@ -430,17 +236,10 @@ void rirq_addr(RIRQCode * ic, byte n, void * addr)
ic->code[p + 1] = (unsigned)addr >> 8;
}
void rirq_addrhi(RIRQCode * ic, byte n, byte hi)
{
byte p = irqai[n];
ic->code[p + 1] = hi;
}
void rirq_data(RIRQCode * ic, byte n, byte data)
{
byte p = irqdi[n];
// ic->code[p] = data;
(volatile char *)(ic->code)[p] = data;
ic->code[p] = data;
}
void rirq_write(RIRQCode * ic, byte n, void * addr, byte data)
@ -479,165 +278,45 @@ void rirq_clear(byte n)
rasterIRQRows[n] = 255;
}
void rirq_init_tables(void)
void rirq_init(bool kernalIRQ)
{
for(byte i=0; i<NUM_IRQS; i++)
{
rasterIRQRows[i] = 255;
rasterIRQIndex[i + 1] = i;
rasterIRQIndex[i] = i;
}
rasterIRQIndex[0] = NUM_IRQS;
rasterIRQRows[NUM_IRQS] = 0;
rasterIRQNext[NUM_IRQS] = 255;
}
void rirq_init_kernal(void)
{
rirq_init_tables();
__asm
{
sei
#if 0
// disable CIA interrupts
lda #$7f
sta $dc0d
sta $dd0d
#endif
}
*(void **)0x0314 = rirq_isr_kernal_io;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_kernal_noio(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0x0314 = rirq_isr_kernal_noio;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_crt(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0x0314 = rirq_isr_io.kentry;
*(void **)0xfffe = rirq_isr_io;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_crt_noio(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0x0314 = rirq_isr_noio.kentry;
*(void **)0xfffe = rirq_isr_noio;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_io(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0xfffe = rirq_isr_ram_io;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_memmap(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0xfffe = rirq_isr_noio;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init(bool kernalIRQ)
{
if (kernalIRQ)
rirq_init_kernal();
*(void **)0x0314 = irq1;
else
rirq_init_io();
*(void **)0xfffe = irq0;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_wait(void)
{
char i0 = rirq_pcount;
char i1;
do {
i1 = rirq_count;
} while (i0 == i1);
rirq_pcount = i1;
while (tpos != npos) ;
npos++;
}
void rirq_sort(bool inirq)
void rirq_sort(void)
{
// disable raster interrupts while sorting
nextIRQ = 0xff;
#if 1
byte maxr = rasterIRQRows[rasterIRQIndex[1]];
for(byte i = 2; i<NUM_IRQS + 1; i++)
{
byte ri = rasterIRQIndex[i];
byte rr = rasterIRQRows[ri];
if (rr < maxr)
{
rasterIRQIndex[i] = rasterIRQIndex[i - 1];
byte j = i, rj;
while (rr < rasterIRQRows[(rj = rasterIRQIndex[j - 2])])
{
rasterIRQIndex[j - 1] = rj;
j--;
}
rasterIRQIndex[j - 1] = ri;
}
else
maxr = rr;
}
#else
for(byte i = 1; i<NUM_IRQS; i++)
{
byte ri = rasterIRQIndex[i];
@ -650,32 +329,12 @@ void rirq_sort(bool inirq)
}
rasterIRQIndex[j] = ri;
}
#endif
#if NUM_IRQS & 3
for(sbyte i=NUM_IRQS-1; i>=0; i--)
rasterIRQNext[i] = rasterIRQRows[rasterIRQIndex[i + 1]];
#else
for(sbyte i=NUM_IRQS/4-1; i>=0; i--)
{
#pragma unroll(full)
for(int j=0; j<4; j++)
rasterIRQNext[i + j * NUM_IRQS / 4] = rasterIRQRows[rasterIRQIndex[i + j * NUM_IRQS / 4 + 1]];
}
#endif
for(byte i=0; i<NUM_IRQS; i++)
rasterIRQNext[i] = rasterIRQRows[rasterIRQIndex[i]];
rirq_pcount = rirq_count;
if (inirq)
nextIRQ = NUM_IRQS - 1;
else
{
byte yp = rasterIRQNext[0];
if (yp != 0xff)
{
vic.raster = yp - 1;
nextIRQ = 0;
}
}
npos++;
vic.raster = rasterIRQNext[nextIRQ] - 1;
}
void rirq_start(void)
@ -689,7 +348,6 @@ void rirq_start(void)
lda #100
sta $d012
asl $d019
cli
}
}

View File

@ -3,11 +3,8 @@
#include "types.h"
#ifndef NUM_IRQS
#define NUM_IRQS 16
#endif
extern volatile byte rirq_count;
enum RIRQCodeIndex
{
@ -59,39 +56,7 @@ enum RIRQCodeIndex
RIRQ_ADDR_14 = 78,
RIRQ_DATA_15 = 81,
RIRQ_ADDR_15 = 83,
RIRQ_DATA_16 = 86,
RIRQ_ADDR_16 = 88,
RIRQ_DATA_17 = 91,
RIRQ_ADDR_17 = 93,
RIRQ_DATA_18 = 96,
RIRQ_ADDR_18 = 98,
RIRQ_DATA_19 = 101,
RIRQ_ADDR_19 = 103,
RIRQ_SIZE_20 = 106,
RIRQ_DATA_20 = 106,
RIRQ_ADDR_20 = 108,
RIRQ_DATA_21 = 111,
RIRQ_ADDR_21 = 113,
RIRQ_DATA_22 = 116,
RIRQ_ADDR_22 = 118,
RIRQ_DATA_23 = 121,
RIRQ_ADDR_23 = 123,
RIRQ_DATA_24 = 126,
RIRQ_ADDR_24 = 128,
RIRQ_DATA_25 = 131,
RIRQ_ADDR_25 = 133
RIRQ_ADDR_15 = 88,
};
// One raster interrupt operation, handles up to five writes
@ -102,12 +67,6 @@ typedef struct RIRQCode
byte code[RIRQ_SIZE];
} RIRQCode;
typedef struct RQIRCode20
{
RIRQCode c;
byte code[RIRQ_SIZE_20 - RIRQ_SIZE];
} RIRQCode20;
// Build one raster IRQ operation of the given size (wait + #ops) for up to 5 instructions
void rirq_build(RIRQCode * ic, byte size);
@ -123,21 +82,17 @@ inline void rirq_call(RIRQCode * ic, byte n, void * addr);
// Change the address of a raster IRQ write command
inline void rirq_addr(RIRQCode * ic, byte n, void * addr);
// Change the high byte of the address of a raster IRQ write command
inline void rirq_addrhi(RIRQCode * ic, byte n, byte hi);
// Change the data of a raster IRQ write command
inline void rirq_data(RIRQCode * ic, byte n, byte data);
// Add a delay of 5 * cycles to a raster IRQ
inline void rirq_delay(RIRQCode * ic, byte cycles);
// Place a raster IRQ into one of the 16 slots, the interrupt will fire
// one line below the given row
// Place a raster IRQ into one of the 16 slots
inline void rirq_set(byte n, byte row, RIRQCode * write);
// Remove a raster IRQ from one of the 16 slots
inline void rirq_clear(byte n);
inline void rirq_clear(byte n)
// Change the vertical position of the raster IRQ of one of the slots
inline void rirq_move(byte n, byte row);
@ -146,31 +101,7 @@ inline void rirq_move(byte n, byte row);
// Initialize the raster IRQ system with either the kernal IRQ vector
// or the hardware IRQ vector if the kernal ROM is turned off (which is
// the less resource hungry option)
inline void rirq_init(bool kernalIRQ);
// Raster IRQ through kernal, with IO range always enabled
// calls kernal continuation
void rirq_init_kernal(void);
// Raster IRQ through kernal, with IO range not always enabled
// calls kernal continuation
void rirq_init_kernal_noio(void);
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range always enabled
// does not call kernal continuation
void rirq_init_crt(void);
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range not always enabled
// does not call kernal continuation
void rirq_init_crt_noio(void);
// Raster IRQ through RAM vector, with ROM disabled and IO range always enabled
// does not call kernal continuation
void rirq_init_io(void);
// Raster IRQ through RAM vector, with ROM disabled and IO range not always enabled
// does not call kernal continuation
void rirq_init_memmap(void);
void rirq_init(bool kernalIRQ);
// Start raster IRQ
void rirq_start(void);
@ -179,9 +110,8 @@ void rirq_start(void);
void rirq_stop(void);
// Sort the raster IRQ, must be performed at the end of the frame after changing
// the vertical position of one of the interrupt operations.
// Set the inirq flag to true when calling this from an interrupt
void rirq_sort(bool inirq = false);
// the vertical position of one of the interrupt operatins.
void rirq_sort(void);
// Wait for the last raster IRQ op to have completed. Must be called before a
// sort if the raster IRQ system is active

View File

@ -1,97 +0,0 @@
#include "reu.h"
int reu_count_pages(void)
{
volatile char c, d;
c = 0;
reu_store(0, &c, 1);
reu_load(0, &d, 1);
if (d == 0)
{
c = 0x47;
reu_store(0, &c, 1);
reu_load(0, &d, 1);
if (d == 0x47)
{
for(int i=1; i<256; i++)
{
long l = (long)i << 16;
c = 0x47;
reu_store(l, &c, 1);
c = 0x00;
reu_store(0, &c, 1);
reu_load(l, &d, 1);
if (d != 0x47)
return i;
}
return 256;
}
}
return 0;
}
inline void reu_store(unsigned long raddr, const volatile char * sp, unsigned length)
{
reu.laddr = (word)sp;
reu.raddr = raddr;
reu.rbank = raddr >> 16;
reu.length = length;
reu.ctrl = REU_CTRL_INCL | REU_CTRL_INCR;
reu.cmd = REU_CMD_EXEC | REU_CMD_FF00 | REU_CMD_STORE;
}
inline void reu_load(unsigned long raddr, volatile char * dp, unsigned length)
{
reu.laddr = (word)dp;
reu.raddr = raddr;
reu.rbank = raddr >> 16;
reu.length = length;
reu.ctrl = REU_CTRL_INCL | REU_CTRL_INCR;
reu.cmd = REU_CMD_EXEC | REU_CMD_FF00 | REU_CMD_LOAD;
}
inline void reu_fill(unsigned long raddr, char c, unsigned length)
{
reu.laddr = (word)&c;
reu.raddr = raddr;
reu.rbank = raddr >> 16;
reu.length = length;
reu.ctrl = REU_CTRL_FIXL | REU_CTRL_INCR;
reu.cmd = REU_CMD_EXEC | REU_CMD_FF00 | REU_CMD_STORE;
}
inline void reu_load2d(unsigned long raddr, volatile char * dp, char height, unsigned width, unsigned stride)
{
reu.ctrl = REU_CTRL_INCL | REU_CTRL_INCR;
reu.laddr = (word)dp;
for(char i=0; i<height; i++)
{
reu.length = width;
reu.raddr = raddr;
reu.rbank = raddr >> 16;
reu.cmd = REU_CMD_EXEC | REU_CMD_FF00 | REU_CMD_LOAD;
raddr += stride;
}
}
inline void reu_load2dpage(unsigned long raddr, volatile char * dp, char height, unsigned width, unsigned stride)
{
reu.ctrl = REU_CTRL_INCL | REU_CTRL_INCR;
reu.laddr = (word)dp;
reu.rbank = raddr >> 16;
for(char i=0; i<height; i++)
{
reu.length = width;
reu.raddr = raddr;
reu.cmd = REU_CMD_EXEC | REU_CMD_FF00 | REU_CMD_LOAD;
raddr += stride;
}
}

View File

@ -1,68 +0,0 @@
#ifndef C64_REU_H
#define C64_REU_H
#include "types.h"
#define REU_STAT_IRQ 0x80
#define REU_STAT_EOB 0x40
#define REU_STAT_FAULT 0x20
#define REU_STAT_SIZE 0x10
#define REU_STAT_VERSION 0x0f
#define REU_CTRL_FIXL 0x80
#define REU_CTRL_FIXR 0x40
#define REU_CTRL_INCL 0x00
#define REU_CTRL_INCR 0x00
#define REU_IRQ_ENABLE 0x80
#define REU_IRQ_EOB 0x40
#define REU_IRQ_FAULT 0x20
#define REU_CMD_EXEC 0x80
#define REU_CMD_AUTO 0x20
#define REU_CMD_FF00 0x10
#define REU_CMD_STORE 0x00
#define REU_CMD_LOAD 0x01
#define REU_CMD_SWAP 0x02
#define REU_CMD_VERIFY 0x03
struct REU
{
volatile byte status;
volatile byte cmd;
volatile word laddr;
volatile word raddr;
volatile byte rbank;
volatile word length;
volatile byte irqmask;
volatile byte ctrl;
};
#define reu (*((struct REU *)0xdf00))
// Count the number of 64k pages in the REU, the test is destructive
int reu_count_pages(void);
// Copy an array of data from C64 memory to the REU memory
inline void reu_store(unsigned long raddr, const volatile char * sp, unsigned length);
// Copy an array of data from REU memory to the C64 memory
inline void reu_load(unsigned long raddr, volatile char * dp, unsigned length);
// Fill an array of data in the REU with a single value
inline void reu_fill(unsigned long raddr, char c, unsigned length);
// Copy a 2D array from REU memory to the C64 memory. The stride parameter
// is the distance of two rows in REU memory
inline void reu_load2d(unsigned long raddr, volatile char * dp, char height, unsigned width, unsigned stride);
inline void reu_load2dpage(unsigned long raddr, volatile char * dp, char height, unsigned width, unsigned stride);
#pragma compile("reu.c")
#endif

View File

@ -1,11 +1,8 @@
#include "sprites.h"
#include "rasterirq.h"
static volatile char * vspriteScreen;
static char * vspriteScreen;
#ifdef VSPRITE_BSS
#pragma bss(VSPRITE_BSS)
#endif
void spr_init(char * screen)
{
@ -72,31 +69,6 @@ void spr_move(char sp, int xpos, int ypos)
vic.spr_msbx &= ~(1 << sp);
}
void spr_move16(char sp, int xpos, int ypos)
{
__assume (sp < 8);
if (ypos < 0 || ypos >= 256 || xpos < 0 || xpos >= 384)
xpos = 384;
vic.spr_pos[sp].y = ypos;
vic.spr_pos[sp].x = xpos & 0xff;
if (xpos & 0x100)
vic.spr_msbx |= 1 << sp;
else
vic.spr_msbx &= ~(1 << sp);
}
int spr_posx(char sp)
{
return vic.spr_pos[sp].x | ((vic.spr_msbx & (1 << sp)) ? 256 : 0);
}
int spr_posy(char sp)
{
return vic.spr_pos[sp].y;
}
void spr_image(char sp, char image)
{
__assume (sp < 8);
@ -111,29 +83,15 @@ void spr_color(char sp, char color)
vic.spr_color[sp] = color;
}
void spr_expand(char sp, bool xexpand, bool yexpand)
{
__assume (sp < 8);
char m = 1 << sp;
#define NUM_SPRITES 16
if (xexpand)
vic.spr_expand_x |= m;
else
vic.spr_expand_x &= ~m;
static char vspriteYLow[NUM_SPRITES], vspriteXLow[NUM_SPRITES], vspriteXHigh[NUM_SPRITES];
static char vspriteImage[NUM_SPRITES], vspriteColor[NUM_SPRITES];
if (yexpand)
vic.spr_expand_y |= m;
else
vic.spr_expand_y &= ~m;
}
static char spriteOrder[16], spriteYPos[17];
static char vspriteYLow[VSPRITES_MAX], vspriteXLow[VSPRITES_MAX], vspriteXHigh[VSPRITES_MAX];
static char vspriteImage[VSPRITES_MAX], vspriteColor[VSPRITES_MAX];
static char spriteOrder[VSPRITES_MAX], spriteYPos[VSPRITES_MAX + 1];
static RIRQCode spirq[VSPRITES_MAX - 8], synch;
static RIRQCode spirq[8], synch;
void vspr_init(char * screen)
@ -144,48 +102,27 @@ void vspr_init(char * screen)
vic.spr_expand_y = 0;
vic.spr_enable = 0xff;
for(int i=0; i<VSPRITES_MAX - 8; i++)
for(int i=0; i<8; i++)
{
#ifdef VSPRITE_REVERSE
int j = (i & 7) ^ 7;
#else
int j = i & 7;
#endif
rirq_build(spirq + i, 5);
rirq_write(spirq + i, 0, &vic.spr_color[j], 0);
rirq_write(spirq + i, 1, &vic.spr_pos[j].x, 0);
rirq_write(spirq + i, 2, &vic.spr_pos[j].y, 0);
rirq_write(spirq + i, 3, &vspriteScreen[j], 0);
rirq_write(spirq + i, 0, &vic.spr_color[i], 0);
rirq_write(spirq + i, 1, &vic.spr_pos[i].x, 0);
rirq_write(spirq + i, 2, &vic.spr_pos[i].y, 0);
rirq_write(spirq + i, 3, &vspriteScreen[i], 0);
rirq_write(spirq + i, 4, &vic.spr_msbx, 0);
rirq_set(i, 80 + 4 * i, spirq + i);
rirq_set(i, 80 + 8 * i, spirq + i);
}
rirq_build(&synch, 0);
rirq_set(VSPRITES_MAX - 8, 250, &synch);
rirq_set(8, 250, &synch);
for(int i=0; i<VSPRITES_MAX; i++)
for(int i=0; i<16; i++)
{
spriteOrder[i] = i;
vspriteYLow[i] = 0xff;
}
}
void vspr_shutdown(void)
{
for(int i=0; i<VSPRITES_MAX - 7; i++)
rirq_clear(i);
}
void vspr_screen(char * screen)
{
vspriteScreen = screen + 0x3f8;
char hi = (unsigned)vspriteScreen >> 8;
#pragma unroll(8)
for(int i=0; i<VSPRITES_MAX - 8; i++)
rirq_addrhi(spirq + i, 3, hi);
}
#pragma native(vspr_init)
void vspr_set(char sp, int xpos, int ypos, char image, char color)
@ -214,21 +151,6 @@ void vspr_move(char sp, int xpos, int ypos)
vspriteXHigh[sp] = (char)(xpos >> 8);
}
void vspr_movex(char sp, int xpos)
{
vspriteXLow[sp] = (char)xpos;
vspriteXHigh[sp] = (char)(xpos >> 8);
}
void vspr_movey(char sp, int ypos)
{
char yp = (char)ypos;
if (ypos & 0xff00)
yp = 0xff;
vspriteYLow[sp] = yp;
}
void vspr_image(char sp, char image)
{
vspriteImage[sp] = image;
@ -246,31 +168,23 @@ void vspr_hide(char sp)
void vspr_sort(void)
{
byte rm = vspriteYLow[spriteOrder[0]];
spriteYPos[1] = rm;
spriteYPos[1] = vspriteYLow[spriteOrder[0]];
for(char i = 1; i<VSPRITES_MAX; i++)
for(char i = 1; i<16; i++)
{
byte ri = spriteOrder[i];
byte rr = vspriteYLow[ri];
if (rr < rm)
byte j = i, rj = spriteYPos[j];
while (rr < rj)
{
byte j = i, rj = rm;
do {
spriteYPos[j + 1] = rj;
spriteOrder[j] = spriteOrder[j - 1];
rj = spriteYPos[j - 1];
j--;
} while (rr < rj);
}
spriteOrder[j] = ri;
spriteYPos[j + 1] = rr;
}
else
{
spriteYPos[i + 1] = rr;
rm = rr;
}
}
}
#pragma native(vspr_sort)
@ -278,68 +192,48 @@ void vspr_sort(void)
void vspr_update(void)
{
char xymask = 0;
volatile char * vsprs = vspriteScreen;
// char sypos[VSPRITES_MAX];
#pragma unroll(full)
char * vsprs = vspriteScreen;
for(char ui=0; ui<8; ui++)
{
byte ri = spriteOrder[ui];
#ifdef VSPRITE_REVERSE
char uj = ui ^ 7;
#else
char uj = ui;
#endif
vic.spr_color[uj] = vspriteColor[ri];
vsprs[uj] = vspriteImage[ri];
#ifdef VSPRITE_REVERSE
xymask = (xymask << 1) | (vspriteXHigh[ri] & 1);
#else
vic.spr_color[ui] = vspriteColor[ri];
vsprs[ui] = vspriteImage[ri];
xymask = ((unsigned)xymask | (vspriteXHigh[ri] << 8)) >> 1;
#endif
vic.spr_pos[uj].x = vspriteXLow[ri];
vic.spr_pos[uj].y = spriteYPos[ui + 1];
// sypos[ui] = vspriteYLow[ri];
vic.spr_pos[ui].x = vspriteXLow[ri];
vic.spr_pos[ui].y = vspriteYLow[ri];
}
vic.spr_msbx = xymask;
#pragma unroll(full)
bool done = false;
if (spriteYPos[8] < 230)
{
char m = 1;
for(char ti=0; ti<8; ti++)
{
for(char ti=0; ti<VSPRITES_MAX - 8; ti++)
{
if (!done && spriteYPos[ti + 9] < 250)
{
byte ri = spriteOrder[ti + 8];
rirq_move(ti, spriteYPos[ti + 1] + 23);
#ifdef VSPRITE_REVERSE
char m = 0x80 >> (ti & 7);
#else
char m = 1 << (ti & 7);
#endif
xymask |= m;
if (!(vspriteXHigh[ri] & 1))
if (!vspriteXHigh[ri])
xymask ^= m;
rirq_data(spirq + ti, 2, spriteYPos[ti + 9]);
rirq_data(spirq + ti, 0, vspriteColor[ri]);
rirq_data(spirq + ti, 1, vspriteXLow[ri]);
rirq_data(spirq + ti, 2, vspriteYLow[ri]);
rirq_data(spirq + ti, 3, vspriteImage[ri]);
rirq_data(spirq + ti, 4, xymask);
// spriteYPos[ti + 9] = vspriteYLow[ri];
rirq_move(ti, spriteYPos[ti + 1] + 21);
m <<= 1;
}
}
else
{
for(char ti=0; ti<8; ti++)
rirq_clear(ti);
done = true;
}
}
}

View File

@ -15,22 +15,10 @@ void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, boo
inline void spr_show(char sp, bool show);
// move a sprite to the given position, only uses 8 bit y and 9 bit x
// move a sprite the
inline void spr_move(char sp, int xpos, int ypos);
// get current x position of sprite
inline int spr_posx(char sp);
// get current y position of sprite
inline int spr_posy(char sp);
// move a sprite to the given position, only uses 16 bit y and 16 bit x,
// moves the sprite to a zero y position if offscreen
void spr_move16(char sp, int xpos, int ypos);
// change the image of a sprite
inline void spr_image(char sp, char image);
@ -39,10 +27,6 @@ inline void spr_image(char sp, char image);
inline void spr_color(char sp, char color);
// change the image of a sprite
inline void spr_expand(char sp, bool xexpand, bool yexpand);
// The virtual sprite system works with the rasterirq library to multiplex
// 16 virtual sprites onto the actual eight hardware sprites. It uses the slots
// 0 to 8 of the rasterirq library to switch the sprites mid screen. The
@ -60,18 +44,10 @@ inline void spr_expand(char sp, bool xexpand, bool yexpand);
// rirq_sort();
//
#ifndef VSPRITES_MAX
#define VSPRITES_MAX 16
#endif
// initialize the virtual (multiplexed) sprite system, offering 16 sprites
void vspr_init(char * screen);
void vspr_shutdown(void);
void vspr_screen(char * screen);
// set one sprite with the given attribute
void vspr_set(char sp, int xpos, int ypos, char image, char color);
@ -80,11 +56,6 @@ void vspr_set(char sp, int xpos, int ypos, char image, char color);
inline void vspr_move(char sp, int xpos, int ypos);
inline void vspr_movex(char sp, int xpos);
inline void vspr_movey(char sp, int ypos);
// change the image of a virtual sprite
inline void vspr_image(char sp, char image);

View File

@ -16,12 +16,7 @@ void vic_sprxy(byte s, int x, int y)
vic.spr_msbx &= ~(1 << s);
}
int vic_sprgetx(byte s)
{
return vic.spr_pos[s].x | ((vic.spr_msbx & (1 << s)) ? 256 : 0);
}
void vic_setmode(VicMode mode, const char * text, const char * font)
void vic_setmode(VicMode mode, char * text, char * font)
{
switch (mode)
{
@ -45,8 +40,6 @@ void vic_setmode(VicMode mode, const char * text, const char * font)
vic.ctrl1 = VIC_CTRL1_BMM | VIC_CTRL1_DEN | VIC_CTRL1_RSEL | 3;
vic.ctrl2 = VIC_CTRL2_CSEL | VIC_CTRL2_MCM;
break;
default:
__assume(false);
}
cia2.pra = (cia2.pra & 0xfc) | (((unsigned)text >> 14) ^ 0x03);
@ -73,15 +66,6 @@ void vic_waitFrame(void)
;
}
void vic_waitFrames(char n)
{
while (n > 0)
{
vic_waitFrame();
n--;
}
}
void vic_waitLine(int line)
{
char upper = (char)(line >> 1) & VIC_CTRL1_RST8;
@ -94,41 +78,4 @@ void vic_waitLine(int line)
} while ((vic.ctrl1 & VIC_CTRL1_RST8) != upper);
}
void vic_waitBelow(int line)
{
char upper = (char)(line >> 1) & VIC_CTRL1_RST8;
char lower = (char)line;
if (upper)
{
do
{
while (vic.raster <= lower)
;
} while (!(vic.ctrl1 & VIC_CTRL1_RST8));
}
else
{
while (vic.raster <= lower)
;
}
}
void vic_waitRange(char below, char above)
{
while (vic.ctrl1 & VIC_CTRL1_RST8)
;
if (vic.raster >= above)
{
while (!(vic.ctrl1 & VIC_CTRL1_RST8))
;
while (vic.ctrl1 & VIC_CTRL1_RST8)
;
}
while (vic.raster < below)
;
}
#pragma native(vic_waitLine)

View File

@ -91,15 +91,12 @@ enum VicMode
// set the display mode and base address. This will also
// adapt the bank.
void vic_setmode(VicMode mode, const char * text, const char * font);
void vic_setmode(VicMode mode, char * text, char * font);
// put a sprite at the given x/y location, taking care of the
// x MSB
inline void vic_sprxy(byte s, int x, int y);
// Read the sprite x position from the LSB and MSB register
inline int vic_sprgetx(byte s);
// wait for the beam to reach the bottom of the visual area
inline void vic_waitBottom(void);
@ -109,18 +106,9 @@ inline void vic_waitTop(void);
// wait for the top of the frame and then for the bottom of the visual area
inline void vic_waitFrame(void);
// wait for n frames
void vic_waitFrames(char n);
// wait for a specific raster line
void vic_waitLine(int line);
// wait for beam to be below a line
void vic_waitBelow(int line);
// wait for beam to be in a given range on screen
void vic_waitRange(char below, char above);
// reference to the VIC chip
#define vic (*((struct VIC *)0xd000))

View File

@ -2,425 +2,176 @@
static IOCharMap giocharmap = IOCHM_ASCII;
#if defined(__C128__)
#pragma code(lowcode)
__asm bsout
{
ldx #0
stx 0xff00
jsr 0xffd2
sta 0xff01
}
__asm bsin
{
lda #0
sta 0xff00
jsr 0xffe4
sta 0xff01
}
__asm bsget
{
lda #0
sta 0xff00
jsr 0xffcf
sta 0xff01
}
__asm bsplot
{
lda #0
sta 0xff00
jsr 0xfff0
sta 0xff01
}
__asm bsinit
{
lda #0
sta 0xff00
jsr 0xff81
sta 0xff01
}
__asm dswap
{
sta 0xff00
jsr 0xff5f
sta 0xff01
}
#pragma code(code)
#elif defined(__C128B__) || defined(__C128E__)
#define dswap 0xff5f
#define bsout 0xffd2
#define bsin 0xffe4
#define bsget 0xffcf
#define bsplot 0xfff0
#define bsinit 0xff81
#elif defined(__PLUS4__)
#pragma code(lowcode)
__asm bsout
{
sta 0xff3e
jsr 0xffd2
sta 0xff3f
}
__asm bsin
{
sta 0xff3e
jsr 0xffe4
sta 0xff3f
}
__asm bsget
{
sta 0xff3e
jsr 0xffcf
sta 0xff3f
}
__asm bsplot
{
sta 0xff3e
jsr 0xfff0
sta 0xff3f
}
__asm bsinit
{
sta 0xff3e
jsr 0xff81
sta 0xff3f
}
#pragma code(code)
#elif defined(__ATARI__)
__asm bsout
{
tax
lda 0xe407
pha
lda 0xe406
pha
txa
}
__asm bsin
{
lda 0xe405
pha
lda 0xe404
pha
}
__asm bsget
{
lda 0xe405
pha
lda 0xe404
pha
}
__asm bsplot
{
}
__asm bsinit
{
}
#elif defined(__VIC20__)
#define bsout 0xffd2
#define bsin 0xffe4
#define bsplot 0xfff0
#define bsget 0xffcf
__asm bsinit
{
lda #147
jmp $ffd2
}
#elif defined(__CBMPET__)
#define bsout 0xffd2
#define bsin 0xffe4
__asm bsplot
{
/* no equivalent on PET */
}
__asm bsinit
{
/* no equivalent on PET */
}
#define bsget 0xffcf
#else
#define bsout 0xffd2
#define bsin 0xffe4
#define bsplot 0xfff0
#define bsinit 0xff81
#define bsget 0xffcf
#endif
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
void dispmode40col(void)
{
if (*(volatile char *)0xd7 >= 128)
{
__asm
{
jsr dswap
}
}
}
void dispmode80col(void)
{
if (*(volatile char *)0xd7 < 128)
{
__asm
{
jsr dswap
}
}
}
#endif
void iocharmap(IOCharMap chmap)
{
giocharmap = chmap;
#if !defined(__ATARI__)
if (chmap == IOCHM_PETSCII_1)
putrch(128 + 14);
putch(128 + 14);
else if (chmap == IOCHM_PETSCII_2)
putrch(14);
#endif
putch(14);
}
void putrch(char c)
__asm putpch
{
__asm {
lda c
jsr bsout
}
ldx giocharmap
cpx #IOCHM_ASCII
bcc w3
cmp #10
bne w1
lda #13
w1:
cpx #IOCHM_PETSCII_1
bcc w3
cmp #65
bcc w3
cmp #123
bcs w3
cmp #97
bcs w2
cmp #91
bcs w3
w2:
eor #$20
cpx #IOCHM_PETSCII_2
beq w3
and #$df
w3:
jmp 0xffd2
}
void putpch(char c)
__asm getpch
{
#if defined(__ATARI__)
if (c == 10)
c = 0x9b;
#else
if (giocharmap >= IOCHM_ASCII)
{
if (c == '\n')
c = 13;
else if (c == '\t')
{
char n = wherex() & 3;
do {
putrch(' ');
} while (++n < 4);
return;
}
else if (giocharmap >= IOCHM_PETSCII_1)
{
if (c >= 65 && c < 123)
{
if (c >= 97 || c < 91)
{
#if defined(__CBMPET__)
if (c >= 97)
c ^= 0xa0;
c ^= 0x20;
#else
c ^= 0x20;
#endif
jsr 0xffe4
if (giocharmap == IOCHM_PETSCII_1)
c &= 0xdf;
}
}
}
}
ldx giocharmap
cpx #IOCHM_ASCII
bcc w3
#endif
cmp #13
bne w1
lda #10
w1:
cpx #IOCHM_PETSCII_1
bcc w3
putrch(c);
}
static char convch(char ch)
{
#if !defined(__ATARI__)
if (giocharmap >= IOCHM_ASCII)
{
if (ch == 13)
ch = 10;
else if (giocharmap >= IOCHM_PETSCII_1)
{
if (ch >= 65 && ch < 219)
{
if (ch >= 193)
ch ^= 0xa0;
if (ch < 123 && (ch >= 97 || ch < 91))
ch ^= 0x20;
}
}
}
#endif
return ch;
}
char getrch(void)
{
return __asm {
jsr bsget
sta accu
};
}
char getpch(void)
{
return convch(getrch());
cmp #65
bcc w3
cmp #123
bcs w3
cmp #97
bcs w2
cmp #91
bcs w3
w2:
eor #$20
w3:
}
char kbhit(void)
int kbhit(void)
{
#if defined(__CBMPET__)
return __asm
{
lda $9e
sta accu
};
#else
return __asm
__asm
{
lda $c6
sta accu
};
#endif
lda #0
sta accu + 1
}
}
char getche(void)
int getche(void)
{
char ch;
do {
ch = __asm {
jsr bsin
sta accu
};
} while (!ch);
__asm
{
L1:
jsr getpch
cmp #0
beq L1
sta accu
jsr putpch
lda #0
sta accu + 1
}
}
int getch(void)
{
__asm
{
L1:
jsr getpch
cmp #0
beq L1
sta accu
lda #0
sta accu + 1
}
}
void putch(int c)
{
__asm {
lda ch
jsr bsout
lda c
jsr 0xffd2
}
return convch(ch);
}
char getch(void)
{
char ch;
do {
ch = __asm {
jsr bsin
sta accu
};
} while (!ch);
return convch(ch);
}
char getchx(void)
{
char ch = __asm {
jsr bsin
sta accu
};
return convch(ch);
}
void putch(char c)
{
putpch(c);
}
void clrscr(void)
{
putrch(147);
__asm
{
jsr $ff5b
}
}
void textcursor(bool show)
{
*(volatile char *)0xcc = show ? 0 : 1;
*(char *)0xcc = show ? 0 : 1;
}
void gotoxy(char cx, char cy)
void gotoxy(int cx, int cy)
{
#if defined(__CBMPET__)
#define CURS_X 0xc6
#define CURS_Y 0xd8
#define SCREEN_PTR 0xc4
#define SCR_LINELEN 0xd5
__assume(cy < 25);
*(volatile char *)CURS_X = cx;
*(volatile char *)CURS_Y = cy;
if (*(volatile char *)SCR_LINELEN > 40)
cy <<= 1;
const unsigned off = cy * 40;
* (volatile unsigned *)SCREEN_PTR = off + 0x8000;
#else
__asm
{
ldx cy
ldy cx
clc
jsr bsplot
jsr $fff0
}
#endif
}
void textcolor(char c)
void textcolor(int c)
{
*(volatile char *)0x0286 = c;
__asm
{
lda c
sta $0286
}
}
void bgcolor(char c)
int wherex(void)
{
*(volatile char *)0xd021 = c;
__asm
{
lda $d3
sta accu
lda #0
sta accu + 1
}
}
void bordercolor(char c)
int wherey(void)
{
*(volatile char *)0xd020 = c;
}
void revers(char r)
__asm
{
if (r)
putrch(18);
else
putrch(18 + 128);
lda $d6
sta accu
lda #0
sta accu + 1
}
char wherex(void)
{
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
return *(volatile char *)0xec;
#elif defined(__PLUS4__)
return *(volatile char *)0xca;
#else
return *(volatile char *)0xd3;
#endif
}
char wherey(void)
{
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
return *(volatile char *)0xeb;
#elif defined(__PLUS4__)
return *(volatile char *)0xcd;
#else
return *(volatile char *)0xd6;
#endif
}

View File

@ -18,95 +18,28 @@ extern IOCharMap giocharmap;
void iocharmap(IOCharMap chmap);
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
void dispmode40col(void);
void dispmode80col(void);
#endif
#define PETSCII_CURSOR_LEFT 0x9d
#define PETSCII_CURSOR_RIGHT 0x1d
#define PETSCII_CURSOR_UP 0x91
#define PETSCII_CURSOR_DOWN 0x11
#define PETSCII_HOME 0x13
#define PETSCII_CLEAR 0x94
#define PETSCII_DEL 0x14
#define PETSCII_INSERT 0x94
#define PETSCII_STOP 0x03
#define PETSCII_RETURN 0x0d
int kbhit(void);
#define PETSCII_F1 0x85
#define PETSCII_F2 0x89
#define PETSCII_F3 0x86
#define PETSCII_F4 0x8a
#define PETSCII_F5 0x87
#define PETSCII_F6 0x8b
#define PETSCII_F7 0x88
#define PETSCII_F8 0x8c
int getche(void);
enum ConioColors
{
COLOR_BLACK,
COLOR_WHITE,
COLOR_RED,
COLOR_CYAN,
COLOR_PURPLE,
COLOR_GREEN,
COLOR_BLUE,
COLOR_YELLOW,
int getch(void);
COLOR_ORANGE,
COLOR_BROWN,
COLOR_LT_RED,
COLOR_DARK_GREY,
COLOR_MED_GREY,
COLOR_LT_GREEN,
COLOR_LT_BLUE,
COLOR_LT_GREY
};
// Lowlevel console in/out
// using petscii translation
void putpch(char c);
char getpch(void);
// using no translation
inline void putrch(char c);
inline char getrch(void);
// Standard console in/out
char kbhit(void);
char getche(void);
char getch(void);
// like getch but does not wait, returns zero if no
// key is pressed
char getchx(void);
void putch(char c);
void putch(int c);
void clrscr(void);
void gotoxy(char x, char y);
void gotoxy(int x, int y);
inline void textcolor(char c);
void textcolor(int c);
inline void bgcolor(char c);
int wherex(void);
inline void bordercolor(char c);
inline void revers(char r);
inline char wherex(void);
inline char wherey(void);
int wherey(void);
// show or hide the text cursor
inline void textcursor(bool show);
void textcursor(bool show);
#pragma compile("conio.c")

Some files were not shown because too many files have changed in this diff Show More