62 Commits

Author SHA1 Message Date
Godzil
330cba592d Cosmetic, and add missing files to the CMakeLists. 2022-06-27 22:33:36 +01:00
Godzil
e48f7a76a7 Merge the latest changes. 2022-06-27 22:14:47 +01:00
Godzil
4800cf0823 Commented some code to let it build. 2022-06-27 18:20:11 +01:00
Godzil
a37414b079 Cleanup memory and added file_access. 2022-06-27 18:19:51 +01:00
Godzil
e9d7f1aa04 Add base address for IO ports to easily allow multiple instance of the same device. 2022-06-27 17:57:03 +01:00
Godzil
37e4b219d4 Add a skeleton for the interrupt controller 2022-06-27 17:04:55 +01:00
Godzil
d6a2a77303 Add the possibility to pass parameter to device_init
and add a device_type_t used to know what parameter to pass to init
when needed.
2022-06-27 17:04:37 +01:00
Godzil
f45995167e Add some temporary disabled code for each peripheral
(copied from io.c)
2022-06-27 17:02:35 +01:00
Godzil
83e4b8d5d9 Some more cosmetics. 2022-06-27 17:01:07 +01:00
Godzil
4d345079ae Fix building
Most patches are temporary and there just to let the code to build. It will not work in the current state.
Also now force the use of paged memory. It was not working properly because of the way the old GPU code is working.
2022-06-27 16:59:11 +01:00
Godzil
5f61fb612a Merge branch 'master' into rewrite 2022-06-25 21:23:05 +01:00
Godzil
2305ce975b Mostly cosmetic changes
Update headers year
Remove useless /// headers that eat lines for no reasons
Fixed build issues because of stupid me doing stupid stuff in prototypes.
Added color and mono GPU stub.
Also a tad of code cleaning.
2022-03-14 14:50:41 +00:00
Manoël Trapier
01ffa3a834 Add apt update. part 2 2022-03-12 12:04:45 +00:00
Manoël Trapier
fce2815300 Add apt update. 2022-03-12 12:04:18 +00:00
Manoël Trapier
662a45d02f Create codeql-analysis.yml 2022-02-28 15:32:33 +00:00
Manoël Trapier
bb324dc12e Remplace travis build badge with github's one. 2022-02-28 12:33:51 +00:00
Godzil
017983f692 Trying to make the google action to work. 2022-02-28 12:31:43 +00:00
Godzil
b4b1bd83d0 Fix a typo 2022-02-25 18:19:00 +00:00
Manoël Trapier
a85e1ff083 Need to checkout with submodule silly! 2022-02-23 18:02:31 +00:00
Manoël Trapier
4c9ba704ea Testing github action
Travis is no longer free. So need to test alternatives.
2022-02-23 17:59:53 +00:00
Godzil
6f56a8efda Starting a rewrite of how the IO works.
Currently 100% broken, also going to change how devices are selected
for each system so no more if/else everywhere and system should be more accurate.
2021-12-20 19:12:33 +00:00
Godzil
8fa2ef06ab Rename some functions and a tad of cleanup. 2021-12-20 19:12:33 +00:00
Godzil
4fc5193bc7 Add testserial part of the build. 2021-12-20 19:12:30 +00:00
Godzil
1df15b0192 Uniformise copyright headers. 2021-12-20 19:12:12 +00:00
Godzil
6f539fff1e Not sure how I missed the R_RM8 and R_RM16 decoder. 2021-04-16 00:39:26 +01:00
Godzil
c90b99d650 Fix table size. 2021-04-16 00:33:48 +01:00
Godzil
49a1943cda Add proper support for indirect call/jmp 2021-04-16 00:32:56 +01:00
Godzil
4082d37cb0 Add missing mov cs, rm and mov rm, cs opcode. 2021-04-16 00:32:08 +01:00
Godzil
146e2b2c1d Fix some headers (code is original here) and some cosmetics 2021-04-15 23:17:38 +01:00
Godzil
698d960bed Add some useful GPU debug logs 2021-04-15 23:17:01 +01:00
Godzil
62c5812b34 Add #ifdef around EEPROM debug prints 2021-04-15 23:08:03 +01:00
Godzil
7f7410c8f8 First step to get a debugger:
Decode instructions.


I now have an headache.
A couple of instruction are still not properly decoded.
I need to find proper documentation on them.
2021-04-15 23:07:13 +01:00
Godzil
0e02ee829f I'm constantly amazed by how poorly coded this emulator was.
SRAM and EEPROM were inverted and not all known value was in there.
Also fixed the rom metadata header that was missing one byte.
2021-04-09 23:55:58 +01:00
Godzil
4512def23a Change how SRAM/EEPROM mask are calculated 2021-04-09 23:19:23 +01:00
Godzil
46e90dcca1 Remove useless variable 2021-04-09 23:18:53 +01:00
Godzil
2e9685215b Starting work on making memory access more straigforward with less branching code. 2021-04-09 23:18:31 +01:00
Godzil
bddcaddf1f Fix a signed/unsigned warning 2021-04-09 23:11:25 +01:00
Godzil
5559269387 Use stdbool instead of non standard ifdefs 2021-04-09 23:11:10 +01:00
Godzil
b3c0a39d00 Init the memory after everything is loaded 2021-04-09 23:09:55 +01:00
Godzil
8ab6b20815 Fix a mistake in loading SRAM/EEP file name 2021-04-09 23:09:22 +01:00
Godzil
dd53d5bfd9 Update the stub boot rom to "enable" the 16bit cart access mode.
(the emulator do not care about that but it is just to be more accurate)
2021-04-09 23:08:29 +01:00
Godzil
5ba3560378 Let's use double instead of integer to the ticks. 2021-04-09 23:07:46 +01:00
Godzil
ac3779e640 Add a way to pretend displaying while actualy not displayint
to go around some weirdness with Valgrind that crashwhen using OpenGL.
2021-04-06 23:11:30 +01:00
Godzil
da26704390 Oops. Stupid memset..
(always blame the tools)
2021-04-06 23:10:30 +01:00
Godzil
2ced18d151 Change the log to my good old trusty log framework. 2021-04-06 23:08:22 +01:00
Godzil
359b05a518 Add a link to Mesen 2021-04-05 15:16:17 +01:00
Godzil
3771c65f2c Add a nifty travis badge to show how great the build it! 2021-04-05 15:01:48 +01:00
Godzil
4f4e4d148a Add a fancy README.
(ok not so fancy, but there are images!)
2021-04-05 14:59:38 +01:00
Godzil
cc1060775c Major code cleanup and code reformating 2021-04-05 14:19:35 +01:00
Godzil
4e5f796d6a Remove the "color schemes". 2021-04-05 13:40:29 +01:00
Godzil
3818e03e55 Now that we have system, let's also load the Swan Crystal irom. 2021-04-05 13:37:31 +01:00
Godzil
94dc2fc463 Missed some changes for the color/b&w logic changes 2021-04-05 13:36:02 +01:00
Godzil
d45d838378 Remove all the unused "statistics" code. 2021-04-05 13:33:13 +01:00
Godzil
18d9038639 Update .gitignore 2021-04-05 13:23:59 +01:00
Godzil
925bfd3b65 Change the way the system type is managed
and changed the logic on how the GPU use "color". 
Now IO register tell properly the selected system, and B&W swan does not allow to switch to color. Also the Swan do not start in color mode as it should.
2021-04-05 13:23:44 +01:00
Godzil
330262b55c Remove the "initial IO" table as most values are wrong anyway.
If there are some initial value that need to be set, it is per system, not globally like that.
2021-04-05 12:24:12 +01:00
Godzil
357d4e4ede Deleted the makefile as it is no longer supported 2021-04-05 00:20:22 +01:00
Godzil
d45822951f As this is C project, rename all source file to .c 2021-04-05 00:18:55 +01:00
Godzil
864fda651d Update travis file. 2021-04-04 23:35:13 +01:00
Godzil
065849cf68 Add stdint.h into headers that (may) need it. 2021-04-04 23:28:36 +01:00
Godzil
dbc7d6e940 Update splash string to show "NewOswan" 2021-04-04 23:19:04 +01:00
Godzil
432844304e Add a simple boot rom stub
so we can start the emulated console without need for special case in the code, and not adding any copyrighted material in the project.
Also automatically copy the stub rom in the build folder.
2021-04-04 23:18:51 +01:00
84 changed files with 13207 additions and 12247 deletions

38
.github/workflows/cmake.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: CMake
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
BUILD_TYPE: Release
jobs:
build:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.allow_failure }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-latest ]
allow_failure: [ false ]
# include:
# - os: macos-latest
# allow_failure: true
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Install needed dependencies
run: sudo apt update && sudo apt install xorg-dev libglu1-mesa-dev
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

62
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '43 19 * * 5'
env:
BUILD_TYPE: Debug
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: true
- name: Install needed dependencies
run: sudo apt update && sudo apt install xorg-dev libglu1-mesa-dev
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
- name: Running Cmake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Building
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@
*.orig *.orig
*.rej *.rej
rom/ rom/
ROMs/
.idea/ .idea/
*.zip *.zip
*.sav *.sav

View File

@@ -1,38 +1,63 @@
dist: bionic
language: c language: c
os:
- linux
# - osx
#matrix:
# allow_failures:
# - os: osx
addons: addons:
apt: apt:
packages: packages:
- libsdl1.2debian - xorg-dev
- libsdl1.2-dev - libglu1-mesa-dev
compiler:
- clang
- gcc
script: script:
- make
- mkdir build - mkdir build
- cd build - cd build
- cmake .. - cmake ..
- make - make
cache: jobs:
directories: include:
- '$HOME/.sonar/cache' - os: linux
dist: bionic
arch: amd64
compiler: gcc
#before_install: - os: linux
# - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi dist: bionic
# - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install glew; fi arch: amd64
compiler: clang
#install: true - os: linux
dist: focal
arch: amd64
compiler: gcc
#after_success: - os: linux
# - bash <(curl -s https://codecov.io/bash) dist: focal
arch: amd64
compiler: clang
- os: osx
compiler: clang
osx_image: xcode12.2
- os: linux
dist: focal
arch: arm64
compiler: gcc
- os: osx
compiler: clang
osx_image: xcode10.3
- os: osx
compiler: clang
osx_image: xcode11.6
- os: osx
compiler: clang
osx_image: xcode12
allow_failures:
- os: linux
arch: arm64
- os: osx

View File

@@ -29,15 +29,23 @@ set(CMAKE_CXX_FLAGS ${COMP_FLAGS})
message("-- Building version ${VERSION}") message("-- Building version ${VERSION}")
add_executable(wonderswan main.cpp) add_executable(wonderswan main.c)
set_property(TARGET wonderswan PROPERTY CXX_STANDARD 98) set_property(TARGET wonderswan PROPERTY CXX_STANDARD 98)
target_compile_definitions(wonderswan PUBLIC VERSION="${VERSION}") target_compile_definitions(wonderswan PUBLIC VERSION="${VERSION}")
target_include_directories(wonderswan PUBLIC source) target_include_directories(wonderswan PUBLIC source)
add_custom_command(
TARGET wonderswan POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/irom_stub/*.bin
${CMAKE_CURRENT_BINARY_DIR}/
)
add_subdirectory(source) add_subdirectory(source)
target_link_libraries(wonderswan wswan glfw ${OPENGL_glu_LIBRARY} ${OPENGL_gl_LIBRARY}) target_link_libraries(wonderswan wswan glfw ${OPENGL_glu_LIBRARY} ${OPENGL_gl_LIBRARY})
add_executable(dumpinfo dumpinfo.c) add_executable(dumpinfo dumpinfo.c)
add_executable(testserial testserial.c)

View File

@@ -1,57 +0,0 @@
wonderswan_CXX_SRCS = main.cpp \
source/audio.cpp \
source/gpu.cpp \
source/io.cpp \
source/log.cpp \
source/memory.cpp \
source/emulate.cpp \
source/rom.cpp \
source/ws.cpp \
source/nec/nec.cpp
OBJS = $(wonderswan_CXX_SRCS:.cpp=.o)
all: wonderswan dumpinfo
# CXX = g++
CXXFLAGS = -g -O2 `sdl-config --cflags` -Wall -std=c++98 -Wno-write-strings -Wno-unused-result
OPTIONS = -D_REENTRANT -I. -DVERSION=\"`git describe --tags --long --dirty`\"
LIBRARY_PATH =
SDL_LIBS = `sdl-config --libs`
LIBS = -g $(LIBRARY_PATH) $(SDL_LIBS)
ALLCFLAGS = $(CFLAGS) $(CEXTRA) $(OPTIONS) $(ALLFLAGS)
ALLCXXFLAGS=$(CXXFLAGS) $(CXXEXTRA) $(OPTIONS) $(ALLFLAGS)
CLEAN_FILES = wonderswan
.SUFFIXES: .cpp
main.o: main.cpp
.c.o:
$(CC) -c $(ALLCFLAGS) -o $@ $<
.cpp.o:
$(CXX) -c $(ALLCXXFLAGS) -o $@ $<
.PHONY: all install uninstall clean distclean depend dummy
$(SUBDIRS:%=%/__clean__): dummy
cd `dirname $@` && $(MAKE) clean
$(EXTRASUBDIRS:%=%/__clean__): dummy
-cd `dirname $@` && $(RM) $(CLEAN_FILES)
clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
$(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(OBJS) $(EXES:%.exe=%) $(EXES:%=%.so) $(EXES:%=%.spec.o) $(DLLS:%=%.so) $(DLLS:%=%.spec.o)
dumpinfo: dumpinfo.o
$(CXX) $(LIBS) -o $@ $(<)
wonderswan: $(OBJS)
$(CXX) -o $@ $(OBJS) $(LIBS)

76
README.md Normal file
View File

@@ -0,0 +1,76 @@
NewOswan *(name likely to change)*
==================================
[![CMake](https://github.com/Godzil/NewOswan/actions/workflows/cmake.yml/badge.svg)](https://github.com/Godzil/NewOswan/actions/workflows/cmake.yml)
### What is this project?
NewOswan is a WonderSwan emulator originally based on oswan-unix and heavily modified to be more accurate and better
hardware support.
### I don't care about the blabla, just show me the thing running
Ok ok, here are some screenshots:
Using a Swan Crystal boot rom:
![Console configuration menu](./doc/configmenu.png)
Wonderswan Crystal boot splash:
![SwanCrystal boot splash](./doc/bootsplash.png)
Clock Tower:
![Boot screen of ClockTower](./doc/clocktower.png)
Star Hearts:
![Boot screen of Star Hearts](./doc/starhearts1.png)
![Ingame screen of Star Hearts](./doc/starhearts2.png)
### What's different from oswan-unix?
A couple of things:
- NewOswan do properly support the internal EEPROM and cartridge EEPROM.
The original version was based in improper and innacurate hardware documentation and was accessing and storing the
information in an incorrect way.
- NewOswan support the internal bootrom of all the three model of the WonderSwan.
- NewOswan also provide stub version for the bootrom if you don't own the original console, you can still
use the emulator withtout copyright infreigement. (no copyrighted materiel is included with the emulator for obvious
reasons)
- NewOswan use OpenGL instead of SDL
- Sound is currently not supported
- NewOswan is currently not meant as a fully operational emulator as this project mostly started as a way to test game
and the original hardware. Still the idea is to make it overtime as accurate as possible
- It is now pure C (the original code was based on a C project with some unneeded C++ here and there)
- 64-Bit clean, the original code was making assumption on some type size that can break on a 64bit system
- Build and run on Mac OS X, Linux x86 and ARM, and probably more systems.
- Some crude debugging tools that can only be enabled at compile time
- Tons of fancy logs in the console! Like:
```
IEEP: RA:143F RD:0006 A:03F C:WRI - Write? Yes : 0006
IEEP: RA:1440 RD:0101 A:040 C:WRI - Write? Yes : 0101
IEEP: RA:1441 RD:0016 A:041 C:WRI - Write? Yes : 0016
IEEP: RA:1442 RD:0000 A:042 C:WRI - Write? Yes : 0000
WriteIO(6A, 00) [F000:0018h];
WriteIO(6B, 00) [F000:0018h];
Icons H
WriteIO(6A, 00) [F000:0018h];
WriteIO(6B, 00) [F000:0018h];
```
- And many more thing I probably forgot about as this project was originally not version managed as it was just a crude
hack on the original code and are not in the logs.
### Futur plans
- Complete refactor of the code.
- Add a proper CPU debugger
- Add other nice debugging tool like the GPU status and other things that could be needed. Acheiving the level of the tools
provided by the NES emulator [Mesen](https://www.mesen.ca) would be nice.
- Being able to rotate the screen
- Maybe being able to change the game at runtime instead of start time
- Full Audio support
### The boot rom stubs
You can find the source and file in the `irom_stub` folder.
They are identical and for now provide only the logic to boot a cart. There is no bootsplash nor configuration menu.
A bootsplash may be added later.
Feel free to use these stub for your own emulator if you wish, just be nice and put a line saying you are using it and
a link to this project in your documentation :)

BIN
doc/bootsplash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

BIN
doc/clocktower.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 KiB

BIN
doc/configmenu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

BIN
doc/starhearts1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

BIN
doc/starhearts2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 KiB

View File

@@ -1,3 +1,11 @@
/*******************************************************************************
* NewOswan
* dumpinfo.c: Tool to dump the metadata info about a cart rom image.
*
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@@ -17,7 +25,7 @@ char *load_file(char *filename, uint32_t *fileSize)
fstat(fd, &FileStat); fstat(fd, &FileStat);
ret_ptr = (char *)mmap(NULL, FileStat.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); ret_ptr = (char *)mmap(NULL, FileStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
*fileSize = FileStat.st_size; *fileSize = FileStat.st_size;
@@ -64,29 +72,26 @@ int main(int argc, char *argv[])
if (content != NULL) if (content != NULL)
{ {
data = (struct cart_metadata*)&(content[size - sizeof(struct cart_metadata)]); data = (struct cart_metadata *)&(content[size - sizeof(struct cart_metadata)]);
printf("%s:\n", argv[1]); printf("%s:\n", argv[1]);
if (data->farjump[0] == 0xEA) if (data->farjump[0] == 0xEA)
{ {
printf("[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", printf("[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", data->publishId, data->gameId[0],
data->publishId, data->gameId[0], data->gameId[1], data->flags2, data->romInfo, data->saveInfo, data->gameId[1], data->flags2, data->romInfo, data->saveInfo, data->flags & 0xFF,
data->flags & 0xFF, (data->flags>>8) & 0xFF, data->crc & 0xFF, (data->crc>>8) & 0xFF); (data->flags >> 8) & 0xFF, data->crc & 0xFF, (data->crc >> 8) & 0xFF);
printf(" - Reset @ %02X%02X:%02X%02Xh\n", printf(" - Reset @ %02X%02X:%02X%02Xh\n", data->farjump[4], data->farjump[3], data->farjump[2],
data->farjump[4], data->farjump[3], data->farjump[1]);
data->farjump[2], data->farjump[1]);
printf(" - publisher: %02X, gameId: %01X%02X\n", data->publishId, data->gameId[0], data->gameId[1]); printf(" - publisher: %02X, gameId: %01X%02X\n", data->publishId, data->gameId[0], data->gameId[1]);
printf(" - %s want to write to EEPROM\n", data->flags2&0x80?"Do":"Do not"); printf(" - %s want to write to EEPROM\n", data->flags2 & 0x80 ? "Do" : "Do not");
printf(" - %s user defined bootsplash\n", data->flagExt&0x80?"Dissallow":"Allow"); printf(" - %s user defined bootsplash\n", data->flagExt & 0x80 ? "Dissallow" : "Allow");
printf(" - Is %sbootable on a normal swan\n", data->flagExt&0x0F?"not ":""); printf(" - Is %sbootable on a normal swan\n", data->flagExt & 0x0F ? "not " : "");
printf(" - ROM Size: %02Xh\n", data->romInfo); printf(" - ROM Size: %02Xh\n", data->romInfo);
printf(" - Save type & Size: %02Xh\n", data->saveInfo); printf(" - Save type & Size: %02Xh\n", data->saveInfo);
printf(" - Flags: %d cycles ROM, %d bit ROM bus, %sRTC, %s orientation\n", printf(" - Flags: %d cycles ROM, %d bit ROM bus, %sRTC, %s orientation\n", data->flags & 0x004 ? 1 : 3,
data->flags & 0x004?1:3, data->flags & 0x002 ? 8 : 16, data->flags & 0x100 ? "" : "No ",
data->flags & 0x002?8:16, data->flags & 0x001 ? "Vertical" : "Horizontal");
data->flags & 0x100?"":"No ",
data->flags & 0x001?"Vertical":"Horizontal");
printf(" - CRC: %04Xh\n", data->crc); printf(" - CRC: %04Xh\n", data->crc);
ret = 0; ret = 0;
} }

20
irom_stub/Makefile Normal file
View File

@@ -0,0 +1,20 @@
.PHONY: all clean
all: ws_irom.bin wsc_irom.bin wc_irom.bin
clean:
@echo " RM"
@rm -f *.bin
ws_irom.bin: irom_stub.asm
@echo " AS $@"
@nasm $^ -o $@ -DWONDERSWAN=1
wsc_irom.bin: irom_stub.asm
@echo " AS $@"
@nasm $^ -o $@ -DWONDERSWANCOLOR=1
wc_irom.bin: irom_stub.asm
@echo " AS $@"
@nasm $^ -o $@ -DSWANCRYSTAL=1

110
irom_stub/irom_stub.asm Normal file
View File

@@ -0,0 +1,110 @@
; WonderSwan Internal ROM Stub
; --------------------------------------
; Version 1.0
; This is a replacement for the internal rom to prevent using/including any copyrighted material.
; It does nothing, just lauching the cartridge.
; It may later include a bootsplah.
%ifdef WONDERSWAN
%define ROM_SIZE 4096
%define ROM_SEG 0FF00h
%else
%define ROM_SIZE 8192
%define ROM_SEG 0FE00h
%endif
; Setup NASM for a 80186
bits 16
cpu 186
org 0000h
%define JUMPER_LOCATION 0000h:0400h
; ---------------------------------------------------------------------------------------------
; Boot ROM jumper
; ---------------------------------------------------------------------------------------------
; Lock the bootrom
; Clear a bit of itself
; Jump to FFFF:FFF0
;
; Must be copied to 0000:0400 then jmp 0000:0400
ram_jumper:
; Lock the boot rom away
IN al, 0A0h
OR al, 001h ; Bit 0 lock the boot rom
out 0A0h, al
mov ax, cs
mov es, ax
mov di, 0400h
mov cx, (.rm_te_end - ram_jumper)
xor ax, ax
xor bx, bx
.rm_te_end:
rep stosb
jmp 0FFFFh:00000h
ram_jumper_end:
_start:
cli
cld
push cs
pop ds
in al, 0A0h
; Bit 2 - 1 = cart using 16bit data bus
or al, 004h
out 0A0h, al
xor ax, ax
mov es, ax
; Clear the IRAM
mov di, 0
mov cx, 16384
xor al, al
rep stosb ; STOSB -> ES:DI
; Copy the jumper
mov si, ram_jumper
mov cx, (ram_jumper_end - ram_jumper)
mov di, 0400h
xor ax, ax
mov es, ax
rep movsb ; DS:SI -> ES:DI
; Do some register cleanup
mov al, 0FFh
out 0C0h, al
out 0C1h, al
out 0C2h, al
xor ax, ax
xor cx, cx
xor dx, dx
mov ds, ax
mov es, ax
; Jump to the jumper!
jmp JUMPER_LOCATION
%ifdef WONDERSWAN
db "WonderSwan"
%elifdef WONDERSWANCOLOR
db "WonderSwan Color"
%elifdef SWANCRYSTAL
db "WonderSwan Crystal"
%else
%endif
db " internal ROM Stub for NewOswan (c)2021 986-Studio"
; Create at the end of the block, add padding if needed
TIMES (ROM_SIZE - 16) - ($-$$) DB 0FFh
jmp ROM_SEG:_start ; 0
db 00 ; ?? ; 5
db 0F0h ; Dev ID ; 6
db 00 ; Min Swan type ; 7
db 00000100b ; flags ; C
db 01 ; No RTC ; D
dw 0FFFFh ; CRC (need to update it after, but as not used by the rom, no need for now)

BIN
irom_stub/wc_irom.bin Normal file

Binary file not shown.

BIN
irom_stub/ws_irom.bin Normal file

Binary file not shown.

BIN
irom_stub/wsc_irom.bin Normal file

Binary file not shown.

162
main.c Normal file
View File

@@ -0,0 +1,162 @@
/******************************************************************************
* NewOswan
* main.c: Entry point
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <log.h>
#include <rom.h>
#include <nec.h>
#include <memory.h>
#include <gpu.h>
#include <io.h>
#include <ws.h>
#include <emulate.h>
#include <audio.h>
#define LOG_PATH "oswan.log"
int sram_path_explicit = 0;
int ieep_path_explicit = 0;
int ws_mk_savpath()
{
char *w;
if (sram_path_explicit)
{
return 0;
}
if (ws_sram_path != NULL)
{
free(ws_sram_path);
}
ws_sram_path = (char *)malloc(strlen(ws_rom_path) + 2);
strcpy(ws_sram_path, ws_rom_path);
w = strrchr(ws_sram_path, '.');
if (NULL == w)
{
strcpy(ws_sram_path, "error.sav");
return 1;
}
strcpy(w, ".sav");
return 0;
}
int ws_mk_ieppath()
{
char *w;
if (ieep_path_explicit)
{
return 0;
}
if (ws_ieep_path != NULL)
{
free(ws_ieep_path);
}
ws_ieep_path = (char *)malloc(strlen(ws_rom_path) + 2);
strcpy(ws_ieep_path, ws_rom_path);
w = strrchr(ws_ieep_path, '.');
if (NULL == w)
{
strcpy(ws_ieep_path, "error.iep");
return 1;
}
strcpy(w, ".iep");
return 0;
}
int main(int argc, char *argv[])
{
wssystem_t ws_system = WS_SYSTEM_AUTODETECT;
snprintf(app_window_title, 255, "Oswan %s - Esc to return to GUI", VERSION);
Log(TLOG_ALWAYS, NULL, "NewOswan %s (built at: %s %s)", VERSION, __DATE__, __TIME__);
ws_rom_path = NULL;
for (int n = 1 ; n < argc ; ++n)
{
if (argv[n][0] == '-')
{
switch (argv[n][1])
{
case 'C':
if (++n < argc)
{
ws_cyclesByLine = atoi(argv[n]);
}
Log(TLOG_ALWAYS, "main", "Cycles by line set to %d", ws_cyclesByLine);
break;
case 'w':
if (++n < argc)
{
ws_system = atoi(argv[n]);
}
Log(TLOG_ALWAYS, "main", "WonderSwan set to %d", ws_system);
break;
case 's':
if (++n < argc)
{
ws_sram_path = argv[n];
}
sram_path_explicit = 1;
break;
default:break;
}
}
else
{
ws_rom_path = argv[n];
ws_mk_savpath();
ws_mk_ieppath();
}
}
while (!app_terminate)
{
if (!ws_rom_path)
{
exit(0);
}
if (ws_rom_path)
{
ws_set_system(ws_system);
if (ws_init(ws_rom_path))
{
ws_reset();
ws_emulate();
}
ws_done();
}
}
return (0);
}

216
main.cpp
View File

@@ -1,216 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// Wonderswan emulator
////////////////////////////////////////////////////////////////////////////////
//
// 13.04.2002: Fixed a small bug causing crashes
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include "source/log.h"
#include "source/rom.h"
#include "source/nec/nec.h"
#include "source/memory.h"
#include "source/gpu.h"
#include "source/io.h"
#include "source/ws.h"
#include "source/emulate.h"
#include "source/audio.h"
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
#define LOG_PATH "oswan.log"
int gui_command=GUI_COMMAND_NONE;
int gui_mainDialogRunning;
int gui_controls_configuration_Running;
int gui_get_key_Running;
int gui_get_key_key;
int ws_videoEnhancementType=0;
int ws_colourScheme=COLOUR_SCHEME_DEFAULT;
int ws_system=WS_SYSTEM_COLOR;
int sram_path_explicit = 0;
int ieep_path_explicit = 0;
int ws_mk_savpath()
{
char *w;
if (sram_path_explicit)
{
return 0;
}
if (ws_sram_path != NULL)
{
free(ws_sram_path);
}
ws_sram_path = (char *)malloc(strlen(ws_rom_path) + 2);
strcpy(ws_sram_path, ws_rom_path);
w = strrchr(ws_sram_path, '.');
if (NULL == w)
{
strcpy(ws_sram_path, "error.sav");
return 1;
}
strcpy(w, ".sav");
return 0;
}
int ws_mk_ieppath()
{
char *w;
if (ieep_path_explicit)
{
return 0;
}
if (ws_ieep_path != NULL)
{
free(ws_ieep_path);
}
ws_ieep_path = (char *)malloc(strlen(ws_rom_path) + 2);
strcpy(ws_ieep_path, ws_rom_path);
w = strrchr(ws_ieep_path, '.');
if (NULL == w)
{
strcpy(ws_ieep_path, "error.iep");
return 1;
}
strcpy(w, ".iep");
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
if (!log_init(LOG_PATH))
{
printf("Warning: cannot open log file %s\n",LOG_PATH);
}
snprintf(app_window_title, 255, "Oswan %s - Esc to return to GUI", VERSION);
fprintf(log_get(),"Oswan-unix %s (built at: %s %s)\n",VERSION , __DATE__,__TIME__);
ws_system = WS_SYSTEM_COLOR;
ws_rom_path = NULL;
for (int n = 1; n < argc; ++n)
{
if (argv[n][0] == '-')
{
switch(argv[n][1])
{
case 'C':
if (++n < argc)
{
ws_cyclesByLine = atoi(argv[n]);
}
fprintf(log_get(), "Cycles by line set to %d\n", ws_cyclesByLine);
break;
case 'w':
if (++n < argc)
{
ws_system = atoi(argv[n]);
}
fprintf(log_get(), "WonderSwan set to %d\n", ws_system);
break;
case 's':
if (++n < argc)
{
ws_sram_path = argv[n];
}
sram_path_explicit = 1;
break;
default:
break;
}
}
else
{
ws_rom_path = argv[n];
ws_mk_savpath();
ws_mk_ieppath();
}
}
while (!app_terminate)
{
if (!ws_rom_path)
{
app_gameRunning=0;
exit(0);
}
if (ws_rom_path)
{
ws_set_system(ws_system);
if (ws_init(ws_rom_path))
{
app_rotated=ws_rotated();
app_gameRunning=1;
if (ws_system == WS_SYSTEM_COLOR)
{
ws_gpu_operatingInColor=1;
}
ws_set_colour_scheme(ws_colourScheme);
ws_reset();
ws_emulate();
}
ws_done();
}
}
log_done();
return(0);
}

View File

@@ -1,50 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by gui.rc
//
#define IDD_DIALOG_MAIN 101
#define IDB_BITMAP1 102
#define IDB_BITMAP2 103
#define IDC_BUTTON_LOAD 1000
#define IDC_BUTTON_RESET 1001
#define IDC_BUTTON_EXIT 1002
#define IDC_RADIO1 1003
#define IDC_RADIO_WINDOWED 1003
#define IDC_RADIO2 1004
#define IDC_RADIO_FULLSCREEN 1004
#define IDC_BUTTON_LOADSTATE 1005
#define IDC_BUTTON_SAVESTATE 1006
#define IDC_RADIO3 1007
#define IDC_BUTTON_CONTINUE 1007
#define IDC_RADIO4 1008
#define IDC_BUTTON_CONTROLS 1008
#define IDC_RADIO5 1009
#define IDC_RADIO_STANDARD_MODE 1009
#define IDC_RADIO6 1010
#define IDC_RADIO_DOUBLESIZE_MODE 1010
#define IDC_RADIO7 1011
#define IDC_RADIO_SCANLINES_MODE 1011
#define IDC_RADIO8 1012
#define IDC_RADIO_50PRCTSCANLINES_MODE 1012
#define IDC_RADIO9 1013
#define IDC_RADIO_SPECIAL_MODE 1013
#define IDC_RADIO_SYSTEM_AUTODETECT 1014
#define IDC_RADIO_SYSTEM_MONO 1015
#define IDC_RADIO_SYSTEM_COLOR 1016
#define IDC_RADIO_2XSAI 1017
#define IDC_RADIO_SUPER2XSAI 1018
#define IDC_COLOUR_DEFAULT 1019
#define IDC_COLOUR_AMBER 1020
#define IDC_COLOUR_GREEN 1021
#define IDC_RADIO_SUPEREAGLE 1022
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1021
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -1,10 +1,23 @@
set(SOURCES audio.cpp emulate.cpp gpu.cpp io.cpp log.cpp memory.cpp rom.cpp ws.cpp) set(SOURCES emulate.c gpu.c io.c log.c memory.c rom.c ws.c file_access.c)
set(HEADERS audio.h emulate.h gpu.h ieeprom.h initialIo.h io.h log.h memory.h rom.h ws.h) set(PERIPHERAL_SOURCES peripherals/audio.c peripherals/buttons.c peripherals/color_gpu.c peripherals/color_system.c
peripherals/debug.c peripherals/dma.c peripherals/eeprom.c peripherals/mono_gpu.c peripherals/mono_system.c
peripherals/rtc.c peripherals/universal_luxor.c peripherals/interrupt_controller.c peripherals/rs232.c
peripherals/timer.c)
set(PERIPHERAL_HEADERS includes/interrupt_controller.h)
set(HEADERS includes/audio.h includes/device.h includes/emulate.h includes/gpu.h includes/io.h includes/log.h
includes/memory.h includes/nec.h includes/nec_debugger.h includes/necintrf.h includes/rom.h includes/ws.h
includes/file_access.h)
add_library(wswan ${SOURCES} ${HEADERS}) option(FAKE_DISPLAY "Disable OpenGL and fake displaying" OFF)
add_library(wswan ${SOURCES} ${PERIPHERAL_SOURCES} ${HEADERS} ${PERIPHERAL_HEADERS})
if (FAKE_DISPLAY)
target_compile_options(wswan PRIVATE -DPRETENT_DISPLAY)
endif()
target_link_libraries(wswan nec_v30 glfw ${OPENGL_glu_LIBRARY} ${OPENGL_gl_LIBRARY}) target_link_libraries(wswan nec_v30 glfw ${OPENGL_glu_LIBRARY} ${OPENGL_gl_LIBRARY})
target_include_directories(wswan PUBLIC .) target_include_directories(wswan PUBLIC includes/)
add_subdirectory(nec) add_subdirectory(nec)

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,11 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Main emulation loop * NewOswan
//////////////////////////////////////////////////////////////////////////////// * emulate.c:
// *
// * Based on the original Oswan-unix
// * Copyright (c) 2014-2022 986-Studio. All rights reserved.
// *
// ******************************************************************************/
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -21,33 +19,33 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/time.h> #include <sys/time.h>
#ifndef PRETENT_DISPLAY
#define GLFW_INCLUDE_GLEXT #define GLFW_INCLUDE_GLEXT
#define GL_SILENCE_DEPRECATION #define GL_SILENCE_DEPRECATION
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
/* "Apple" fix */ /* "Apple" fix */
#ifndef GL_TEXTURE_RECTANGLE #ifndef GL_TEXTURE_RECTANGLE
#define GL_TEXTURE_RECTANGLE GL_TEXTURE_RECTANGLE_EXT #define GL_TEXTURE_RECTANGLE GL_TEXTURE_RECTANGLE_EXT
#endif #endif
#endif /* PRETENT_DISPLAY */
#include "log.h" #include <log.h>
#include "io.h" #include <io.h>
#include "ws.h" #include <ws.h>
#include "rom.h" #include <rom.h>
#include "./nec/nec.h" #include "nec.h"
#include "./nec/necintrf.h" #include "necintrf.h"
#include "gpu.h" #include <gpu.h>
#include "audio.h" #include <audio.h>
#include "memory.h" #include <memory.h>
char app_window_title[256];
int app_gameRunning=0;
int app_terminate=0;
int app_fullscreen=0;
int app_rotated=0;
char app_window_title[256];
int app_terminate = 0;
int ws_key_esc = 0; int ws_key_esc = 0;
#ifndef PRETENT_DISPLAY
/* Open GL stuffs */ /* Open GL stuffs */
typedef struct GLWindow_t GLWindow; typedef struct GLWindow_t GLWindow;
struct KeyArray struct KeyArray
@@ -68,13 +66,13 @@ struct GLWindow_t
}; };
static GLWindow mainWindow; static GLWindow mainWindow;
static int window_num = 0; static int window_num = 0;
static void ShowScreen(GLWindow *g, int w, int h) static void ShowScreen(GLWindow *g, int w, int h)
{ {
glBindTexture(GL_TEXTURE_RECTANGLE, g->videoTexture); glBindTexture(GL_TEXTURE_RECTANGLE, g->videoTexture);
// glTexSubImage2D is faster when not using a texture range // glTexSubImage2D is faster when not using a texture range
glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, w, h, glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, w, h, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, g->videoMemory);
GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, g->videoMemory);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f);
@@ -92,12 +90,14 @@ static void ShowScreen(GLWindow *g, int w, int h)
glFlush(); glFlush();
} }
static void GLWindowInitEx(GLWindow *g, int w, int h) static void GLWindowInitEx(GLWindow *g, int w, int h)
{ {
g->WIDTH = w; g->WIDTH = w;
g->HEIGHT = h; g->HEIGHT = h;
g->videoTexture = window_num++; g->videoTexture = window_num++;
} }
static void setupGL(GLWindow *g, int w, int h) static void setupGL(GLWindow *g, int w, int h)
{ {
g->videoMemory = (uint8_t *)malloc(w * h * sizeof(uint16_t)); g->videoMemory = (uint8_t *)malloc(w * h * sizeof(uint16_t));
@@ -120,10 +120,6 @@ static void setupGL(GLWindow *g, int w, int h)
glEnable(GL_TEXTURE_RECTANGLE); glEnable(GL_TEXTURE_RECTANGLE);
glBindTexture(GL_TEXTURE_RECTANGLE, g->videoTexture); glBindTexture(GL_TEXTURE_RECTANGLE, g->videoTexture);
// glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_NV_EXT, 0, NULL);
// glTexParameteri(GL_TEXTURE_RECTANGLE_NV_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
// glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -134,6 +130,7 @@ static void setupGL(GLWindow *g, int w, int h)
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
} }
void restoreGL(GLWindow *g) void restoreGL(GLWindow *g)
{ {
//Tell OpenGL how to convert from coordinates to pixel values //Tell OpenGL how to convert from coordinates to pixel values
@@ -154,6 +151,7 @@ void restoreGL(GLWindow *g)
glEnable(GL_TEXTURE_RECTANGLE); glEnable(GL_TEXTURE_RECTANGLE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
} }
static void kbHandler(GLFWwindow *window, int key, int scan, int action, int mod) static void kbHandler(GLFWwindow *window, int key, int scan, int action, int mod)
{ {
struct KeyArray *keyArray; struct KeyArray *keyArray;
@@ -174,16 +172,19 @@ static void kbHandler(GLFWwindow *window, int key, int scan, int action, int mod
/*printf("key:%d, state:%d debounce:%d, laststate:%d\n", key, keyArray[key].curState, /*printf("key:%d, state:%d debounce:%d, laststate:%d\n", key, keyArray[key].curState,
keyArray[key].debounced, keyArray[key].lastState);*/ keyArray[key].debounced, keyArray[key].lastState);*/
} }
static void sizeHandler(GLFWwindow *window, int xs, int ys) static void sizeHandler(GLFWwindow *window, int xs, int ys)
{ {
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glViewport(0, 0, xs, ys); glViewport(0, 0, xs, ys);
ShowScreen(&mainWindow, 244, 144); ShowScreen(&mainWindow, 244, 144);
} }
static void error_callback(int error, const char *description) static void error_callback(int error, const char *description)
{ {
puts(description); puts(description);
} }
static void initDisplay(GLWindow *g) static void initDisplay(GLWindow *g)
{ {
int h = g->HEIGHT; int h = g->HEIGHT;
@@ -198,7 +199,7 @@ static void initDisplay(GLWindow *g)
if (!(g->windows = glfwCreateWindow(g->WIDTH, g->HEIGHT, "Main", NULL, NULL))) if (!(g->windows = glfwCreateWindow(g->WIDTH, g->HEIGHT, "Main", NULL, NULL)))
{ {
glfwTerminate(); glfwTerminate();
fprintf(stderr, "Window creation error...\n"); Log(TLOG_PANIC, "emulate", "Window creation error...");
abort(); abort();
} }
@@ -216,10 +217,12 @@ static void initDisplay(GLWindow *g)
glfwSetKeyCallback(g->windows, kbHandler); glfwSetKeyCallback(g->windows, kbHandler);
glfwSetWindowSizeCallback(g->windows, sizeHandler); glfwSetWindowSizeCallback(g->windows, sizeHandler);
} }
static void clearScreen(GLWindow *g) static void clearScreen(GLWindow *g)
{ {
memset(g->videoMemory, 0, sizeof(uint8_t) * g->WIDTH * g->HEIGHT * 4); memset(g->videoMemory, 0, sizeof(uint16_t) * g->WIDTH * g->HEIGHT);
} }
static void updateScreen(GLWindow *g) static void updateScreen(GLWindow *g)
{ {
/* Update windows code */ /* Update windows code */
@@ -228,17 +231,6 @@ static void updateScreen(GLWindow *g)
glfwSwapBuffers(g->windows); glfwSwapBuffers(g->windows);
glfwPollEvents(); glfwPollEvents();
} }
uint64_t getTicks()
{
struct timeval curTime;
uint64_t ticks;
/* Get datetime */
gettimeofday(&curTime, NULL);
ticks = (curTime.tv_sec* 1000) + curTime.tv_usec / 1000;
return ticks;
}
static inline int getKeyState(int key) static inline int getKeyState(int key)
{ {
@@ -247,111 +239,171 @@ static inline int getKeyState(int key)
static void read_keys() static void read_keys()
{ {
ws_key_start=0; #if 0
ws_key_x4=0; ws_key_start = 0;
ws_key_x2=0; ws_key_x4 = 0;
ws_key_x1=0; ws_key_x2 = 0;
ws_key_x3=0; ws_key_x1 = 0;
ws_key_y4=0; ws_key_x3 = 0;
ws_key_y2=0; ws_key_y4 = 0;
ws_key_y1=0; ws_key_y2 = 0;
ws_key_y3=0; ws_key_y1 = 0;
ws_key_button_a=0; ws_key_y3 = 0;
ws_key_button_b=0; ws_key_button_a = 0;
ws_key_button_b = 0;
if (getKeyState(GLFW_KEY_E)) if (getKeyState(GLFW_KEY_E))
{ {
dump_memory(); dump_memory();
} }
if (getKeyState(GLFW_KEY_R)) if (getKeyState(GLFW_KEY_R))
{ {
printf("Boop\n"); Log(TLOG_DEBUG, "emulate", "Boop reset");
ws_reset(); ws_reset();
} }
if (getKeyState(GLFW_KEY_ESCAPE)) if (getKeyState(GLFW_KEY_ESCAPE))
{ {
ws_key_esc = 1; ws_key_esc = 1;
} }
if ( getKeyState(GLFW_KEY_UP)) if (getKeyState(GLFW_KEY_UP))
{ {
ws_key_x1=1; ws_key_x1 = 1;
} }
if ( getKeyState(GLFW_KEY_DOWN)) if (getKeyState(GLFW_KEY_DOWN))
{ {
ws_key_x3=1; ws_key_x3 = 1;
} }
if (getKeyState(GLFW_KEY_RIGHT)) if (getKeyState(GLFW_KEY_RIGHT))
{ {
ws_key_x2=1; ws_key_x2 = 1;
} }
if (getKeyState(GLFW_KEY_LEFT)) if (getKeyState(GLFW_KEY_LEFT))
{ {
ws_key_x4=1; ws_key_x4 = 1;
} }
if (getKeyState(GLFW_KEY_ENTER)) if (getKeyState(GLFW_KEY_ENTER))
{ {
ws_key_start=1; ws_key_start = 1;
} }
if (getKeyState(GLFW_KEY_C)) if (getKeyState(GLFW_KEY_C))
{ {
ws_key_button_a=1; ws_key_button_a = 1;
} }
if (getKeyState(GLFW_KEY_X)) if (getKeyState(GLFW_KEY_X))
{ {
ws_key_button_b=1; ws_key_button_b = 1;
} }
if (getKeyState(GLFW_KEY_W)) if (getKeyState(GLFW_KEY_W))
{ {
ws_key_y1=1; ws_key_y1 = 1;
} }
if (getKeyState(GLFW_KEY_A)) if (getKeyState(GLFW_KEY_A))
{ {
ws_key_y4=1; ws_key_y4 = 1;
} }
if (getKeyState(GLFW_KEY_S)) if (getKeyState(GLFW_KEY_S))
{ {
ws_key_y3=1; ws_key_y3 = 1;
} }
if (getKeyState(GLFW_KEY_D)) if (getKeyState(GLFW_KEY_D))
{ {
ws_key_y2=1; ws_key_y2 = 1;
} }
if (getKeyState(GLFW_KEY_O)) if (getKeyState(GLFW_KEY_O))
{ {
ws_cyclesByLine+=10; ws_cyclesByLine += 10;
} }
if (getKeyState(GLFW_KEY_L)) if (getKeyState(GLFW_KEY_L))
{ {
ws_cyclesByLine-=10; ws_cyclesByLine -= 10;
} }
#endif
}
#else
typedef struct PseudoWindow_t
{
uint8_t *videoMemory;
int WIDTH;
int HEIGHT;
} PseudoWindow_t;
static PseudoWindow_t mainWindow;
static void GLWindowInitEx(PseudoWindow_t *g, int w, int h)
{
g->WIDTH = w;
g->HEIGHT = h;
}
static void initDisplay(PseudoWindow_t *g)
{
int w = g->WIDTH;
int h = g->HEIGHT;
g->videoMemory = (uint8_t *)malloc(w * h * sizeof(uint16_t));
memset(g->videoMemory, 0, w * h * sizeof(uint16_t));
}
static void clearScreen(PseudoWindow_t *g)
{
memset(g->videoMemory, 0, sizeof(uint16_t) * g->WIDTH * g->HEIGHT);
}
static void updateScreen(PseudoWindow_t *g)
{
}
static void read_keys()
{
static uint32_t i = 0;
ws_key_start = 0;
ws_key_x4 = 0;
ws_key_x2 = 0;
ws_key_x1 = 0;
ws_key_x3 = 0;
ws_key_y4 = 0;
ws_key_y2 = 0;
ws_key_y1 = 0;
ws_key_y3 = 0;
ws_key_button_a = 0;
ws_key_button_b = 0;
if (i > 1024)
{
ws_key_esc = 1;
}
i++;
}
#endif /* PRETENT_DISPLAY */
double getTicks()
{
struct timeval curTime;
double ticks;
/* Get datetime */
gettimeofday(&curTime, NULL);
ticks = (curTime.tv_sec * 1000.) + curTime.tv_usec / 1000.;
return ticks;
} }
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_emulate(void) void ws_emulate(void)
{ {
int32_t nCount = 0; int32_t nCount = 0;
@@ -365,10 +417,12 @@ void ws_emulate(void)
initDisplay(&mainWindow); initDisplay(&mainWindow);
clearScreen(&mainWindow); clearScreen(&mainWindow);
updateScreen(&mainWindow); updateScreen(&mainWindow);
int16_t *backBuffer = (int16_t *)mainWindow.videoMemory; int16_t *backBuffer = (int16_t *)mainWindow.videoMemory;
dNormalLast = (double)getTicks(); dNormalLast = getTicks();
#define HCLK (1000. / 12000.)
while (1) while (1)
{ {
@@ -376,18 +430,17 @@ void ws_emulate(void)
dTemp = getTicks(); dTemp = getTicks();
dTime = dTemp - dNormalLast; dTime = dTemp - dNormalLast;
nCount = (int32_t)(dTime * HCLK); // does this calculation make sense?
nCount = (int32_t)(dTime * 0.07547); // does this calculation make sense?
if (nCount <= 0) if (nCount <= 0)
{ {
/* Sleep for 2ms */ /* Sleep for 500us */
usleep(2000); usleep(500);
} // No need to do anything for a bit } // No need to do anything for a bit
else else
{ {
dNormalLast += nCount * (1 / 0.07547); dNormalLast += nCount * (1 / HCLK);
if (nCount > 10) if (nCount > 10)
{ {
@@ -406,10 +459,10 @@ void ws_emulate(void)
} }
} }
/* What is this mess? Frameskip? */
for (i = 0 ; i < nCount - 1 ; i++) for (i = 0 ; i < nCount - 1 ; i++)
{ {
while (!ws_executeLine(backBuffer, 0)) while (!ws_executeLine(backBuffer, 1))
{ {
} }
} }

View File

@@ -1,30 +0,0 @@
#ifndef EMULATE_H
#define EMULATE_H
#define KEY_ENTER 0x0D
#define KEY_SPACE 0x20
#define KEY_ESC 0x1b
#define KEY_UP 0x26
#define KEY_DOWN 0x28
#define KEY_LEFT 0x25
#define KEY_RIGHT 0x27
#define KEY_BUTTON1 0x57
#define KEY_BUTTON2 0x58
#define GUI_COMMAND_NONE 0
#define GUI_COMMAND_RESET 1
#define GUI_COMMAND_SCHEME_CHANGE 2
#define GUI_COMMAND_FILTER_CHANGE 3
extern char app_window_title[256];
extern int app_gameRunning;
extern int app_terminate;
extern int app_fullscreen;
extern int app_rotated;
void ws_emulate(void);
#endif /* EMULATE_H */

83
source/file_access.c Normal file
View File

@@ -0,0 +1,83 @@
/*******************************************************************************
* NewOswan
* file_access.c: File manipulation functions
*
* Created by Manoël Trapier on 27/06/2022.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
* This file is OS specific and this need to be changed at some point.
*
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <file_access.h>
#include <log.h>
char *load_file(char *filename, bool readOnly)
{
int fd;
char *ret_ptr;
struct stat FileStat;
int flags = readOnly?MAP_ANONYMOUS:MAP_SHARED;
fd = open(filename, O_RDWR);
fstat(fd, &FileStat);
Log(TLOG_DEBUG, "memory", "Trying to load %s, size = %lu...", filename, (unsigned long)FileStat.st_size);
ret_ptr = (char *)mmap(NULL, FileStat.st_size, PROT_READ | PROT_WRITE, flags, fd, 0);
close(fd);
if (ret_ptr == MAP_FAILED)
{
ret_ptr = NULL;
}
return ret_ptr;
}
char *create_file(char *filename, uint32_t size)
{
int fd;
uint32_t i;
char *ret_ptr;
char buf[] = {0};
Log(TLOG_DEBUG, "memory", "Trying to create %s, size = %u...\n", filename, size);
fd = open(filename, O_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_TRUNC, 0644);
fchmod(fd, 0644);
close(fd);
sync();
fd = open(filename, O_RDWR);
for (i = 0 ; i < size ; i++)
{
write(fd, buf, 1);
}
close(fd);
sync();
fd = open(filename, O_RDWR);
ret_ptr = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (ret_ptr == MAP_FAILED)
{
ret_ptr = NULL;
}
return ret_ptr;
}

1930
source/gpu.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __GPU_H__
#define __GPU_H__
#define COLOUR_SCHEME_DEFAULT 0
#define COLOUR_SCHEME_AMBER 1
#define COLOUR_SCHEME_GREEN 2
extern uint8_t ws_gpu_scanline;
extern uint8_t ws_gpu_operatingInColor;
extern uint8_t ws_videoMode;
extern int16_t ws_palette[16*4];
extern int8_t ws_paletteColors[8];
extern int16_t wsc_palette[16*16];
extern unsigned int ws_gpu_unknownPort;
extern uint32_t vblank_count;
void ws_gpu_init(void);
void ws_gpu_done(void);
void ws_gpu_reset(void);
void ws_gpu_renderScanline(int16_t *framebuffer);
void ws_gpu_changeVideoMode(uint8_t value);
void ws_gpu_write_byte(uint32_t offset, uint8_t value);
int ws_gpu_port_write(uint32_t port, uint8_t value);
uint8_t ws_gpu_port_read(uint8_t port);
void ws_gpu_set_colour_scheme(int scheme);
void ws_gpu_changeVideoMode(uint8_t value);
void ws_gpu_forceColorSystem(void);
void ws_gpu_forceMonoSystem(void);
void ws_gpu_clearCache(void);
#endif

View File

@@ -1,191 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
uint8_t DefaultBWEEprom[]=
{
0xff,0xff,0xff,0xff,0xff,0xff,192,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,127,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,252,0xff,1,0xff,253,0xff,253,0xff,253,0xff,253,
0xff,253,0xff,253,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x00,3,3,0x00,0x00,0x00,64,128,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135,5,140,9,5,12,139,12,144,0x00,0x00,2,
0x00,76,165,0x00,128,0x00,0x00,0x00,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x00,6,6,6,6,6,0x00,0x00,0x00,0x00,0x00,
1,128,15,0x00,1,1,1,15,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
'W'-54,'O'-54,'N'-54,'D'-54,'E'-54,'R'-54,'S'-54,'W'-54,'A'-54,'N'-54,0x00,0x00,0x00,0x00,0x00,
0x00,32,1,1,33,1,4,0x00,1,
0x00,152,60,127,74,1,53,1,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff
};
uint8_t DefaultColorEEprom[]=
{
0xff,0xff,0xff,0xff,0xff,0xff,192,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,127,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,252,0xff,1,0xff,253,0xff,253,0xff,253,0xff,253,
0xff,253,0xff,253,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x00,3,3,0x00,0x00,0x00,64,128,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135,5,140,9,5,12,139,12,144,0x00,0x00,2,
0x00,76,165,0x00,128,0x00,0x00,0x00,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,0xff,127,
0xff,127,0xff,127,0xff,127,0xff,127,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x00,6,6,6,6,6,0x00,0x00,0x00,0x00,0x00,
1,128,15,0x00,1,1,1,15,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
'W'-54,'O'-54,'N'-54,'D'-54,'E'-54,'R'-54,'S'-54,'W'-54,'A'-54,'N'-54,0x00,0x00,0x00,0x00,0x00,
0x00,32,1,1,33,1,4,0x00,1,
0x00,152,60,127,74,1,53,1,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff
};

View File

@@ -1,17 +1,17 @@
////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// * NewOswan
////////////////////////////////////////////////////////////////////////////// * audio.h:
// *
// * Based on the original Oswan-unix
// * Copyright (c) 2014-2022 986-Studio. All rights reserved.
// *
// ******************************************************************************/
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __AUDIO_H__ #ifndef __AUDIO_H__
#define __AUDIO_H__ #define __AUDIO_H__
#include <stdint.h>
void ws_audio_init(); void ws_audio_init();
void ws_audio_reset(); void ws_audio_reset();
void ws_audio_port_write(uint32_t port, uint8_t value); void ws_audio_port_write(uint32_t port, uint8_t value);

52
source/includes/device.h Normal file
View File

@@ -0,0 +1,52 @@
/*******************************************************************************
* NewOswan
* device.h:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __DEVICE_H__
#define __DEVICE_H__
#include <stdint.h>
/***
* Ticks are the fasted clock in the system
* Each device which need to be clocked use a multiple of the tick
* number as their own clock.
*/
typedef uint64_t tick_t;
typedef void (*device_init)(uint8_t baseAddress, void *param);
typedef void (*device_reset)(void);
typedef void (*device_free)(void);
typedef void (*device_update)(tick_t ticks);
typedef enum device_type_t
{
DT_INTERRUPT_CONTROLLER,
DT_GPU,
DT_BUTTONS,
DT_DMA,
DT_LUXOR,
DT_AUDIO,
DT_SYSTEM,
DT_RTC,
DT_RS232,
DT_EEPROM,
DT_DEBUG,
} device_type_t;
typedef struct device_t
{
device_init init; /***< Function called to init the device - Non optional */
device_update update; /***< Function called on updates - Optional */
device_reset reset; /***< Function called to reset the device - Optional */
device_free free; /***< Function called to deinit the device - Optional */
device_type_t deviceType; /***< Used to tell the type of device, could be useful to pass the
* right parameters to init - Non optional */
} device_t;
#endif /* __DEVICE_H__ */

20
source/includes/emulate.h Normal file
View File

@@ -0,0 +1,20 @@
/*******************************************************************************
* NewOswan
* emulate.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef EMULATE_H
#define EMULATE_H
#include <stdint.h>
extern char app_window_title[256];
extern int app_terminate;
void ws_emulate(void);
#endif /* EMULATE_H */

View File

@@ -0,0 +1,19 @@
/*******************************************************************************
* NewOswan
* file_access.h:
*
* Created by Manoël Trapier on 26/06/2022.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __FILE_ACCESS_H__
#define __FILE_ACCESS_H__
#include <stdint.h>
#include <stdbool.h>
char *create_file(char *filename, uint32_t size);
char *load_file(char *filename, bool readOnly);
#endif /* __FILE_ACCESS_H__ */

43
source/includes/gpu.h Normal file
View File

@@ -0,0 +1,43 @@
/*******************************************************************************
* NewOswan
* gpu.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __GPU_H__
#define __GPU_H__
#include <stdint.h>
struct ws_gpu_t
{
uint8_t scanline;
uint32_t cyclecount;
};
extern uint8_t ws_gpu_scanline;
extern uint8_t ws_gpu_operatingInColor;
extern uint8_t ws_videoMode;
extern int16_t ws_palette[16 * 4];
extern int8_t ws_paletteColors[8];
extern int16_t wsc_palette[16 * 16];
extern unsigned int ws_gpu_unknownPort;
extern uint32_t vblank_count;
void ws_gpu_init(void);
void ws_gpu_done(void);
void ws_gpu_reset(void);
void ws_gpu_renderScanline(int16_t *framebuffer);
void ws_gpu_changeVideoMode(uint8_t value);
void ws_gpu_write_byte(uint32_t offset, uint8_t value);
int ws_gpu_port_write(uint32_t port, uint8_t value);
uint8_t ws_gpu_port_read(uint8_t port);
void ws_gpu_changeVideoMode(uint8_t value);
void ws_gpu_clearCache(void);
#endif

View File

@@ -0,0 +1,32 @@
/*******************************************************************************
* NewOswan
* interrupt_controller.h:
*
* Created by Manoël Trapier on 14/03/2022.
* Copyright (c) 2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __INTERRUPT_CONTROLLER_H__
#define __INTERRUPT_CONTROLLER_H__
#include <device.h>
typedef enum hw_interrupt_type_t
{
/* They are in the same order as the hardware */
HWI_SERIAL_TX = 0,
HWI_KEY,
HWI_CART,
HWI_SERIAL_RX,
HWI_LINE_COMPARE,
HWI_VBLANK_TIMER,
HWI_VBLANK,
HWI_HBLANK_TIMER,
} hw_interrupt_type_t;
extern device_t InterruptController;
void trigger_interrupt(hw_interrupt_type_t type);
#endif /* __INTERRUPT_CONTROLLER_H__ */

31
source/includes/io.h Normal file
View File

@@ -0,0 +1,31 @@
/*******************************************************************************
* NewOswan
* io.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __IO_H__
#define __IO_H__
#include <stdint.h>
void io_init(void);
void io_reset(void);
void io_cleanup(void);
uint8_t io_readport(uint8_t port);
void io_writeport(uint8_t port, uint8_t value);
typedef uint8_t (*io_read)(void *pdata, uint8_t port);
typedef void (*io_write)(void *pdata, uint8_t port, uint8_t value);
void register_io_hook(uint8_t baseAddress, uint8_t port, io_read readHook, void *pdata, io_write writeHook);
void register_io_hook_array(uint8_t baseAddress, const uint8_t *portList, uint8_t listLen, io_read readHook, io_write writeHook,
void *pdata);
#define UNUSED_PARAMETER(_s) (void *)(_s)
#endif

125
source/includes/log.h Normal file
View File

@@ -0,0 +1,125 @@
/*******************************************************************************
* NewOswan
* log.h: C Fancy Logger
*
* Created by Manoël Trapier on 20/01/2009.
* Copyright (c) 2009-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef _LOG_H
#define _LOG_H
#ifdef __cplusplus
extern "C" {
#endif
//#define ALLOW_COLORS
#ifdef ALLOW_COLORS
#define __C(c) "\x1B[" c "m"
#else
#define __C(c) ""
#endif
#define ANSI_COLOR __C
#define FBLACK ANSI_COLOR("30")
#define FRED ANSI_COLOR("31")
#define FGREEN ANSI_COLOR("32")
#define FYELLOW ANSI_COLOR("33")
#define FBLUE ANSI_COLOR("34")
#define FMAGENTA ANSI_COLOR("35")
#define FCYAN ANSI_COLOR("36")
#define FWHITE ANSI_COLOR("37")
#define BBLACK ANSI_COLOR("40")
#define BRED ANSI_COLOR("41")
#define BGREEN ANSI_COLOR("42")
#define BYELLOW ANSI_COLOR("43")
#define BBLUE ANSI_COLOR("44")
#define BMAGENTA ANSI_COLOR("45")
#define BCYAN ANSI_COLOR("46")
#define BWHITE ANSI_COLOR("47")
#define CNORMAL ANSI_COLOR("0")
enum
{
TLOG_ALWAYS = -1,
TLOG_PANIC = 0,
TLOG_ERROR,
TLOG_WARNING,
TLOG_NORMAL,
TLOG_VERBOSE,
TLOG_DEBUG,
};
//#define LOG_ALWAYS_FFLUSH
#define DYNA_LOG_LEVEL
#define SET_DEBUG_LOG
/* Set if DYNALOG is set the maximum compiled log level */
#ifndef MAXIMUM_DEBUG_LEVEL
#ifndef SET_DEBUG_LOG
#define MAXIMUM_DEBUG_LEVEL TLOG_NORMAL
#else
#define MAXIMUM_DEBUG_LEVEL TLOG_DEBUG
#endif
#endif /* MAXIMUM_DEBUG_LEVEL */
/* Set the default log level */
#ifndef SET_DEBUG_LOG
#define DEFAULT_DEBUG_LEVEL TLOG_PANIC
#else
#define DEFAULT_DEBUG_LEVEL TLOG_DEBUG
#endif
/******************************************************************************/
/* DO NOT MESS AFTER THIS LINE */
/******************************************************************************/
#ifdef DYNA_LOG_LEVEL
# ifdef MAX_DEBUG_LEVEL
# undef MAX_DEBUG_LEVEL
# endif
# ifdef __LOG_C_INTERNAL_
int MAX_DEBUG_LEVEL = DEFAULT_DEBUG_LEVEL;
#else
extern int MAX_DEBUG_LEVEL;
#endif
#else
# ifndef MAX_DEBUG_LEVEL
# define MAX_DEBUG_LEVEL DEFAULT_DEBUG_LEVEL
# endif
#endif
#define Log(_level, _user, _fmt, ...)\
if (_level <= MAXIMUM_DEBUG_LEVEL)\
if ((_level <= MAX_DEBUG_LEVEL) || (_level <= TLOG_PANIC))\
do { log_real(_level, _user, _fmt, ##__VA_ARGS__); } while(0)
void log_real(int level, const char *user, const char *fmt, ...);
#define LOG(_level, _str, ...) if ((_level <= MAX_DEBUG_LEVEL) || (_level <= TLOG_PANIC)) do { fputs(_str, stderr); } while(0)
#define LOGCODE(_level, _user, _code)\
if (_level <= MAXIMUM_DEBUG_LEVEL) do{\
Log(_level, _user, "");\
if ((_level <= MAX_DEBUG_LEVEL) || (_level <= TLOG_PANIC))\
do { _code; fprintf(stderr, "\n"); } while(0); } while(0)
#define INFOL(_level, _fmt) LOGCODE(_level, "INFOL", { printf _fmt; })
#define FUNC_IN() Log(TLOG_VERBOSE, NULL, ">>%s", __func__)
#define FUNC_OUT() Log(TLOG_VERBOSE, NULL, "<<%s", __func__)
#define FUNC_OUTR(out) Log(TLOG_VERBOSE, NULL, "<<%s (%d)", __func__, out)
void log_displayPanic(int signal);
#ifdef __cplusplus
}
#endif
#endif /* _LOG_H */

37
source/includes/memory.h Normal file
View File

@@ -0,0 +1,37 @@
/*******************************************************************************
* NewOswan
* memory.h:
*
*
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include <stdint.h>
void dump_memory();
/***
* Set a memory page with a granularity of 4-16
* @param bank: the bank (0-F) to set
* @param pointer: a pointer to the memory to set
*/
void set_memory_bank(uint8_t bank, uint8_t *pointer);
/***
* Set a memory page with a granularity of 8-12
* @param bank: the bank (0-FF) to set
* @param pointer: a pointer to the memory to set
*/
void set_memory_page(uint8_t page, uint8_t *pointer);
#define mem_readop mem_readmem20
#define mem_readop_arg mem_readmem20
void mem_writemem20(uint32_t addr, uint8_t value);
uint8_t mem_readmem20(uint32_t addr);
#endif /* __MEMORY_H__ */

405
source/includes/nec.h Normal file
View File

@@ -0,0 +1,405 @@
/******************************************************************************
* NewOswan
* nec.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __NEC_H_
#define __NEC_H_
#include <stdint.h>
#include <stdbool.h>
#include "necintrf.h"
typedef enum
{
ES, CS, SS, DS
} SREGS;
typedef enum
{
AW, CW, DW, BW, SP, BP, IX, IY
} WREGS;
typedef enum
{
AL, AH, CL, CH, DL, DH, BL, BH, SPL, SPH, BPL, BPH, IXL, IXH, IYL, IYH
} BREGS;
#pragma pack(1)
typedef union
{
/* eight general registers */
uint16_t w[8]; /* viewed as 16 bits registers */
uint8_t b[16]; /* or as 8 bit registers */
} necbasicregs;
typedef struct
{
necbasicregs regs;
uint16_t sregs[4];
uint16_t ip;
int32_t SignVal;
int32_t AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */
uint32_t TF, IF, DF, MF; /* 0 or 1 valued flags */ /* OB[19.07.99] added Mode Flag V30 */
uint32_t int_vector;
uint32_t pending_irq;
uint32_t nmi_state;
uint32_t irq_state;
int (*irq_callback)(int irqline);
} nec_Regs;
#pragma pack()
#define NEC_NMI_INT_VECTOR 2
/* Cpu types, steps of 8 to help the cycle count calculation */
#define V33 0
#define V30 8
#define V20 16
/* parameter x = result, y = source 1, z = source 2 */
#define SetTF(x) (I.TF = (x))
#define SetIF(x) (I.IF = (x))
#define SetDF(x) (I.DF = (x))
#define SetMD(x) (I.MF = (x)) /* OB [19.07.99] Mode Flag V30 */
#define SetCFB(x) (I.CarryVal = (x) & 0x100)
#define SetCFW(x) (I.CarryVal = (x) & 0x10000)
#define SetAF(x, y, z) (I.AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
#define SetSF(x) (I.SignVal = (x))
#define SetZF(x) (I.ZeroVal = (x))
#define SetPF(x) (I.ParityVal = (x))
#define SetSZPF_Byte(x) (I.SignVal=I.ZeroVal=I.ParityVal=(int8_t)(x))
#define SetSZPF_Word(x) (I.SignVal=I.ZeroVal=I.ParityVal=(int16_t)(x))
#define SetOFW_Add(x, y, z) (I.OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
#define SetOFB_Add(x, y, z) (I.OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
#define SetOFW_Sub(x, y, z) (I.OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
#define SetOFB_Sub(x, y, z) (I.OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
#define ADDB { uint32_t res=dst+src; SetCFB(res); SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(uint8_t)res; }
#define ADDW { uint32_t res=dst+src; SetCFW(res); SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(uint16_t)res; }
#define SUBB { uint32_t res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(uint8_t)res; }
#define SUBW { uint32_t res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(uint16_t)res; }
#define ORB dst|=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Byte(dst)
#define ORW dst|=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Word(dst)
#define ANDB dst&=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Byte(dst)
#define ANDW dst&=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Word(dst)
#define XORB dst^=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Byte(dst)
#define XORW dst^=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Word(dst)
#define CF (I.CarryVal!=0)
#define SF (I.SignVal<0)
#define ZF (I.ZeroVal==0)
#define PF parity_table[(uint8_t)I.ParityVal]
#define AF (I.AuxVal!=0)
#define OF (I.OverVal!=0)
#define MD (I.MF!=0)
/************************************************************************/
#define SegBase(Seg) (I.sregs[Seg] << 4)
#define DefaultBase(Seg) ((seg_prefix && (Seg==DS || Seg==SS)) ? (prefix_base) : (uint32_t)(I.sregs[Seg] << 4))
#define GetMemB(Seg, Off) (/*nec_ICount-=((Off)&1)?1:0,*/ (uint8_t)mem_readmem20((DefaultBase(Seg)+(Off))))
#define GetMemW(Seg, Off) (/*nec_ICount-=((Off)&1)?1:0,*/ (uint16_t) mem_readmem20((DefaultBase(Seg)+(Off))) + (mem_readmem20((DefaultBase(Seg)+((Off)+1)))<<8) )
#define PutMemB(Seg, Off, x) { /*nec_ICount-=((Off)&1)?1:0*/; mem_writemem20((DefaultBase(Seg)+(Off)),(x)); }
#define PutMemW(Seg, Off, x) { /*nec_ICount-=((Off)&1)?1:0*/; PutMemB(Seg,Off,(x)&0xff); PutMemB(Seg,(Off)+1,(uint8_t)((x)>>8)); }
/* Todo: Remove these later - plus readword could overflow */
#define ReadByte(ea) (/*nec_ICount-=((ea)&1)?1:0,*/ (uint8_t)mem_readmem20((ea)))
#define ReadWord(ea) (/*nec_ICount-=((ea)&1)?1:0,*/ mem_readmem20((ea))+(mem_readmem20(((ea)+1))<<8))
#define WriteByte(ea, val) { /*nec_ICount-=((ea)&1)?1:0*/; mem_writemem20((ea),val); }
#define WriteWord(ea, val) { /*nec_ICount-=((ea)&1)?1:0*/; mem_writemem20((ea),(uint8_t)(val)); mem_writemem20(((ea)+1),(val)>>8); }
#define read_port(port) io_readport(port)
#define write_port(port, val) io_writeport(port,val)
#define FETCH (mem_readop_arg((I.sregs[CS]<<4)+I.ip++))
#define FETCHOP (mem_readop((I.sregs[CS]<<4)+I.ip++))
#define FETCHWORD(var) { var=mem_readop_arg((((I.sregs[CS]<<4)+I.ip)))+(mem_readop_arg((((I.sregs[CS]<<4)+I.ip+1)))<<8); I.ip+=2; }
#define PUSH(val) { I.regs.w[SP]-=2; WriteWord((((I.sregs[SS]<<4)+I.regs.w[SP])),val); }
#define POP(var) { var = ReadWord((((I.sregs[SS]<<4)+I.regs.w[SP]))); I.regs.w[SP]+=2; }
#define PEEK(addr) ((uint8_t)mem_readop_arg(addr))
#define PEEKOP(addr) ((uint8_t)mem_readop(addr))
#define GetModRM uint32_t ModRM=mem_readop_arg((I.sregs[CS]<<4)+I.ip++)
/* Cycle count macros:
CLK - cycle count is the same on all processors
CLKS - cycle count differs between processors, list all counts
CLKW - cycle count for word read/write differs for odd/even source/destination address
CLKM - cycle count for reg/mem instructions
CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses
Prefetch & buswait time is not emulated.
Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated.
#define CLK(all) nec_ICount-=all
#define CLKS(v20,v30,v33) { const uint32_t ccount=(v20<<16)|(v30<<8)|v33; nec_ICount-=(ccount>>cpu_type)&0x7f; }
#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e) { const uint32_t ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_ICount-=(I.ip&1)?((ocount>>cpu_type)&0x7f):((ecount>>cpu_type)&0x7f); }
#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const uint32_t ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_ICount-=( ModRM >=0xc0 )?((ccount>>cpu_type)&0x7f):((mcount>>cpu_type)&0x7f); }
#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall) { const uint32_t ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_ICount-=vall; else nec_ICount-=(I.ip&1)?((ocount>>cpu_type)&0x7f):((ecount>>cpu_type)&0x7f); }
*/
#define CLKS(v20, v30, v33) { const uint32_t ccount=(v20<<16)|(v30<<8)|v33; nec_ICount-=(ccount>>cpu_type)&0x7f; }
#define CLK(all) nec_ICount-=all
#define CLKW(v30MZo, v30MZe) { nec_ICount-=(I.ip&1)?v30MZo:v30MZe; }
#define CLKM(v30MZm, v30MZ) { nec_ICount-=( ModRM >=0xc0 )?v30MZ:v30MZm; }
#define CLKR(v30MZo, v30MZe, vall) { if (ModRM >=0xc0) nec_ICount-=vall; else nec_ICount-=(I.ip&1)?v30MZo:v30MZe; }
#define CompressFlags() (uint16_t)(CF | (PF << 2) | (AF << 4) | (ZF << 6) \
| (SF << 7) | (I.TF << 8) | (I.IF << 9) \
| (I.DF << 10) | (OF << 11))
#define ExpandFlags(f) \
{ \
I.CarryVal = (f) & 1; \
I.ParityVal = !((f) & 4); \
I.AuxVal = (f) & 16; \
I.ZeroVal = !((f) & 64); \
I.SignVal = (f) & 128 ? -1 : 0; \
I.TF = ((f) & 256) == 256; \
I.IF = ((f) & 512) == 512; \
I.DF = ((f) & 1024) == 1024; \
I.OverVal = (f) & 2048; \
I.MF = ((f) & 0x8000) == 0x8000; \
}
#define IncWordReg(Reg) \
uint16_t tmp = (uint16_t)I.regs.w[Reg]; \
uint16_t tmp1 = tmp+1; \
I.OverVal = (tmp == 0x7fff); \
SetAF(tmp1,tmp,1); \
SetSZPF_Word(tmp1); \
I.regs.w[Reg]=tmp1
#define DecWordReg(Reg) \
uint16_t tmp = (uint16_t)I.regs.w[Reg]; \
uint16_t tmp1 = tmp-1; \
I.OverVal = (tmp == 0x8000); \
SetAF(tmp1,tmp,1); \
SetSZPF_Word(tmp1); \
I.regs.w[Reg]=tmp1
#define JMP(flag) \
int tmp = (int)((int8_t)FETCH); \
if (flag) \
{ \
I.ip = (uint16_t)(I.ip+tmp); \
nec_ICount-=3; \
return; \
}
#define ADJ4(param1, param2) \
if (AF || ((I.regs.b[AL] & 0xf) > 9)) \
{ \
int tmp; \
I.regs.b[AL] = tmp = I.regs.b[AL] + param1; \
I.AuxVal = 1; \
} \
if (CF || (I.regs.b[AL] > 0x9f)) \
{ \
I.regs.b[AL] += param2; \
I.CarryVal = 1; \
} \
SetSZPF_Byte(I.regs.b[AL])
#define ADJB(param1, param2) \
if (AF || ((I.regs.b[AL] & 0xf) > 9)) \
{ \
I.regs.b[AL] += param1; \
I.regs.b[AH] += param2; \
I.AuxVal = 1; \
I.CarryVal = 1; \
} \
else \
{ \
I.AuxVal = 0; \
I.CarryVal = 0; \
} \
I.regs.b[AL] &= 0x0F
#define BITOP_BYTE \
ModRM = FETCH; \
if (ModRM >= 0xc0) { \
tmp=I.regs.b[Mod_RM.RM.b[ModRM]]; \
} \
else { \
(*GetEA[ModRM])(); \
tmp=ReadByte(EA); \
}
#define BITOP_WORD \
ModRM = FETCH; \
if (ModRM >= 0xc0) { \
tmp=I.regs.w[Mod_RM.RM.w[ModRM]]; \
} \
else { \
(*GetEA[ModRM])(); \
tmp=ReadWord(EA); \
}
#define BIT_NOT \
if (tmp & (1<<tmp2)) \
tmp &= ~(1<<tmp2); \
else \
tmp |= (1<<tmp2)
#define XchgAWReg(Reg) \
uint16_t tmp; \
tmp = I.regs.w[Reg]; \
I.regs.w[Reg] = I.regs.w[AW]; \
I.regs.w[AW] = tmp
#define ROL_BYTE I.CarryVal = dst & 0x80; dst = (dst << 1)+CF
#define ROL_WORD I.CarryVal = dst & 0x8000; dst = (dst << 1)+CF
#define ROR_BYTE I.CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<7)
#define ROR_WORD I.CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<15)
#define ROLC_BYTE dst = (dst << 1) + CF; SetCFB(dst)
#define ROLC_WORD dst = (dst << 1) + CF; SetCFW(dst)
#define RORC_BYTE dst = (CF<<8)+dst; I.CarryVal = dst & 0x01; dst >>= 1
#define RORC_WORD dst = (CF<<16)+dst; I.CarryVal = dst & 0x01; dst >>= 1
#define SHL_BYTE(c) dst <<= c; SetCFB(dst); SetSZPF_Byte(dst); PutbackRMByte(ModRM,(uint8_t)dst)
#define SHL_WORD(c) dst <<= c; SetCFW(dst); SetSZPF_Word(dst); PutbackRMWord(ModRM,(uint16_t)dst)
#define SHR_BYTE(c) dst >>= c-1; I.CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(uint8_t)dst)
#define SHR_WORD(c) dst >>= c-1; I.CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(uint16_t)dst)
#define SHRA_BYTE(c) dst = ((int8_t)dst) >> (c-1); I.CarryVal = dst & 0x1; dst = ((int8_t)((uint8_t)dst)) >> 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(uint8_t)dst)
#define SHRA_WORD(c) dst = ((int16_t)dst) >> (c-1); I.CarryVal = dst & 0x1; dst = ((int16_t)((uint16_t)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(uint16_t)dst)
#define DIVUB \
uresult = I.regs.w[AW]; \
uresult2 = uresult % tmp; \
if ((uresult /= tmp) > 0xff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.b[AL] = uresult; \
I.regs.b[AH] = uresult2; \
}
#define DIVB \
result = (int16_t)I.regs.w[AW]; \
result2 = result % (int16_t)((int8_t)tmp); \
if ((result /= (int16_t)((int8_t)tmp)) > 0xff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.b[AL] = result; \
I.regs.b[AH] = result2; \
}
#define DIVUW \
uresult = (((uint32_t)I.regs.w[DW]) << 16) | I.regs.w[AW];\
uresult2 = uresult % tmp; \
if ((uresult /= tmp) > 0xffff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.w[AW]=uresult; \
I.regs.w[DW]=uresult2; \
}
#define DIVW \
result = ((uint32_t)I.regs.w[DW] << 16) + I.regs.w[AW]; \
result2 = result % (int32_t)((int16_t)tmp); \
if ((result /= (int32_t)((int16_t)tmp)) > 0xffff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.w[AW]=result; \
I.regs.w[DW]=result2; \
}
#define ADD4S { \
int i,v1,v2,result; \
int count = (I.regs.b[CL]+1)/2; \
uint16_t di = I.regs.w[IY]; \
uint16_t si = I.regs.w[IX]; \
I.ZeroVal = I.CarryVal = 0; \
for (i=0;i<count;i++) { \
tmp = GetMemB(DS, si); \
tmp2 = GetMemB(ES, di); \
v1 = (tmp>>4)*10 + (tmp&0xf); \
v2 = (tmp2>>4)*10 + (tmp2&0xf); \
result = v1+v2+I.CarryVal; \
I.CarryVal = result > 99 ? 1 : 0; \
result = result % 100; \
v1 = ((result/10)<<4) | (result % 10); \
PutMemB(ES, di,v1); \
if (v1) I.ZeroVal = 1; \
si++; \
di++; \
} \
}
#define SUB4S { \
int count = (I.regs.b[CL]+1)/2; \
int i,v1,v2,result; \
uint16_t di = I.regs.w[IY]; \
uint16_t si = I.regs.w[IX]; \
I.ZeroVal = I.CarryVal = 0; \
for (i=0;i<count;i++) { \
tmp = GetMemB(ES, di); \
tmp2 = GetMemB(DS, si); \
v1 = (tmp>>4)*10 + (tmp&0xf); \
v2 = (tmp2>>4)*10 + (tmp2&0xf); \
if (v1 < (v2+I.CarryVal)) { \
v1+=100; \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 1; \
} else { \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 0; \
} \
v1 = ((result/10)<<4) | (result % 10); \
PutMemB(ES, di,v1); \
if (v1) I.ZeroVal = 1; \
si++; \
di++; \
} \
}
#define CMP4S { \
int count = (I.regs.b[CL]+1)/2; \
int i,v1,v2,result; \
uint16_t di = I.regs.w[IY]; \
uint16_t si = I.regs.w[IX]; \
I.ZeroVal = I.CarryVal = 0; \
for (i=0;i<count;i++) { \
tmp = GetMemB(ES, di); \
tmp2 = GetMemB(DS, si); \
v1 = (tmp>>4)*10 + (tmp&0xf); \
v2 = (tmp2>>4)*10 + (tmp2&0xf); \
if (v1 < (v2+I.CarryVal)) { \
v1+=100; \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 1; \
} else { \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 0; \
} \
v1 = ((result/10)<<4) | (result % 10); \
if (v1) I.ZeroVal = 1; \
si++; \
di++; \
} \
}
#endif /* __NEC_H_ */

View File

@@ -0,0 +1,16 @@
/******************************************************************************
* NewOswan
* nec_debugger.h:
*
* Created by Manoël Trapier on 14/04/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __NEC_DEBUGGER_H__
#define __NEC_DEBUGGER_H__
int nec_decode_instruction(uint16_t segment, uint16_t offset, char *buffer, unsigned int bufferSize);
#endif /* __NEC_DEBUGGER_H__ */

View File

@@ -0,0 +1,49 @@
/******************************************************************************
* NewOswan
* necintrf.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
/* ASG 971222 -- rewrote this interface */
#ifndef __NECITRF_H__
#define __NECITRF_H__
#include <stdint.h>
enum
{
NEC_IP = 1,
NEC_AW,
NEC_CW,
NEC_DW,
NEC_BW,
NEC_SP,
NEC_BP,
NEC_IX,
NEC_IY,
NEC_FLAGS,
NEC_ES,
NEC_CS,
NEC_SS,
NEC_DS,
NEC_VECTOR,
NEC_PENDING,
NEC_NMI_STATE,
NEC_IRQ_STATE
};
/* Public variables */
extern int nec_ICount;
/* Public functions */
void nec_set_irq_line(int irqline, int state);
void nec_set_reg(int regnum, uint32_t val);
int nec_execute(int cycles);
unsigned nec_get_reg(int regnum);
void nec_reset(void *param);
void nec_int(uint16_t vector);
#endif /* __NECITRF_H__ */

70
source/includes/rom.h Normal file
View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* NewOswan
* rom.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __ROM_H__
#define __ROM_H__
#include <stdint.h>
#define WS_ROM_SIZE_2MBIT 1
#define WS_ROM_SIZE_4MBIT 2
#define WS_ROM_SIZE_8MBIT 3
#define WS_ROM_SIZE_16MBIT 4
#define WS_ROM_SIZE_24MBIT 5
#define WS_ROM_SIZE_32MBIT 6
#define WS_ROM_SIZE_48MBIT 7
#define WS_ROM_SIZE_64MBIT 8
#define WS_ROM_SIZE_128MBIT 9
#define WS_EEPROM_SIZE_NONE 0
#define WS_EEPROM_SIZE_1k 0x10
#define WS_EEPROM_SIZE_16k 0x20
#define WS_EEPROM_SIZE_32k 0x30
/* 40 is not valid */
#define WS_EEPROM_SIZE_8k 0x50
#define WS_EEPROM_SIZE_4k 0x60
#define WS_EEPROM_SIZE_2k 0x70
#define WS_SRAM_SIZE_NONE 0
#define WS_SRAM_SIZE_64k 0x01
#define WS_SRAM_SIZE_256k 0x02
#define WS_SRAM_SIZE_1M 0x03
#define WS_SRAM_SIZE_2M 0x04
#define WS_SRAM_SIZE_4M 0x05
#pragma pack(1)
typedef struct ws_romHeaderStruct
{
/* Miss "Fixed Data" (F5h) */
uint8_t developperId; /* Maker Code L */
uint8_t minimumSupportSystem; /* Maker Code H */
uint8_t cartId; /* Title code */
uint8_t gameVersion; /* Version */
uint8_t romSize; /* ROM Size */
uint8_t saveSize; /* XROM/XEROM Size */
uint8_t cartFlags; /* Boot loader */
uint8_t realtimeClock; /* Syb System LSI */
uint16_t checksum; /* Checksum */
} ws_romHeaderStruct;
#pragma pack()
uint8_t *ws_rom_load(char *path, uint32_t *romSize);
void ws_rom_dumpInfo(uint8_t *wsrom, uint32_t wsromSize);
ws_romHeaderStruct *ws_rom_getHeader(uint8_t *wsrom, uint32_t wsromSize);
uint32_t ws_rom_sramSize(uint8_t *wsrom, uint32_t wsromSize);
uint32_t ws_rom_eepromSize(uint8_t *wsrom, uint32_t wsromSize);
static inline uint8_t *ws_get_page_ptr(uint8_t *wsrom, uint32_t romSize, uint16_t page)
{
uint32_t temp = page << 16;
temp &= (romSize - 1);
return &wsrom[temp];
}
#endif /* __ROM_H__ */

38
source/includes/ws.h Normal file
View File

@@ -0,0 +1,38 @@
/*******************************************************************************
* NewOswan
* ws.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#ifndef __WS_H__
#define __WS_H__
#include <stdint.h>
typedef enum wssystem_t
{
WS_SYSTEM_AUTODETECT = 0, WS_SYSTEM_MONO, WS_SYSTEM_COLOR, WS_SYSTEM_CRYSTAL,
} wssystem_t;
extern uint32_t ws_cyclesByLine;
int ws_init(char *rompath);
int ws_rotated(void);
void ws_set_system(wssystem_t system);
wssystem_t ws_get_system();
void ws_reset(void);
int ws_executeLine(int16_t *framebuffer, int renderLine);
void ws_patchRom(void);
int ws_loadState(char *statepath);
int ws_saveState(char *statepath);
void ws_done(void);
extern char *ws_sram_path;
extern char *ws_ieep_path;
extern char *ws_rom_path;
#endif /* __WS_H__ */

View File

@@ -1,271 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// Initial I/O values
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
uint8_t initialIoValue[256]=
{
0x00,//0
0x00,//1
0x9d,//2
0xbb,//3
0x00,//4
0x00,//5
0x00,//6
0x26,//7
0xfe,//8
0xde,//9
0xf9,//a
0xfb,//b
0xdb,//c
0xd7,//d
0x7f,//e
0xf5,//f
0x00,//10
0x00,//11
0x00,//12
0x00,//13
0x01,//14
0x00,//15
0x9e,//16
0x9b,//17
0x00,//18
0x00,//19
0x00,//1a
0x00,//1b
0x99,//1c
0xfd,//1d
0xb7,//1e
0xdf,//1f
0x30,//20
0x57,//21
0x75,//22
0x76,//23
0x15,//24
0x73,//25
0x77,//26
0x77,//27
0x20,//28
0x75,//29
0x50,//2a
0x36,//2b
0x70,//2c
0x67,//2d
0x50,//2e
0x77,//2f
0x57,//30
0x54,//31
0x75,//32
0x77,//33
0x75,//34
0x17,//35
0x37,//36
0x73,//37
0x50,//38
0x57,//39
0x60,//3a
0x77,//3b
0x70,//3c
0x77,//3d
0x10,//3e
0x73,//3f
0x00,//40
0x00,//41
0x00,//42
0x00,//43
0x00,//44
0x00,//45
0x00,//46
0x00,//47
0x00,//48
0x00,//49
0x00,//4a
0x00,//4b
0x00,//4c
0x00,//4d
0x00,//4e
0x00,//4f
0x00,//50
0x00,//51
0x00,//52
0x00,//53
0x00,//54
0x00,//55
0x00,//56
0x00,//57
0x00,//58
0x00,//59
0x00,//5a
0x00,//5b
0x00,//5c
0x00,//5d
0x00,//5e
0x00,//5f
0x0a,//60
0x00,//61
0x00,//62
0x00,//63
0x00,//64
0x00,//65
0x00,//66
0x00,//67
0x00,//68
0x00,//69
0x00,//6a
0x0f,//6b
0x00,//6c
0x00,//6d
0x00,//6e
0x00,//6f
0x00,//70
0x00,//71
0x00,//72
0x00,//73
0x00,//74
0x00,//75
0x00,//76
0x00,//77
0x00,//78
0x00,//79
0x00,//7a
0x00,//7b
0x00,//7c
0x00,//7d
0x00,//7e
0x00,//7f
0x00,//80
0x00,//81
0x00,//82
0x00,//83
0x00,//84
0x00,//85
0x00,//86
0x00,//87
0x00,//88
0x00,//89
0x00,//8a
0x00,//8b
0x00,//8c
0x1f,//8d 1d ?
0x00,//8e
0x00,//8f
0x00,//90
0x00,//91
0x00,//92
0x00,//93
0x00,//94
0x00,//95
0x00,//96
0x00,//97
0x00,//98
0x00,//99
0x00,//9a
0x00,//9b
0x00,//9c
0x00,//9d
0x03,//9e
0x00,//9f
0x80,//a0
0x00,//a1
0x00,//a2
0x00,//a3
0x0,//a4 2b
0x0,//a5 7f
0x4f,//a6
0xff,//a7 cf ?
0x00,//a8
0x00,//a9
0x00,//aa
0x00,//ab
0x00,//ac
0x00,//ad
0x00,//ae
0x00,//af
0x00,//b0
0xdb,//b1
0x00,//b2
0x00,//b3
0x00,//b4
0x40,//b5
0x00,//b6
0x00,//b7
0x00,//b8
0x00,//b9
0x01,//ba
0x00,//bb
0x42,//bc
0x00,//bd
0x83,//be
0x00,//bf
0x2f,//c0
0x3f,//c1
0xff,//c2
0xff,//c3
0x00,//c4
0x00,//c5
0x00,//c6
0x00,//c7
0xd1,//c8?
0xd1,//c9
0xd1,//ca
0xd1,//cb
0xd1,//cc
0xd1,//cd
0xd1,//ce
0xd1,//cf
0xd1,//d0
0xd1,//d1
0xd1,//d2
0xd1,//d3
0xd1,//d4
0xd1,//d5
0xd1,//d6
0xd1,//d7
0xd1,//d8
0xd1,//d9
0xd1,//da
0xd1,//db
0xd1,//dc
0xd1,//dd
0xd1,//de
0xd1,//df
0xd1,//e0
0xd1,//e1
0xd1,//e2
0xd1,//e3
0xd1,//e4
0xd1,//e5
0xd1,//e6
0xd1,//e7
0xd1,//e8
0xd1,//e9
0xd1,//ea
0xd1,//eb
0xd1,//ec
0xd1,//ed
0xd1,//ee
0xd1,//ef
0xd1,//f0
0xd1,//f1
0xd1,//f2
0xd1,//f3
0xd1,//f4
0xd1,//f5
0xd1,//f6
0xd1,//f7
0xd1,//f8
0xd1,//f9
0xd1,//fa
0xd1,//fb
0xd1,//fc
0xd1,//fd
0xd1,//fe
0xd1 //ff
};

121
source/io.c Normal file
View File

@@ -0,0 +1,121 @@
/*******************************************************************************
* NewOswan
* io.c: I/O ports implementaton
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <log.h>
#include <rom.h>
#include <nec.h>
#include <necintrf.h>
#include <gpu.h>
#include <audio.h>
#include <memory.h>
#include <ws.h>
#include <io.h>
//#define IO_DUMP
typedef struct ioregistry_t
{
io_read read; /***< Read function for a specific IO port */
io_write write; /***< Write function for a specific IO port */
void *private; /***< Private data for the peripheral if needed. */
uint8_t base_address; /***< Base IO address. Used create a "local" value when calling the read/write function */
} ioregistry_t;
ioregistry_t io_registry[0x100];
extern uint32_t romAddressMask;
extern nec_Regs I;
extern uint64_t nec_monotonicCycles;
extern uint32_t sramSize;
FILE *ioLogFp = NULL;
void io_init(void)
{
#ifdef IO_DUMP
ioLogFp = fopen("iodump.csv", "wt");
#endif
}
void io_cleanup(void)
{
#ifdef IO_DUMP
fclose(ioLogFp);
#endif
}
void register_io_hook(uint8_t baseAddress, uint8_t port, io_read readHook, void *pdata, io_write writeHook)
{
io_registry[baseAddress + port].base_address = baseAddress;
io_registry[baseAddress + port].read = readHook;
io_registry[baseAddress + port].write = writeHook;
io_registry[baseAddress + port].private = pdata;
}
void register_io_hook_array(uint8_t baseAddress, const uint8_t *portList, uint8_t listLen, io_read readHook, io_write writeHook,
void *pdata)
{
uint16_t i;
for(i = 0; i < listLen; i++)
{
io_registry[baseAddress + portList[i]].base_address = baseAddress;
io_registry[baseAddress + portList[i]].read = readHook;
io_registry[baseAddress + portList[i]].write = writeHook;
io_registry[baseAddress + portList[i]].private = pdata;
}
}
uint8_t io_readport(uint8_t port)
{
uint8_t retVal = 0;
if (io_registry[port].read)
{
uint8_t localPort = port - io_registry[port].base_address;
retVal = io_registry[port].read(io_registry[port].private, localPort);
}
else
{
Log(TLOG_DEBUG, "IO", "CPU tried to read IO %02Xh - May be a bug", port);
}
#ifdef IO_DUMP
if (ioLogFp)
{
fprintf(ioLogFp, "%lu, R, %02X, %02X\n", nec_monotonicCycles, port, retVal);
}
#endif
return retVal;
}
void io_writeport(uint8_t port, uint8_t value)
{
if (io_registry[port].write)
{
uint8_t localPort = port - io_registry[port].base_address;
io_registry[port].write(io_registry[port].private, localPort, value);
}
else
{
Log(TLOG_DEBUG, "IO", "CPU tried to write %02Xh to IO %02Xh - MAy be a bug", value, port);
}
#ifdef IO_DUMP
if (ioLogFp)
{
fprintf(ioLogFp, "%llu, W, %02X, %02X\n", nec_monotonicCycles, port, value);
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __IO_H__
#define __IO_H__
extern uint8_t *ws_ioRam;
extern uint8_t ws_key_start;
extern uint8_t ws_key_x4;
extern uint8_t ws_key_x2;
extern uint8_t ws_key_x1;
extern uint8_t ws_key_x3;
extern uint8_t ws_key_y4;
extern uint8_t ws_key_y2;
extern uint8_t ws_key_y1;
extern uint8_t ws_key_y3;
extern uint8_t ws_key_button_a;
extern uint8_t ws_key_button_b;
void ws_io_init(void);
void ws_io_reset(void);
void ws_io_flipControls(void);
void ws_io_done(void);
#endif

140
source/log.c Normal file
View File

@@ -0,0 +1,140 @@
/*******************************************************************************
* NewOswan
* log.c: C Fancy Logger
*
* Created by Manoël Trapier on 20/01/2009.
* Copyright (c) 2009-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#define __LOG_C_INTERNAL_
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <log.h>
#include <sys/time.h>
#include <time.h>
#include <syslog.h>
void log_displayPanic(int signal)
{
size_t size = 0;
//size = backtrace(array, 30);
/* Now flood user with unusefull data. */
fprintf(stderr, FYELLOW "\n\n ----- " FYELLOW " YICK! ERROR YICK! [bt:%zu]" FYELLOW "----- \n", size);
// get void*'s for all entries on the stack
// print out all the frames to stderr
fprintf(stderr, " ----- Error: signal: %d -----\n" FRED, signal);
//backtrace_symbols_fd(array, size, 2);
fprintf(stderr, FYELLOW "\n\n ----- " FYELLOW " YICK! ERROR YICK! " FYELLOW "----- " CNORMAL "\n");
}
void time_stamp_line(void)
{
/* Time "0" will be thefirst log line */
static char firstRun = 1;
static struct timeval firstTime;
struct timeval curTime;
int cMin, cSec;
long long cMSec;
/* Get datetime */
gettimeofday(&curTime, NULL);
if (firstRun == 1)
{
firstRun = 0;
firstTime.tv_sec = curTime.tv_sec;
firstTime.tv_usec = curTime.tv_usec;
}
cMSec = ((curTime.tv_sec - firstTime.tv_sec) * 1000) + (curTime.tv_usec - firstTime.tv_usec) / 1000;
cSec = (cMSec / 1000);
cMSec %= 1000;
cMin = cSec / 60;
cSec %= 60;
/* Put cursor at start of line */
fprintf(stderr, "%c[s", 0x1B);
fprintf(stderr, "%c[7000D", 0x1B);
fprintf(stderr, "%c[1C", 0x1B);
fprintf(stderr, FWHITE"[" FYELLOW "%03d" FRED "." FBLUE "%02d" FRED "." FGREEN "%03lld" FWHITE "]" CNORMAL, cMin,
cSec, cMSec);
fprintf(stderr, "%c[u", 0x1B);
}
void log_real(int level, const char *user, const char *fmt, ...)
{
int i;
va_list va;
/* The LOG_PANIC must always be displayed */
if ((level <= MAX_DEBUG_LEVEL) || (level <= TLOG_PANIC))
{
fprintf(stderr, CNORMAL);
time_stamp_line();
fprintf(stderr, CNORMAL " | ");
switch (level)
{
case TLOG_PANIC: fprintf(stderr, BRED FWHITE); break;
case TLOG_ERROR: fprintf(stderr, FRED); break;
case TLOG_WARNING: fprintf(stderr, FYELLOW); break;
default:
case TLOG_NORMAL: fprintf(stderr, FGREEN); break;
case TLOG_VERBOSE: fprintf(stderr, FCYAN); break;
case TLOG_DEBUG: fprintf(stderr, BBLUE FWHITE); break;
}
if (user != NULL)
{
i = strlen(user);
if (i < 12)
{
i = 12 - i;
for (; i >= 0 ; i--)
{
fprintf(stderr, " ");
}
}
fprintf(stderr, "%s", user);
}
else
{
switch (level)
{
case TLOG_PANIC: fprintf(stderr, " PANIC"); break;
case TLOG_ERROR: fprintf(stderr, " Error"); break;
case TLOG_WARNING: fprintf(stderr, " Warning"); break;
default:
case TLOG_NORMAL: fprintf(stderr, " Info"); break;
case TLOG_VERBOSE: fprintf(stderr, " Verbose"); break;
case TLOG_DEBUG: fprintf(stderr, " Debug"); break;
}
}
fprintf(stderr, CNORMAL " | ");
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
if (fmt[0] != 0)
{
fprintf(stderr, "\n");
}
#ifdef LOG_ALWAYS_FFLUSH
/* Systematicaly flush */
fflush(stderr);
#endif
}
}

View File

@@ -1,67 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include "log.h"
FILE *log_stream=NULL;
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
int log_init(char *path)
{
//log_stream=fopen(path,"wrt");
log_stream = stdout;
if (log_stream==NULL)
{
return(0);
}
return(1);
}
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
FILE *log_get(void)
{
return(log_stream);
}
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
void log_done(void)
{
fclose(log_stream);
}

View File

@@ -1,20 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __LOG_H__
#define __LOG_H__
int log_init(char *path);
FILE *log_get(void);
void log_done(void);
#endif

65
source/memory.c Normal file
View File

@@ -0,0 +1,65 @@
/*******************************************************************************
* NewOswan
* memory.c: Memory implementation
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdint.h>
#include <memory.h>
#include <log.h>
void dump_memory()
{
// TODO: Need complete rewrite
}
/* 256 page of 12 bits */
uint8_t *pagedMemory[0x100];
/* Memory address is 20bit and split in 8 (page) - 12 (offset) */
void mem_writemem20(uint32_t addr, uint8_t value)
{
uint8_t page = addr >> 12;
uint16_t offset = addr & 0xFFF;
/* Everything from 3000:0000h is readonly, so we ignore all tentative to write there. */
if (page < 0x30)
{
/* Unmapped will be NULL so just check to be sure */
if (pagedMemory[page])
{
pagedMemory[page][offset] = value;
}
}
}
uint8_t mem_readmem20(uint32_t addr)
{
uint8_t page = addr >> 12;
uint16_t offset = addr & 0xFFF;
if (pagedMemory[page])
{
return pagedMemory[page][offset];
}
return 0x90;
}
/* Set memory bank with a granularity of 4-16 as it is the most common on the WonderSwan */
void set_memory_bank(uint8_t bank, uint8_t *pointer)
{
uint8_t page = bank << 4;
for(int i = 0; i < 16; i++)
{
pagedMemory[page | i] = pointer + (i * 0x1000);
}
}
void set_memory_page(uint8_t page, uint8_t *pointer)
{
pagedMemory[page] = pointer;
}

View File

@@ -1,448 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// Memory
////////////////////////////////////////////////////////////////////////////////
// Notes: need to optimize cpu_writemem20
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "log.h"
#include "rom.h"
#include "./nec/nec.h"
#include "io.h"
#include "gpu.h"
#include "audio.h"
#include "memory.h"
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
#define IO_ROM_BANK_BASE_SELECTOR 0xC0
uint8_t *ws_rom;
uint8_t *ws_staticRam;
uint8_t *internalRam;
uint8_t *externalEeprom;
char *internalBWIRom;
char *internalColorIRom;
char *internalBWEeprom;
char *internalColorEeprom;
uint16_t *internalEeprom;
extern uint8_t *ws_ioRam;
uint16_t ws_rom_checksum;
uint8_t ws_haveColorIRom;
uint8_t ws_haveBWIRom;
uint32_t sramAddressMask;
uint32_t externalEepromAddressMask;
uint32_t romAddressMask;
uint32_t romSize;
int ws_sram_dirty = 0;
extern nec_Regs I;
void dump_memory()
{
int i;
FILE *fp;
printf("Dumping memory....\n");
fp = fopen("iram.bin", "wb");
fwrite(internalRam, 1, 0x10000, fp);
fclose(fp);
fp = fopen("sram.bin", "wb");
fwrite(ws_staticRam, 1, 0x10000, fp);
fclose(fp);
fp = fopen("rom.bin", "wb");
fwrite(ws_rom, 1, romSize, fp);
fclose(fp);
fp = fopen("memorydump.bin", "wb");
fwrite(internalRam, 1, 0x10000, fp);
/* page 1 */
fwrite(&(ws_staticRam[0 & sramAddressMask]), 1, 0x10000, fp);
fwrite(&(ws_rom[((ws_ioRam[IO_ROM_BANK_BASE_SELECTOR+2]&((romSize>>16)-1))<<16)]), 1, 0x10000, fp);
fwrite(&(ws_rom[((ws_ioRam[IO_ROM_BANK_BASE_SELECTOR+3]&((romSize>>16)-1))<<16)]), 1, 0x10000, fp);
for(i = 4; i < 0x10; i++)
{
int romBank=(256-(((ws_ioRam[IO_ROM_BANK_BASE_SELECTOR]&0xf)<<4)|(i&0xf)));
fwrite(&(ws_rom[(unsigned)(romSize-(romBank<<16))]), 1, 0x10000, fp);
}
fclose(fp);
fp = fopen("registers.bin", "wb");
fwrite(ws_ioRam, 1, 256, fp);
fclose(fp);
fp = fopen("cpuregs.bin", "wb");
/* CS */
fwrite(&I.sregs[CS], 1, 2, fp);
/* IP */
fwrite(&I.ip, 1, 2, fp);
fclose(fp);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void cpu_writemem20(uint32_t addr, uint8_t value)
{
uint32_t offset=addr&0xffff;
uint32_t bank=addr>>16;
if (!bank)
{
// 0 - RAM - 16 KB (WS) / 64 KB (WSC) internal RAM
ws_gpu_write_byte(offset,value);
ws_audio_write_byte(offset,value);
}
else if (bank==1)
{
// 1 - SRAM (cart)
ws_staticRam[offset&sramAddressMask]=value;
ws_sram_dirty = 1;
}
// other banks are read-only
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint8_t cpu_readmem20(uint32_t addr)
{
uint32_t offset=addr&0xffff;
uint32_t bank=addr>>16;
//uint16_t romBank;
uint8_t hwReg;
uint32_t temp;
uint8_t ret;
switch (bank)
{
case 0: // 0 - RAM - 16 KB (WS) / 64 KB (WSC) internal RAM
if (ws_gpu_operatingInColor)
{
return(internalRam[offset]);
}
else if (offset<0x4000)
{
return(internalRam[offset]);
}
return(0x90);
case 1: // 1 - SRAM (cart)
return ws_staticRam[offset&sramAddressMask];
case 2:
// Bank 2
hwReg = ws_ioRam[0xC2];
temp = hwReg << 16;
temp += offset;
temp &= (romSize - 1);
return ws_rom[temp];
case 3:
// Bank 3
hwReg = ws_ioRam[0xC3];
temp = hwReg << 16;
temp += offset;
temp &= (romSize - 1);
return ws_rom[temp];
case 0xF:
hwReg = ws_ioRam[0xA0];
if (!(hwReg & 1))
{
if (ws_gpu_operatingInColor && ws_haveColorIRom)
{
if (addr >= 0xFE000)
{
ret = internalColorIRom[addr & ~0xFE000];
return ret;
}
}
else if (!ws_gpu_operatingInColor && ws_haveBWIRom)
{
if (addr >= 0xFF000)
{
ret = internalBWIRom[addr & ~0xFF000];
return ret;
}
}
}
// fall through
default:
hwReg = ws_ioRam[0xC0];
temp = hwReg << 20;
temp += addr & 0xFFFFF;
temp &= (romSize - 1);
return ws_rom[temp];
}
return(0x90);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
char *load_file(char *filename)
{
int fd;
char *ret_ptr;
struct stat FileStat;
fd = open(filename, O_RDWR);
fstat(fd, &FileStat);
printf("Trying to load %s, size = %lu...\n",filename, (unsigned long)FileStat.st_size);
ret_ptr = (char *)mmap(NULL, FileStat.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (ret_ptr == MAP_FAILED)
{
ret_ptr = NULL;
}
return ret_ptr;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
char *create_file(char *filename, uint32_t size)
{
int fd;
uint32_t i;
char *ret_ptr;
char buf[] = { 0 };
printf("Trying to create %s, size = %u...\n",filename, size);
fd = open(filename, O_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_TRUNC, 0644);
fchmod(fd, 0644);
close(fd);
sync();
fd = open(filename, O_RDWR);
for(i = 0; i < size; i++)
{
write(fd, buf, 1);
}
close(fd);
sync();
fd = open(filename, O_RDWR);
ret_ptr = (char *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (ret_ptr == MAP_FAILED)
{
ret_ptr = NULL;
}
return ret_ptr;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_memory_init(uint8_t *rom, uint32_t wsRomSize)
{
ws_romHeaderStruct *ws_romHeader;
ws_rom=rom;
romSize=wsRomSize;
ws_romHeader=ws_rom_getHeader(ws_rom,romSize);
ws_rom_checksum=ws_romHeader->checksum;
internalRam=(uint8_t*)malloc(0x10000);
sramAddressMask=ws_rom_sramSize(ws_rom,romSize)-1;
externalEepromAddressMask=ws_rom_eepromSize(ws_rom,romSize)-1;
internalBWIRom = load_file("ws_irom.bin");
internalColorIRom = load_file("wsc_irom.bin");
internalBWEeprom = load_file("ws_ieeprom.bin");
if ( internalBWEeprom == NULL )
{
internalBWEeprom = create_file("ws_ieeprom.bin", BW_IEEPROM_SIZE);
}
internalColorEeprom = load_file("wsc_ieeprom.bin");
if ( internalColorEeprom == NULL )
{
internalColorEeprom = create_file("wsc_ieeprom.bin", COLOR_IEEPROM_SIZE);
}
internalEeprom = (uint16_t *)internalBWEeprom;
if (ws_gpu_operatingInColor)
{
internalEeprom = (uint16_t *)internalColorEeprom;
}
ws_haveBWIRom = false;
ws_haveColorIRom = false;
if (internalBWIRom != NULL)
{
printf("Color IROM Found!\n");
ws_haveBWIRom = true;
}
if (internalColorIRom != NULL)
{
printf("B&W IROM Found!\n");
ws_haveColorIRom = true;
}
romAddressMask=romSize-1;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_memory_reset(void)
{
memset(internalRam,0,0x10000);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_memory_done(void)
{
free(internalRam);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint8_t *memory_getRom(void)
{
return(ws_rom);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint32_t memory_getRomSize(void)
{
return(romSize);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint16_t memory_getRomCrc(void)
{
return(ws_rom_checksum);
}

View File

@@ -1,37 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __MEMORY_H__
#define __MEMORY_H__
extern uint8_t *ws_staticRam;
extern uint8_t *internalRam;
extern uint8_t *externalEeprom;
void ws_memory_init(uint8_t *rom, uint32_t romSize);
void ws_memory_reset(void);
uint8_t *memory_getRom(void);
uint32_t memory_getRomSize(void);
uint16_t memory_getRomCrc(void);
void ws_memory_done(void);
void memory_load(int fp);
void memory_save(int fp);
char *create_file(char *filename, uint32_t size);
char *load_file(char *filename);
void dump_memory();
#define BW_IEEPROM_SIZE (128)
#define COLOR_IEEPROM_SIZE (2048)
#endif

View File

@@ -1,4 +1,6 @@
set(SOURCES nec.cpp) set(SOURCES nec.c nec_debugger.c)
set(HEADERS nec.h necea.h necinstr.h necintrf.h necmodrm.h) set(HEADERS ../includes/nec.h necea.h necinstr.h ../includes/necintrf.h necmodrm.h ../includes/nec_debugger.h)
add_library(nec_v30 ${SOURCES} ${HEADERS}) add_library(nec_v30 ${SOURCES} ${HEADERS})
target_include_directories(nec_v30 PUBLIC ../includes/)

4256
source/nec/nec.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,394 +0,0 @@
#ifndef __NEC_H_
#define __NEC_H_
#include "necintrf.h"
typedef enum { ES, CS, SS, DS } SREGS;
typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS;
typedef enum { AL,AH,CL,CH,DL,DH,BL,BH,SPL,SPH,BPL,BPH,IXL,IXH,IYL,IYH } BREGS;
#pragma pack(1)
typedef union
{
/* eight general registers */
uint16_t w[8]; /* viewed as 16 bits registers */
uint8_t b[16]; /* or as 8 bit registers */
} necbasicregs;
typedef struct
{
necbasicregs regs;
uint16_t sregs[4];
uint16_t ip;
int32_t SignVal;
int32_t AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */
uint32_t TF, IF, DF, MF; /* 0 or 1 valued flags */ /* OB[19.07.99] added Mode Flag V30 */
uint32_t int_vector;
uint32_t pending_irq;
uint32_t nmi_state;
uint32_t irq_state;
int (*irq_callback)(int irqline);
} nec_Regs;
#pragma pack()
#define NEC_NMI_INT_VECTOR 2
/* Cpu types, steps of 8 to help the cycle count calculation */
#define V33 0
#define V30 8
#define V20 16
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
/* parameter x = result, y = source 1, z = source 2 */
#define SetTF(x) (I.TF = (x))
#define SetIF(x) (I.IF = (x))
#define SetDF(x) (I.DF = (x))
#define SetMD(x) (I.MF = (x)) /* OB [19.07.99] Mode Flag V30 */
#define SetCFB(x) (I.CarryVal = (x) & 0x100)
#define SetCFW(x) (I.CarryVal = (x) & 0x10000)
#define SetAF(x,y,z) (I.AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
#define SetSF(x) (I.SignVal = (x))
#define SetZF(x) (I.ZeroVal = (x))
#define SetPF(x) (I.ParityVal = (x))
#define SetSZPF_Byte(x) (I.SignVal=I.ZeroVal=I.ParityVal=(int8_t)(x))
#define SetSZPF_Word(x) (I.SignVal=I.ZeroVal=I.ParityVal=(int16_t)(x))
#define SetOFW_Add(x,y,z) (I.OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
#define SetOFB_Add(x,y,z) (I.OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
#define SetOFW_Sub(x,y,z) (I.OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
#define SetOFB_Sub(x,y,z) (I.OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
#define ADDB { uint32_t res=dst+src; SetCFB(res); SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(uint8_t)res; }
#define ADDW { uint32_t res=dst+src; SetCFW(res); SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(uint16_t)res; }
#define SUBB { uint32_t res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(uint8_t)res; }
#define SUBW { uint32_t res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(uint16_t)res; }
#define ORB dst|=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Byte(dst)
#define ORW dst|=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Word(dst)
#define ANDB dst&=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Byte(dst)
#define ANDW dst&=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Word(dst)
#define XORB dst^=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Byte(dst)
#define XORW dst^=src; I.CarryVal=I.OverVal=I.AuxVal=0; SetSZPF_Word(dst)
#define CF (I.CarryVal!=0)
#define SF (I.SignVal<0)
#define ZF (I.ZeroVal==0)
#define PF parity_table[(uint8_t)I.ParityVal]
#define AF (I.AuxVal!=0)
#define OF (I.OverVal!=0)
#define MD (I.MF!=0)
/************************************************************************/
#define SegBase(Seg) (I.sregs[Seg] << 4)
#define DefaultBase(Seg) ((seg_prefix && (Seg==DS || Seg==SS)) ? prefix_base : I.sregs[Seg] << 4)
#define GetMemB(Seg,Off) (/*nec_ICount-=((Off)&1)?1:0,*/ (uint8_t)cpu_readmem20((DefaultBase(Seg)+(Off))))
#define GetMemW(Seg,Off) (/*nec_ICount-=((Off)&1)?1:0,*/ (uint16_t) cpu_readmem20((DefaultBase(Seg)+(Off))) + (cpu_readmem20((DefaultBase(Seg)+((Off)+1)))<<8) )
#define PutMemB(Seg,Off,x) { /*nec_ICount-=((Off)&1)?1:0*/; cpu_writemem20((DefaultBase(Seg)+(Off)),(x)); }
#define PutMemW(Seg,Off,x) { /*nec_ICount-=((Off)&1)?1:0*/; PutMemB(Seg,Off,(x)&0xff); PutMemB(Seg,(Off)+1,(uint8_t)((x)>>8)); }
/* Todo: Remove these later - plus readword could overflow */
#define ReadByte(ea) (/*nec_ICount-=((ea)&1)?1:0,*/ (uint8_t)cpu_readmem20((ea)))
#define ReadWord(ea) (/*nec_ICount-=((ea)&1)?1:0,*/ cpu_readmem20((ea))+(cpu_readmem20(((ea)+1))<<8))
#define WriteByte(ea,val) { /*nec_ICount-=((ea)&1)?1:0*/; cpu_writemem20((ea),val); }
#define WriteWord(ea,val) { /*nec_ICount-=((ea)&1)?1:0*/; cpu_writemem20((ea),(uint8_t)(val)); cpu_writemem20(((ea)+1),(val)>>8); }
#define read_port(port) cpu_readport(port)
#define write_port(port,val) cpu_writeport(port,val)
#define FETCH (cpu_readop_arg((I.sregs[CS]<<4)+I.ip++))
#define FETCHOP (cpu_readop((I.sregs[CS]<<4)+I.ip++))
#define FETCHWORD(var) { var=cpu_readop_arg((((I.sregs[CS]<<4)+I.ip)))+(cpu_readop_arg((((I.sregs[CS]<<4)+I.ip+1)))<<8); I.ip+=2; }
#define PUSH(val) { I.regs.w[SP]-=2; WriteWord((((I.sregs[SS]<<4)+I.regs.w[SP])),val); }
#define POP(var) { var = ReadWord((((I.sregs[SS]<<4)+I.regs.w[SP]))); I.regs.w[SP]+=2; }
#define PEEK(addr) ((uint8_t)cpu_readop_arg(addr))
#define PEEKOP(addr) ((uint8_t)cpu_readop(addr))
#define GetModRM uint32_t ModRM=cpu_readop_arg((I.sregs[CS]<<4)+I.ip++)
/* Cycle count macros:
CLK - cycle count is the same on all processors
CLKS - cycle count differs between processors, list all counts
CLKW - cycle count for word read/write differs for odd/even source/destination address
CLKM - cycle count for reg/mem instructions
CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses
Prefetch & buswait time is not emulated.
Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated.
#define CLK(all) nec_ICount-=all
#define CLKS(v20,v30,v33) { const uint32_t ccount=(v20<<16)|(v30<<8)|v33; nec_ICount-=(ccount>>cpu_type)&0x7f; }
#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e) { const uint32_t ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_ICount-=(I.ip&1)?((ocount>>cpu_type)&0x7f):((ecount>>cpu_type)&0x7f); }
#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const uint32_t ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_ICount-=( ModRM >=0xc0 )?((ccount>>cpu_type)&0x7f):((mcount>>cpu_type)&0x7f); }
#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall) { const uint32_t ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_ICount-=vall; else nec_ICount-=(I.ip&1)?((ocount>>cpu_type)&0x7f):((ecount>>cpu_type)&0x7f); }
*/
#define CLKS(v20,v30,v33) { const uint32_t ccount=(v20<<16)|(v30<<8)|v33; nec_ICount-=(ccount>>cpu_type)&0x7f; }
#define CLK(all) nec_ICount-=all
#define CLKW(v30MZo,v30MZe) { nec_ICount-=(I.ip&1)?v30MZo:v30MZe; }
#define CLKM(v30MZm,v30MZ) { nec_ICount-=( ModRM >=0xc0 )?v30MZ:v30MZm; }
#define CLKR(v30MZo,v30MZe,vall) { if (ModRM >=0xc0) nec_ICount-=vall; else nec_ICount-=(I.ip&1)?v30MZo:v30MZe; }
#define CompressFlags() (uint16_t)(CF | (PF << 2) | (AF << 4) | (ZF << 6) \
| (SF << 7) | (I.TF << 8) | (I.IF << 9) \
| (I.DF << 10) | (OF << 11))
#define ExpandFlags(f) \
{ \
I.CarryVal = (f) & 1; \
I.ParityVal = !((f) & 4); \
I.AuxVal = (f) & 16; \
I.ZeroVal = !((f) & 64); \
I.SignVal = (f) & 128 ? -1 : 0; \
I.TF = ((f) & 256) == 256; \
I.IF = ((f) & 512) == 512; \
I.DF = ((f) & 1024) == 1024; \
I.OverVal = (f) & 2048; \
I.MF = ((f) & 0x8000) == 0x8000; \
}
#define IncWordReg(Reg) \
uint16_t tmp = (uint16_t)I.regs.w[Reg]; \
uint16_t tmp1 = tmp+1; \
I.OverVal = (tmp == 0x7fff); \
SetAF(tmp1,tmp,1); \
SetSZPF_Word(tmp1); \
I.regs.w[Reg]=tmp1
#define DecWordReg(Reg) \
uint16_t tmp = (uint16_t)I.regs.w[Reg]; \
uint16_t tmp1 = tmp-1; \
I.OverVal = (tmp == 0x8000); \
SetAF(tmp1,tmp,1); \
SetSZPF_Word(tmp1); \
I.regs.w[Reg]=tmp1
#define JMP(flag) \
int tmp = (int)((int8_t)FETCH); \
if (flag) \
{ \
I.ip = (uint16_t)(I.ip+tmp); \
nec_ICount-=3; \
return; \
}
#define ADJ4(param1,param2) \
if (AF || ((I.regs.b[AL] & 0xf) > 9)) \
{ \
int tmp; \
I.regs.b[AL] = tmp = I.regs.b[AL] + param1; \
I.AuxVal = 1; \
} \
if (CF || (I.regs.b[AL] > 0x9f)) \
{ \
I.regs.b[AL] += param2; \
I.CarryVal = 1; \
} \
SetSZPF_Byte(I.regs.b[AL])
#define ADJB(param1,param2) \
if (AF || ((I.regs.b[AL] & 0xf) > 9)) \
{ \
I.regs.b[AL] += param1; \
I.regs.b[AH] += param2; \
I.AuxVal = 1; \
I.CarryVal = 1; \
} \
else \
{ \
I.AuxVal = 0; \
I.CarryVal = 0; \
} \
I.regs.b[AL] &= 0x0F
#define BITOP_BYTE \
ModRM = FETCH; \
if (ModRM >= 0xc0) { \
tmp=I.regs.b[Mod_RM.RM.b[ModRM]]; \
} \
else { \
(*GetEA[ModRM])(); \
tmp=ReadByte(EA); \
}
#define BITOP_WORD \
ModRM = FETCH; \
if (ModRM >= 0xc0) { \
tmp=I.regs.w[Mod_RM.RM.w[ModRM]]; \
} \
else { \
(*GetEA[ModRM])(); \
tmp=ReadWord(EA); \
}
#define BIT_NOT \
if (tmp & (1<<tmp2)) \
tmp &= ~(1<<tmp2); \
else \
tmp |= (1<<tmp2)
#define XchgAWReg(Reg) \
uint16_t tmp; \
tmp = I.regs.w[Reg]; \
I.regs.w[Reg] = I.regs.w[AW]; \
I.regs.w[AW] = tmp
#define ROL_BYTE I.CarryVal = dst & 0x80; dst = (dst << 1)+CF
#define ROL_WORD I.CarryVal = dst & 0x8000; dst = (dst << 1)+CF
#define ROR_BYTE I.CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<7)
#define ROR_WORD I.CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<15)
#define ROLC_BYTE dst = (dst << 1) + CF; SetCFB(dst)
#define ROLC_WORD dst = (dst << 1) + CF; SetCFW(dst)
#define RORC_BYTE dst = (CF<<8)+dst; I.CarryVal = dst & 0x01; dst >>= 1
#define RORC_WORD dst = (CF<<16)+dst; I.CarryVal = dst & 0x01; dst >>= 1
#define SHL_BYTE(c) dst <<= c; SetCFB(dst); SetSZPF_Byte(dst); PutbackRMByte(ModRM,(uint8_t)dst)
#define SHL_WORD(c) dst <<= c; SetCFW(dst); SetSZPF_Word(dst); PutbackRMWord(ModRM,(uint16_t)dst)
#define SHR_BYTE(c) dst >>= c-1; I.CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(uint8_t)dst)
#define SHR_WORD(c) dst >>= c-1; I.CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(uint16_t)dst)
#define SHRA_BYTE(c) dst = ((int8_t)dst) >> (c-1); I.CarryVal = dst & 0x1; dst = ((int8_t)((uint8_t)dst)) >> 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(uint8_t)dst)
#define SHRA_WORD(c) dst = ((int16_t)dst) >> (c-1); I.CarryVal = dst & 0x1; dst = ((int16_t)((uint16_t)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(uint16_t)dst)
#define DIVUB \
uresult = I.regs.w[AW]; \
uresult2 = uresult % tmp; \
if ((uresult /= tmp) > 0xff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.b[AL] = uresult; \
I.regs.b[AH] = uresult2; \
}
#define DIVB \
result = (int16_t)I.regs.w[AW]; \
result2 = result % (int16_t)((int8_t)tmp); \
if ((result /= (int16_t)((int8_t)tmp)) > 0xff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.b[AL] = result; \
I.regs.b[AH] = result2; \
}
#define DIVUW \
uresult = (((uint32_t)I.regs.w[DW]) << 16) | I.regs.w[AW];\
uresult2 = uresult % tmp; \
if ((uresult /= tmp) > 0xffff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.w[AW]=uresult; \
I.regs.w[DW]=uresult2; \
}
#define DIVW \
result = ((uint32_t)I.regs.w[DW] << 16) + I.regs.w[AW]; \
result2 = result % (int32_t)((int16_t)tmp); \
if ((result /= (int32_t)((int16_t)tmp)) > 0xffff) { \
nec_interrupt(0,0); break; \
} else { \
I.regs.w[AW]=result; \
I.regs.w[DW]=result2; \
}
#define ADD4S { \
int i,v1,v2,result; \
int count = (I.regs.b[CL]+1)/2; \
uint16_t di = I.regs.w[IY]; \
uint16_t si = I.regs.w[IX]; \
I.ZeroVal = I.CarryVal = 0; \
for (i=0;i<count;i++) { \
tmp = GetMemB(DS, si); \
tmp2 = GetMemB(ES, di); \
v1 = (tmp>>4)*10 + (tmp&0xf); \
v2 = (tmp2>>4)*10 + (tmp2&0xf); \
result = v1+v2+I.CarryVal; \
I.CarryVal = result > 99 ? 1 : 0; \
result = result % 100; \
v1 = ((result/10)<<4) | (result % 10); \
PutMemB(ES, di,v1); \
if (v1) I.ZeroVal = 1; \
si++; \
di++; \
} \
}
#define SUB4S { \
int count = (I.regs.b[CL]+1)/2; \
int i,v1,v2,result; \
uint16_t di = I.regs.w[IY]; \
uint16_t si = I.regs.w[IX]; \
I.ZeroVal = I.CarryVal = 0; \
for (i=0;i<count;i++) { \
tmp = GetMemB(ES, di); \
tmp2 = GetMemB(DS, si); \
v1 = (tmp>>4)*10 + (tmp&0xf); \
v2 = (tmp2>>4)*10 + (tmp2&0xf); \
if (v1 < (v2+I.CarryVal)) { \
v1+=100; \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 1; \
} else { \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 0; \
} \
v1 = ((result/10)<<4) | (result % 10); \
PutMemB(ES, di,v1); \
if (v1) I.ZeroVal = 1; \
si++; \
di++; \
} \
}
#define CMP4S { \
int count = (I.regs.b[CL]+1)/2; \
int i,v1,v2,result; \
uint16_t di = I.regs.w[IY]; \
uint16_t si = I.regs.w[IX]; \
I.ZeroVal = I.CarryVal = 0; \
for (i=0;i<count;i++) { \
tmp = GetMemB(ES, di); \
tmp2 = GetMemB(DS, si); \
v1 = (tmp>>4)*10 + (tmp&0xf); \
v2 = (tmp2>>4)*10 + (tmp2&0xf); \
if (v1 < (v2+I.CarryVal)) { \
v1+=100; \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 1; \
} else { \
result = v1-(v2+I.CarryVal); \
I.CarryVal = 0; \
} \
v1 = ((result/10)<<4) | (result % 10); \
if (v1) I.ZeroVal = 1; \
si++; \
di++; \
} \
}
#endif /* __NEC_H_ */

1270
source/nec/nec_debugger.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,11 @@
/******************************************************************************
* NewOswan
* necea.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
static uint32_t EA; static uint32_t EA;
static uint16_t EO; static uint16_t EO;
@@ -5,194 +13,206 @@ static uint16_t E16;
static unsigned EA_000(void) static unsigned EA_000(void)
{ {
EO=I.regs.w[BW]+I.regs.w[IX]; EO = I.regs.w[BW] + I.regs.w[IX];
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_001(void) static unsigned EA_001(void)
{ {
EO=I.regs.w[BW]+I.regs.w[IY]; EO = I.regs.w[BW] + I.regs.w[IY];
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_002(void) static unsigned EA_002(void)
{ {
EO=I.regs.w[BP]+I.regs.w[IX]; EO = I.regs.w[BP] + I.regs.w[IX];
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_003(void) static unsigned EA_003(void)
{ {
EO=I.regs.w[BP]+I.regs.w[IY]; EO = I.regs.w[BP] + I.regs.w[IY];
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_004(void) static unsigned EA_004(void)
{ {
EO=I.regs.w[IX]; EO = I.regs.w[IX];
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_005(void) static unsigned EA_005(void)
{ {
EO=I.regs.w[IY]; EO = I.regs.w[IY];
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_006(void) static unsigned EA_006(void)
{ {
EO=FETCH; EO = FETCH;
EO+=FETCH<<8; EO += FETCH << 8;
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_007(void) static unsigned EA_007(void)
{ {
EO=I.regs.w[BW]; EO = I.regs.w[BW];
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_100(void) static unsigned EA_100(void)
{ {
EO=(I.regs.w[BW]+I.regs.w[IX]+(int8_t)FETCH); EO = (I.regs.w[BW] + I.regs.w[IX] + (int8_t)FETCH);
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_101(void) static unsigned EA_101(void)
{ {
EO=(I.regs.w[BW]+I.regs.w[IY]+(int8_t)FETCH); EO = (I.regs.w[BW] + I.regs.w[IY] + (int8_t)FETCH);
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_102(void) static unsigned EA_102(void)
{ {
EO=(I.regs.w[BP]+I.regs.w[IX]+(int8_t)FETCH); EO = (I.regs.w[BP] + I.regs.w[IX] + (int8_t)FETCH);
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_103(void) static unsigned EA_103(void)
{ {
EO=(I.regs.w[BP]+I.regs.w[IY]+(int8_t)FETCH); EO = (I.regs.w[BP] + I.regs.w[IY] + (int8_t)FETCH);
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_104(void) static unsigned EA_104(void)
{ {
EO=(I.regs.w[IX]+(int8_t)FETCH); EO = (I.regs.w[IX] + (int8_t)FETCH);
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_105(void) static unsigned EA_105(void)
{ {
EO=(I.regs.w[IY]+(int8_t)FETCH); EO = (I.regs.w[IY] + (int8_t)FETCH);
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_106(void) static unsigned EA_106(void)
{ {
EO=(I.regs.w[BP]+(int8_t)FETCH); EO = (I.regs.w[BP] + (int8_t)FETCH);
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_107(void) static unsigned EA_107(void)
{ {
EO=(I.regs.w[BW]+(int8_t)FETCH); EO = (I.regs.w[BW] + (int8_t)FETCH);
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_200(void) static unsigned EA_200(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[BW]+I.regs.w[IX]+(int16_t)E16; EO = I.regs.w[BW] + I.regs.w[IX] + (int16_t)E16;
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_201(void) static unsigned EA_201(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[BW]+I.regs.w[IY]+(int16_t)E16; EO = I.regs.w[BW] + I.regs.w[IY] + (int16_t)E16;
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_202(void) static unsigned EA_202(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[BP]+I.regs.w[IX]+(int16_t)E16; EO = I.regs.w[BP] + I.regs.w[IX] + (int16_t)E16;
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_203(void) static unsigned EA_203(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[BP]+I.regs.w[IY]+(int16_t)E16; EO = I.regs.w[BP] + I.regs.w[IY] + (int16_t)E16;
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_204(void) static unsigned EA_204(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[IX]+(int16_t)E16; EO = I.regs.w[IX] + (int16_t)E16;
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_205(void) static unsigned EA_205(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[IY]+(int16_t)E16; EO = I.regs.w[IY] + (int16_t)E16;
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned EA_206(void) static unsigned EA_206(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[BP]+(int16_t)E16; EO = I.regs.w[BP] + (int16_t)E16;
EA=DefaultBase(SS)+EO; EA = DefaultBase(SS) + EO;
return EA; return EA;
} }
static unsigned EA_207(void) static unsigned EA_207(void)
{ {
E16=FETCH; E16 = FETCH;
E16+=FETCH<<8; E16 += FETCH << 8;
EO=I.regs.w[BW]+(int16_t)E16; EO = I.regs.w[BW] + (int16_t)E16;
EA=DefaultBase(DS)+EO; EA = DefaultBase(DS) + EO;
return EA; return EA;
} }
static unsigned (*GetEA[192])(void)= static unsigned (*GetEA[192])(void) =
{ {
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103, EA_104, EA_105,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203, EA_204, EA_205,
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203,
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201,
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, };
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207
};

View File

@@ -1,3 +1,12 @@
/******************************************************************************
* NewOswan
* necinstr.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
static void i_add_br8(void); static void i_add_br8(void);
static void i_add_wr16(void); static void i_add_wr16(void);
static void i_add_r8b(void); static void i_add_r8b(void);
@@ -247,261 +256,261 @@ static void i_ffpre(void);
static void i_wait(void); static void i_wait(void);
void (*nec_instruction[256])(void) = void (*nec_instruction[256])(void) =
{ {
i_add_br8, /* 0x00 */ i_add_br8, /* 0x00 */
i_add_wr16, /* 0x01 */ i_add_wr16, /* 0x01 */
i_add_r8b, /* 0x02 */ i_add_r8b, /* 0x02 */
i_add_r16w, /* 0x03 */ i_add_r16w, /* 0x03 */
i_add_ald8, /* 0x04 */ i_add_ald8, /* 0x04 */
i_add_axd16, /* 0x05 */ i_add_axd16, /* 0x05 */
i_push_es, /* 0x06 */ i_push_es, /* 0x06 */
i_pop_es, /* 0x07 */ i_pop_es, /* 0x07 */
i_or_br8, /* 0x08 */ i_or_br8, /* 0x08 */
i_or_wr16, /* 0x09 */ i_or_wr16, /* 0x09 */
i_or_r8b, /* 0x0a */ i_or_r8b, /* 0x0a */
i_or_r16w, /* 0x0b */ i_or_r16w, /* 0x0b */
i_or_ald8, /* 0x0c */ i_or_ald8, /* 0x0c */
i_or_axd16, /* 0x0d */ i_or_axd16, /* 0x0d */
i_push_cs, /* 0x0e */ i_push_cs, /* 0x0e */
i_pre_nec /* 0x0f */, i_pre_nec, /* 0x0f */
i_adc_br8, /* 0x10 */ i_adc_br8, /* 0x10 */
i_adc_wr16, /* 0x11 */ i_adc_wr16, /* 0x11 */
i_adc_r8b, /* 0x12 */ i_adc_r8b, /* 0x12 */
i_adc_r16w, /* 0x13 */ i_adc_r16w, /* 0x13 */
i_adc_ald8, /* 0x14 */ i_adc_ald8, /* 0x14 */
i_adc_axd16, /* 0x15 */ i_adc_axd16, /* 0x15 */
i_push_ss, /* 0x16 */ i_push_ss, /* 0x16 */
i_pop_ss, /* 0x17 */ i_pop_ss, /* 0x17 */
i_sbb_br8, /* 0x18 */ i_sbb_br8, /* 0x18 */
i_sbb_wr16, /* 0x19 */ i_sbb_wr16, /* 0x19 */
i_sbb_r8b, /* 0x1a */ i_sbb_r8b, /* 0x1a */
i_sbb_r16w, /* 0x1b */ i_sbb_r16w, /* 0x1b */
i_sbb_ald8, /* 0x1c */ i_sbb_ald8, /* 0x1c */
i_sbb_axd16, /* 0x1d */ i_sbb_axd16, /* 0x1d */
i_push_ds, /* 0x1e */ i_push_ds, /* 0x1e */
i_pop_ds, /* 0x1f */ i_pop_ds, /* 0x1f */
i_and_br8, /* 0x20 */ i_and_br8, /* 0x20 */
i_and_wr16, /* 0x21 */ i_and_wr16, /* 0x21 */
i_and_r8b, /* 0x22 */ i_and_r8b, /* 0x22 */
i_and_r16w, /* 0x23 */ i_and_r16w, /* 0x23 */
i_and_ald8, /* 0x24 */ i_and_ald8, /* 0x24 */
i_and_axd16, /* 0x25 */ i_and_axd16, /* 0x25 */
i_es, /* 0x26 */ i_es, /* 0x26 */
i_daa, /* 0x27 */ i_daa, /* 0x27 */
i_sub_br8, /* 0x28 */ i_sub_br8, /* 0x28 */
i_sub_wr16, /* 0x29 */ i_sub_wr16, /* 0x29 */
i_sub_r8b, /* 0x2a */ i_sub_r8b, /* 0x2a */
i_sub_r16w, /* 0x2b */ i_sub_r16w, /* 0x2b */
i_sub_ald8, /* 0x2c */ i_sub_ald8, /* 0x2c */
i_sub_axd16, /* 0x2d */ i_sub_axd16, /* 0x2d */
i_cs, /* 0x2e */ i_cs, /* 0x2e */
i_das, /* 0x2f */ i_das, /* 0x2f */
i_xor_br8, /* 0x30 */ i_xor_br8, /* 0x30 */
i_xor_wr16, /* 0x31 */ i_xor_wr16, /* 0x31 */
i_xor_r8b, /* 0x32 */ i_xor_r8b, /* 0x32 */
i_xor_r16w, /* 0x33 */ i_xor_r16w, /* 0x33 */
i_xor_ald8, /* 0x34 */ i_xor_ald8, /* 0x34 */
i_xor_axd16, /* 0x35 */ i_xor_axd16, /* 0x35 */
i_ss, /* 0x36 */ i_ss, /* 0x36 */
i_aaa, /* 0x37 */ i_aaa, /* 0x37 */
i_cmp_br8, /* 0x38 */ i_cmp_br8, /* 0x38 */
i_cmp_wr16, /* 0x39 */ i_cmp_wr16, /* 0x39 */
i_cmp_r8b, /* 0x3a */ i_cmp_r8b, /* 0x3a */
i_cmp_r16w, /* 0x3b */ i_cmp_r16w, /* 0x3b */
i_cmp_ald8, /* 0x3c */ i_cmp_ald8, /* 0x3c */
i_cmp_axd16, /* 0x3d */ i_cmp_axd16, /* 0x3d */
i_ds, /* 0x3e */ i_ds, /* 0x3e */
i_aas, /* 0x3f */ i_aas, /* 0x3f */
i_inc_ax, /* 0x40 */ i_inc_ax, /* 0x40 */
i_inc_cx, /* 0x41 */ i_inc_cx, /* 0x41 */
i_inc_dx, /* 0x42 */ i_inc_dx, /* 0x42 */
i_inc_bx, /* 0x43 */ i_inc_bx, /* 0x43 */
i_inc_sp, /* 0x44 */ i_inc_sp, /* 0x44 */
i_inc_bp, /* 0x45 */ i_inc_bp, /* 0x45 */
i_inc_si, /* 0x46 */ i_inc_si, /* 0x46 */
i_inc_di, /* 0x47 */ i_inc_di, /* 0x47 */
i_dec_ax, /* 0x48 */ i_dec_ax, /* 0x48 */
i_dec_cx, /* 0x49 */ i_dec_cx, /* 0x49 */
i_dec_dx, /* 0x4a */ i_dec_dx, /* 0x4a */
i_dec_bx, /* 0x4b */ i_dec_bx, /* 0x4b */
i_dec_sp, /* 0x4c */ i_dec_sp, /* 0x4c */
i_dec_bp, /* 0x4d */ i_dec_bp, /* 0x4d */
i_dec_si, /* 0x4e */ i_dec_si, /* 0x4e */
i_dec_di, /* 0x4f */ i_dec_di, /* 0x4f */
i_push_ax, /* 0x50 */ i_push_ax, /* 0x50 */
i_push_cx, /* 0x51 */ i_push_cx, /* 0x51 */
i_push_dx, /* 0x52 */ i_push_dx, /* 0x52 */
i_push_bx, /* 0x53 */ i_push_bx, /* 0x53 */
i_push_sp, /* 0x54 */ i_push_sp, /* 0x54 */
i_push_bp, /* 0x55 */ i_push_bp, /* 0x55 */
i_push_si, /* 0x56 */ i_push_si, /* 0x56 */
i_push_di, /* 0x57 */ i_push_di, /* 0x57 */
i_pop_ax, /* 0x58 */ i_pop_ax, /* 0x58 */
i_pop_cx, /* 0x59 */ i_pop_cx, /* 0x59 */
i_pop_dx, /* 0x5a */ i_pop_dx, /* 0x5a */
i_pop_bx, /* 0x5b */ i_pop_bx, /* 0x5b */
i_pop_sp, /* 0x5c */ i_pop_sp, /* 0x5c */
i_pop_bp, /* 0x5d */ i_pop_bp, /* 0x5d */
i_pop_si, /* 0x5e */ i_pop_si, /* 0x5e */
i_pop_di, /* 0x5f */ i_pop_di, /* 0x5f */
i_pusha, /* 0x60 */ i_pusha, /* 0x60 */
i_popa, /* 0x61 */ i_popa, /* 0x61 */
i_chkind, /* 0x62 */ i_chkind, /* 0x62 */
i_invalid, /* 0x63 */ i_invalid, /* 0x63 */
i_repnc, /* 0x64 */ i_repnc, /* 0x64 */
i_repc, /* 0x65 */ i_repc, /* 0x65 */
i_invalid, /* 0x66 */ i_invalid, /* 0x66 */
i_invalid, /* 0x67 */ i_invalid, /* 0x67 */
i_push_d16, /* 0x68 */ i_push_d16, /* 0x68 */
i_imul_d16, /* 0x69 */ i_imul_d16, /* 0x69 */
i_push_d8, /* 0x6a */ i_push_d8, /* 0x6a */
i_imul_d8, /* 0x6b */ i_imul_d8, /* 0x6b */
i_insb, /* 0x6c */ i_insb, /* 0x6c */
i_insw, /* 0x6d */ i_insw, /* 0x6d */
i_outsb, /* 0x6e */ i_outsb, /* 0x6e */
i_outsw, /* 0x6f */ i_outsw, /* 0x6f */
i_jo, /* 0x70 */ i_jo, /* 0x70 */
i_jno, /* 0x71 */ i_jno, /* 0x71 */
i_jc, /* 0x72 */ i_jc, /* 0x72 */
i_jnc, /* 0x73 */ i_jnc, /* 0x73 */
i_jz, /* 0x74 */ i_jz, /* 0x74 */
i_jnz, /* 0x75 */ i_jnz, /* 0x75 */
i_jce, /* 0x76 */ i_jce, /* 0x76 */
i_jnce, /* 0x77 */ i_jnce, /* 0x77 */
i_js, /* 0x78 */ i_js, /* 0x78 */
i_jns, /* 0x79 */ i_jns, /* 0x79 */
i_jp, /* 0x7a */ i_jp, /* 0x7a */
i_jnp, /* 0x7b */ i_jnp, /* 0x7b */
i_jl, /* 0x7c */ i_jl, /* 0x7c */
i_jnl, /* 0x7d */ i_jnl, /* 0x7d */
i_jle, /* 0x7e */ i_jle, /* 0x7e */
i_jnle, /* 0x7f */ i_jnle, /* 0x7f */
i_80pre, /* 0x80 */ i_80pre, /* 0x80 */
i_81pre, /* 0x81 */ i_81pre, /* 0x81 */
i_82pre, /* 0x82 */ i_82pre, /* 0x82 */
i_83pre, /* 0x83 */ i_83pre, /* 0x83 */
i_test_br8, /* 0x84 */ i_test_br8, /* 0x84 */
i_test_wr16, /* 0x85 */ i_test_wr16, /* 0x85 */
i_xchg_br8, /* 0x86 */ i_xchg_br8, /* 0x86 */
i_xchg_wr16, /* 0x87 */ i_xchg_wr16, /* 0x87 */
i_mov_br8, /* 0x88 */ i_mov_br8, /* 0x88 */
i_mov_wr16, /* 0x89 */ i_mov_wr16, /* 0x89 */
i_mov_r8b, /* 0x8a */ i_mov_r8b, /* 0x8a */
i_mov_r16w, /* 0x8b */ i_mov_r16w, /* 0x8b */
i_mov_wsreg, /* 0x8c */ i_mov_wsreg, /* 0x8c */
i_lea, /* 0x8d */ i_lea, /* 0x8d */
i_mov_sregw, /* 0x8e */ i_mov_sregw, /* 0x8e */
i_popw, /* 0x8f */ i_popw, /* 0x8f */
i_nop, /* 0x90 */ i_nop, /* 0x90 */
i_xchg_axcx, /* 0x91 */ i_xchg_axcx, /* 0x91 */
i_xchg_axdx, /* 0x92 */ i_xchg_axdx, /* 0x92 */
i_xchg_axbx, /* 0x93 */ i_xchg_axbx, /* 0x93 */
i_xchg_axsp, /* 0x94 */ i_xchg_axsp, /* 0x94 */
i_xchg_axbp, /* 0x95 */ i_xchg_axbp, /* 0x95 */
i_xchg_axsi, /* 0x97 */ i_xchg_axsi, /* 0x97 */
i_xchg_axdi, /* 0x97 */ i_xchg_axdi, /* 0x97 */
i_cbw, /* 0x98 */ i_cbw, /* 0x98 */
i_cwd, /* 0x99 */ i_cwd, /* 0x99 */
i_call_far, /* 0x9a */ i_call_far, /* 0x9a */
i_wait, /* 0x9b */ i_wait, /* 0x9b */
i_pushf, /* 0x9c */ i_pushf, /* 0x9c */
i_popf, /* 0x9d */ i_popf, /* 0x9d */
i_sahf, /* 0x9e */ i_sahf, /* 0x9e */
i_lahf, /* 0x9f */ i_lahf, /* 0x9f */
i_mov_aldisp, /* 0xa0 */ i_mov_aldisp, /* 0xa0 */
i_mov_axdisp, /* 0xa1 */ i_mov_axdisp, /* 0xa1 */
i_mov_dispal, /* 0xa2 */ i_mov_dispal, /* 0xa2 */
i_mov_dispax, /* 0xa3 */ i_mov_dispax, /* 0xa3 */
i_movsb, /* 0xa4 */ i_movsb, /* 0xa4 */
i_movsw, /* 0xa5 */ i_movsw, /* 0xa5 */
i_cmpsb, /* 0xa6 */ i_cmpsb, /* 0xa6 */
i_cmpsw, /* 0xa7 */ i_cmpsw, /* 0xa7 */
i_test_ald8, /* 0xa8 */ i_test_ald8, /* 0xa8 */
i_test_axd16, /* 0xa9 */ i_test_axd16, /* 0xa9 */
i_stosb, /* 0xaa */ i_stosb, /* 0xaa */
i_stosw, /* 0xab */ i_stosw, /* 0xab */
i_lodsb, /* 0xac */ i_lodsb, /* 0xac */
i_lodsw, /* 0xad */ i_lodsw, /* 0xad */
i_scasb, /* 0xae */ i_scasb, /* 0xae */
i_scasw, /* 0xaf */ i_scasw, /* 0xaf */
i_mov_ald8, /* 0xb0 */ i_mov_ald8, /* 0xb0 */
i_mov_cld8, /* 0xb1 */ i_mov_cld8, /* 0xb1 */
i_mov_dld8, /* 0xb2 */ i_mov_dld8, /* 0xb2 */
i_mov_bld8, /* 0xb3 */ i_mov_bld8, /* 0xb3 */
i_mov_ahd8, /* 0xb4 */ i_mov_ahd8, /* 0xb4 */
i_mov_chd8, /* 0xb5 */ i_mov_chd8, /* 0xb5 */
i_mov_dhd8, /* 0xb6 */ i_mov_dhd8, /* 0xb6 */
i_mov_bhd8, /* 0xb7 */ i_mov_bhd8, /* 0xb7 */
i_mov_axd16, /* 0xb8 */ i_mov_axd16, /* 0xb8 */
i_mov_cxd16, /* 0xb9 */ i_mov_cxd16, /* 0xb9 */
i_mov_dxd16, /* 0xba */ i_mov_dxd16, /* 0xba */
i_mov_bxd16, /* 0xbb */ i_mov_bxd16, /* 0xbb */
i_mov_spd16, /* 0xbc */ i_mov_spd16, /* 0xbc */
i_mov_bpd16, /* 0xbd */ i_mov_bpd16, /* 0xbd */
i_mov_sid16, /* 0xbe */ i_mov_sid16, /* 0xbe */
i_mov_did16, /* 0xbf */ i_mov_did16, /* 0xbf */
i_rotshft_bd8, /* 0xc0 */ i_rotshft_bd8, /* 0xc0 */
i_rotshft_wd8, /* 0xc1 */ i_rotshft_wd8, /* 0xc1 */
i_ret_d16, /* 0xc2 */ i_ret_d16, /* 0xc2 */
i_ret, /* 0xc3 */ i_ret, /* 0xc3 */
i_les_dw, /* 0xc4 */ i_les_dw, /* 0xc4 */
i_lds_dw, /* 0xc5 */ i_lds_dw, /* 0xc5 */
i_mov_bd8, /* 0xc6 */ i_mov_bd8, /* 0xc6 */
i_mov_wd16, /* 0xc7 */ i_mov_wd16, /* 0xc7 */
i_enter, /* 0xc8 */ i_enter, /* 0xc8 */
i_leave, /* 0xc9 */ i_leave, /* 0xc9 */
i_retf_d16, /* 0xca */ i_retf_d16, /* 0xca */
i_retf, /* 0xcb */ i_retf, /* 0xcb */
i_int3, /* 0xcc */ i_int3, /* 0xcc */
i_int, /* 0xcd */ i_int, /* 0xcd */
i_into, /* 0xce */ i_into, /* 0xce */
i_iret, /* 0xcf */ i_iret, /* 0xcf */
i_rotshft_b, /* 0xd0 */ i_rotshft_b, /* 0xd0 */
i_rotshft_w, /* 0xd1 */ i_rotshft_w, /* 0xd1 */
i_rotshft_bcl, /* 0xd2 */ i_rotshft_bcl, /* 0xd2 */
i_rotshft_wcl, /* 0xd3 */ i_rotshft_wcl, /* 0xd3 */
i_aam, /* 0xd4 */ i_aam, /* 0xd4 */
i_aad, /* 0xd5 */ i_aad, /* 0xd5 */
i_setalc, i_setalc, /* 0xd6 */
i_trans, /* 0xd7 */ i_trans, /* 0xd7 */
i_fpo, /* 0xd8 */ i_fpo, /* 0xd8 */
i_fpo, /* 0xd9 */ i_fpo, /* 0xd9 */
i_fpo, /* 0xda */ i_fpo, /* 0xda */
i_fpo, /* 0xdb */ i_fpo, /* 0xdb */
i_fpo, /* 0xdc */ i_fpo, /* 0xdc */
i_fpo, /* 0xdd */ i_fpo, /* 0xdd */
i_fpo, /* 0xde */ i_fpo, /* 0xde */
i_fpo, /* 0xdf */ i_fpo, /* 0xdf */
i_loopne, /* 0xe0 */ i_loopne, /* 0xe0 */
i_loope, /* 0xe1 */ i_loope, /* 0xe1 */
i_loop, /* 0xe2 */ i_loop, /* 0xe2 */
i_jcxz, /* 0xe3 */ i_jcxz, /* 0xe3 */
i_inal, /* 0xe4 */ i_inal, /* 0xe4 */
i_inax, /* 0xe5 */ i_inax, /* 0xe5 */
i_outal, /* 0xe6 */ i_outal, /* 0xe6 */
i_outax, /* 0xe7 */ i_outax, /* 0xe7 */
i_call_d16, /* 0xe8 */ i_call_d16, /* 0xe8 */
i_jmp_d16, /* 0xe9 */ i_jmp_d16, /* 0xe9 */
i_jmp_far, /* 0xea */ i_jmp_far, /* 0xea */
i_jmp_d8, /* 0xeb */ i_jmp_d8, /* 0xeb */
i_inaldx, /* 0xec */ i_inaldx, /* 0xec */
i_inaxdx, /* 0xed */ i_inaxdx, /* 0xed */
i_outdxal, /* 0xee */ i_outdxal, /* 0xee */
i_outdxax, /* 0xef */ i_outdxax, /* 0xef */
i_lock, /* 0xf0 */ i_lock, /* 0xf0 */
i_invalid, /* 0xf1 */ i_invalid, /* 0xf1 */
i_repne, /* 0xf2 */ i_repne, /* 0xf2 */
i_repe, /* 0xf3 */ i_repe, /* 0xf3 */
i_hlt, /* 0xf4 */ i_hlt, /* 0xf4 */
i_cmc, /* 0xf5 */ i_cmc, /* 0xf5 */
i_f6pre, /* 0xf6 */ i_f6pre, /* 0xf6 */
i_f7pre, /* 0xf7 */ i_f7pre, /* 0xf7 */
i_clc, /* 0xf8 */ i_clc, /* 0xf8 */
i_stc, /* 0xf9 */ i_stc, /* 0xf9 */
i_di, /* 0xfa */ i_di, /* 0xfa */
i_ei, /* 0xfb */ i_ei, /* 0xfb */
i_cld, /* 0xfc */ i_cld, /* 0xfc */
i_std, /* 0xfd */ i_std, /* 0xfd */
i_fepre, /* 0xfe */ i_fepre, /* 0xfe */
i_ffpre /* 0xff */ i_ffpre /* 0xff */
}; };

View File

@@ -1,77 +0,0 @@
/* ASG 971222 -- rewrote this interface */
#ifndef __NECITRF_H_
#define __NECITRF_H_
enum
{
NEC_IP=1, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY,
NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS,
NEC_VECTOR, NEC_PENDING, NEC_NMI_STATE, NEC_IRQ_STATE
};
/* Public variables */
extern int nec_ICount;
/* Public functions */
/*
#define v20_ICount nec_ICount
extern void v20_init(void);
extern void v20_reset(void *param);
extern void v20_exit(void);
extern int v20_execute(int cycles);
extern unsigned v20_get_context(void *dst);
extern void v20_set_context(void *src);
extern unsigned v20_get_reg(int regnum);
extern void v20_set_reg(int regnum, unsigned val);
extern void v20_set_irq_line(int irqline, int state);
extern void v20_set_irq_callback(int (*callback)(int irqline));
extern const char *v20_info(void *context, int regnum);
extern unsigned v20_dasm(char *buffer, unsigned pc);
#define v30_ICount nec_ICount
extern void v30_init(void);
extern void v30_reset(void *param);
extern void v30_exit(void);
extern int v30_execute(int cycles);
extern unsigned v30_get_context(void *dst);
extern void v30_set_context(void *src);
extern unsigned v30_get_reg(int regnum);
extern void v30_set_reg(int regnum, unsigned val);
extern void v30_set_irq_line(int irqline, int state);
extern void v30_set_irq_callback(int (*callback)(int irqline));
extern const char *v30_info(void *context, int regnum);
extern unsigned v30_dasm(char *buffer, unsigned pc);
#define v33_ICount nec_ICount
extern void v33_init(void);
extern void v33_reset(void *param);
extern void v33_exit(void);
extern int v33_execute(int cycles);
extern unsigned v33_get_context(void *dst);
extern void v33_set_context(void *src);
extern unsigned v33_get_reg(int regnum);
extern void v33_set_reg(int regnum, unsigned val);
extern void v33_set_irq_line(int irqline, int state);
extern void v33_set_irq_callback(int (*callback)(int irqline));
extern const char *v33_info(void *context, int regnum);
extern unsigned v33_dasm(char *buffer, unsigned pc);
*/
void nec_set_irq_line(int irqline, int state);
void nec_set_reg(int regnum, uint32_t val);
int nec_execute(int cycles);
unsigned nec_get_reg(int regnum);
void nec_reset (void *param);
void nec_int(uint16_t vector);
uint8_t cpu_readport(uint8_t);
void cpu_writeport(uint32_t, uint8_t);
#define cpu_readop cpu_readmem20
#define cpu_readop_arg cpu_readmem20
void cpu_writemem20(uint32_t, uint8_t);
uint8_t cpu_readmem20(uint32_t);
#endif /* __NECITRF_H_ */

View File

@@ -1,107 +1,116 @@
/******************************************************************************
* NewOswan
* necmodrm.h:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
static struct static struct
{ {
struct struct
{ {
WREGS w[256]; WREGS w[256];
BREGS b[256]; BREGS b[256];
} reg; } reg;
struct struct
{ {
WREGS w[256]; WREGS w[256];
BREGS b[256]; BREGS b[256];
} RM; } RM;
} Mod_RM; } Mod_RM;
#define RegWord(ModRM) I.regs.w[Mod_RM.reg.w[ModRM]] #define RegWord(ModRM) I.regs.w[Mod_RM.reg.w[ModRM]]
#define RegByte(ModRM) I.regs.b[Mod_RM.reg.b[ModRM]] #define RegByte(ModRM) I.regs.b[Mod_RM.reg.b[ModRM]]
#define GetRMWord(ModRM) \ #define GetRMWord(ModRM) \
((ModRM) >= 0xc0 ? I.regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(), ReadWord( EA ) )) ((ModRM) >= 0xc0 ? I.regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(), ReadWord( EA ) ))
#define PutbackRMWord(ModRM,val) \ #define PutbackRMWord(ModRM, val) \
{ \ { \
if (ModRM >= 0xc0) I.regs.w[Mod_RM.RM.w[ModRM]]=val; \ if (ModRM >= 0xc0) I.regs.w[Mod_RM.RM.w[ModRM]]=val; \
else WriteWord(EA,val); \ else WriteWord(EA,val); \
} }
#define GetnextRMWord ReadWord((EA&0xf0000)|((EA+2)&0xffff)) #define GetnextRMWord ReadWord((EA&0xf0000)|((EA+2)&0xffff))
#define PutRMWord(ModRM,val) \ #define PutRMWord(ModRM, val) \
{ \ { \
if (ModRM >= 0xc0) \ if (ModRM >= 0xc0) \
I.regs.w[Mod_RM.RM.w[ModRM]]=val; \ I.regs.w[Mod_RM.RM.w[ModRM]]=val; \
else { \ else { \
(*GetEA[ModRM])(); \ (*GetEA[ModRM])(); \
WriteWord( EA ,val); \ WriteWord( EA ,val); \
} \ } \
} }
#define PutImmRMWord(ModRM) \ #define PutImmRMWord(ModRM) \
{ \ { \
int16_t val; \ int16_t val; \
if (ModRM >= 0xc0) \ if (ModRM >= 0xc0) \
FETCHWORD(I.regs.w[Mod_RM.RM.w[ModRM]]) \ FETCHWORD(I.regs.w[Mod_RM.RM.w[ModRM]]) \
else { \ else { \
(*GetEA[ModRM])(); \ (*GetEA[ModRM])(); \
FETCHWORD(val) \ FETCHWORD(val) \
WriteWord( EA , val); \ WriteWord( EA , val); \
} \ } \
} }
#define GetRMByte(ModRM) \ #define GetRMByte(ModRM) \
((ModRM) >= 0xc0 ? I.regs.b[Mod_RM.RM.b[ModRM]] : ReadByte( (*GetEA[ModRM])() )) ((ModRM) >= 0xc0 ? I.regs.b[Mod_RM.RM.b[ModRM]] : ReadByte( (*GetEA[ModRM])() ))
#define PutRMByte(ModRM,val) \ #define PutRMByte(ModRM, val) \
{ \ { \
if (ModRM >= 0xc0) \ if (ModRM >= 0xc0) \
I.regs.b[Mod_RM.RM.b[ModRM]]=val; \ I.regs.b[Mod_RM.RM.b[ModRM]]=val; \
else \ else \
WriteByte( (*GetEA[ModRM])() ,val); \ WriteByte( (*GetEA[ModRM])() ,val); \
} }
#define PutImmRMByte(ModRM) \ #define PutImmRMByte(ModRM) \
{ \ { \
if (ModRM >= 0xc0) \ if (ModRM >= 0xc0) \
I.regs.b[Mod_RM.RM.b[ModRM]]=FETCH; \ I.regs.b[Mod_RM.RM.b[ModRM]]=FETCH; \
else { \ else { \
(*GetEA[ModRM])(); \ (*GetEA[ModRM])(); \
WriteByte( EA , FETCH ); \ WriteByte( EA , FETCH ); \
} \ } \
} }
#define PutbackRMByte(ModRM,val) \ #define PutbackRMByte(ModRM, val) \
{ \ { \
if (ModRM >= 0xc0) \ if (ModRM >= 0xc0) \
I.regs.b[Mod_RM.RM.b[ModRM]]=val; \ I.regs.b[Mod_RM.RM.b[ModRM]]=val; \
else \ else \
WriteByte(EA,val); \ WriteByte(EA,val); \
} }
#define DEF_br8 \ #define DEF_br8 \
uint32_t ModRM = FETCH,src,dst; \ uint32_t ModRM = FETCH,src,dst; \
src = RegByte(ModRM); \ src = RegByte(ModRM); \
dst = GetRMByte(ModRM) dst = GetRMByte(ModRM)
#define DEF_wr16 \ #define DEF_wr16 \
uint32_t ModRM = FETCH,src,dst; \ uint32_t ModRM = FETCH,src,dst; \
src = RegWord(ModRM); \ src = RegWord(ModRM); \
dst = GetRMWord(ModRM) dst = GetRMWord(ModRM)
#define DEF_r8b \ #define DEF_r8b \
uint32_t ModRM = FETCH,src,dst; \ uint32_t ModRM = FETCH,src,dst; \
dst = RegByte(ModRM); \ dst = RegByte(ModRM); \
src = GetRMByte(ModRM) src = GetRMByte(ModRM)
#define DEF_r16w \ #define DEF_r16w \
uint32_t ModRM = FETCH,src,dst; \ uint32_t ModRM = FETCH,src,dst; \
dst = RegWord(ModRM); \ dst = RegWord(ModRM); \
src = GetRMWord(ModRM) src = GetRMWord(ModRM)
#define DEF_ald8 \ #define DEF_ald8 \
uint32_t src = FETCH; \ uint32_t src = FETCH; \
uint32_t dst = I.regs.b[AL] uint32_t dst = I.regs.b[AL]
#define DEF_axd16 \ #define DEF_axd16 \
uint32_t src = FETCH; \ uint32_t src = FETCH; \
uint32_t dst = I.regs.w[AW]; \ uint32_t dst = I.regs.w[AW]; \
src += (FETCH << 8) src += (FETCH << 8)

1335
source/peripherals/audio.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
/*******************************************************************************
* NewOswan
* buttons.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#if 0
case 0xb5:
read
w1 = ws_ioRam[0xb5];
if (w1 & 0x40)
{
w2 = 0x00;
w2 = (ws_key_start << 1) | (ws_key_button_a << 2) | (ws_key_button_b << 3);
retVal = (uint8_t)((w1 & 0xf0) | w2);
break;
}
if (w1 & 0x20)
{
w2 = 0x00;
w2 = (ws_key_x1 << 0) | (ws_key_x2 << 1) | (ws_key_x3 << 2) | (ws_key_x4 << 3);
retVal = (uint8_t)((w1 & 0xf0) | w2);
break;
}
if (w1 & 0x10)
{
w2 = 0x00;
w2 = (ws_key_y1 << 0) | (ws_key_y2 << 1) | (ws_key_y3 << 2) | (ws_key_y4 << 3);
retVal = (uint8_t)((w1 & 0xf0) | w2);
}
write:
#endif

View File

@@ -0,0 +1,8 @@
/*******************************************************************************
* NewOswan
* color_gpu.c: Implementation of the color GPU (Wonderswan Color & SwanCrystal)
*
* Created by Manoël Trapier on 14/03/2022.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* NewOswan
* color_system.c: IO specific to the WonderSwan Color systems.
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#if 0
Shall we split color and crystal, there are some subtles differences on some registers
READ
case 0x62:
switch (ws_get_system())
{
case WS_SYSTEM_AUTODETECT:
case WS_SYSTEM_MONO:
case WS_SYSTEM_COLOR:
retVal = 0x00;
break;
case WS_SYSTEM_CRYSTAL:
retVal = 0x80;
break;
}
break;
WRITE
if ((port == 0xA0) && (ws_ioRam[port] & 0x01) && (~value & 0x01))
{
value |= 0x01;
}
case 0xA0:
/* Force cart handshake to be set */
ws_ioRam[port] |= 0x80;
if (value & 0x01)
{
Log(TLOG_WARNING, "A0", "Oh yeah %02X BABY", value);
#ifdef USE_PAGED_MEMORY_ACCESS
uint32_t romSize;
uint8_t *rom = getRom(&romSize);
set_memory_bank(0xF, ws_get_page_ptr(rom, romSize, (ws_ioRam[0xC0] & 0x0F << 4) + 0x0F));
#endif
}
break;
#endif

View File

@@ -0,0 +1,36 @@
/*******************************************************************************
* NewOswan
* debug.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdint.h>
extern uint8_t *ws_ioRam;
uint8_t debug_io_read(void *pdata, uint8_t port)
{
switch (port)
{
}
}
void debug_io_write(void *pdata, uint8_t port, uint8_t value)
{
switch (port)
{
case 0xF1:
printf("%d\n", (signed short)((value << 8) | ws_ioRam[0xF0]));
break;
case 0xF2:
printf("%c", value);
fflush(stdout);
break;
}
}

106
source/peripherals/dma.c Normal file
View File

@@ -0,0 +1,106 @@
/*******************************************************************************
* NewOswan
* dma.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#if 0
Need to check how to differenciate all the DMA types.
WRITE:
case 0x48: // DMA
// bit 7 set to start dma transfer
if (value & 0x80)
{
uint32_t dma_start = (ws_ioRam[0x41] << 8) | (ws_ioRam[0x40]) | (ws_ioRam[0x42] << 16);
uint32_t dma_dest = (ws_ioRam[0x45] << 8) | (ws_ioRam[0x44]) | (ws_ioRam[0x43] << 16);
uint32_t dma_size = (ws_ioRam[0x47] << 8) | (ws_ioRam[0x46]);
uint8_t dma_inc = (value & 0x01) ? -1: 1;
Log(TLOG_VERBOSE, "DMA", "Starting DMA from %08X to %08X (len: %08X, inc: %d)",
dma_start, dma_dest, dma_size, dma_inc);
for (uint32_t ix = 0 ; ix < dma_size ; ix++)
{
mem_writemem20(dma_dest, mem_readmem20(dma_start));
dma_start += dma_inc;
dma_dest += dma_inc;
}
ws_ioRam[0x47] = 0;
ws_ioRam[0x46] = 0;
ws_ioRam[0x41] = (uint8_t)(dma_start >> 8);
ws_ioRam[0x40] = (uint8_t)(dma_start & 0xff);
ws_ioRam[0x45] = (uint8_t)(dma_dest >> 8);
ws_ioRam[0x44] = (uint8_t)(dma_dest & 0xff);
ws_ioRam[0x48] = 0;
}
break;
#endif
#if 0
/* DMAs */
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
break;
case 0x48: // DMA
// bit 7 set to start dma transfer
if (value & 0x80)
{
uint32_t dma_start = (ws_ioRam[0x41] << 8) | (ws_ioRam[0x40]) | (ws_ioRam[0x42] << 16);
uint32_t dma_dest = (ws_ioRam[0x45] << 8) | (ws_ioRam[0x44]) | (ws_ioRam[0x43] << 16);
uint32_t dma_size = (ws_ioRam[0x47] << 8) | (ws_ioRam[0x46]);
uint8_t dma_inc = (value & 0x01) ? -1: 1;
Log(TLOG_VERBOSE, "DMA", "Starting DMA from %08X to %08X (len: %08X, inc: %d)",
dma_start, dma_dest, dma_size, dma_inc);
for (uint32_t ix = 0 ; ix < dma_size ; ix++)
{
mem_writemem20(dma_dest, mem_readmem20(dma_start));
dma_start += dma_inc;
dma_dest += dma_inc;
}
ws_ioRam[0x47] = 0;
ws_ioRam[0x46] = 0;
ws_ioRam[0x41] = (uint8_t)(dma_start >> 8);
ws_ioRam[0x40] = (uint8_t)(dma_start & 0xff);
ws_ioRam[0x45] = (uint8_t)(dma_dest >> 8);
ws_ioRam[0x44] = (uint8_t)(dma_dest & 0xff);
ws_ioRam[0x48] = 0;
}
break;
/* DMA Start! */
case 0x52:
break;
#endif

336
source/peripherals/eeprom.c Normal file
View File

@@ -0,0 +1,336 @@
/*******************************************************************************
* NewOswan
* eeprom.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <memory.h>
#include <nec.h>
#include <log.h>
#include <gpu.h>
extern uint8_t *externalEeprom;
extern uint16_t *internalEeprom;
enum
{
EEPROM_SUBCOMMAND = 0, /* 00 00 */
EEPROM_WRITE, /* 01 xx */
EEPROM_READ, /* 10 xx */
EEPROM_ERASE, /* 11 xx */
EEPROM_WRITEDISABLE, /* 00 00 */
EEPROM_WRITEALL, /* 00 01 */
EEPROM_ERASEALL, /* 00 10 */
EEPROM_WRITEENABLE /* 00 11 */
};
char *eii_CommandName[] = {
"SUB", "WRI", "RED", "ERA", "WRD", "WRA", "ERL", "WRE",
};
uint8_t iee_WriteEnable = false;
uint16_t iee_SelAddress = 0;
uint16_t iee_Databuffer = 0;
uint8_t iee_Mode = EEPROM_READ;
uint8_t cee_WriteEnable = true;
uint16_t cee_SelAddress = 0;
uint16_t cee_Databuffer = 0;
uint8_t cee_Mode = EEPROM_READ;
// TODO: temporary
extern uint8_t *ws_ioRam;
uint8_t rs232_io_read(void *pdata, uint8_t port)
{
uint8_t retVal;
switch (port)
{
case 0xba: // eeprom even byte read
retVal = iee_Databuffer & 0x00FF;
break;
case 0xbb: // eeprom odd byte read
retVal = (iee_Databuffer & 0xFF00) >> 8;
break;
case 0xbe: // internal eeprom status/command register
// ack eeprom write
if (ws_ioRam[0xbe] & 0x20)
{
retVal = ws_ioRam[0xbe] | 2;
break;
}
// ack eeprom read
if (ws_ioRam[0xbe] & 0x10)
{
retVal = ws_ioRam[0xbe] | 1;
break;
}
// else ack both
retVal = ws_ioRam[0xbe] | 3;
break;
case 0xC8:
// ack eeprom write
if (ws_ioRam[0xbe] & 0x20)
{
retVal = ws_ioRam[0xbe] | 2;
break;
}
// ack eeprom read
if (ws_ioRam[0xbe] & 0x10)
{
retVal = ws_ioRam[0xbe] | 1;
break;
}
// else ack both
retVal = ws_ioRam[0xbe] | 3;
break;
case 0xC4: // eeprom even byte read
return cee_Databuffer & 0x00FF;
case 0xC5: // eeprom odd byte read
return (cee_Databuffer & 0xFF00) >> 8;
}
}
void rs232_io_write(void *pdata, uint8_t port, uint8_t value)
{
uint8_t retVal;
switch (port)
{
/* Internal EEPROM */
case 0xba: /* DATA Low */
iee_Databuffer = iee_Databuffer & 0xFF00;
iee_Databuffer = iee_Databuffer | (value);
break;
case 0xbb: /* Data High */
iee_Databuffer = iee_Databuffer & 0x00FF;
iee_Databuffer = iee_Databuffer | (value << 8);
break;
case 0xBC: /* Address Low */
case 0xBD: /* Address High */
break;
case 0xBE: /* Command / Status */
{
uint16_t address, command, subcmd;
iee_SelAddress = (ws_ioRam[0xBD] << 8) | ws_ioRam[0xBC];
if (ws_gpu_operatingInColor)
{
/*
13 00
S CCaa AAAA AAAA
0001 0011 0000 0000
*/
/* S CC aaAAAAAAAA */
command = (iee_SelAddress >> 10) & 0x3;
address = iee_SelAddress & 0x3FF;
subcmd = (iee_SelAddress >> 8) & 0x03;
}
else
{
/* S CC aaAAAA */
command = (iee_SelAddress >> 6) & 0x3;
address = iee_SelAddress & 0x3F;
subcmd = (iee_SelAddress >> 4) & 0x03;
}
if (command == EEPROM_SUBCOMMAND)
{
command = EEPROM_WRITEDISABLE + subcmd;
}
#ifdef EEPROM_DEBUG
printf("IEEP: RA:%04X RD:%04X A:%03X C:%s", iee_SelAddress, iee_Databuffer, address, eii_CommandName[command]);
#endif
if (value & 0x40)
{
/* Sub command */
#ifdef EEPROM_DEBUG
printf(" - Sub");
#endif
if (command == EEPROM_WRITEENABLE)
{
#ifdef EEPROM_DEBUG
printf(" Write Enable\n");
#endif
iee_WriteEnable = true;
}
else if (command == EEPROM_WRITEDISABLE)
{
#ifdef EEPROM_DEBUG
printf(" Write Disable\n");
#endif
iee_WriteEnable = false;
}
else if (command == EEPROM_ERASEALL)
{
#ifdef EEPROM_DEBUG
printf(" Erase All\n");
#endif
if (ws_gpu_operatingInColor)
{
//memset(internalEeprom, 0, COLOR_IEEPROM_SIZE);
}
else
{
//memset(internalEeprom, 0, BW_IEEPROM_SIZE);
}
}
#ifdef EEPROM_DEBUG
else
{
printf(" Write All?\n");
}
#endif
}
else if (value & 0x20)
{
/* Write */
#ifdef EEPROM_DEBUG
printf(" - Write?");
#endif
if (iee_WriteEnable)
{
#ifdef EEPROM_DEBUG
printf(" Yes : %04X\n", iee_Databuffer);
#endif
internalEeprom[address] = iee_Databuffer;
}
#ifdef EEPROM_DEBUG
else
{
printf(" No\n");
}
#endif
}
else if (value & 0x10)
{
/* Read */
#ifdef EEPROM_DEBUG
printf(" - Read");
#endif
iee_Databuffer = internalEeprom[address];
#ifdef EEPROM_DEBUG
printf(" Data : %04X\n", iee_Databuffer);
#endif
}
#ifdef EEPROM_DEBUG
else
{
printf(" Unknown value: %02X\n", value);
}
#endif
fflush(stdout);
}
break;
/* Cart EEPROM */
case 0xC4: /* Data High */
cee_Databuffer = cee_Databuffer & 0xFF00;
cee_Databuffer = cee_Databuffer | (value);
break;
case 0xC5: /* Data High */
cee_Databuffer = cee_Databuffer & 0x00FF;
cee_Databuffer = cee_Databuffer | (value << 8);
break;
case 0xC6: /* Address Low */
case 0xC7: /* Address High */
break;
case 0xC8: /* Command / Status */
{
uint16_t address, command, subcmd; /*, start;*/
cee_SelAddress = (ws_ioRam[0xBD] << 8) | ws_ioRam[0xBC];
/* S CC aaAAAA */
command = (cee_SelAddress >> 6) & 0x3;
address = cee_SelAddress & 0x3F;
subcmd = (cee_SelAddress >> 4) & 0x03;
if (command == EEPROM_SUBCOMMAND)
{
command = EEPROM_WRITEDISABLE + subcmd;
}
printf("CEEP: RA:%04X RD:%04X A:%03X C:%s", cee_SelAddress, cee_Databuffer, address, eii_CommandName[command]);
if (value & 0x40)
{
/* Sub command */
printf(" - Sub");
if (command == EEPROM_WRITEENABLE)
{
printf(" Write Enable\n");
cee_WriteEnable = true;
}
else if (command == EEPROM_WRITEDISABLE)
{
printf(" Write Disable\n");
cee_WriteEnable = false;
}
else if (command == EEPROM_ERASEALL)
{
printf(" Erase All\n");
/* Nothing here at the moment */
}
else
{
printf(" Write All?\n");
}
}
else if (value & 0x20)
{
/* Write */
printf(" - Write?");
if (cee_WriteEnable)
{
printf(" Yes : %04X\n", cee_Databuffer);
externalEeprom[address] = cee_Databuffer;
}
else
{
printf(" No\n");
}
}
else if (value & 0x10)
{
/* Read */
printf(" - Read");
cee_Databuffer = externalEeprom[address];
printf(" Data : %04X\n", cee_Databuffer);
}
else
{
printf(" Unknown value: %02X@", value);
}
fflush(stdout);
}
break;
case 0xCB:
break;
}
}

View File

@@ -0,0 +1,98 @@
/*******************************************************************************
* NewOswan
* interrupt_controller.c:
*
* Created by Manoël Trapier on 14/03/2022.
* Copyright (c) 2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <device.h>
#include <io.h>
#include <interrupt_controller.h>
/* device internal parameters */
typedef struct ic_params_t
{
uint8_t address_base;
uint8_t int_enable_mask;
uint8_t int_status;
} ic_params_t;
static ic_params_t interrupt_controller;
static uint8_t IC_IO_read(void *pdata, uint8_t port)
{
ic_params_t *params = (ic_params_t *)pdata;
switch(port)
{
case 0x0: return params->address_base;
case 0x2: return params->int_enable_mask;
case 0x4: return params->int_status;
}
return 0x90;
}
static void IC_IO_write(void *pdata, uint8_t port, uint8_t value)
{
ic_params_t *params = (ic_params_t *)pdata;
switch(port)
{
case 0x0: params->address_base = value; break;
case 0x2: params->int_enable_mask = value; break;
}
}
static void IC_IO_write_ack(void *pdata, uint8_t port, uint8_t value)
{
ic_params_t *params = (ic_params_t *)pdata;
// De-assert CPU interrupt accordingly to the mask in value
}
static void IC_init(uint8_t baseAddress, void *params)
{
UNUSED_PARAMETER(params);
register_io_hook(baseAddress, 0x0, IC_IO_read, IC_IO_write, &interrupt_controller);
register_io_hook(baseAddress, 0x2, IC_IO_read, IC_IO_write, &interrupt_controller);
register_io_hook(baseAddress, 0x4, IC_IO_read, NULL, &interrupt_controller);
register_io_hook(baseAddress, 0x6, NULL, IC_IO_write_ack, &interrupt_controller);
}
static void IC_reset()
{
interrupt_controller.int_enable_mask = 0;
interrupt_controller.address_base = 0;
}
device_t InterruptController =
{
.init = IC_init,
.reset = IC_reset,
.free = NULL,
.deviceType = DT_INTERRUPT_CONTROLLER,
};
/* Exported functions */
void trigger_interrupt(hw_interrupt_type_t type)
{
uint16_t int_vector = interrupt_controller.address_base & 0xF8 + (uint8_t)type;
/* Check that the INT is enabled */
if ((interrupt_controller.int_enable_mask >> type) & 0x1)
{
/* TODO: Do we have to enable that even if the int is not enabled? */
interrupt_controller.int_status |= (1 << type);
// Fire the NEC interrupt
}
}

View File

@@ -0,0 +1,128 @@
/*******************************************************************************
* NewOswan
* mono_gpu.c: Implementation of the monochrome GPU
*
* Created by Manoël Trapier on 14/03/2022.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#if 0
READ
case 0xA0:
case 0xAA:
case 0xAB:
case 0xAC:
case 0xAD:
retVal = ws_gpu_port_read(port);
WRITE
case 0x00:
Log(TLOG_DEBUG, "GPU", "Screen enabled: W2:%c W2M:%c, SW:%c, S:%c, S2:%c, S1:%c",
(value & 0x20)?'Y':'N',
(value & 0x10)?'I':'O',
(value & 0x08)?'Y':'N',
(value & 0x04)?'Y':'N',
(value & 0x02)?'Y':'N',
(value & 0x01)?'Y':'N');
break;
case 0x04:
if (ws_gpu_operatingInColor)
{
Log(TLOG_DEBUG, "GPU", "Sprite base: %04X", (value & 0x1F) << 9);
}
else
{
Log(TLOG_DEBUG, "GPU", "Sprite base: %04X", (value & 0x3F) << 9);
}
break;
case 0x07:
if (ws_gpu_operatingInColor)
{
Log(TLOG_DEBUG, "GPU", "Sprite Screen1 base: %04X", (value & 0x7) << 11);
Log(TLOG_DEBUG, "GPU", "Sprite Screen2 base: %04X", (value & 0x70) << (11-4));
}
else
{
Log(TLOG_DEBUG, "GPU", "Sprite Screen1 base: %04X", (value & 0xF) << 11);
Log(TLOG_DEBUG, "GPU", "Sprite Screen2 base: %04X", (value & 0xF0) << (11-4));
}
break;
case 0x10:
//Log(TLOG_DEBUG, "GPU", "Sprite Screen1 X scroll: %d", value);
break;
case 0x11:
//Log(TLOG_DEBUG, "GPU", "Sprite Screen1 T scroll: %d", value);
break;
case 0x12:
//Log(TLOG_DEBUG, "GPU", "Sprite Screen2 X scroll: %d", value);
break;
case 0x13:
//Log(TLOG_DEBUG, "GPU", "Sprite Screen2 Y scroll: %d", value);
break;
case 0x01:
case 0x02:
case 0x03:
case 0x05:
case 0x06:
case 0x08:
case 0x09:
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
case 0x14:
break;
case 0x15:
Log(TLOG_DEBUG, "io", "Icons %c %c %c %c %c %c %c %c", (value >> 7) & 1 ? '?' : ' ', (value >> 6) & 1 ? '?' : ' ',
(value >> 5) & 1 ? '3' : ' ', (value >> 4) & 1 ? '2' : ' ', (value >> 3) & 1 ? '1' : ' ',
(value >> 2) & 1 ? 'H' : ' ', (value >> 1) & 1 ? 'V' : ' ', (value >> 0) & 1 ? 'S' : ' ');
break;
/* Palettes ? */
case 0x1C:
case 0x25:
case 0x2F:
case 0x38:
case 0x1D:
case 0x26:
case 0x30:
case 0x39:
case 0x1E:
case 0x27:
case 0x31:
case 0x3A:
case 0x1F:
case 0x28:
case 0x32:
case 0x3B:
case 0x20:
case 0x29:
case 0x33:
case 0x3C:
case 0x21:
case 0x2A:
case 0x34:
case 0x3E:
case 0x22:
case 0x2B:
case 0x35:
case 0x3F:
case 0x23:
case 0x2C:
case 0x36:
case 0x24:
case 0x2E:
case 0x37:
break;
#endif

View File

@@ -0,0 +1,91 @@
/*******************************************************************************
* NewOswan
* mono_system.c: IOs specific to the original WonderSwan
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#if 0
READ
case 0x62:
switch (ws_get_system())
{
case WS_SYSTEM_AUTODETECT:
case WS_SYSTEM_MONO:
case WS_SYSTEM_COLOR:
retVal = 0x00;
break;
case WS_SYSTEM_CRYSTAL:
retVal = 0x80;
break;
}
break;
WRITE
if ((port == 0xA0) && (ws_ioRam[port] & 0x01) && (~value & 0x01))
{
value |= 0x01;
}
case 0xA0:
/* Force cart handshake to be set */
ws_ioRam[port] |= 0x80;
if (value & 0x01)
{
Log(TLOG_WARNING, "A0", "Oh yeah %02X BABY", value);
#ifdef USE_PAGED_MEMORY_ACCESS
uint32_t romSize;
uint8_t *rom = getRom(&romSize);
set_memory_bank(0xF, ws_get_page_ptr(rom, romSize, (ws_ioRam[0xC0] & 0x0F << 4) + 0x0F));
#endif
}
break;
#endif
#if 0
case 0x62:
switch (ws_get_system())
{
case WS_SYSTEM_AUTODETECT:
case WS_SYSTEM_MONO:
case WS_SYSTEM_COLOR:
retVal = 0x00;
break;
case WS_SYSTEM_CRYSTAL:
retVal = 0x80;
break;
}
break;
case 0xA0:
/* Force cart handshake to be set */
ws_ioRam[port] |= 0x80;
if (value & 0x01)
{
Log(TLOG_WARNING, "A0", "Oh yeah %02X BABY", value);
#ifdef USE_PAGED_MEMORY_ACCESS
uint32_t romSize;
uint8_t *rom = getRom(&romSize);
set_memory_bank(0xF, ws_get_page_ptr(rom, romSize, (ws_ioRam[0xC0] & 0x0F << 4) + 0x0F));
#endif
}
break;
#endif

230
source/peripherals/rs232.c Normal file
View File

@@ -0,0 +1,230 @@
/*******************************************************************************
* NewOswan
* rs232.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <unistd.h> /* UNIX standard function definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/mman.h>
#include <fcntl.h>
#include <nec.h>
#include <log.h>
/* Temporary */
extern uint8_t *ws_ioRam;
/* Serial port */
#define BDR_9600 (0)
#define BDR_38400 (1)
#define SERIAL_PORT "/dev/tty.USA19H141P1.1"
static int serialfd = -1;
static int serial_have_data = 0;
static unsigned char serial_data = 0;
static int serial_speed = BDR_9600;
static void open_serial()
{
if (serialfd < 0)
{
serialfd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
//set_baudrate(serial_speed);
serial_have_data = 0;
}
}
static void set_baudrate(int speed)
{
struct termios options;
if (serialfd < 0)
{
return;
}
tcgetattr(serialfd, &options);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
if (speed == BDR_9600)
{
cfsetispeed(&options, B9600);
}
else
{
cfsetospeed(&options, B38400);
}
#if 0
options.c_cflag &= ~CNEW_RTSCTS;
#else
options.c_cflag &= ~CRTSCTS;
#endif
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
tcsetattr(serialfd, TCSANOW, &options);
/* Make sure read is not blocking */
fcntl(serialfd, F_SETFL, FNDELAY);
}
static void close_serial()
{
close(serialfd);
serialfd = -1;
}
static void check_serial_data()
{
unsigned char buf[10];
int f;
if (serialfd < 0)
{
return;
}
if (serial_have_data == 0)
{
f = read(serialfd, buf, 1);
if (f > 0)
{
Log(TLOG_DEBUG, "serial", "Have data from serial [%d]!", f);
fflush(stdout);
serial_have_data = 0x01;
serial_data = buf[0];
}
}
if (serial_have_data > 0)
{
/* Gen an int if enabled */
if (ws_ioRam[0xB2] & 0x04)
{
ws_ioRam[0xb6] &= ~0x04;
Log(TLOG_DEBUG, "serial", "SERIAL INNNNNTTTT!!!!!!!");
nec_int((ws_ioRam[0xb0] + 3) * 4);
}
}
}
static unsigned char read_serial()
{
unsigned char buf[10];
int f;
if (serialfd < 0)
{
return 0xFF;
}
if (serial_have_data > 0)
{
serial_have_data = 0;
return serial_data;
}
f = read(serialfd, buf, 1);
if (f == 1)
{
return buf[0];
}
return 0x42;
}
static void write_serial(unsigned char value)
{
if (serialfd < 0)
{
return;
}
write(serialfd, &value, 1);
}
uint8_t rs232_io_read(void *pdata, uint8_t port)
{
uint8_t retVal;
switch(port)
{
case 0xB1:
retVal = read_serial();
Log(TLOG_DEBUG, "serial", "Read %02X", retVal);
goto exit;
case 0xB3:
check_serial_data();
if (ws_ioRam[0xB3] & 0x80)
{
retVal = (ws_ioRam[0xB3] & ~1) | serial_have_data | 0x04;
}
else
{
retVal = 0x00;
}
Log(TLOG_DEBUG, "serial", "<<<<RS232STA: %02X [%c%c%cxx%c%c%c]", retVal, (retVal & 0x80) ? 'E' : 'd',
(retVal & 0x40) ? '3' : '9', (retVal & 0x20) ? 'R' : 'n', (retVal & 0x04) ? 'E' : 'f',
(retVal & 0x02) ? 'V' : 'n', (retVal & 0x01) ? 'D' : 'e');
goto exit;
}
exit:
return retVal;
}
void rs232_io_write(void *pdata, uint8_t port, uint8_t value)
{
switch(port)
{
case 0xB1:
write_serial(value);
break;
case 0xB3:
Log(TLOG_DEBUG, "serial", ">>>>RS232STA: %02X [%c%c%cxx%c%c%c]", value, (value & 0x80) ? 'E' : 'd', (value & 0x40) ? '3' : '9',
(value & 0x20) ? 'R' : 'n', (value & 0x04) ? 'E' : 'f', (value & 0x02) ? 'V' : 'n',
(value & 0x01) ? 'D' : 'e');
/* Serial status: 7 = Enable, 6 = baudrate, 5 = Overrun reset
2 = Send Buffer empty
1 = Overrun
0 = Data Received
*/
serial_speed = ((value & 040) == 0x00) ? BDR_9600 : BDR_38400;
if ((value & 0x80) == 0x80)
{
open_serial();
set_baudrate(serial_speed);
check_serial_data();
}
break;
}
}
void rs232_init()
{
}

103
source/peripherals/rtc.c Normal file
View File

@@ -0,0 +1,103 @@
/*******************************************************************************
* NewOswan
* rtc.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdint.h>
#include <time.h>
static int rtcDataRegisterReadCount = 0;
// TODO: Temporary to let build for now
static uint8_t ws_ioRam[0x100];
uint8_t rtc_io_read(void *pdata, uint8_t port)
{
uint8_t retVal = 0;
switch (port)
{
case 0xca : // RTC Command and status register
// set ack to always 1
retVal = (ws_ioRam[0xca] | 0x80);
goto exit;
case 0xcb : // RTC data register
if (ws_ioRam[0xca] == 0x15) // get time command
{
struct tm *newtime;
time_t long_time;
time(&long_time);
newtime = localtime(&long_time);
#define BCD(value) ((value/10)<<4)|(value%10)
switch (rtcDataRegisterReadCount)
{
case 0:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_year - 100);
goto exit;
case 1:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_mon);
goto exit;
case 2:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_mday);
goto exit;
case 3:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_wday);
goto exit;
case 4:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_hour);
goto exit;
case 5:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_min);
goto exit;
case 6:
rtcDataRegisterReadCount = 0;
retVal = BCD(newtime->tm_sec);
goto exit;
}
return 0;
}
else
{
// set ack
retVal = (ws_ioRam[0xcb] | 0x80);
goto exit;
}
}
exit:
return retVal;
}
void rtc_io_write(void *pdata, uint8_t port, uint8_t value)
{
switch(port)
{
case 0xca:
if (value == 0x15)
{
rtcDataRegisterReadCount = 0;
}
break;
}
}

View File

@@ -0,0 +1,8 @@
/*******************************************************************************
* NewOswan
* timer.c:
*
* Created by Manoël Trapier on 26/06/2022.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/

View File

@@ -0,0 +1,81 @@
/*******************************************************************************
* NewOswan
* universal_luxor.c: Implement a "universal" version of both known version
* of Luxor (Bandai 2001 and Bandai 2003) as there is no way from the ROM
* to really know which version is on the original cart.
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#if 0
READ
case 0xc0 : // ???
retVal = ((ws_ioRam[0xc0] & 0xf) | 0x20);
goto exit;
case 0xD0:
retVal = 0;
goto exit;
case 0xCC:
case 0xCD:
retVal = 0;
break;
WRITE
case 0xC0:
{
/* page 4 to F */
uint32_t romSize;
uint8_t *rom = getRom(&romSize);
for (int i = 0x04 ; i < 0x10 ; i++)
{
set_memory_bank(i, ws_get_page_ptr(rom, romSize, (value << 4) + i));
}
if (!(ws_ioRam[0xA0] & 0x01))
{
set_irom_overlay();
}
break;
}
case 0xC1:
/* Sram bank */
if (sramSize > 0)
{
uint32_t sramSize;
uint8_t *sram = getSram(&sramSize);
set_memory_bank(0x1, ws_get_page_ptr(sram, sramSize, value));
}
break;
case 0xC2:
{
/* page 4 to F */
uint32_t romSize;
uint8_t *rom = getRom(&romSize);
/* Page 2 */
set_memory_bank(0x2, ws_get_page_ptr(rom, romSize, value));
break;
}
case 0xC3:
{
/* page 4 to F */
uint32_t romSize;
uint8_t *rom = getRom(&romSize);
/* Page 3 */
set_memory_bank(0x3, ws_get_page_ptr(rom, romSize, value));
break;
}
#endif

140
source/rom.c Normal file
View File

@@ -0,0 +1,140 @@
/*******************************************************************************
* NewOswan
* rom.c:
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <log.h>
#include <rom.h>
uint8_t *ws_rom_load(char *path, uint32_t *romSize)
{
int fd;
uint8_t *ret_ptr;
struct stat FileStat;
fd = open(path, O_RDWR);
fstat(fd, &FileStat);
*romSize = FileStat.st_size;
ret_ptr = (uint8_t *)mmap(NULL, FileStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (ret_ptr == MAP_FAILED)
{
ret_ptr = NULL;
*romSize = 0;
}
return ret_ptr;
}
const char *eepromSizeName[] =
{
[WS_EEPROM_SIZE_NONE] = "none",
[WS_EEPROM_SIZE_1k] = "1kbits",
[WS_EEPROM_SIZE_16k] = "16kbits",
[WS_EEPROM_SIZE_8k] = "8kbits",
};
const char *sramSizeName[] =
{
[WS_SRAM_SIZE_NONE] = "none",
[WS_SRAM_SIZE_64k] = "64kbit",
[WS_SRAM_SIZE_256k] = "256kbit",
[WS_SRAM_SIZE_1M] = "1Mbits",
[WS_SRAM_SIZE_2M] = "2Mbits",
[WS_SRAM_SIZE_4M] = "4Mbits",
};
void ws_rom_dumpInfo(uint8_t *wsrom, uint32_t romSize)
{
ws_romHeaderStruct *romHeader = ws_rom_getHeader(wsrom, romSize);
Log(TLOG_NORMAL, "rom", "developper Id 0x%.2x", romHeader->developperId);
Log(TLOG_NORMAL, "rom", "cart Id 0x%.2x", romHeader->cartId);
Log(TLOG_NORMAL, "rom", "minimum system %s", (romHeader->minimumSupportSystem == 0) ? "Wonderswan mono" : "Wonderswan color");
Log(TLOG_NORMAL, "rom", "size %i Mbits", (romSize >> 20) << 3);
Log(TLOG_NORMAL, "rom", "eeprom %s", eepromSizeName[romHeader->saveSize & 0xf]);
Log(TLOG_NORMAL, "rom", "sram %s", sramSizeName[romHeader->saveSize & 0xF0]);
Log(TLOG_NORMAL, "rom", "rtc %s", (romHeader->realtimeClock) ? "Yes" : "None");
Log(TLOG_NORMAL, "rom", "checksum 0x%.4x", romHeader->checksum);
}
ws_romHeaderStruct *ws_rom_getHeader(uint8_t *wsrom, uint32_t wsromSize)
{
ws_romHeaderStruct *wsromHeader = (ws_romHeaderStruct *)(wsrom + wsromSize - sizeof(ws_romHeaderStruct));
return (wsromHeader);
}
uint32_t ws_rom_sramSize(uint8_t *wsrom, uint32_t wsromSize)
{
ws_romHeaderStruct *romHeader = ws_rom_getHeader(wsrom, wsromSize);
switch (romHeader->saveSize & 0x0f)
{
case WS_SRAM_SIZE_NONE:
return 0;
case WS_SRAM_SIZE_64k:
return 0x2000;
case WS_SRAM_SIZE_256k:
return 0x8000;
case WS_SRAM_SIZE_1M:
return 0x20000;
case WS_SRAM_SIZE_2M:
return 0x40000;
case WS_SRAM_SIZE_4M:
return 0x80000;
default:
Log(TLOG_PANIC, "ROM", "Invalid SRAM size (%02X)! Please check cart metadata!", romHeader->saveSize);
}
return (0);
}
uint32_t ws_rom_eepromSize(uint8_t *wsrom, uint32_t wsromSize)
{
ws_romHeaderStruct *romHeader = ws_rom_getHeader(wsrom, wsromSize);
switch (romHeader->saveSize & 0xf0)
{
case WS_EEPROM_SIZE_NONE:
return 0;
case WS_EEPROM_SIZE_1k:
return 0x80;
case WS_EEPROM_SIZE_16k:
return 0x800;
case WS_EEPROM_SIZE_8k:
return 0x100;
default:
Log(TLOG_PANIC, "ROM", "Invalid SRAM size (%02X)! Please check cart metadata!", romHeader->saveSize);
}
return (0);
}

View File

@@ -1,214 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "log.h"
#include "rom.h"
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint8_t *ws_rom_load(char *path, uint32_t *romSize)
{
int fd;
uint8_t *ret_ptr;
struct stat FileStat;
fd = open(path, O_RDWR);
fstat(fd, &FileStat);
*romSize = FileStat.st_size;
ret_ptr = (uint8_t *)mmap(NULL, FileStat.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (ret_ptr == MAP_FAILED)
{
ret_ptr = NULL;
*romSize = 0;
}
return ret_ptr;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_rom_dumpInfo(uint8_t *wsrom, uint32_t romSize)
{
ws_romHeaderStruct *romHeader=ws_rom_getHeader(wsrom,romSize);
fprintf(log_get(),"rom: developper Id 0x%.2x\n",romHeader->developperId);
fprintf(log_get(),"rom: cart Id 0x%.2x\n",romHeader->cartId);
fprintf(log_get(),"rom: minimum system %s\n",(romHeader->minimumSupportSystem==WS_SYSTEM_MONO)?"Wonderswan mono":"Wonderswan color");
fprintf(log_get(),"rom: size %i Mbits\n",(romSize>>20)<<3);
fprintf(log_get(),"rom: eeprom ");
switch (romHeader->eepromSize&0xf)
{
case WS_EEPROM_SIZE_NONE:
{
fprintf(log_get(),"none\n");
break;
}
case WS_EEPROM_SIZE_64k:
{
fprintf(log_get(),"64 kb\n");
break;
}
case WS_EEPROM_SIZE_256k:
{
fprintf(log_get(),"256 kb\n");
break;
}
}
fprintf(log_get(),"rom: sram ");
switch (romHeader->eepromSize&0xf0)
{
case WS_SRAM_SIZE_NONE:
{
fprintf(log_get(),"none\n");
break;
}
case WS_SRAM_SIZE_1k:
{
fprintf(log_get(),"1 kb\n");
break;
}
case WS_SRAM_SIZE_16k:
{
fprintf(log_get(),"16 kb\n");
break;
}
case WS_SRAM_SIZE_8k:
{
fprintf(log_get(),"8 kn\n");
break;
}
}
fprintf(log_get(),"rom: rtc %s\n",(romHeader->realtimeClock)?"Yes":"None");
fprintf(log_get(),"checksum 0x%.4x\n",romHeader->checksum);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
ws_romHeaderStruct *ws_rom_getHeader(uint8_t *wsrom, uint32_t wsromSize)
{
ws_romHeaderStruct *wsromHeader = (ws_romHeaderStruct *)(wsrom + wsromSize - 10);
return(wsromHeader);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint32_t ws_rom_sramSize(uint8_t *wsrom, uint32_t wsromSize)
{
ws_romHeaderStruct *romHeader=ws_rom_getHeader(wsrom,wsromSize);
switch (romHeader->eepromSize&0xf0)
{
case WS_SRAM_SIZE_NONE:
return(0);
case WS_SRAM_SIZE_1k:
return(0x400);
case WS_SRAM_SIZE_16k:
return(0x4000);
case WS_SRAM_SIZE_8k:
return(0x2000);
}
return(0);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint32_t ws_rom_eepromSize(uint8_t *wsrom, uint32_t wsromSize)
{
ws_romHeaderStruct *romHeader=ws_rom_getHeader(wsrom,wsromSize);
switch (romHeader->eepromSize&0xf)
{
case WS_EEPROM_SIZE_NONE:
return(0);
case WS_EEPROM_SIZE_64k:
return(0x10000);
case WS_EEPROM_SIZE_256k:
return(0x40000);
}
return(0);
}

View File

@@ -1,57 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __ROM_H__
#define __ROM_H__
#define WS_SYSTEM_MONO 0
#define WS_SYSTEM_COLOR 1
#define WS_ROM_SIZE_2MBIT 1
#define WS_ROM_SIZE_4MBIT 2
#define WS_ROM_SIZE_8MBIT 3
#define WS_ROM_SIZE_16MBIT 4
#define WS_ROM_SIZE_24MBIT 5
#define WS_ROM_SIZE_32MBIT 6
#define WS_ROM_SIZE_48MBIT 7
#define WS_ROM_SIZE_64MBIT 8
#define WS_ROM_SIZE_128MBIT 9
#define WS_EEPROM_SIZE_NONE 0
#define WS_SRAM_SIZE_NONE 0
#define WS_EEPROM_SIZE_64k 1
#define WS_EEPROM_SIZE_256k 2
#define WS_SRAM_SIZE_1k 10
#define WS_SRAM_SIZE_16k 20
#define WS_SRAM_SIZE_8k 50
typedef struct ws_romHeaderStruct
{
uint8_t developperId;
uint8_t minimumSupportSystem;
uint8_t cartId;
uint8_t romSize;
uint8_t eepromSize;
uint8_t additionnalCapabilities;
uint8_t realtimeClock;
uint16_t checksum;
} ws_romHeaderStruct;
uint8_t *ws_rom_load(char *path, uint32_t *romSize);
void ws_rom_dumpInfo(uint8_t *wsrom, uint32_t wsromSize);
ws_romHeaderStruct *ws_rom_getHeader(uint8_t *wsrom, uint32_t wsromSize);
uint32_t ws_rom_sramSize(uint8_t *wsrom, uint32_t wsromSize);
uint32_t ws_rom_eepromSize(uint8_t *wsrom, uint32_t wsromSize);
#endif

380
source/ws.c Normal file
View File

@@ -0,0 +1,380 @@
/*******************************************************************************
* NewOswan
* ws.c: Base wonderswan implementation
*
* Based on the original Oswan-unix
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <log.h>
#include <rom.h>
#include "nec.h"
#include "necintrf.h"
#include <memory.h>
#include <gpu.h>
#include <io.h>
#include <audio.h>
#include <ws.h>
uint32_t ws_cycles;
uint32_t ws_skip;
uint32_t ws_cyclesByLine = 0;
uint32_t vblank_count = 0;
char *ws_sram_path = NULL;
char *ws_ieep_path = NULL;
char *ws_rom_path = NULL;
wssystem_t systemType;
void ws_patchRom(void)
{
}
int ws_init(char *rompath)
{
uint8_t *rom;
uint32_t romSize;
if ((rom = ws_rom_load(rompath, &romSize)) == NULL)
{
Log(TLOG_PANIC, "ws", "Error: cannot load %s", rompath);
return (0);
}
#if 0
ws_staticRam = (uint8_t *)load_file(ws_sram_path);
if (ws_staticRam == NULL)
{
ws_staticRam = (uint8_t *)create_file(ws_sram_path, 0x10000);
}
if (ws_staticRam == NULL)
{
Log(TLOG_PANIC, "ws", "Card SRAM load error!\n");
return 0;
}
externalEeprom = (uint8_t *)load_file(ws_ieep_path);
if (externalEeprom == NULL)
{
externalEeprom = (uint8_t *)create_file(ws_ieep_path, 0x100000);
}
if (externalEeprom == NULL)
{
Log(TLOG_PANIC, "ws", "Card EEPROM load error!\n");
return 0;
}
ws_memory_init(rom, romSize);
ws_patchRom();
#endif
io_init();
//ws_audio_init();
//ws_gpu_init();
return (1);
}
void ws_reset(void)
{
//io_reset();
//ws_audio_reset();
//ws_gpu_reset();
nec_reset(NULL);
nec_set_reg(NEC_SP, 0x2000);
}
int ws_executeLine(int16_t *framebuffer, int renderLine)
{
int drawWholeScreen = 0;
//ws_audio_process();
// update scanline register
//ws_ioRam[2] = ws_gpu_scanline;
/* Why twice like that and random cycle count???? */
ws_cycles = nec_execute((ws_cyclesByLine >> 1) + (rand() & 7));
ws_cycles += nec_execute((ws_cyclesByLine >> 1) + (rand() & 7));
if (ws_cycles >= ws_cyclesByLine + ws_cyclesByLine)
{
ws_skip = ws_cycles / ws_cyclesByLine;
}
else
{
ws_skip = 1;
}
ws_cycles %= ws_cyclesByLine;
#if 0
for (uint32_t uI = 0 ; uI < ws_skip ; uI++)
{
if (renderLine)
{
ws_gpu_renderScanline(framebuffer);
}
ws_gpu_scanline++;
if (ws_gpu_scanline == 144)
{
drawWholeScreen = 1;
}
}
if (ws_gpu_scanline > 158)
{
ws_gpu_scanline = 0;
{
#if 0
if ((ws_ioRam[0xb2] & 32)) /* VBLANK Timer */
{
/* TODO: REPAIR THAT SHIT */
ws_ioRam[0xb6] &= ~32;
nec_int((ws_ioRam[0xb0] + 5) * 4);
}
#endif
}
}
#endif
#if 0
ws_ioRam[2] = ws_gpu_scanline;
#endif
if (drawWholeScreen)
{
#if 0
if (ws_ioRam[0xb2] & 64) /* VBLANK INT */
{
ws_ioRam[0xb6] &= ~64;
nec_int((ws_ioRam[0xb0] + 6) * 4);
}
#endif
vblank_count++;
}
#if 0
if (ws_ioRam[0xa4] && (ws_ioRam[0xb2] & 128)) /*HBLANK TMR*/
{
/* TODO: Check that shit */
if (!ws_ioRam[0xa5])
{
ws_ioRam[0xa5] = ws_ioRam[0xa4];
}
if (ws_ioRam[0xa5])
{
ws_ioRam[0xa5]--;
}
if ((!ws_ioRam[0xa5]) && (ws_ioRam[0xb2] & 128))
{
ws_ioRam[0xb6] &= ~128;
nec_int((ws_ioRam[0xb0] + 7) * 4);
}
}
if ((ws_ioRam[0x2] == ws_ioRam[0x3]) && (ws_ioRam[0xb2] & 16)) /*SCANLINE INT*/
{
ws_ioRam[0xb6] &= ~16;
nec_int((ws_ioRam[0xb0] + 4) * 4);
}
#endif
return (drawWholeScreen);
}
void ws_done(void)
{
io_cleanup();
//ws_audio_done();
//ws_gpu_done();
}
void ws_set_system(wssystem_t system)
{
if (system == WS_SYSTEM_AUTODETECT)
{
system = WS_SYSTEM_CRYSTAL;
}
systemType = system;
}
wssystem_t ws_get_system()
{
return systemType;
}
#define MacroLoadNecRegisterFromFile(F, R) \
read(fp,&value,sizeof(value)); \
nec_set_reg(R,value);
int ws_loadState(char *statepath)
{
// TODO: need a complete rewrite
#if 0
Log(TLOG_NORMAL, "ws", "loading %s\n", statepath);
uint16_t crc = memory_getRomCrc();
uint16_t newCrc;
unsigned value;
uint8_t ws_newVideoMode;
int fp = open(statepath, O_RDONLY);
if (fp == -1)
{
return (0);
}
read(fp, &newCrc, 2);
if (newCrc != crc)
{
return (-1);
}
MacroLoadNecRegisterFromFile(fp, NEC_IP);
MacroLoadNecRegisterFromFile(fp, NEC_AW);
MacroLoadNecRegisterFromFile(fp, NEC_BW);
MacroLoadNecRegisterFromFile(fp, NEC_CW);
MacroLoadNecRegisterFromFile(fp, NEC_DW);
MacroLoadNecRegisterFromFile(fp, NEC_CS);
MacroLoadNecRegisterFromFile(fp, NEC_DS);
MacroLoadNecRegisterFromFile(fp, NEC_ES);
MacroLoadNecRegisterFromFile(fp, NEC_SS);
MacroLoadNecRegisterFromFile(fp, NEC_IX);
MacroLoadNecRegisterFromFile(fp, NEC_IY);
MacroLoadNecRegisterFromFile(fp, NEC_BP);
MacroLoadNecRegisterFromFile(fp, NEC_SP);
MacroLoadNecRegisterFromFile(fp, NEC_FLAGS);
MacroLoadNecRegisterFromFile(fp, NEC_VECTOR);
MacroLoadNecRegisterFromFile(fp, NEC_PENDING);
MacroLoadNecRegisterFromFile(fp, NEC_NMI_STATE);
MacroLoadNecRegisterFromFile(fp, NEC_IRQ_STATE);
read(fp, internalRam, 65536);
read(fp, ws_staticRam, 65536);
read(fp, ws_ioRam, 256);
read(fp, ws_paletteColors, 8);
read(fp, ws_palette, 16 * 4 * 2);
read(fp, wsc_palette, 16 * 16 * 2);
read(fp, &ws_newVideoMode, 1);
read(fp, &ws_gpu_scanline, 1);
read(fp, externalEeprom, 131072);
ws_audio_readState(fp);
close(fp);
// force a video mode change to make all tiles dirty
ws_gpu_clearCache();
#endif
return (1);
}
#define MacroStoreNecRegisterToFile(F, R) \
value=nec_get_reg(R); \
write(fp,&value,sizeof(value));
int ws_saveState(char *statepath)
{
// TODO: need a complete rewrite
#if 0
uint16_t crc = memory_getRomCrc();
uint32_t value;
char newPath[1024];
Log(TLOG_DEBUG, "ws", "saving %s\n", statepath);
if (strlen(statepath) < 4)
{
sprintf(newPath, "%s.wss", statepath);
}
else
{
int len = strlen(statepath);
if ((statepath[len - 1] != 's') && (statepath[len - 1] != 'S'))
{
sprintf(newPath, "%s.wss", statepath);
}
else if ((statepath[len - 2] != 's') && (statepath[len - 2] != 'S'))
{
sprintf(newPath, "%s.wss", statepath);
}
else if ((statepath[len - 3] != 'w') && (statepath[len - 3] != 'w'))
{
sprintf(newPath, "%s.wss", statepath);
}
else if (statepath[len - 4] != '.')
{
sprintf(newPath, "%s.wss", statepath);
}
else
{
sprintf(newPath, "%s", statepath);
}
}
int fp = open(newPath, O_RDWR | O_CREAT, 0644);
if (fp == -1)
{
return (0);
}
write(fp, &crc, 2);
MacroStoreNecRegisterToFile(fp, NEC_IP);
MacroStoreNecRegisterToFile(fp, NEC_AW);
MacroStoreNecRegisterToFile(fp, NEC_BW);
MacroStoreNecRegisterToFile(fp, NEC_CW);
MacroStoreNecRegisterToFile(fp, NEC_DW);
MacroStoreNecRegisterToFile(fp, NEC_CS);
MacroStoreNecRegisterToFile(fp, NEC_DS);
MacroStoreNecRegisterToFile(fp, NEC_ES);
MacroStoreNecRegisterToFile(fp, NEC_SS);
MacroStoreNecRegisterToFile(fp, NEC_IX);
MacroStoreNecRegisterToFile(fp, NEC_IY);
MacroStoreNecRegisterToFile(fp, NEC_BP);
MacroStoreNecRegisterToFile(fp, NEC_SP);
MacroStoreNecRegisterToFile(fp, NEC_FLAGS);
MacroStoreNecRegisterToFile(fp, NEC_VECTOR);
MacroStoreNecRegisterToFile(fp, NEC_PENDING);
MacroStoreNecRegisterToFile(fp, NEC_NMI_STATE);
MacroStoreNecRegisterToFile(fp, NEC_IRQ_STATE);
write(fp, internalRam, 65536);
write(fp, ws_staticRam, 65536);
write(fp, ws_ioRam, 256);
write(fp, ws_paletteColors, 8);
write(fp, ws_palette, 16 * 4 * 2);
write(fp, wsc_palette, 16 * 16 * 2);
write(fp, &ws_videoMode, 1);
write(fp, &ws_gpu_scanline, 1);
write(fp, externalEeprom, 131072);
ws_audio_writeState(fp);
close(fp);
#endif
return (1);
}
int ws_rotated(void)
{
//uint8_t *rom = memory_getRom();
//uint32_t romSize = memory_getRomSize();
//return (rom[romSize - 4] & 1);
return 0;
}

View File

@@ -1,523 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// Wonderswan emulator
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
// 07.04.2002: speed problems partially fixed
// 13.04.2002: Set cycles by line to 256 (according to toshi)
// this seems to work well in most situations with
// the new nec v30 cpu core
//
//
//
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include "log.h"
#include "rom.h"
#include "./nec/nec.h"
#include "./nec/necintrf.h"
#include "memory.h"
#include "gpu.h"
#include "io.h"
#include "audio.h"
#include "ws.h"
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint32_t ws_cycles;
uint32_t ws_skip;
uint32_t ws_cyclesByLine=0;
uint32_t vblank_count=0;
char *ws_sram_path = NULL;
char *ws_ieep_path = NULL;
char *ws_rom_path = NULL;
extern int ws_gpu_forceColorSystemBool;
extern int ws_gpu_forceMonoSystemBool;
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_patchRom(void)
{
uint8_t *rom=memory_getRom();
uint32_t romSize=memory_getRomSize();
fprintf(log_get(),"developper Id: 0x%.2x\nGame Id: 0x%.2x\n",rom[romSize-10],rom[romSize-8]);
if (!ws_cyclesByLine)
{
ws_cyclesByLine=256;
}
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int ws_init(char *rompath)
{
uint8_t *rom;
uint32_t romSize;
if ((rom=ws_rom_load(rompath,&romSize))==NULL)
{
printf("Error: cannot load %s\n",rompath);
return(0);
}
if ((ws_gpu_forceColorSystemBool == 0) && (ws_gpu_forceMonoSystemBool == 0))
{
/* Nothing forced try to "auto detect" */
if (rompath[strlen(rompath)-1]=='c')
{
ws_gpu_operatingInColor=1;
}
else
{
ws_gpu_operatingInColor=0;
}
}
ws_memory_init(rom, romSize);
ws_patchRom();
ws_staticRam = (uint8_t *)load_file(ws_ieep_path);
if (ws_staticRam == NULL)
{
ws_staticRam = (uint8_t *)create_file(ws_sram_path, 0x10000);
}
if (ws_staticRam == NULL)
{
printf("Card SRAM load error!\n");
return 0;
}
externalEeprom = (uint8_t *)load_file(ws_ieep_path);
if (externalEeprom == NULL)
{
externalEeprom = (uint8_t *)create_file(ws_ieep_path, 0x100000);
}
if (externalEeprom == NULL)
{
printf("Card EEPROM load error!\n");
return 0;
}
ws_io_init();
ws_audio_init();
ws_gpu_init();
if (ws_rotated())
{
ws_io_flipControls();
}
return(1);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_reset(void)
{
ws_memory_reset();
ws_io_reset();
ws_audio_reset();
ws_gpu_reset();
nec_reset(NULL);
nec_set_reg(NEC_SP,0x2000);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int ws_executeLine(int16_t *framebuffer, int renderLine)
{
int drawWholeScreen=0;
ws_audio_process();
// update scanline register
ws_ioRam[2]=ws_gpu_scanline;
/* Why twice like that and random cycle count???? */
ws_cycles=nec_execute((ws_cyclesByLine>>1)+(rand()&7));
ws_cycles+=nec_execute((ws_cyclesByLine>>1)+(rand()&7));
if(ws_cycles>=ws_cyclesByLine+ws_cyclesByLine)
{
ws_skip=ws_cycles/ws_cyclesByLine;
}
else
{
ws_skip=1;
}
ws_cycles%=ws_cyclesByLine;
for(uint32_t uI=0; uI<ws_skip; uI++)
{
if (renderLine)
{
ws_gpu_renderScanline(framebuffer);
}
ws_gpu_scanline++;
if(ws_gpu_scanline==144)
{
drawWholeScreen=1;
}
}
if(ws_gpu_scanline>158)
{
ws_gpu_scanline=0;
{
if((ws_ioRam[0xb2]&32)) /* VBLANK Timer */
{
/* TODO: REPAIR THAT SHIT */
ws_ioRam[0xb6]&=~32;
nec_int((ws_ioRam[0xb0]+5)*4);
}
}
}
ws_ioRam[2]=ws_gpu_scanline;
if(drawWholeScreen)
{
if(ws_ioRam[0xb2]&64) /* VBLANK INT */
{
ws_ioRam[0xb6]&=~64;
nec_int((ws_ioRam[0xb0]+6)*4);
}
vblank_count++;
}
if(ws_ioRam[0xa4]&&(ws_ioRam[0xb2]&128)) /*HBLANK TMR*/
{
/* TODO: Check that shit */
if(!ws_ioRam[0xa5])
{
ws_ioRam[0xa5]=ws_ioRam[0xa4];
}
if(ws_ioRam[0xa5])
{
ws_ioRam[0xa5]--;
}
if((!ws_ioRam[0xa5])&&(ws_ioRam[0xb2]&128))
{
ws_ioRam[0xb6]&=~128;
nec_int((ws_ioRam[0xb0]+7)*4);
}
}
if((ws_ioRam[0x2]==ws_ioRam[0x3])&&(ws_ioRam[0xb2]&16)) /*SCANLINE INT*/
{
ws_ioRam[0xb6]&=~16;
nec_int((ws_ioRam[0xb0]+4)*4);
}
return(drawWholeScreen);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_done(void)
{
ws_memory_done();
ws_io_done();
ws_audio_done();
ws_gpu_done();
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_set_colour_scheme(int scheme)
{
ws_gpu_set_colour_scheme(scheme);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_set_system(int system)
{
if (system==WS_SYSTEM_COLOR)
{
ws_gpu_forceColorSystem();
}
else if (system==WS_SYSTEM_MONO)
{
ws_gpu_forceMonoSystem();
}
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
#define MacroLoadNecRegisterFromFile(F,R) \
read(fp,&value,sizeof(value)); \
nec_set_reg(R,value);
int ws_loadState(char *statepath)
{
fprintf(log_get(),"loading %s\n",statepath);
uint16_t crc=memory_getRomCrc();
uint16_t newCrc;
unsigned value;
uint8_t ws_newVideoMode;
int fp = open(statepath, O_RDONLY);
if (fp == -1)
{
return(0);
}
read(fp, &newCrc, 2);
if (newCrc!=crc)
{
return(-1);
}
MacroLoadNecRegisterFromFile(fp,NEC_IP);
MacroLoadNecRegisterFromFile(fp,NEC_AW);
MacroLoadNecRegisterFromFile(fp,NEC_BW);
MacroLoadNecRegisterFromFile(fp,NEC_CW);
MacroLoadNecRegisterFromFile(fp,NEC_DW);
MacroLoadNecRegisterFromFile(fp,NEC_CS);
MacroLoadNecRegisterFromFile(fp,NEC_DS);
MacroLoadNecRegisterFromFile(fp,NEC_ES);
MacroLoadNecRegisterFromFile(fp,NEC_SS);
MacroLoadNecRegisterFromFile(fp,NEC_IX);
MacroLoadNecRegisterFromFile(fp,NEC_IY);
MacroLoadNecRegisterFromFile(fp,NEC_BP);
MacroLoadNecRegisterFromFile(fp,NEC_SP);
MacroLoadNecRegisterFromFile(fp,NEC_FLAGS);
MacroLoadNecRegisterFromFile(fp,NEC_VECTOR);
MacroLoadNecRegisterFromFile(fp,NEC_PENDING);
MacroLoadNecRegisterFromFile(fp,NEC_NMI_STATE);
MacroLoadNecRegisterFromFile(fp,NEC_IRQ_STATE);
read(fp,internalRam,65536);
read(fp,ws_staticRam,65536);
read(fp,ws_ioRam,256);
read(fp,ws_paletteColors,8);
read(fp,ws_palette,16*4*2);
read(fp,wsc_palette,16*16*2);
read(fp,&ws_newVideoMode,1);
read(fp,&ws_gpu_scanline,1);
read(fp,externalEeprom,131072);
ws_audio_readState(fp);
close(fp);
// force a video mode change to make all tiles dirty
ws_gpu_clearCache();
return(1);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
#define MacroStoreNecRegisterToFile(F,R) \
value=nec_get_reg(R); \
write(fp,&value,sizeof(value));
int ws_saveState(char *statepath)
{
uint16_t crc=memory_getRomCrc();
uint32_t value;
char *newPath;
fprintf(log_get(),"saving %s\n",statepath);
newPath=new char[1024];
if (strlen(statepath)<4)
{
sprintf(newPath,"%s.wss",statepath);
}
else
{
int len=strlen(statepath);
if ((statepath[len-1]!='s')&&(statepath[len-1]!='S'))
{
sprintf(newPath,"%s.wss",statepath);
}
else if ((statepath[len-2]!='s')&&(statepath[len-2]!='S'))
{
sprintf(newPath,"%s.wss",statepath);
}
else if ((statepath[len-3]!='w')&&(statepath[len-3]!='w'))
{
sprintf(newPath,"%s.wss",statepath);
}
else if (statepath[len-4]!='.')
{
sprintf(newPath,"%s.wss",statepath);
}
else
{
sprintf(newPath,"%s",statepath);
}
}
int fp=open(newPath, O_RDWR|O_CREAT, 0644);
delete newPath;
if (fp==-1)
{
return(0);
}
write(fp,&crc,2);
MacroStoreNecRegisterToFile(fp,NEC_IP);
MacroStoreNecRegisterToFile(fp,NEC_AW);
MacroStoreNecRegisterToFile(fp,NEC_BW);
MacroStoreNecRegisterToFile(fp,NEC_CW);
MacroStoreNecRegisterToFile(fp,NEC_DW);
MacroStoreNecRegisterToFile(fp,NEC_CS);
MacroStoreNecRegisterToFile(fp,NEC_DS);
MacroStoreNecRegisterToFile(fp,NEC_ES);
MacroStoreNecRegisterToFile(fp,NEC_SS);
MacroStoreNecRegisterToFile(fp,NEC_IX);
MacroStoreNecRegisterToFile(fp,NEC_IY);
MacroStoreNecRegisterToFile(fp,NEC_BP);
MacroStoreNecRegisterToFile(fp,NEC_SP);
MacroStoreNecRegisterToFile(fp,NEC_FLAGS);
MacroStoreNecRegisterToFile(fp,NEC_VECTOR);
MacroStoreNecRegisterToFile(fp,NEC_PENDING);
MacroStoreNecRegisterToFile(fp,NEC_NMI_STATE);
MacroStoreNecRegisterToFile(fp,NEC_IRQ_STATE);
write(fp,internalRam,65536);
write(fp,ws_staticRam,65536);
write(fp,ws_ioRam,256);
write(fp,ws_paletteColors,8);
write(fp,ws_palette,16*4*2);
write(fp,wsc_palette,16*16*2);
write(fp,&ws_videoMode,1);
write(fp,&ws_gpu_scanline,1);
write(fp,externalEeprom,131072);
ws_audio_writeState(fp);
close(fp);
return(1);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int ws_rotated(void)
{
uint8_t *rom=memory_getRom();
uint32_t romSize=memory_getRomSize();
return(rom[romSize-4]&1);
}

View File

@@ -1,37 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __WS_H__
#define __WS_H__
#define WS_SYSTEM_MONO 0
#define WS_SYSTEM_COLOR 1
#define WS_SYSTEM_AUTODETECT 2
extern uint32_t ws_cyclesByLine;
int ws_init(char *rompath);
int ws_rotated(void);
void ws_set_colour_scheme(int scheme);
void ws_set_system(int system);
void ws_reset(void);
int ws_executeLine(int16_t *framebuffer, int renderLine);
void ws_patchRom(void);
int ws_loadState(char *statepath);
int ws_saveState(char *statepath);
void ws_done(void);
extern char *ws_sram_path;
extern char *ws_ieep_path;
extern char *ws_rom_path;
#endif

View File

@@ -1,3 +1,11 @@
/******************************************************************************
* NewOswan
* testserial.c: A simple tool to test serial in/out
*
* Copyright (c) 2014-2022 986-Studio. All rights reserved.
*
******************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -7,6 +15,10 @@
#include <errno.h> /* Error number definitions */ #include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */ #include <termios.h> /* POSIX terminal control definitions */
/*
* The code, as is, was part of a fuzzer for the WonderSwan Tetris game.
*/
/* Serial port */ /* Serial port */
#define BDR_9600 (0) #define BDR_9600 (0)
#define BDR_38400 (1) #define BDR_38400 (1)