Giter Club home page Giter Club logo

devkitsms's People

Contributors

amoibos avatar computernerd avatar gokuone avatar joppyfurr avatar megakode avatar mikehdt avatar raphnet avatar sverx avatar wootguy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

devkitsms's Issues

Ability to install a vblank handler

It would be nice to have a SMS_setVerticalInterruptHandler() to install a callback that would run every vblank, similar to the way line interrupts work.

Adding examples to this repo

I was wondering what you would think of adding an examples/ directory to the root of the repo, where examples and demos using different devkitSMS features could be added? I notice there is no such thing, so maybe you prefer to have this elsewhere?

For instance, when contributing new features, I often make a simple program to test it but there is no good place to share it right now. I think it would make sense to have examples here, those could also be an easy starting point for new projects.

32bits variables

It's not a problem, but is there a way to make calculations with 32-bit variables?

tried:

unsigned long ab = 0x10001;
char buffer[24];
sprintf(buffer, "%d", sizeof(ab));
draw_text(buffer, 9, 2);
sprintf(buffer, "%d", ab);
draw_text(buffer, 9, 3);

But this print:
4 and 1, so unsignd long is 32 bits but why cannot show?

drawText method.

void draw_text(unsigned char* text, unsigned char x, unsigned char y)
{
//const unsigned int* pnt = devkitSMS_font__tiles__1bpp;
unsigned char idx = 0;
while ('\0' != text[idx])
{
signed char tile = text[idx];// -TEXT_ROOT;
SMS_setNextTileatXY(x++, y);
SMS_setTile(SMS_TextRenderer_offset + tile);
idx++;
}
}

Tile Id Offset Meta Sprite Feature Request

I don't know if this has been implemented yet, or exists. Say a metasprite has been defined eg:

// Frame 0 of multi framed sprite, for entity with loads of states, but tiles may be located differently for each instance:
const unsigned char sprite_00[] = { 0, 0, 0, 8, 0, 2, 16, 0, 4, 0, 16, 6, 8, 16, 8, 16, 16, 10, 0, 32, 12, 8, 32, 14, METASPRITE_END };

Is there a way to offset the tile id, so that the tile id starts with the array tile id + offset?

Sort of like:
SMS_addMetaSprite(x, y, [offset], sprite_00);

Where [offset] would be applied to the defined tile id for each sprite.

General questions about the library

Hi sverx

First of all, I want to really thank you for your work grouping all that code into a single, coherent unit. This way it is much easier to do something for the SMS (sometime I plan to do when I have enough time).

I also wanted to ask you some questions about it:

  • Does the library allow 8x16 sprites?
  • Is the library tested in real hardware? What about Mega Drive + everdrive combo?
  • What's your estimation about library's completeness? Is there something important lacking from it?
  • Do you plan to add some tutorials about several how to-s or a somewhat complete example?

Again, thak you very much for your work :)

Using PSGlib with banked code

Hey there! I'd like to ask for some help with integrating PSGlib onto a project while using banked code.

Up until now I had been compiling my project like this:
sdcc -c -mz80 vania.c sdcc -c -mz80 --constseg BANK2 assets.c sdcc -c -mz80 --codeseg BANK1 xtra.c sdcc -o vania.ihx -mz80 --no-std-crt0 --opt-code-speed --data-loc 0xC000 -Wl-b_BANK1=0x14000 -Wl-b_BANK2=0x28000 crt0b_sms.rel SMSlib.lib PSGlib.rel vania.rel xtra.rel assets.rel makesms vania.ihx build/vania.sms

So bank1 contains banked code and bank2 contains assets. It was working perfectly, but I decided to add one extra bank for code and another for data, so I could better understand the process. So it went:

sdcc -c -mz80 vania.c sdcc -c -mz80 --codeseg CODEBANK1 xtra.c sdcc -c -mz80 --codeseg CODEBANK2 newcode.c sdcc -c -mz80 --constseg DATABANK3 assets.c sdcc -c -mz80 --constseg DATABANK4 tilemap.c sdcc -o vania.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_CODEBANK1=0x14000 -Wl-b_CODEBANK2=0x24000 -Wl-b_DATABANK3=0x38000 -Wl-b_DATABANK4=0x48000 crt0b_sms.rel SMSlib.lib vania.rel xtra.rel newcode.rel assets.rel tilemap.rel makesms vania.ihx build/vania.sms

However, I found out (after way too long, haha) that the only way I could get the ROM to boot at all was by removing PSGlib from the project. It does boot, however there are some glitches due to (I guess) some overlap in RAM due to the lack of PSGlib.

So upon checking the readme for devkitSMS, there are no examples in which banked code is used alongside PSGlib. I've tried inserting the code for the library manually into my main file, to no avail. However, I copied the small example for banked code on SMSPower, added PSGlib to the command line and got it to work fine. (I should note however that I did not test if the library itself worked)

I noticed that apparently PSGlib located itself on bank0 in this test project, so I thought that maybe there was not enough room on bank0, although I doubt this is the case since theres is 4K+ left, and when using PSGlib before it still had 3K+.

So finally, my question is whether it's even possible to use PSGlib with banked code, if there's some detail I'm missing, etc.

Thanks in advance! =D

PSGSetMusicVolumeAttenuation seems not to be working

I'm trying to implement a fade-in , fade-out with the music, but it looks like the PSGSetMusicVolumeAttenuation is not working properly. Setting it to any value (from 0 to 15) makes the music be reduced a some static cracks. Has anyone tried to perform such a fade effect?

SMS_saveROMBank() implementation in SMSLib.h makes it only usable in the same scope as SMS_restoreBank()

SMS_saveROMBank is implemented as the following define:

#define SMS_saveROMBank() unsigned char _saved_slot2_ROM_bank = ROM_bank_to_be_mapped_on_slot2

This causes the var _saved_slot2_ROM_bank to be defined only in the same scope where SMS_saveROMBank is used. So, any call to SMS_restoreROMBank outside that scope will fail.

As an example, in my codebase have something like

if(flashCartridge) {
     SMS_saveROMBank();
     SMS_mapBANK(SAVE_BANK);
} else {
    SMS_enableSRAM();
}
//Do saving stuff
if(flashCartridge) {
     SMS_restoreROMBank();
} else {
    SMS_disableSRAM();
}

Interrupt and VDP processing

I'm working on H-INT and V-INT.

When my program is using VDP function while H-INT and V-INT, graphics glitches sometimes occur.
Yes, I know the reason, both main loop and H/V-INT uses VDP function, graphics glitches occur.

Can I avoid this issue? I think DISABLE_INTERRUPTS & ENABLE_INTERRUPTS is not work properly...

issue with compressed songs spawning multiple banks

Hey @raphnet !

I had an heads up about a strange bug that happens only with compressed songs with the PSGLIB_MULTIBANK version of the PSGlib library.

I suspect the issue happens when the two-byte address of a substring ends up exactly at the end of the bank ($BFFE, $BFFF) - in this case the mapper still retains the 'old' bank number when you get to this line so when the compressed block ends the music continues from the beginning of the bank that is the previous one instead of the one that should be, as you're saving $8000 in HL
ld (_PSGMusicSubstringRetAddr),hl ; save return address
but you're NOT saving the incremented bank number...

Can you look into this? Thanks! 🙇

Macros to save/restore the bank mapped to slot2?

I was wondering if macros to save/restore the bank mapped to slot 2 would be something you would like to add to SMSlib.

Here is something I find extremely useful in my projects regarding data access by slot2. My convention is that by default, whenever the bank has to be changed to access data, it is to be set back to what it was before returning to avoid unwanted side effects.

For instance, in complex code which accesses banked data but also does calls to functions which may in turn also need to access banked data (in different banks), this helps a lot:

#define SAVEBANK()  uint8_t _org_bank = ROM_bank_to_be_mapped_on_slot2
#define RESTOREBANK()   SMS_mapROMBank(_org_bank)

So I just place one SAVEBANK() in the function, change the bank any number of time, and add one RESTOREBANK() before each return statement.

Using the above I also implemented a few convenience macros around the default SMSlib functions like this one:

#define SMS_loadTilesBank(src,bank,tilefrom,size) \ 
        do { \ 
            SAVEBANK(); \
            SMS_mapROMBank(bank); \
            SMS_loadTiles(src, tilefrom, size); \
            RESTOREBANK(); \
        } while(0)

What do you think? Let me know if you would like me to prepare a pull request.

assets2banks with files > 16kb in size

Hello,

Have been trying to use assets2banks with files larger than 16kb and even with --allowsplitting it didn't output any banks, and just gave the "Fatal: no banks generated" error

I had a play about with the python code and managed to get it working by making some changes at around line 480 where i set the part.size and apartgrp.size like this:

                    if a.size <= gf and offset == 0:
                        apartgrp.add_asset(a)
                    else:
                        part = Asset(a.name + "_PART" + str(partno), l)
                        part.data = a.data[offset:offset+l]
                        part.size = l
                        apartgrp.size += l
                        apartgrp.add_asset(part)

I think apartgrp.size needs to be set as it's is used in the gf = 16384 - apartgrp.size and if apartgrp.size > 0: in that section to actually add the assets to banks

Have uploaded my modified version but I'm sure you'll know the proper way to do it!

Thanks,
Joe
assets2banks.zip

Can I use the makesms to convert the file that contains CODE and DATA bank

Can I use the makesms to convert the file that contains CODE and DATA bank?

func1.c~~~~~~
#pragma codeseg CODEBANK1
func1() __banked
~~~~~~

func2.c~~~~~~
#pragma codeseg CODEBANK2
func2() __banked
~~~~~~

data2.c~~~~~~
#pragma constseg DATABANK2
data2()
~~~~~~

data3.c~~~~~~
#pragma constseg DATABANK3
data3()
~~~~~~

#>sdcc -o file.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_CODEBANK1=0x14000 -Wl-b_CODEBANK2=0x24000 -Wl-b_DATABANK2=0x8000 -Wl-b_DATABANK3=0x8000 crt0b_sms.rel SMSlib.lib main.rel fun1.rel func2.rel data2.rel data3.rel
#> makesms file.ihx file.sms

-> It won't run properly...?

New Unsafe and Vertical Orientation Functions

First request:
While Devkit SMS has great horizontal consecutive tile setting functions, these are not as speedy if called for consecutive vertical tiles.

SMS_setNextTileatXY and SMS_setTile are pretty quick, especially if SMS_setNextTileatXY is set once before a loop calls SMS_setTile.
However, if the same is done in a vertical orientation of consecutive tiles. It takes quite a performance hit.
May I suggest a SMS_setNextTileatYX, or something to that affect?

The general thought is that whatever auto incrementor that is used for consecutive horizontal tiles function, can be utilized for consecutive vertical tiles, as well.

Second Request:
UNSAFE versions of SMS_VRAMmemset and SMS_VRAMmemsetW

Thank you for your time.

MetaSprite clipping?

Using metasprites seems to clip sprites when they hit the top of the screen (y = 0). If I use the old addSprite method, the sprite stays on screen partially. Is this by design?

Example project

I'm very interested to use this library but I wondered if there are any sample projects that use this library? I've searched but haven't been able to find anything.

PSGLib - Allow to set volume attenuation on SFX

In PSGLib, the function void PSGSetMusicVolumeAttenuation (unsigned char attenuation); exists and it's great.

I want to use it to lower the volume all of the music to compensate for the SMS2's sound volume ramp being squashed in the upper values, and have it as an option to toggle in my game.
However, I noticed that there was no equivalent function for the sound effects.

Is it trivial enough to add?

SG/SC -> SG_byte_brief_array_to_VDP_data

Hi, I read the content of SG_byte_brief_array_to_VDP_data function and I found it copies data from a ram buffer to SAT.
I wonder if you can insert a reverse-copy function in order manage the sprites-on-a-line limit (4 on SC/SG).
Usually I copy SAT buffer to vram SAT in normal mode on even frames and copy SAT buffer to vram SAT in reverse mode on odd frames.
Probably (if I didn't see it) could be useful a "SG_byte_reverse_array_to_VDP_data" function.

Times ago I built it by myself in ASM but I put it in CRT function as standard/fast function.

What do you think about it?

Cheers,
Saverio

Need clear vram on startup

Hello!!!
When running on real Master System II, the logo SEGA dont is removed after devkit finish startup.
Configured the Emulicious emu with same bios(EU with Alex kid in memory), cause the same issue. Só i make a clearscreen code in asm and run at begin from me main program.
I dont know how to do a Pull requests (rsrsrs) so, need clear vram at startup to remove logo SEGA from screen.
Thats not a issue, Sorry doing this here

SC-3000 Cassette Support

Hi,

I'm not sure where else to put this, but I've been playing with loading SGlib programs from tape and have now got interrupts working. I thought I'd post a copy of my modified crt0_sg.s here in case you wanted to make use of it.

The LOAD command from basic puts things at 0x9800
It is jumped to using CALL &H9800 from BASIC.

For memory layout, I use:

  • 0x8000 as the start of work-ram, for 5.5 KiB
  • 0x9600 as the interrupt vector table (using interrupt-mode 2)
  • 0x9800 is the start of loaded code, where the first line of crt0 gets placed
  • 0x9898 is the interrupt vector
  • 0x98a0 is the code-loc that I pass to the linker, although I'm not sure if this is needed. The intention was to prevent user-code from clobbering anything in crt0.

If counting from 0x9800, the program can reach 12 KiB on a BASIC IIIa cartridge, or 26 KiB on a BASIC IIIb cartridge.

Cheers,
Joppy

;--------------------------------------------------------------------------
; *** this is a modified version aimed to SG-1000 homebrew - sverx\2015 ***
; *** additional changes aimed at SC-3000 tape homebrew - JoppyFurr\2024 ***
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
;  crt0.s - Generic crt0.s for a Z80
;
;  Copyright (C) 2000, Michael Hope
;
;  This library is free software; you can redistribute it and/or modify it
;  under the terms of the GNU General Public License as published by the
;  Free Software Foundation; either version 2, or (at your option) any
;  later version.
;
;  This library is distributed in the hope that it will be useful,
;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;  GNU General Public License for more details.
;
;  You should have received a copy of the GNU General Public License
;  along with this library; see the file COPYING. If not, write to the
;  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
;   MA 02110-1301, USA.
;
;  As a special exception, if you link this library with other files,
;  some of which are compiled with SDCC, to produce an executable,
;  this library does not by itself cause the resulting executable to
;  be covered by the GNU General Public License. This exception does
;  not however invalidate any other reasons why the executable file
;   might be covered by the GNU General Public License.
;--------------------------------------------------------------------------


; SC-3000 Tape Changes:
;  - No interrupt handling, BASIC owns the vector addresses.
;  - Code begins at 0x9800
;    -> Has up to 0xc7ff for BASIC IIIa (12 KiB)
;    -> Has up to 0xffff for BASIC IIIb (26 KiB)
;  - RAM at 0x8000 -- 0x95ff (5.5 KiB) will be free once we take over from basic.
;  - Interrupt Vector table at 0x9600 -- 0x9700 (257 bytes)

  .module crt0
  .globl  _main
  .area _HEADER (ABS)
  .org 0x9800

start::
  di                ; disable interrupt
  ld sp,#0x95f0     ; set stack pointer at end of our 5.5k block of RAM
  xor a             ; clear RAM (to value 0x00)
  ld hl,#0x8000     ;   by setting value 0
  ld (hl),a         ;   to $c000 and
  ld de,#0x8001     ;   copying (LDIR) it to next byte
  ld bc,#0x1600-17  ;   for 5.5 KB minus 17 bytes
  ldir              ;   do that

  ;; ensure this runs fine on SC-3000 too
  ld a,#0x92
  out (0xDF),a      ; Config PPI (no effect on SG-1000)
  ld a,#7
  out (0xDE),a      ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000)

  ;; Set up for interrupt-mode 2
  ;; Register I controls the vector MSB. The vector LSB is whatever happens to be on the bus.
  ;; So, a 257-entry table with a single repeated byte (0x98) will give us a reliable 0x9898 call.
  im 2              ; interrupt mode 2 (this will not change)
  ld a,#0x96        ; Vector table at 0x9600, between work-ram and code.
  ld i,a

  ld a,#0x98
  ld hl,#0x9600
  ld (hl),a         ; Initialize first byte of vector table at 0x9600 to value 0x98
  ld de,#0x9601     ; Prepare copy to the next byte
  ld bc,#0x0100     ; Copy for 256 bytes, giving 257 bytes total.
  ldir

  ;; Initialise global variables
  call    gsinit
  call    _SG_init
  ei                ; re-enable interrupts before going to main()
  call  _main
  jp  _exit

  .org 0x9898       ; handle IRQ
  jp _SG_isr

  ;; Ordering of segments for the linker.
  .area _HOME
  .area _CODE
  .area _INITIALIZER
  .area   _GSINIT
  .area   _GSFINAL

  .area _DATA
  .area _INITIALIZED
  .area _BSEG
  .area   _BSS
  .area   _HEAP

  .area   _CODE
__clock::
  ld  a,#2
  rst     0x08
  ret

_exit::
  ;; Exit - special code to the emulator
  ld a,#0
  rst 0x08
1$:
  halt
  jr 1$

  .area   _GSINIT
gsinit::
  ld  bc, #l__INITIALIZER
  ld  a, b
  or  a, c
  jr  Z, gsinit_next
  ld  de, #s__INITIALIZED
  ld  hl, #s__INITIALIZER
  ldir
gsinit_next:

  .area   _GSFINAL
  ret

I cannot compile this unless I add #include <stdbool.h> to SMSlib.h

I am wondering how you were able to compile devkitSMS without the extra include. What stdbool.h does according to http://pubs.opengroup.org/onlinepubs/9699919799//basedefs/stdbool.h.html is expand bool to _Bool which allows me to compile it. Doing a search and replace for bool changing it to _Bool also allows me to compile it.

In C there is no keyword that I am aware of called bool; only _Bool please see http://en.cppreference.com/w/c/keyword.

I am using the latest snapshot of SDCC as of the time of writing the issue which is: 3.5.2 #9277

devkitSMS adopted in z88dk

Thank you sverx for writing such a great library for sms. We like to collect shiny things in z88dk so devkitSMS has been incorporated into the new c library in z88dk for the sms. What has not been implemented is anything associated with GG or SC1000 as we're not sure yet if those machines are better served by their own independent targets inside z88dk; if it's decided to keep them part of the sms target, those functions will be added too. I chose not to go the fork route because keeping things compatible with sdcc was restricting too much what we could do.

I am sharing to let you know, first of all, but also because you are welcome to take anything back into the original project that you may find useful. In particular we've rewritten the C bits in assembler and separated each function into individual files. The assembler rewrite reduces size and allows more preserve_regs flags to be specified which can improve on code quality a small amount. It also makes the library directly accessible to asm programmers. The fine granularity allows the linker to pick out individual subroutines from the library which can reduce program size somewhat.

SDCC-compatible headers

  • You will see defines in terms of "__FOO". Defines are kept in the implementation's namespace (beginning with double underscore) and then are selectively revealed into the user's namespace via header files.

PSGlib source code
SMSlib source code

  • c/sdcc holds the c interface to the assembly functions
  • z80 holds the assembly implementation

How devkitSMS is configured inside z88dk

  • Lines 10-18 are meant to be user-configurable. I'm not sure if modifying PNTADDRESS, SATADDRESS, CRAMADDRESS is all it takes to move these things around in VRAM?
  • The ENABLE_MDPAD option is used to control whether the regular ISR or the MDPAD_ISR is active when the devkitSMS crt is used.
  • Non-zero values for ISRST_SMSCRT0RSTXX will cause calls to the SMS_CRT0_RSTXX functions to be replaced with restarts.

devkitSMS page zero code

  • Optional page zero code for crts that want to have devkitSMS automatically configured in compiles.

devkitSMS crt

  • Follows the page zero code above.

You can use devkitSMS with any crt but a devkitSMS-specific one is selected with "-startup=8" on compile lines. What this will do is place the two RSTs and the MI / NMI isrs in the right places, like what is done with native devkitSMS's crt for sdcc.

For testing we are using some source from the smspower website:

split-screen
Your split screen example. The original bmp assets are not committed - only the processed form required by the compile. I hope it's ok if we can use it in our examples directory?

These others we do not have permission to host so they are temporarily in a separate branch that will ultimately be deleted:
Temporary Examples
(I'm also still working a bit in there so the readme.txt are a little curt)

The one main difference between devkitSMS and this adaptation is that the macros used to defined the SEGA/SDSC headers are turned into no-ops. In z88dk, header information is specified via pragmas which you will find (optionally) defined in zpragma.inc files associated with the examples above.

Thanks again sverx; feel free to close any time.

SMS_setTileatXY

#enhancement

Is there any way to assign tile flags to the target? In my use case, it would be nice if the target xy tile used the sprite palette instead of the background palette. I'd imagine if this were supported, that you would need to consider the other bits as well (flipping, priority, etc.. etc..)

Unless there's another function that would be better for this. I do like the simplicity of the function, when changing a single tile on the map. Thank you for your time.

crt0_sg.s incorrect initialization of I/O chip

Hi,

I noticed when testing my code on an SC-3000H, that gamepad input was not working correctly.
Instead of taking input from my gamepad, the input was coming from a handful of keyboard keys.

It looks like the cause is that in crt0_sg.s, the I/O chip control register is being initialized with 0x9f when it should be initialized with 0x92.

  ld a,#0x9F
  out (0xDF),a      ; Config PPI (no effect on SG-1000)

Cheers,
Joppy

ihx2sms fails with multi-segment static libraries

When linking with a static library containing multiple code segments/banks, SDCC seems to arrange the segments in a random order (not in the order the lib sources were compiled and linked). This breaks ihx2sms because it assumes segment order == link order.

One way to solve this would be to have ihx2sms read the .map file which shows the order SDCC placed the segments in the .ihx file. Doing that would also eliminate the need to link objects in a specific order.

SMS_readPaddle() never returns if the paddle is disconnected

When the paddle reading functions were reworked and replaced by assembly code, the return value changed from int to unsigned char. This exactly fits the range of values reported by a paddle, which is good, but then there is no longer a way to report a timeout which occurs if the user disconnects the paddle.

So I was wondering if a pull request changing the return type back to int and also implementing timeouts in the assembly code would be acceptable or not. Is it allowed (by the SMS user manual) to change controllers when the power is on anyway?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.