Просмотр полной версии : Чтение файла в tr-dos
hippiman
27.09.2011, 09:34
Прошу помощи. Пишу на z88dk и только начал изучать ассемблер. Потребовалось мне сделать загрузку файлов с дискетки. Т.к. ни в z88dk ни в spritepack подобных функций я не нашел, то пришлось вооружаться поиском, книгами и получилось вот это
void tr_dos_load (char *filename,char* dest)
{
sprintf(asm_filename,"%s",filename);
asm_adres=&asm_dat[0];
asm_len=0;
#asm
di
.LOAD
CALL SET_NAMEL ; готовим сист.
; переменные
LD C,10 ; ищем файл
CALL 15635
LD A,C
BIT 7,C
JR Z,LD_1
jp ext
RET
.LD_1 ; грузим...
LD A,C
LD C,8
CALL 15635
XOR A
LD (23801),A
LD (23824),A
LD A,3
LD HL,(_asm_adres)
LD C,14
CALL 15635
JP ext
.SET_NAMEL
LD HL,_asm_filename ; перекидываем
LD DE,23773 ; имя файла
LD BC,8
LDIR
LD A,67 ; тип файла м.б.
LD (23781),A ; любой, кроме
LD A,9 ; поиск файла
LD (23814),A ; по 9 символам
RET
.ext
ei
#endasm
sprintf(dest,"%s",asm_dat);
}
С выключенными прерываниями функция работает, но когда я включаю прерывания функцией sp_InitIM2(0xf1f1) сбрасывает спектрум при обращении. Помогите мне разобраться что не так и довести ее в работоспособное состояние.
при обращении к ТР-Дос и переходе по адресу #3dхх происходит подключение РОМ ТРДос
Далее происходит отработка программы именно в этом РОМе
при приходе прерывания РОМ ТРдос отключается и соответственно
возвращение из Прерывания происходит непоймикуда и потому РЕСЕТ!
null_device
27.09.2011, 10:36
Как было написано в книге Ларченко-Родионова (http://vtrdos.ru/book/ZX_TRDOS.ZIP) (стр. 196). Работа tr-dos с прерываниями реализована плохо (точнее, никак не реализована). В частности, это относится к работе во втором режиме прерывания (насколько я понял, речь шла о im2).
Проблема в "аппаратном переключении" ПЗУ tr-dos в стандартное ПЗУ sos (стандартное spectrum ПЗУ) в момент прихода прерывания. И его "невозврат" в tr-dos по завершении обработки прерывания (т.е. вместо выполнения кода tr-dos будет выполняться, что-то из sos). В книге, для корректной работы в режиме IM2, используют "разницу" в этих ПЗУ для значения вектора прерывания (а значит и определения, с каком из ПЗУ, в данный момент работает компьютер). Там же приводится пример программы, работающей во втором режиме прерывания, независимо от того, "находитесь" вы в sos или tr-dos.
Помогите мне разобраться что не так и довести ее в работоспособное состояние.
1. для чего тебе вообще загрузка с включенными прерываниями?
если для понтов то подумай как это будет выглядеть в ТАПке
2 если загрузка действительно нужна, то посмотри загрузчик в
http://www.worldofspectrum.org/infoseekid.cgi?id=0012860 в этой игрушке -
он работает везде, во всяком случае нареканий не было.
3 ну и пара советов
1 загрузку стандартными средствами трудно переделать под ИМ2 изза того, что Дос периодически лазает в ПЗУ басика
2 отследить какое ПЗУ включено невозможно, можно только предположить
hippiman
27.09.2011, 11:26
Все разобрался. Спасибо подтолкнули в нужное русло :). Прерывания во время загрузки мне не нужны вообще. Теперь перед обращениями к тр-дос просто переключаю на 1й режим, а после на 2й.
Все разобрался. Спасибо подтолкнули в нужное русло . Прерывания во время загрузки мне не нужны вообще. Теперь перед обращениями к тр-дос просто переключаю на 1й режим, а после на 2й.
Йожег, сабж милион раз обсосан в электронной ZX прессе (http://zxpress.ru/articles_list.php?tag=13). (там процедуры как правило актуальнее реликтовых книг)
newart, Общение с живыми оно же завсегда лучше
Все разобрался. Спасибо подтолкнули в нужное русло :). Прерывания во время загрузки мне не нужны вообще. Теперь перед обращениями к тр-дос просто переключаю на 1й режим, а после на 2й.
может просто запретить их?
может просто запретить их?
прерывания трдос само запрещает
а потом снова разрешает... и привет:v2_dizzy_messed:
hippiman
27.09.2011, 16:38
что-то все равно не выходит. Теперь функция отрабатывает после вызова
sp_InitIM2(0xf1f1);
sp_CreateGenericISR(0xf1f1);
но вылетает с криками "out of memory" если ее вызвать после любой функции spritepack'a.
А вылетает она на этих строчках.
LD C,10
CALL 15635
Может быть нужно какую-то область памяти предварительно сохранять, а потом восстанавливать?
а стек где? и код где?
а переменные ДОС инициализированны?
память до #6100 лучше не трогать
hippiman
27.09.2011, 17:33
ок
компилирую для запуска с адреса 24676
unsigned char asm_dat[512];
unsigned char asm_filename[9];
unsigned short asm_len;
static unsigned asm_adres;
void tr_dos_load (char *filename,char* dest)
{
sprintf(asm_filename,"%s",filename);
asm_adres=asm_dat[0];
asm_len=0;
#asm
IM 1
.LOAD
call 15649
ld c,0
CALL 15635
CALL SET_NAMEL ; готовим сист.
; переменные
LD C,10 ; ищем файл
CALL 15635
LD A,C
BIT 7,C
JR Z,LD_1
jp ext
RET
.LD_1 ; грузим...
LD A,C
LD C,8
CALL 15635
XOR A
LD (23801),A
LD (23824),A
LD A,3
LD HL,(_asm_adres)
LD C,14
CALL 15635
JP ext
.SET_NAMEL
LD HL,_asm_filename ; перекидываем
LD DE,23773 ; имя файла
LD BC,8
LDIR
LD A,67 ; тип файла м.б.
LD (23781),A ; любой, кроме
LD A,9 ; поиск файла
LD (23814),A ; по 9 символам
RET
.ext
IM 2
#endasm
sprintf(dest,"%s",asm_dat);
printf("%d",asm_dat[0]);
sp_WaitForKey();
}
сама функция. Вызов call 15649 , подготавливает переменные. Я правильно понимаю?
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <sound.h>
#include <game.h>
#include <malloc.h>
extern uchar boxx[];
extern uchar *lastk; /* system variable LAST_K */
#asm
._lastk defw 23560;
#endasm
#pragma output STACKPTR=61439
struct window mine; /* Window structure */
void *my_malloc(uint bytes)
{
return sp_BlockAlloc(0);
}
void *u_malloc = my_malloc;
void *u_free = sp_FreeBlock;
int clock_isr(void)
{
....
....
}
struct sp_SS *tmp;
uint key_left, key_right, key_up, key_down,key_pause,x,y,lx,ly,a,b,c,kn;
struct figure fg;
struct game_field fld;
short sx,sy;
uchar rotflag;
uchar kl='o';
uchar kr='p';
uchar ku='q';
uchar kdd='a';
uchar kp=' ';
uchar main_menu()
{
uchar buf[32];
uchar lvl[512];
uchar a,b,c,d,submenu,curspeed,keypressed;
uint ka,kb,kc,kd,ke,k1,k2,k3,k4,k5,k6,k7,k8,k9,k0,chkk, chkh;
ka = sp_LookupKey('a');
kb = sp_LookupKey('b');
kc = sp_LookupKey('c');
kd = sp_LookupKey('d');
ke = sp_LookupKey('e');
kn = sp_LookupKey('n');
chkk=sp_LookupKey('k');
chkh=sp_LookupKey('h');
k1 = sp_LookupKey('1');
k2 = sp_LookupKey('2');
k3 = sp_LookupKey('3');
k4 = sp_LookupKey('4');
k5 = sp_LookupKey('5');
k6 = sp_LookupKey('6');
k7 = sp_LookupKey('7');
k8 = sp_LookupKey('8');
k9 = sp_LookupKey('9');
k0 = sp_LookupKey('0');
tr_dos_load("level ",lvl); // этот вызов срабатывает
sp_Border(BLACK);
ps.bounds = sp_ClipStruct;
ps.colour=PAPER_BLACK|INK_WHITE|BRIGHT;
ps.colour=PAPER_BLACK|INK_WHITE|BRIGHT;
sp_ComputePos(&ps, 7,2);
sp_PrintString(&ps, "tetris 2 returns");
sp_ComputePos(&ps, 10,4);
sp_PrintString(&ps, "main menu");
sp_ComputePos(&ps, 7,10);
sp_PrintString(&ps, "a: new game");
sp_ComputePos(&ps, 7,12);
sp_PrintString(&ps, "b: set controll");
sp_ComputePos(&ps, 7,14);
sp_PrintString(&ps, "c: enter password");
sp_ComputePos(&ps, 7,16);
sp_PrintString(&ps, "d: select speed");
sp_ComputePos(&ps, 7,18);
sp_PrintString(&ps, "e: autorepeat");
if(autorepeat==0)
{
sp_PrintString(&ps, " false");
}
else
{
sp_PrintString(&ps, " true");
}
c=1;
d=0;
submenu=0;
curspeed=255;
tr_dos_load("level ",lvl); // а на этом вызове уже слетает
....
тут уже не работает
....
}
main()
{
uchar a,cntr;
uint kk1;
#asm
di
#endasm
sp_InitIM2(0xf1f1);
sp_CreateGenericISR(0xf1f1);
sp_RegisterHookLast(255, clock_isr);
#asm
ei
#endasm
time.lspd=8;
sp_Initialize(bgcolor, ' ');
prepare_tile(&fg);
//-----------------
unlimited_lives=0;
autorepeat=1;
while(1)
{
fld->lives=3;
fld->cur_level=1;
main_menu();
...
дальше неинтересно
может не мучаться, а сделать через функцию чтения сектора?, вычитываешь каталог, ищешь файл, находишь трек/сайд/сектор и читаешь по секторам...
Друг, ты забыл сохранять перед вызовом доса HL`
После возврата восстановить.
ex hl,hl`
push hl
call 15635
pop hl
ex hl,hl`
Ну типа того...
---------- Post added at 21:15 ---------- Previous post was at 20:53 ----------
сама функция. Вызов call 15649 , подготавливает переменные. Я правильно понимаю?
Ага, только она один раз вызывается в самом начале( если, конечно не затираешь область сис переменных потом)
второй раз вызывать её не обязательно.
hippiman
29.09.2011, 11:11
дальнейшее изучение показало, что :
вешается на любом вызове функции 15635
после вызова функции sp_PrintString из движка spritepack. У меня есть ее исходники, но асм я еще практически совсем не знаю. Выложить их сюда?
Все! Разобрался. Эта функция меняла данные в IY. Вернул туда 23610 и все заработало.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot