| Разработка и ромхакинг > Программирование |
| z88dk и блочная графика |
| (1/1) |
| SMax:
Делаю игрушку на C z88dk под zx80. Никак не могу победить блочную графику, выводит пустые строки и всё. Коды с 0x80 по 0x8F. Уже по всякому изгалялся, никак не выводятся. Подскажите как блочную графику вывести на экран? --- Код: ---#include <stdio.h> void main(void) { int i; printf("System character set test:\n"); printf("==========================\n"); // Тест стандартных ASCII символов printf("ASCII (32-127): "); for(i = 32; i < 127; i++) { putchar(i); } printf("\n\n"); // Тест символов блочной графики printf("Block graphics (128-143):\n"); for(i = 128; i <= 143; i++) { printf("Code %3d: [%c]\n", i, (char)i); } // Тест альтернативных кодов printf("\nAlternative codes (176-223):\n"); for(i = 176; i <= 223; i++) { printf("%c", (char)i); } printf("\n"); } --- Конец кода --- zcc +zx -lm -create-app -clib=sdcc_iy -o blocks blocks.c |
| Sharpnull:
Стандартный шрифт в роме и кодировка (набор символов) такая https://en.wikipedia.org/wiki/ZX80_character_set. Можно определить свой шрифт https://github.com/z88dk/z88dk/wiki/Classic-GenericConsole#defining-a-custom-font, пример кода https://github.com/z88dk/z88dk/blob/2e38490f409973d45e8af4844bd2e58f4ec21e28/examples/spectrum/fontexample.c. UPD: Я дал пример кода для ZX Spectrum, а не ZX80. |
| SMax:
--- Цитата: Sharpnull от 21 Октябрь 2025, 11:32:24 ---Стандартный шрифт в роме и кодировка (набор символов) такая https://en.wikipedia.org/wiki/ZX80_character_set. Можно определить свой шрифт https://github.com/z88dk/z88dk/wiki/Classic-GenericConsole#defining-a-custom-font, пример кода https://github.com/z88dk/z88dk/blob/2e38490f409973d45e8af4844bd2e58f4ec21e28/examples/spectrum/fontexample.c. UPD: Я дал пример кода для ZX Spectrum, а не ZX80. --- Конец цитаты --- Да, я что-то ошибся. Мне надо для ZX Spectrum. По ссылкам пробежался. Не совсем то что надо, но всё равно спасибо большое. Пригодится. Особенно fontexample.c Хотелось бы чтобы просто набрал что-то вроде printf("\x8B\x83\x87\n"); и не заморачиваться с костылями. |
| Sharpnull:
Оказывается, что z88dk определяет шрифты только до 127, с 128 нужно задать самому https://github.com/z88dk/z88dk/wiki/Classic-GenericConsole#defining-udgs. Я взял из z88dk\examples\console\dstar_gencon.c код для простого вывода доп. символов 0x80 - 0x83: --- Код: ---#include <stdio.h> #include <font/font.h> #include <sys/ioctl.h> static unsigned char udgs[] = { 0b01111110, // Wall 0b10101001, 0b11000111, 0b10110001, 0b11001011, 0b10100101, 0b10101001, 0b01111110, 0b00000000, // bubble 0b00000000, 0b00011000, 0b00100100, 0b00100100, 0b00011000, 0b00000000, 0b00000000, 0b00000000, // movable ball 0b00111100, 0b01110110, 0b01111010, 0b01111010, 0b01111110, 0b00111100, 0b00000000, 0b00000000, // movable block 0b01111110, 0b01000010, 0b01000010, 0b01000010, 0b01000010, 0b01111110, 0b00000000}; void print(const char *name, void *font); int main() { void *param = &udgs; console_ioctl(IOCTL_GENCON_SET_UDGS, ¶m); printf("%c%c\n",1,32); print("default", (void *)15616); printf("Test \x80\x81\x82\x83"); getchar(); } void print(const char *name, void *font) { console_ioctl(IOCTL_GENCON_SET_FONT32, &font); printf("This is font %s\n",name); for ( int i = 32 ; i < 128 + 4; i++ ) { printf("%c",i); } printf("\n\n"); } --- Конец кода --- Компилировал как zcc +zx -vn -lndos fontexample.c -create-app -o fontexample.bin. Вам остаётся в udgs добавить свою графику символов. UPD: Вы можете нарисовать шрифт в 8x8 Pixel ROM Font Editor https://www.min.at/prinz/o/software/pixelfont/ и File > Export as C include. UPD2: Для теста я использовал 128-255 символы: |
| SMax:
Я тоже подумал про UDG, хотя это ненормально, если уже есть готовые символы в ZX Spectrum. Даже уже начал рисовать эти символы. А потом просто написал вопрос на форуме www.z88dk.org https://www.z88dk.org/forum/viewtopic.php?t=12088 И мне ответили! Работает! --- Код: ---/* * zcc +zx -vn -startup=30 -clib=sdcc_iy block.c -o block -create-app */ #include <stdio.h> void main(void) { for( uint8_t i=0x80; i <= 0x8F; i++ ) { printf("0x%02X = %c\n", i, i); } } --- Конец кода --- |
| Sharpnull:
--- Цитата: SMax от 21 Октябрь 2025, 18:48:56 ---Работает! --- Конец цитаты --- Получается отличие только в -startup=30, этот параметр задаёт вариант для target. Их много https://github.com/z88dk/z88dk/tree/2e38490f409973d45e8af4844bd2e58f4ec21e28/libsrc/_DEVELOPMENT/target/zx/startup, со значением 30, кроме системного шрифта, ещё какие-то изменения. Ещё бы знать где посмотреть подробное описание каждого значения, но это уже проблема разработчиков под ZX. |
| SMax:
Про это описано в ZXSpectrumZSDCCnewlib_02_HelloWorld.md #### -startup=30 (crt30) 32x24 rom print routine, no scanf much smaller than other crts because the rom is used for output Я не телепат, как понять, что это то что мне надо?! Ну хоть что-то! На самом деле я уже счастлив, не надо использовать костыли! Моя игра чисто текстовая (ZX Spectrum 48K) и каждый байт имеет значение. --- Код: ---/* * zcc +zx -vn -startup=30 -clib=sdcc_iy block.c -o block -create-app */ #include <stdio.h> void main(void) { printf("\x8B\x83\x7fMaxim_Sivkov_2025\x83\x87\n"); for (int i = 1; i < 19; i++) { printf("\x8A \x85\n"); } printf("\x8E\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8D"); } --- Конец кода --- |
| SMax:
Теперь другая проблема появилась. Не могу изменить цвет коды для INK, PAPER перестали работать. --- Код: ---puts("\x10\x31"); --- Конец кода --- Говорит Invalid Colour Прям беда какая-то. |
| Sharpnull:
--- Цитата: SMax от 22 Октябрь 2025, 12:32:55 ---Говорит Invalid Colour --- Конец цитаты --- Ну так -startup=30 не поддерживает control code, этот CRT по минимуму сделан. И про вопрос выше, также нет поддержки функции scanf(), которую вы знаете, но предполагаю, что чтение ввода всё-таки осталось, иначе был бы бесполезный CRT. |
| SMax:
--- Цитата: Sharpnull от 22 Октябрь 2025, 14:50:07 ---Ну так -startup=30 не поддерживает control code, этот CRT по минимуму сделан. И про вопрос выше, также нет поддержки функции scanf(), которую вы знаете, но предполагаю, что чтение ввода всё-таки осталось, иначе был бы бесполезный CRT. --- Конец цитаты --- Тяжко с нуля это всё воспринимать, особенно с учётом, что в Си я полный ноль. Незнание базовых библиотек и синтаксиса напрягает. Вот строка компиляции кода: zcc +zx -vn -startup=30 -clib=sdcc_iy -create-app minesweaper.c -o minesweaper И код: --- Код: ---#include <stdio.h> #include <arch/zx.h> //#include <arch/spectrum.h> //#include <stdlib.h> #define FLASH_ON "\x12\x31" #define FLASH_OFF "\x12\x30" #define BRIGHT_ON "\x13\x31" #define BRIGHT_OFF "\x13\x30" #define INK "\x10" #define PAPER "\x11" #define BLACK "\x30" #define BLUE "\x31" #define RED "\x32" #define WHITE "\x37" #define AT "\x16" #define printInk(k) printf("\x10%c", '0'+k) #define printPaper(k) printf("\x11%c", '0'+k) #define printAt(row, col) printf("\x16%c%c", (row)+32, (col)+32) void main(void) { zx_cls(PAPER_WHITE); zx_border(PAPER_BLACK); //puts(INK BLUE); //not work //zx_colour(112); //not work //zx_colour(PAPER_BLACK|INK_WHITE); //not work //printInk(1); //not work //printPaper(1); //not work //printAt(1,1); //not work printf("\x8B\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x87\n"); for (int i = 1; i < 20; i++) { printf("\x8A \x85\n"); } printf("\x8E\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8C\x8D\n\n"); } --- Конец кода --- Готов к любой идее как победить проблему. Даже если идея безумная. |
| Sharpnull:
--- Цитата: SMax от 22 Октябрь 2025, 18:02:40 ---Готов к любой идее как победить проблему --- Конец цитаты --- Возможно для CRT 30 стандартный для спектрума способ окрашивания текста. Я ввёл printf("\x16\x0A\x03\x10\x01\x11\x06\x13\x01Hello good Sir!"); и получил жёлтый фон и синий текст как здесь https://youtu.be/5qiXx5P6oUc?t=2443. Для \x16\x0A\x03\x10\x01\x11\x06\x13\x01 у него написано AT 22,3 INK Blue PAPER yellow FLASH 1. |
| SMax:
--- Цитата: Sharpnull от 22 Октябрь 2025, 20:36:24 ---Возможно для CRT 30 стандартный для спектрума способ окрашивания текста. Я ввёл printf("\x16\x0A\x03\x10\x01\x11\x06\x13\x01Hello good Sir!"); и получил жёлтый фон и синий текст как здесь https://youtu.be/5qiXx5P6oUc?t=2443. Для \x16\x0A\x03\x10\x01\x11\x06\x13\x01 у него написано AT 22,3 INK Blue PAPER yellow FLASH 1. --- Конец цитаты --- Оригинально получилось. Я всякие варианты перебирал, но не догадался ввести именно так. Что интересно, работают цвета с \x01 по \x07. На \x00 ругается. Осталось разобраться как вывести BLACK Color |
| Sharpnull:
--- Цитата: SMax от 23 Октябрь 2025, 07:59:33 ---На \x00 ругается. Осталось разобраться как вывести BLACK Color --- Конец цитаты --- В языке C строки завершаются нулём, поэтому нельзя передать 0x00. Не знаю лучший способ, но можно передать 0x00 в putchar(): --- Код: ---putchar(0x10); // Ink putchar(0x03); putchar(0x11); // Paper putchar(0x00); printf("Test"); --- Конец кода --- Или через fwrite() записать нужное кол-во байт, но занимает больше кода (размер .tap файла): --- Код: ---fwrite("\x10\x03\x11\x00", 1, 4, stdout); printf("Test"); --- Конец кода --- UPD: Так получше: --- Код: ---#define BLACK 0x00 #define BLUE 0x01 #define RED 0x02 #define MAGENTA 0x03 #define GREEN 0x04 #define CYAN 0x05 #define YELLOW 0x06 #define WHITE 0x07 void set_ink(uint8_t c) { putchar(0x10); putchar(c); } void set_paper(uint8_t c) { putchar(0x11); putchar(c); } ... set_ink(MAGENTA); set_paper(BLACK); printf("Test"); --- Конец кода --- |
| SMax:
--- Цитата: Sharpnull от 23 Октябрь 2025, 14:21:08 ---putchar(0x10); // Ink putchar(0x03); putchar(0x11); // Paper putchar(0x00); printf("Test"); --- Конец цитаты --- Это то, что надо. Плюс я столкнулся с проблемой установки курсора в позицию экрана AT 0;0 С помощью кода: --- Код: ---putchar(0x16); // AT putchar(0x00); putchar(0x00); printf("Test4"); --- Конец кода --- эта проблема легко решается! Спасибо большое, пойду дальше мучаться и страдать. Впереди ещё определение символа и атрибута по координатам. |
| Sharpnull:
--- Цитата: SMax от 24 Октябрь 2025, 07:05:13 ---эта проблема легко решается! --- Конец цитаты --- Ещё легче, сейчас дошло: printf("\x10\x03\x11%cHello %d", 0, 17);. Т. к. это подстановка, то строка не обрывается из-за символа 0x00. |
| SMax:
Как говорится "Не говори гоп, пока не перепрыгнешь" Потерял кучу времени, пока не дошло, что тут что-то не так. То выводит на экран не туда, то вообще программа вылетает с ошибкой. --- Код: ---//zcc +zx -vn -startup=30 -clib=sdcc_iy -create-app test.c -o test #include <stdio.h> #include <arch/zx.h> #include <stdlib.h> void printAT(unsigned char row, unsigned char col) { putchar(0x16); // AT putchar(row); putchar(col); } void main(void) { printAT(9,9); printf("9"); printAT(10,10); printf("10"); //GOTO 13;13 printAT(11,11); printf("11"); printAT(13,13); printf("13"); //Crash while(2>1) {} } --- Конец кода --- При вводе для команды AT 0x0A;0x0A прыгает в позицию 13;13. А если ввести команду AT 0x0D;0x0D то вообще с ошибкой вываливается. Как я догадываюсь, это из-за того, что x0A и x0D это перевод строки и возврат каретки. Как оно перехватывается черт ногу сломит. Нужен како-то иной способ ввести команду "AT". |
| Sharpnull:
--- Цитата: SMax от 27 Октябрь 2025, 06:34:20 ---При вводе для команды AT 0x0A;0x0A прыгает в позицию 13;13. А если ввести команду AT 0x0D;0x0D то вообще с ошибкой вываливается. --- Конец цитаты --- Происходит замена 10 на 13, а 13 на что-то ещё. Я не нашёл где в коде z88dk это происходит. Лучше спросите на их форуме. Возможно с CRT 30 не предполагалось использование управляющих кодов ZX Spectrum, с CRT 1 и подобных такой проблемы нет. |
| SMax:
Удалось обойти ограничение режима CRT 30 с помощью вставки на ассемблере. Пока работает. Хотя где-то читал, что может глючить. --- Код: ---//zcc +zx -vn -startup=30 -clib=new -create-app test.c -o test #include <stdio.h> //#include <arch/zx.h> //#include <stdlib.h> void putAT(char x, char y) { __asm LD A,22 ; AT command RST 16 ld hl,2 add hl,sp ; skip over return address on stack ld a,(hl) ; y RST 16 inc hl inc hl ld a,(hl) ; x RST 16 __endasm; } void main(void) { char x,y; for (y=0; y<22; y++){ for (x=0; x<32; x++){ putAT(x,y); putchar(0x30); }} while(2>1) {} } --- Конец кода --- |
| Навигация |
| Главная страница сообщений |